code-423n4 / 2021-12-amun-findings

0 stars 0 forks source link

Attacker can break `joinTokenSingle()` by transferring basketToken to the contract #212

Closed code423n4 closed 2 years ago

code423n4 commented 2 years ago

Handle

WatchPug

Vulnerability details

https://github.com/code-423n4/2021-12-amun/blob/98f6e2ff91f5fcebc0489f5871183566feaec307/contracts/basket/contracts/singleJoinExit/SingleTokenJoin.sol#L133-L137

uint256 outputAmount = outputToken.balanceOf(address(this));
require(
    outputAmount == _joinTokenStruct.outputAmount,
    "FAILED_OUTPUT_AMOUNT"
);

In the current implementation, _joinTokenSingle() requires balanceOf outputToken strictly equal to outputAmount in calldata.

However, since anyone can transfer outputToken to the contract, if there are existing outputToken in the balanceOf the contract, joinTokenSingle() will always fail with "FAILED_OUTPUT_AMOUNT".

An attacker can send 1 wei of outputToken and break joinTokenSingle().

The same problem also applies to:

https://github.com/code-423n4/2021-12-amun/blob/98f6e2ff91f5fcebc0489f5871183566feaec307/contracts/basket/contracts/singleJoinExit/SingleTokenJoinV2.sol#L128-L132

uint256 outputAmount = outputToken.balanceOf(address(this));
require(
    outputAmount == _joinTokenStruct.outputAmount,
    "FAILED_OUTPUT_AMOUNT"
);

Recomandation

Change to:

uint256 outputAmount = outputToken.balanceOf(address(this));
require(
    outputAmount >= _joinTokenStruct.outputAmount,
    "FAILED_OUTPUT_AMOUNT"
);

outputToken.safeTransfer(msg.sender, _joinTokenStruct.outputAmount);
loki-sama commented 2 years ago

duplicate #81