POC exploit breaking the withheldLiquidity
of the Tokemak EthPool contract at 0xD3D13a578a53685B4ac36A1Bab31912D2B2A2F36.
The original implementation contract is at 0x77f18a6968a38f9aef1af676420c4799e8b864ee.
The proxy was updated to the new implementation at 0xca77a278a03f3e4648f9dc073729427862d5da31 in block 13098647, mitigating this vulnerability.
export INFURA_API_KEY={your_key}
cargo run
EthPool.preTransferAdjustWithheldLiquidity()
uses msg.sender instead of sender in only part of the function.
When this is called via transferFrom, this can create a situation where transferring funds between accounts leads to accounts with requestedWithdrawals > balance, so we can inflate the withheldLiquidity value without adding more funds.
This breaks a number of important invariants, the most important being
deployableLiquidity = underlyer.balanceOf(this) - withheldLiquidity
The pool now doesn't know the amount of total withheld funds or the deployable funds.
An attacker could also "reserve" some requested withdrawal amount in a controlled account that has no balance, then transfer their funds to that account and withdraw without waiting.
Additionally, other protocols using transferFrom
will be broken if the sender has requestedWithdrawals > 0
.