Closed code423n4 closed 1 year ago
According to the documentation: When the Malt price TWAP drops below a specified threshold (eg 2% below peg) then the protocol will revert any transaction that tries to remove Malt from the AMM pool (ie buying Malt or removing liquidity). Users wanting to remove liquidity can still do so via the UniswapHandler contract that is whitelisted in recovery mode.
.
Therefore it seems this is the intended behavior, especially as there is indeed a whitelist.
0xScotch marked the issue as sponsor disputed
As mentioned above, this is the desired behaviour. The Bonding
contract also has an unbondAndBreak
method that allows staked users to have their LP broken behind the scenes - which always works due to internal whitelisting.
Picodes marked the issue as unsatisfactory: Invalid
Lines of code
https://github.com/code-423n4/2023-02-malt/blob/700f9b468f9cf8c9c5cffaa1eba1b8dea40503f9/contracts/Token/Malt.sol#L120-L128
Vulnerability details
Impact
The protocol is designed to limit buys while malt price is below peg defend threshold. But it is implemented by blocking any malt token transfer which is originated from the target pool. So it unexpectedly blocks users from removing liquidity too. Considering the market conditions is likely unfavorable to users when the peg is broken, users should be allowed to remove their liquidity and sell malt.
Proof of Concept
To implement the design of limiting buys while malt price is below peg, there is a
_beforeTokenTransfer()
hook inMalt
contract.It calls
verifyTransferAndCall()
function ofTransferService
contract.And then
verifyTransfer()
Finally,
verifyTransfer()
function ofPoolTransferVerification
contract is called.As shown on L107 and L115, if
from == address(stakeToken)
and_belowPegCheck()
fails, then the transaction will be reverted(verifyTransfer() return false
). There is no distinction between transfers triggered by liquidity removing and buys.Tools Used
VS Code
Recommended Mitigation Steps
Add a new contract with interface similar to
removeLiquidity()
ofUniswapHandler
contract but allow users to forwardremoveLiquidity()
call to pool. And add the new contract address towhitelist
ofPoolTransferVerification
contract.