The SynthVault._deposit function adds weight for the user that depends on the spot value of the deposit synth amount in BASE.
This spot price can be manipulated and the cost of manipulation is relative to the pool's liquidity.
However, the reward (see calcReward) is measured in BASE tokens unrelated to the pool.
Therefore, if the pool's liquidity is low and the reward reserve is high, the attack can be profitable:
Manipulate the pool spot price of the iSYNTH(_synth).LayerONE() pool by dripping a lot of BASE into it repeatedly (sending lots of smaller trades is less costly due to the path-independence of the continuous liquidity model). This increases the BASE per token price.
Call SynthVault.depositForMember and deposit a small amount of synth token. The iUTILS(_DAO().UTILS()).calcSpotValueInBase(iSYNTH(_synth).LayerONE(), _amount) will return an inflated weight due to the price.
Optionally drip more BASE into the pool and repeat the deposits
Drip back token to the pool to rebalance it
The user's weight is now inflated compared to the deposited / locked-up amount and they can claim a large share of the rewards.
Impact
The cost of the attack depends on the pool's liquidity and the profit depends on the reserve.
It could therefore be profitable under certain circumstances.
Recommended Mitigation Steps
Track a TWAP price of the synth instead, store the deposited synths instead, and compute the weight & total weight on the fly based on the TWAP * deposit amount instead of at the time of deposit.
Handle
cmichel
Vulnerability details
Vulnerability Details
The
SynthVault._deposit
function addsweight
for the user that depends on the spot value of the deposit synth amount inBASE
. This spot price can be manipulated and the cost of manipulation is relative to the pool's liquidity. However, the reward (seecalcReward
) is measured in BASE tokens unrelated to the pool. Therefore, if the pool's liquidity is low and the reward reserve is high, the attack can be profitable:iSYNTH(_synth).LayerONE()
pool by dripping a lot ofBASE
into it repeatedly (sending lots of smaller trades is less costly due to the path-independence of the continuous liquidity model). This increases theBASE
pertoken
price.SynthVault.depositForMember
and deposit a small amount of synth token. TheiUTILS(_DAO().UTILS()).calcSpotValueInBase(iSYNTH(_synth).LayerONE(), _amount)
will return an inflated weight due to the price.BASE
into the pool and repeat the depositstoken
to the pool to rebalance itThe user's
weight
is now inflated compared to the deposited / locked-up amount and they can claim a large share of the rewards.Impact
The cost of the attack depends on the pool's liquidity and the profit depends on the reserve. It could therefore be profitable under certain circumstances.
Recommended Mitigation Steps
Track a TWAP price of the synth instead, store the deposited synths instead, and compute the weight & total weight on the fly based on the TWAP * deposit amount instead of at the time of deposit.