-
Notifications
You must be signed in to change notification settings - Fork 0
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
iamnmt - In SuperPool
, an attacker can move assets to a specific base pool
#487
Comments
SuperPool
, an attacker can move assets to a specific base poolSuperPool
, an attacker can move assets to a specific base pool
#564 is a duplicate of this. Both exploits have same pre-conditions. Qttacker causing reallocation of amounts in base pools by depositing and immediately withdrawing certain amount. Because of the difference in deposit queue and withdraw queue, deposit might happen into one pool A and withdraw can come different pool B. As a result, assets are reallocated from pool B to pool A. The #564 lists the impact as: |
Escalate Per the above comment. In short, these 2 issues have the same root cause. |
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. |
Result: |
Escalations have been resolved successfully! Escalation status:
|
iamnmt
Medium
In
SuperPool
, an attacker can move assets to a specific base poolSummary
In
SuperPool
, the design supply to pools and withdraw from pools in queue will allow an attacker to move assets to a specific base pool.Root Cause
The design supply to pools and withdraw from pools in queue
https://github.com/sentimentxyz/protocol-v2/blob/04bf15565165396608cc0aedacf05897235518fd/src/SuperPool.sol#L524-L543
https://github.com/sentimentxyz/protocol-v2/blob/04bf15565165396608cc0aedacf05897235518fd/src/SuperPool.sol#L548-L580
Internal pre-conditions
Let's call a base pool that an attacker want to move assets is
X
.X
indepositQueue
haveSuperPool#poolCapFor[poolId] != type(uint256).max
orPool#poolDataFor[poolId].poolCap != type(uint256).max
. The meaning of this pre-condition is there is way to deposit toX
.X
inwithdrawQueue
that theSuperPool
has assets in.External pre-conditions
No response
Attack Path
There is a
SuperPool
that has:depositQueue = [A, B, X]
SuperPool#poolCapFor[A] = 100, Pool#poolDataFor[B].poolCap = 100
Pool#getTotalAssets(A) = 50, Pool#getTotalAssets(B) = 50, Pool#getTotalAssets(X) = 0
Pool#getAssetsOf(A, address(SuperPool)) = 50, Pool#getAssetsOf(B, address(SuperPool)) = 50, Pool#getAssetsOf(X, address(SuperPool)) = 0
withdrawQueue = [A, B, X]
This
SuperPool
is satisfied the internal pre-conditions. The base poolA
represents for base pools that haveSuperPool#poolCapFor[poolId] != type(uint256).max
. The base poolB
represents for base pools that havePool#poolDataFor[poolId].poolCap != type(uint256).max
. The goal of this attack is to move assets fromA, B
toX
.An attacker performs the attack in one transaction:
SuperPool#deposit(50, attacker)
. New state:Pool#getTotalAssets(A) = 100
Pool#getAssetsOf(A, address(SuperPool)) = 100
Pool#deposit(B, 50, attacker)
. New state:Pool#getTotalAssets(B) = 100
SuperPool#deposit(100, attacker)
. TheSuperPool
will deposit toX
becauseSuperPool#poolCapFor[A], Pool#poolDataFor[B].poolCap
are reached. New state:Pool#getTotalAssets(X) = 100
Pool#getAssetsOf(X, address(SuperPool)) = 100
SuperPool#withdraw(100, attacker, attacker)
. New state:Pool#getTotalAssets(A) = 0, Pool#getTotalAssets(B) = 0, Pool#getTotalAssets(X) = 100
Pool#getAssetsOf(A, address(SuperPool)) = 0, Pool#getAssetsOf(B, address(SuperPool)) = 0, Pool#getAssetsOf(X, address(SuperPool)) = 100
Pool#withdraw(B, 50, attacker)
. The attacker retrieves the funds deposited in step 2.The attacker moved all assets to
X
. By doing this attack in one transaction, the attacker can flash-loan150
tokens at the start of the attack for step 1 and 2, and then returns150
tokens back at the end of the attack. Note that, the attacker does not hold any shares ofSuperPool
orPool
at the end of the attack. Meaning the cost this attack is only gas fee and flash-loan fee.Impact
By moving assets to a specific base pool, an attacker can cause the following larger impacts:
PositionManager#liquidateBadDebt
with this attack to cause loss of funds for theSuperPool
. When the protocol callsPositionManager#liquidateBadDebt
, a base pool that has its bad debt being liquidated will suffer a loss. So, the attacker will move assets from other pools to the pools that has its bad debt being liquidated, which will cause loss of funds to theSuperPool
.Pool#withdraw
whenmaxWithdrawAssets
is not enough. In case of, the pool that the attacker want to withdraw from does not have enough liquidity, the attacker can perform this attack to move assets from other pools to their desired pool.SuperPool
.PoC
No response
Mitigation
Add a two-step
SuperPool#deposit/mint
. First the users stage theirdeposit/mint
. After a short timelock (E.g: 10 seconds), the users can finalize theirdeposit/mint
. This will prevent the attack that uses flash-loan, but if the attacker has enough liquidity, then this attack still can happen.Duplicate of #564
The text was updated successfully, but these errors were encountered: