Maia DAO Ecosystem - Co0nan's results

Efficient liquidity renting and management across chains with Curvenized Uniswap V3.

General Information

Platform: Code4rena

Start Date: 30/05/2023

Pot Size: $300,500 USDC

Total HM: 79

Participants: 101

Period: about 1 month

Judge: Trust

Total Solo HM: 36

Id: 242

League: ETH

Maia DAO Ecosystem

Findings Distribution

Researcher Performance

Rank: 92/101

Findings: 1

Award: $23.91

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

Labels

bug
2 (Med Risk)
satisfactory
edited-by-warden
duplicate-534

Awards

23.9127 USDC - $23.91

External Links

Lines of code

https://github.com/code-423n4/2023-05-maia/blob/main/src/uni-v3-staker/UniswapV3Staker.sol#L342

Vulnerability details

Impact

The function UniswapV3Staker::restakeToken was supposed to allow anyone to call it and restake the tokenID, however, the function call _unstakeToken passing the isNotRestake variable setting it as true insteand of false. Causing the _unstakeToken function to revert on L374

Description

  1. Function UniswapV3Staker::restakeToken got called by anyone as supposed: https://github.com/code-423n4/2023-05-maia/blob/main/src/uni-v3-staker/UniswapV3Staker.sol#L340
function restakeToken(uint256 tokenId) external { IncentiveKey storage incentiveId = stakedIncentiveKey[tokenId]; if (incentiveId.startTime != 0) _unstakeToken(incentiveId, tokenId, true); (IUniswapV3Pool pool, int24 tickLower, int24 tickUpper, uint128 liquidity) = NFTPositionInfo.getPositionInfo(factory, nonfungiblePositionManager, tokenId); _stakeToken(tokenId, pool, tickLower, tickUpper, liquidity); }
  1. It makes a call to _unstakeToken in order to unstake the tokenId, passing the isNotRestake argument as true.

  2. on _unstakeToken at L374, the condition below will result in the following since the owner of the tokenID is not the sender.

if ((isNotRestake || block.timestamp < endTime) && owner != msg.sender) revert NotCalledByOwner(); ----> if (true || true && true) == True - function revert
  1. This should work fine if we call unstakeToken, however, the restakeToken function supposed to be called by anyone. So the isNotRestake here should be set to false in order to pass the condition.

Proof of Concept

We need to first define the function into the IUniswapV3StakerTest.sol interface so we can use it inside the test below:

function restakeToken(uint256 tokenId) external;

Add the following function on /maia/test/uniswap-v3/UniswapV3StakerTest.t.sol

function testRestakeTokenFail() public { // Create a Uniswap V3 pool (pool, poolContract) = UniswapV3Assistant.createPool(uniswapV3Factory, address(token0), address(token1), poolFee); // Initialize 1:1 0.3% fee pool UniswapV3Assistant.initializeBalanced(poolContract); hevm.warp(block.timestamp + 100); // 3338502497096994491500 to give 1 ether per token with 0.3% fee and -60,60 ticks uint256 tokenId = newNFT(-60, 60, 3338502497096994491500); uint256 minWidth = 10; // Create a gauge gauge = createGaugeAndAddToGaugeBoost(pool, minWidth); // Create a Uniswap V3 Staker incentive key = IUniswapV3Staker.IncentiveKey({pool: pool, startTime: IncentiveTime.computeEnd(block.timestamp)}); uint256 rewardAmount = 1 ether; rewardToken.mint(address(this), rewardAmount); rewardToken.approve(address(uniswapV3Staker), rewardAmount); createIncentive(key, rewardAmount); hevm.warp(key.startTime); // Transfer and stake the position in Uniswap V3 Staker nonfungiblePositionManager.safeTransferFrom(address(this), address(uniswapV3Staker), tokenId); (address owner,,, uint256 stakedTimestamp) = uniswapV3Staker.deposits(tokenId); address anon = address(123); hevm.startPrank(anon); // Simulate call the function by 3rd party. uniswapV3Staker.restakeToken(tokenId); hevm.stopPrank(); }

Run it forge test --match-path test/uniswap-v3/UniswapV3StakerTest.t.sol --match-test testRestakeTokenFail and notice the function will revert with error NotCalledByOwner

Tools Used

Manual

Correct the boolean value to false when calling _unstakeToken inside restakeToken.

Assessed type

Context

#0 - c4-judge

2023-07-09T11:43:25Z

trust1995 marked the issue as duplicate of #745

#1 - c4-judge

2023-07-09T11:43:34Z

trust1995 marked the issue as satisfactory

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter