storage collision #260
Labels
3 (High Risk)
Assets can be stolen/lost/compromised directly
bug
Something isn't working
edited-by-warden
primary issue
Highest quality submission among a set of duplicates
sponsor disputed
Sponsor cannot duplicate the issue, or otherwise disagrees this is an issue
unsatisfactory
does not satisfy C4 submission criteria; not eligible for awards
Lines of code
https://github.com/code-423n4/2023-11-panoptic/blob/main/contracts/SemiFungiblePositionManager.sol#L152
https://github.com/code-423n4/2023-11-panoptic/blob/main/contracts/SemiFungiblePositionManager.sol#L375-L378
Vulnerability details
Impact
In
SemiFungiblePositionManager::initializeAMMPool
we useFACTORY.getPool
to get the pool from uniswap with token 0, token 1and fee, it returns the address of the pool and then we use
PanopticMath.getPoolId
to get the first 8 bytes of the address.The problem is that an attacker can create a collision because we only use 8 bytes. It seems that collision is difficult
to happen, but it is not that difficult if we use a fast language such as rust or go, where you can generate address that has
the same first 8 bytes. This is code written in go.
this code could generate billion of addresses in short period.
simple code to brute force first 8 bytes go
the impact here is that an attacker can change the storage here
because it will store changes to the same storage slot when first 8 bytes matches here.
so an attacker can change the storage and this will effect the whole protocol.
Proof of Concept
simple code to brute force first 8 bytes go
NOTE: in this example we are going to use address provided in PanopticMath: 0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8
as and example
SemiFungiblePositionManager::initializeAMMPool
with parms: token0, token1, fee.s_poolContext[uint64(0x8ad599c3A0ff1De0)]
it will be change because of the collision with attacker's pool addressand storage slot will be rewritten with attacker's pool address.
Tools Used
manually
Recommended Mitigation Steps
uint64 poolId = PanopticMath.getPoolId(univ3pool); + if(address(s_poolContext[poolId].pool) != address(0)) revert PoolId_Exits(); while (address(s_poolContext[poolId].pool) != address(0)) { poolId = PanopticMath.getFinalPoolId(poolId, token0, token1, fee); } // store the poolId => UniswapV3Pool information in a mapping // `locked` can be initialized to false because the pool address makes the slot nonzero s_poolContext[poolId] = PoolAddressAndLock({ pool: IUniswapV3Pool(univ3pool), locked: false });
this would be huge problem for the protocol in long term.
Assessed type
Other
The text was updated successfully, but these errors were encountered: