Platform: Code4rena
Start Date: 06/01/2023
Pot Size: $210,500 USDC
Total HM: 27
Participants: 73
Period: 14 days
Judge: 0xean
Total Solo HM: 18
Id: 203
League: ETH
Rank: 55/73
Findings: 1
Award: $121.59
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: CodingNameKiki
Also found by: 0xA5DF, 0xAgro, 0xNazgul, 0xSmartContract, Aymen0909, BRONZEDISC, Bnke0x0, Breeje, Cyfrin, GalloDaSballo, HollaDieWaldfee, IceBear, IllIllI, MyFDsYours, RaymondFam, Ruhum, SaharDevep, Sathish9098, Soosh, Udsen, __141345__, brgltd, btk, carlitox477, chaduke, chrisdior4, cryptonue, delfin454000, descharre, hihen, joestakey, ladboy233, lukris02, luxartvinsec, peanuts, pedr02b2, rotcivegaf, shark, tnevler, yongskiws
121.587 USDC - $121.59
[L-01] Constants not declared [L-02] Inefficient Boolean Mappings [L-03] Checking for collateral assets twice in the same function [NC-01] Storage gaps not explicitly documented [NC-02] Splitting require() statements that use multiple condition [NC-03] To improve the readability, consider changing the event name
In the Distributor.sol contract, the literal values 10000 which are used as maximum amount of shares distributed (L165 and L166)
To improve the code’s readability and facilitate refactoring, consider defining a constant for every “magic value” and ensuring that
all constants have clear names.
In Broker.sol contract L44 In InvalidBrokerMock.sol contract L20
Mappings that contain boolean variables are inefficient in general, because the solidity compiler masks the values to ensure no dirty bits are propagated.
Using mapping(address => uint256)
instead of mapping(address => bool)
eliminates these checks
and the number of SLOADs needed to retrieve an entry from mapping.
In the function setPrimeBasket, the collateral is checked two times, in L230 throught the require statement and in L236 throught the call of the toColl function for an asset. Is it relevant to check two times ? I don't think so, especially since the collateral value is not settable and does not change.
Use another logic, for exemple retrieve the targetName of the asset by creating another function that doesn't check for collateral assuming that the check already done,
When using the proxy pattern for upgrades, it is common practice to include storage gaps on parent contracts to reserve space for potential future variables. The size is typically chosen so that all contracts have the same number of variables (usually 50).
Differents contracts include the storages gaps but they use inconsistent sizes. Sometimes 30, somtimes 37, 42 and so on.If there is any reason to choose a precise gaps size then it's not explicitly documented.
Use a size gaps of 50 for all your contracts. By the way, it's important to remind that gaps storage does not cost additional gas when deploying a contract.
It's a best practice to split the different require statement instead a long require.
Exemple in Deployer.sol L48
If the requirement fail, we cannot explicitly determine which address was set to zero without checking each address one by one.
When the disabled state variable is modified, an event is emited but the event is called
emit BasketSet(nonce, basket.erc20s, refAmts, disabled);
To be logic the event name must be disabledBasketSet or keep basketSet but the emit should be like this :
emit BasketSet(nonce, basket.erc20s, refAmts, !disabled);
#0 - c4-judge
2023-01-25T00:15:20Z
0xean marked the issue as grade-b