-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
0xDazai - SuperPool
fails to correctly deposit into pools
#178
Comments
SuperPool
fails to correctly deposit into poolsSuperPool
fails to correctly deposit into pools
Isn't that the intention of The poolCapFor in the superpool is to do with the super pool itself: Max amount the super pool wants to deposit it into a certain pool. pool.PoolCap is max amount of assets in the pool. The issue is clearly invalid. The issue is considering incorrect definition for state variable |
Escalate. |
You've created a valid escalation! To remove the escalation from consideration: Delete your comment. You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final. |
Every BasePool has different settings which can incentivise users to or not to prefer to deposit into a BasePool ( e.g interest rate , rateModel and so on) . As its said in the docs ‘users who are accessing Sentiment UI has indirect interaction with base pools, Super Pools will take care of efficiently distributing user liquidity across multiple base pools for enhanced liquidity management. ‘ Having this in mind users who are using Sentiment UI fully rely on the correct functionality of the SuperPool contract. Base Pools and SuperPools have a maximum poolCap set which shouldn’t be exceeded. Also BasePools can be used by multiple SuperPools or directly from their contract. These are the ways to deposit into a BasePool and eventually hit their cap depending of the cap value. The issue I am describing is that if SuperPool.poolCapForId is not reached in the ‘deposit’ function the ‘_supplyToPools()’ can call ‘POOL.deposit()’ with bigger value than it is available into the BasePool and the tx will revert because ‘_supplyToPools()’ is not checking how much exactly enough space does the BasePool has before hitting its cap and in case when the free space into the BasePool is smaller than the value which is tried to be deposited the tx will revert instead of depositing the amount which is available into that BasePool and the rest ,if there is any , to be deposited into the next BasePool from the SuperPool queue. |
I recommend @S3v3ru5 to read the report well. With a basic understanding of the code, multiple Superpools, as explained by 0xDazall and others, can use the same pool. |
Sorry for misunderstanding. So the issue is: The available free space in the base pool could be less than the supply amount and the |
The root cause is the most important thing that we should note. For better mitigations, you can check through other duplicates, sometimes the best report is not the best. But we practically are to deposit the minimum between the available space in the main pool (considering other pools) and the supply amount. |
From the readme :
|
Thanks for the input @elhajin, kindly look through the code implementation. The same check flaw exists in the rebalance function. It was indeed an oversight that has been confirmed and will be fixed. We can't risk having an inefficient deposit, withdrawal and rebalance function, can we? Also, Feel free to read other duplicates also. |
Looks like we have an issue here and the deposit function is not working as it should. @ruvaag what do you think? |
Please reconsider the issue #602. It clearly states the similar issue and should be grouped with this bug. |
I think this is valid. The Base Pool cap should be taken into account. the intended behavior is to deposit as much as possible in the pools, and this helps with that. |
The sponsor confirms that we have a issue here. The issue is valid because the Base Pool cap should be considered when calculating the available deposit space in the pool. I will also duplicate #602 to this issue. Planning to reject the escalation and leave the issue as is. I will duplicate #602 to this issue. |
Result: |
Escalations have been resolved successfully! Escalation status:
|
The protocol team fixed this issue in the following PRs/commits: |
0xDazai
Medium
SuperPool
fails to correctly deposit into poolsSummary
When a depositor calls
SuperPool::deposit()
the internal_deposit()
is called, it checks ifastTotalAssets + assets > superPoolCap
, transfers the assets frommsg.sender
tosuperPool address
, mintsshares
toreceiver
and then calls_supplyToPools()
.SuperPool::_deposit()
SuperPool::_supplyToPools()
_supplyToPools()
loops through all pools, depositing assets sequentially until the cap is reached. When it checks if thecap of the poolId
is reached instead of comparing thetotal deposit assets amount
of thepoolId
with thepool.poolCap
to see if there is a free space for depositing into, it only compares the total assets deposited by theSuperPool address
into thepoolId
withpoolCapFor[poolId] mapping
set by theowner of the SuperPool
when the pool was added by callingaddPool()
and subtract the result with the wanted asset value for depositing.Vulnerability Detail
When calculating if there is a free space for depositing into the
poolId
by callinguint256 assetsInPool = POOL.getAssetsOf(poolId, address(this));
it can return bigger value than the actual one left in thepool.poolCap
, increasing the chances ofdeposit()
function for thepoolId
to revert, unsuccessfully filling up the left space in thepoolId
before moving forward to the nextpoolId
if there is any asset amount left.Impact
Fails to correctly fill up assets into pools even if there is any free space to do so.
Code Snippet
PoC
Lets look at the following example:
poolId = 1
creates the pool and setspoolCap = 2000 USDC
SuperPool
poolId = 1
is added to the contract withpoolCapFor[poolId] = 1500
.poolId = 1
by callingSuperPool.deposit()
.a) Now the
poolCapFor[poolId]
free space is 500 USDC.b) And
poolCap free space for poolId = 1
is 1000 USDC.Pool.deposit()
forpoolId = 1
with 600 USDC , andpoolCap free space for poolId = 1
is 400USDC.SuperPool.deposit()
with 500 USDC and it will try to deposit intopoolId = 1
becausepoolCapFor[poolId] free space = 500
, butpoolCap free space = 400
, the tx will revert for that poolId and will move forward and try to deposit into the next pool even when there is free space for 400 USDC .Tool used
Manual Review
Recommendation
In Pool.sol add :
And in SuperPool.sol
The text was updated successfully, but these errors were encountered: