Platform: Code4rena
Start Date: 09/09/2022
Pot Size: $42,000 USDC
Total HM: 2
Participants: 101
Period: 3 days
Judge: hickuphh3
Total Solo HM: 2
Id: 161
League: ETH
Rank: 12/101
Findings: 1
Award: $38.41
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: GalloDaSballo
Also found by: 0x040, 0x1f8b, 0x4non, 0x52, 0x85102, 0xNazgul, 0xSky, 0xSmartContract, Aymen0909, Bnke0x0, CertoraInc, Chandr, Chom, CodingNameKiki, Deivitto, Diana, Funen, JC, Jeiwan, Junnon, KIntern_NA, Lambda, Mohandes, Noah3o6, Ocean_Sky, Picodes, R2, Randyyy, RaymondFam, ReyAdmirado, Rohan16, Rolezn, Samatak, Sm4rty, SnowMan, SooYa, StevenL, Tagir2003, Tointer, TomJ, Tomo, V_B, Waze, _Adam, __141345__, a12jmx, ajtra, ak1, asutorufos, bharg4v, bobirichman, brgltd, c3phas, cccz, cryptonue, cryptostellar5, cryptphi, csanuragjain, d3e4, datapunk, delfin454000, dipp, djxploit, durianSausage, erictee, fatherOfBlocks, gogo, got_targ, hansfriese, horsefacts, hyh, ignacio, innertia, izhuer, karanctf, ladboy233, leosathya, lucacez, lukris02, mics, oyc_109, pashov, pauliax, prasantgupta52, rbserver, ret2basic, rfa, robee, rokinot, rotcivegaf, rvierdiiev, sach1r0, scaraven, sikorico, simon135, smiling_heretic, sorrynotsorry, unforgiven, wagmi, yixxas
38.4075 USDC - $38.41
In contracts/peg/SimpleFeiDaiPSM.sol and contracts/shutdown/redeem/TribeRedeemer.sol lock the pragma to an specific version
The contracts/shutdown/redeem/TribeRedeemer.sol could burn the tokens received by redeem
function
function redeem(address to, uint256 amountIn) external nonReentrant { + IERC20 _redeemedToken = IERC20(redeemedToken); - IERC20(redeemedToken).safeTransferFrom(msg.sender, address(this), amountIn); + _redeemedToken.safeTransferFrom(msg.sender, address(this), amountIn); + _redeemedToken.burn(amountIn); (address[] memory tokens, uint256[] memory amountsOut) = previewRedeem(amountIn); uint256 base = redeemBase; redeemBase = base - amountIn; // decrement the base for future redemptions for (uint256 i = 0; i < tokens.length; i++) { IERC20(tokens[i]).safeTransfer(to, amountsOut[i]); } emit Redeemed(msg.sender, to, amountIn, base); }
In contracts/shutdown/fuse/RariMerkleRedeemer.sol#L164:
From: /// Should set the user's claim amount int he claims mapping for the provided cToken
To: // Should set the user's claim amount in the claims mapping for the provided cToken
The emitted events are not indexed, making off-chain scripts such as front-ends of dApps difficult to filter the events efficiently.
Recommended Mitigation Steps: Add the indexed
keyword in filter parameters of the events
In contracts/peg/SimpleFeiDaiPSM.sol: From:
L27: event Redeem(address to, uint256 amountFeiIn, uint256 amountAssetOut); L29: event Mint(address to, uint256 amountIn, uint256 amountFeiOut);
To:
L27: event Redeem(address indexed to, uint256 amountFeiIn, uint256 amountAssetOut); L29: event Mint(address indexed to, uint256 amountIn, uint256 amountFeiOut);
previewRedeem
in contracts/shutdown/redeem/TribeRedeemer.sol the amountIn
should be lower or equal than base
by definitionfunction previewRedeem(uint256 amountIn) public view returns (address[] memory tokens, uint256[] memory amountsOut) { tokens = tokensReceivedOnRedeem(); amountsOut = new uint256[](tokens.length); uint256 base = redeemBase; + require(base >= amountsIn, "High amountsIn"); for (uint256 i = 0; i < tokensReceived.length; i++) { uint256 balance = IERC20(tokensReceived[i]).balanceOf(address(this)); require(balance != 0, "ZERO_BALANCE"); // @dev, this assumes all of `tokensReceived` and `redeemedToken` // have the same number of decimals uint256 redeemedAmount = (amountIn * balance) / base; amountsOut[i] = redeemedAmount; } }
In the constructor
of contracts/shutdown/redeem/TribeRedeemer.sol:
_redeemedToken
parameter should not be the address(0)
_tokensReceived
array should not be address(0)
_redeemBase
parameter should not be 0
constructor( address _redeemedToken, address[] memory _tokensReceived, uint256 _redeemBase ) { + require(_redeemedToken != address(0), "_redeemedToken should not be address(0)"); redeemedToken = _redeemedToken; + uint256 _tokensReceivedLength; + for (uint256 i; i < _tokensReceivedLength;) { + require(_tokensReceived[i] != address(0), "All tokensReceived should not be address(0)"); + unchecked{ ++i; } + } tokensReceived = _tokensReceived; + require(_redeemBase != 0, "_redeemBase should not be 0"); redeemBase = _redeemBase; }
In the constructor
of contracts/shutdown/fuse/RariMerkleRedeemer.sol the cTokens
should not contains any address(0)
constructor( address token, address[] memory cTokens, uint256[] memory rates, bytes32[] memory roots ) { + uint256 cTokensLength; + for (uint256 i; i < cTokensLength;) { + require(cTokens[i] != address(0), "All cTokens should not be address(0)"); + unchecked{ ++i; } + } _configureExchangeRates(cTokens, rates); _configureMerkleRoots(cTokens, roots); _configureBaseToken(token); }
The MESSAGE_HASH
used in _sign
in RariMerkleRedeemer.sol#L155 defined in MultiMerkleRedeemer.sol#L56 use a poor message "Sample message, please update."
This message don't represent anything, also says update it
The rates setter in the constructor
of contracts/shutdown/fuse/RariMerkleRedeemer.sol can expire
add an expiry date and update the rate in a window time
hasNotSigned
In the signAndClaim
function miss hasNotSigned
modifier
#0 - rotcivegaf
2022-09-20T22:16:54Z
L-07 reference the mid: #51