Platform: Code4rena
Start Date: 16/01/2024
Pot Size: $80,000 USDC
Total HM: 37
Participants: 178
Period: 14 days
Judge: Picodes
Total Solo HM: 4
Id: 320
League: ETH
Rank: 144/178
Findings: 2
Award: $20.45
🌟 Selected for report: 0
🚀 Solo Findings: 0
8.7582 USDC - $8.76
ManagedWallet
contract is responsible for managing the mainWallet and confirmationWallet.
In a case where we want to changeWallets()
, first mainWallet
calls proposeWallets()
and confirmationWallet
sends required ether to establish timelock and after enough time passed proposedMainWallet
calls changeWallets()
to execute the proposal.
changeWallets()
implements a code block to reset
the proposed wallets to simply make it possible to propose again (to pass the overwrite check).
function changeWallets() ... // Reset activeTimelock = type(uint256).max; proposedMainWallet = address(0); proposedConfirmationWallet = address(0); } }
When we want to reject
a proposal, proposedWallet
should just sent less than .05 ether to contract. This only sets activeTimelock
to uint256.max and forgets to reset
the proposed wallets to be able to proposeWallets
again.
receive() external payable { require( msg.sender == confirmationWallet, "Invalid sender" ); // Confirm if .05 or more ether is sent and otherwise reject. if ( msg.value >= .05 ether ) ... else activeTimelock = type(uint256).max; }
Since it is impossible to propose again after rejecting a proposal, it must be accepted otherwise changing team wallets would be impossible and given a false address proposed, contract would break.
Step-by-step overview a case:
mainWallet
and calls proposeWallets()
reject
and propose
again so they send 1 wei to contract to reject the previous proposalproposeWallets()
to propose again but get an error mesage "Cannot overwrite non-zero proposed mainWallet."Here they have one option, to call changeWallets()
with proposedMainWallet
if it is in their use or to stick with same wallet addresses forever.
Manual
Adding required resets inside receive()
to pass the checks to call proposeWallets again.
proposedMainWallet = address(0); proposedConfirmationWallet = address(0);
Other
#0 - c4-judge
2024-02-02T13:53:59Z
Picodes marked the issue as duplicate of #838
#1 - c4-judge
2024-02-17T18:22:37Z
Picodes changed the severity to 2 (Med Risk)
#2 - c4-judge
2024-02-21T16:53:22Z
Picodes marked the issue as satisfactory
🌟 Selected for report: juancito
Also found by: 0x3b, 0xBinChook, 0xCiphky, 0xHelium, 0xMango, 0xOmer, 0xRobocop, 0xSmartContractSamurai, 0xWaitress, 0xbepresent, 0xpiken, 7ashraf, Arz, Audinarey, Banditx0x, Bauchibred, Draiakoo, IceBear, J4X, Jorgect, Kaysoft, KingNFT, Rhaydden, Rolezn, The-Seraphs, Tigerfrake, Topmark, Tripathi, Udsen, ZanyBonzy, a3yip6, b0g0, chaduke, codeslide, csanuragjain, dharma09, djxploit, eta, ether_sky, grearlake, inzinko, jasonxiale, jesjupyter, josephdara, lanrebayode77, linmiaomiao, lsaudit, niroh, oakcobalt, peanuts, pina, sivanesh_808, slvDev, t0x1c, vnavascues, wangxx2026
11.6897 USDC - $11.69
ManagedWallet
contract introduces 2 wallets mainWallet
and confirmationWallet
. It is possible to pick them as same addresses. Since they have different roles they must not be same. Consider adding relevant checks both in constructor
and proposeWallets()
to block the logic fail.
According to the comment, overwriting a proposal should not allowed. Though the mentioned check exist for proposedMainWallet, there isn't for proposedConfirmationWallet
.
approve()
should be replaced with safeIncreaseAllowance()
/ safeDecreaseAllowance()
approve
is subject to known front-running attacks and does not handle non-standard ERC20 behaviors. Consider using safeIncreaseAllowance
and safeDecreaseAllowance
instead:
src/staking/Liquidity.sol: 86 if (swapAmountA > 0) { 87: tokenA.approve(address(pools), swapAmountA); 88 100 else if (swapAmountB > 0) { 101: tokenB.approve(address(pools), swapAmountB); 102 154 // Approve the liquidity to add 155: tokenA.approve(address(pools), maxAmountA); 156: tokenB.approve(address(pools), maxAmountB); 157
Keep in mind that safeApprove() is deprecated by OZ and recommended using their safeIncreaseAllowance()
and safeDecreaseAllowance()
See this discussion: SafeERC20.safeApprove() Has unnecessary and unsecure added behavior
NOTE: In bot report this issue is mentioned but it recommends to use safeApprove()
which is deprecated and not safe to use.
PriceAggregator.setPriceFeed()
It should exist to prevent any undesired outcome. Consider adding:
require( address(newPriceFeed) != address(0), "newPriceFeed address can not be zero" );
#0 - c4-judge
2024-02-03T14:12:47Z
Picodes marked the issue as grade-b