Open c4-bot-2 opened 11 months ago
Picodes marked the issue as duplicate of #519
Picodes marked the issue as satisfactory
I believe this report should be chosen as the primary report for the following reasons:
feesGrowthInsideLastX128
. Picodes marked the issue as selected for report
@0xmonrel I agree with your comment although I am not used to changing "selected for reports" during the post judging QA. An other argument is that this report includes an example (the VRA pool)
Lines of code
https://github.com/code-423n4/2023-11-panoptic/blob/aa86461c9d6e60ef75ed5a1fe36a748b952c8666/contracts/SemiFungiblePositionManager.sol#L521 https://github.com/code-423n4/2023-11-panoptic/blob/aa86461c9d6e60ef75ed5a1fe36a748b952c8666/contracts/SemiFungiblePositionManager.sol#L1004-L1006 https://github.com/code-423n4/2023-11-panoptic/blob/aa86461c9d6e60ef75ed5a1fe36a748b952c8666/contracts/SemiFungiblePositionManager.sol#L1031-L1033 https://github.com/code-423n4/2023-11-panoptic/blob/aa86461c9d6e60ef75ed5a1fe36a748b952c8666/contracts/SemiFungiblePositionManager.sol#L1062-L1066 https://github.com/code-423n4/2023-11-panoptic/blob/aa86461c9d6e60ef75ed5a1fe36a748b952c8666/contracts/SemiFungiblePositionManager.sol#L1209-L1211 https://github.com/code-423n4/2023-11-panoptic/blob/aa86461c9d6e60ef75ed5a1fe36a748b952c8666/contracts/SemiFungiblePositionManager.sol#L626-L630
Vulnerability details
Impact
An attacker can steal all outstanding fees belonging to the SFPM in a uniswap pool if a token in the pool is an ERC777.
Proof of Concept
The attack is possible due to the following sequence of events when minting a short option with
minTokenizedPosition()
:ERC1155 is minted. L521
Liquidity is updated. L1004
An LP position is minted and tokens are transferred from
msg.sender
to uniswap. L1031feesBase is updated. L1062
If at least one of the tokens transferred at step 3 is an ERC777
msg.sender
can implement atokensToSender()
hook and transfer the ERC1155 befores_accountFeesBase[positionKey]
has been updated.registerTokenTransfer()
will copys_accountLiquidity[positionKey]>0
ands_accountFeesBase[positionKey] = 0
such that the receiver now has a ERC1155 position with non-zero liquidity but afeesBase = 0
.When this position is burned the fees collected are calculated based on: L209
The attacker will withdraw fees based on the current value of
feeGrowthInside0LastX128
andfeeGrowthInside1LastX128
and not the difference between the current values and when the short position was created.The attacker can chose the tick range such that
feeGrowthInside1LastX128
andfeeGrowthInside1LastX128
are as large as possible to minimize the liquidity needed steal all available fees.POC
The
AttackImp
contract below implements thetokensToSend()
hook and transfer the ERC1155 beforefeesBase
has been set. An addressAttacker
deploysAttackImp
and callsAttackImp#minAndTransfer()
to start the attack. To finalize the attack they burn the position and steal all available fees that belongs to the SFPM.In the POC we use the VRA pool as an example of a uniswap pool with a ERC777 token.
Create a test file in
2023-11-panoptic/test/foundry/core/Attacker.t.sol
and paste the below code. Runforge test --match-test testAttack --fork-url "https://eth.public-rpc.com" --fork-block-number 18755776 -vvv
to execute the POC.Tools Used
vscode, foundry
Recommended Mitigation Steps
Update liquidity after minting/burning
For redundancy
registerTokensTransfer()
can also use theReentrancyLock()
modifier to always block reentrancy when minting and burning.Assessed type
Reentrancy