AnySwap Permit Attack
Total Losses
$960.0K+
Date
Network
Categories
data validationStep-by-step
- Craft and deploy a contract so that it passes the requirements.
- Find a victim that had
permitthe contract to useWETH. - Call
anySwapOutUnderlyingWithPermitwith your malicious contract and the victim’s address.
Detailed Description
Another attack that relies on an arbitry token parameter. Here, Multichain intended the token to be an Anytoken (Multichain was previously called AnySwap), which they use to track account balances when doing cross-chain transaction.
The anySwapOutUnderlyingWithPermit() method takes a token and will call permit on its underlying and then transfer from the underlying to the token.
The contract fails to take into account that WETH is special: WETH’s fallback function triggers its deposit() method and returns true and does not implement permit, so calls to permit on WETH simply return true.
To make matters worst, most of the users of Multichain had given an unlimited token allowance to the Protocol, so when the contract uses transferFrom it can use an arbitrary amount.
function anySwapOutUnderlyingWithPermit(
address from,
address token,
address to,
uint amount,
uint deadline,
uint8 v,
bytes32 r,
bytes32 s,
uint toChainID
) external {
address _underlying = AnyswapV1ERC20(token).underlying();
IERC20(_underlying).permit(from, address(this), amount, deadline, v, r, s);
TransferHelper.safeTransferFrom(_underlying, from, token, amount);
AnyswapV1ERC20(token).depositVault(amount, from);
_anySwapOut(from, token, to, amount, toChainID);
}
function _anySwapOut(address from, address token, address to, uint amount, uint toChainID) internal {
AnyswapV1ERC20(token).burn(from, amount);
emit LogAnySwapOut(token, from, to, amount, cID(), toChainID);
}
Here, the attacker deployed a contract that returned WETH as the underlying.
permitwill pass due to the reason outlined above, even with no signature.transferFromwill pass if thevictimallowed Multichain withpermit.
Then it is just a matter of findings victims.
Possible mitigations
- Implement a whitelist of allowed tokens.
- Avoid asking users to sign unlimited
allowances.