Platform: Code4rena
Start Date: 13/12/2021
Pot Size: $75,000 USDC
Total HM: 11
Participants: 30
Period: 7 days
Judge: leastwood
Total Solo HM: 4
Id: 68
League: ETH
Rank: 19/30
Findings: 2
Award: $552.57
π Selected for report: 4
π Solo Findings: 0
38.7989 USDC - $38.80
GiveMeTestEther
Use of transfer() might render ETH impossible to withdraw becuase after istanbul hardfork , there is increases in the gas cost of the SLOAD operation and therefore breaks some existing smart contracts.Those contracts will break because their fallback functions used to consume less than 2300 gas, and theyβll now consume more, since 2300 the amount of gas a contractβs fallback function receives if itβs called via Solidityβs transfer() or send() methods. Any smart contract that uses transfer() or send() is taking a hard dependency on gas costs by forwarding a fixed amount of gas: 2300.
https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/
2021-12-amun\contracts\basket\contracts\singleJoinExit\EthSingleTokenJoin.sol: msg.sender.transfer(remainingIntermediateBalance);
2021-12-amun\contracts\basket\contracts\singleJoinExit\EthSingleTokenJoinV2.sol: msg.sender.transfer(remainingIntermediateBalance);
2021-12-amun\contracts\basket\contracts\singleJoinExit\SingleNativeTokenExit.sol: msg.sender.transfer(intermediateTokenBalance);
2021-12-amun\contracts\basket\contracts\singleJoinExit\SingleNativeTokenExitV2.sol: msg.sender.transfer(intermediateTokenBalance);.
Manual Analysis
-use call() to send ETH
π Selected for report: sirhashalot
Also found by: GiveMeTestEther, JMukesh, Ruhum, WatchPug, defsec, robee
76.0316 USDC - $76.03
GiveMeTestEther
The function "_maxApprove()" calls IERC20.approve() that is defined to return a boolean. However, there are legitimate non-standards-compliant tokens like USDT that donβt return a return value on approve(). All IERC20.approve() calls to such tokens will revert because of the missing return value.
https://github.com/code-423n4/2021-12-amun/blob/98f6e2ff91f5fcebc0489f5871183566feaec307/contracts/basket/contracts/singleJoinExit/SingleNativeTokenExit.sol#L39 https://github.com/code-423n4/2021-12-amun/blob/98f6e2ff91f5fcebc0489f5871183566feaec307/contracts/basket/contracts/singleJoinExit/SingleNativeTokenExitV2.sol#L50 https://github.com/code-423n4/2021-12-amun/blob/98f6e2ff91f5fcebc0489f5871183566feaec307/contracts/basket/contracts/singleJoinExit/SingleTokenJoin.sol#L38 https://github.com/code-423n4/2021-12-amun/blob/98f6e2ff91f5fcebc0489f5871183566feaec307/contracts/basket/contracts/singleJoinExit/SingleTokenJoinV2.sol#L48
Manual Analysis
#0 - 0xleastwood
2022-01-23T04:26:03Z
Duplicate of #294
π Selected for report: pauliax
Also found by: GiveMeTestEther, itsmeSTYJ, robee
GiveMeTestEther
Some tokens need to first set the the approve amount to 0 to set it to a non-zero amount (USDT: https://etherscan.io/address/0xdac17f958d2ee523a2206206994597c13d831ec7#code). This makes the _maxApprove() and the approve.selector calls incompatible to such tokens.
approve.selector: https://github.com/code-423n4/2021-12-amun/blob/98f6e2ff91f5fcebc0489f5871183566feaec307/contracts/basket/contracts/callManagers/RebalanceManagerV3.sol#L75 https://github.com/code-423n4/2021-12-amun/blob/98f6e2ff91f5fcebc0489f5871183566feaec307/contracts/basket/contracts/callManagers/RebalanceManagerV2.sol#L70 https://github.com/code-423n4/2021-12-amun/blob/98f6e2ff91f5fcebc0489f5871183566feaec307/contracts/basket/contracts/callManagers/RebalanceManager.sol#L131 https://github.com/code-423n4/2021-12-amun/blob/98f6e2ff91f5fcebc0489f5871183566feaec307/contracts/basket/contracts/callManagers/RebalanceManager.sol#L84
.approve(): https://github.com/code-423n4/2021-12-amun/blob/98f6e2ff91f5fcebc0489f5871183566feaec307/contracts/basket/contracts/singleJoinExit/SingleNativeTokenExit.sol#L39 https://github.com/code-423n4/2021-12-amun/blob/98f6e2ff91f5fcebc0489f5871183566feaec307/contracts/basket/contracts/singleJoinExit/SingleNativeTokenExitV2.sol#L50 https://github.com/code-423n4/2021-12-amun/blob/98f6e2ff91f5fcebc0489f5871183566feaec307/contracts/basket/contracts/singleJoinExit/SingleTokenJoin.sol#L38 https://github.com/code-423n4/2021-12-amun/blob/98f6e2ff91f5fcebc0489f5871183566feaec307/contracts/basket/contracts/singleJoinExit/SingleTokenJoinV2.sol#L48
#0 - 0xleastwood
2022-01-23T04:26:52Z
Duplicate of #269
GiveMeTestEther
Every ETH that wasn't received by "receive() external payable" from "INTERMEDIATE_TOKEN" by calling "withdraw()" cannot be withdrawn. Because in the contract we only transfer INTERMEDIATE_TOKEN.balanceOf(address(this)) and not the ETH balance of the contract, that also could be sent accidentally.
2021-12-amun\contracts\basket\contracts\singleJoinExit\EthSingleTokenJoin.sol: receive() external payable {} 2021-12-amun\contracts\basket\contracts\singleJoinExit\EthSingleTokenJoinV2.sol: receive() external payable {} 2021-12-amun\contracts\basket\contracts\singleJoinExit\SingleNativeTokenExit.sol: receive() external payable {} 2021-12-amun\contracts\basket\contracts\singleJoinExit\SingleNativeTokenExitV2.sol: receive() external payable {}
Manual Analysis
π Selected for report: GiveMeTestEther
78.3316 USDC - $78.33
GiveMeTestEther
Don't need to use safe subtraction in "uint256 timePassed = block.timestamp.sub(lastFeeClaimed);" because block.timestamp is always bigger or equal to lastFeeClaimed.
Save gas by not doing a safe subtraction.
Manual Analysis
π Selected for report: GiveMeTestEther
GiveMeTestEther
"bs.exitFee" can only be <= MAX_EXIT_FEE (1017 = 10 %) So the feeAmount can be at max 10% of _amount. uint256 feeAmount = _amount.mul(bs.exitFee).div(1018); Therefore the subtarction _amount.sub(feeAmount) can't underflow and can write this as "_amount - feeAmount" (save gas by not doin underflow check)
uint256 tokenAmount = tokenBalance.mul(_amount.sub(feeAmount)).div(totalSupply);
No need to do safe subtraction and can save some ags.
Manual Analysis