Platform: Code4rena
Start Date: 12/04/2023
Pot Size: $60,500 USDC
Total HM: 21
Participants: 199
Period: 7 days
Judge: hansfriese
Total Solo HM: 5
Id: 231
League: ETH
Rank: 175/199
Findings: 1
Award: $21.03
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: c3phas
Also found by: 0xDACA, 0xRB, 0xSmartContract, 0xhacksmithh, 0xnev, Aymen0909, BenRai, Breeje, DishWasher, Erko, EvanW, JCN, MohammedRizwan, NoamYakov, Polaris_tow, Proxy, Rageur, Raihan, RaymondFam, ReyAdmirado, SAAJ, Sathish9098, Satyam_Sharma, Udsen, __141345__, aria, codeslide, decade, fatherOfBlocks, hunter_w3b, karanctf, matrix_0wl, nadin, naman1778, niser93, pavankv, petrichor, pfapostol, sebghatullah, slvDev, trysam2003, xmxanuel
21.0255 USDC - $21.03
[G-01] Avoid always reading **state variable
.
In function calculateCurrentFee
, it’s better to create a memory variable for start
rather than repeatedly reading state variable
the state variable minted
in notifyChallengeSucceeded
also encounter the same issue.
contracts/Position.sol 187: return uint32(mintingFeePPM - mintingFeePPM * (time - start) / (exp - start)); 349: uint256 repayment = minted < volumeZCHF ? minted : volumeZCHF; // how much must be burned to make things even
Suggestion as an example:
contracts/Position.sol function calculateCurrentFee() public view returns (uint32) { uint256 exp = expiration; uint256 time = block.timestamp; uint256 _start = start; if (time >= exp){ return 0; } else { return uint32(mintingFeePPM - mintingFeePPM * (time - _start) / (exp - _start)); } }
[G-02] params checking should be on the beginning of a function
function checkCollateral
will revert the transaction if the collateral_ amount is not fulfilled. It’s better to put this line of code in the beginning like the LimitExceed checking
contracts/Position.sol 198: checkCollateral(collateral_, price);
Suggestion:
contracts/Position.sol function mintInternal(address target, uint256 amount, uint256 collateral_) internal { if (minted + amount > limit) revert LimitExceeded(); checkCollateral(collateral_, price); zchf.mint(target, amount, reserveContribution, calculateCurrentFee()); minted += amount; emitUpdate(); }
[G-03] **Avoid using state variable
 in emit (130 gas)
Emit the memory variable or calldata variable instead.
contracts/Position.sol 287: emit MintingUpdate(collateralBalance(), price, minted, limit);
[G-04] Don’t need to cast uint as uint192 and uint 64
Cast it as uint192 and uint 64 won’t save any gas fee because it’s not in a struct. Also, when using elements that are smaller than 32 bytes, your contracts gas usage may be higher.
75: uint192 private totalVotesAtAnchor; // Total number of votes at the anchor time, see comment on the um 76: uint64 private totalVotesAnchorTime; // 40 Bit for the block number, 24 Bit sub-block time resolution
#0 - 0xA5DF
2023-04-27T15:34:11Z
G1 is false since start
is immutable
#1 - c4-judge
2023-05-16T13:54:03Z
hansfriese marked the issue as grade-b