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: 78/199
Findings: 2
Award: $43.63
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: juancito
Also found by: 0xAgro, 0xNorman, 0xSmartContract, 0xStalin, 0xTheC0der, 0xWaitress, 0xhacksmithh, 0xnev, 3dgeville, 8olidity, Arz, Aymen0909, BGSecurity, BRONZEDISC, Bauchibred, Bauer, BenRai, ChainHunters, ChrisTina, CodeFoxInc, DedOhWale, DishWasher, EloiManuel, IceBear, Inspex, Jorgect, Kaysoft, LeoGold, LewisBroadhurst, Madalad, MiloTruck, MohammedRizwan, Nyx, Polaris_tow, RaymondFam, SaharDevep, SanketKogekar, Sathish9098, SolidityATL, Udsen, W0RR1O, aria, ayden, berlin-101, bin2chen, catellatech, codeslide, crc32, decade, descharre, evmboi32, eyexploit, fatherOfBlocks, georgits, giovannidisiena, joestakey, karanctf, kodyvim, ltyu, lukris02, m9800, matrix_0wl, mov, mrpathfindr, nadin, niser93, p0wd3r, parlayan_yildizlar_takimi, pavankv, pontifex, qpzm, ravikiranweb3, rbserver, santipu_, shealtielanz, slvDev, tnevler, wonjun, xmxanuel, yixxas
22.6007 USDC - $22.60
Summary In bid() first transfer the challengebid to challenger and then in line 216 checks the after all computation so it's good practice to check before transfer the challengebid and it's save gas also by avoid computation even the _bidAmountZCHF is lesser than minimumbid.
code snippet:- https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/MintingHub.sol#L216
Summary :- In minterOnly() modifier calls isMinter() and isMinter(positions[msg.sender]) in if else statement to check whether the msg.sender is minter or not.
Modifiers can be used to:
Restrict access Validate inputs Guard against reentrancy hack
But isMinter() function only checks whether the msg.sender is minter or not return true or false . minterOnly() modifier checks true or false return by isMinter() function ,so instead of minterOnly() modifier we can use directly isMinter() in require or if else statement even it saves gas .
code snippet:- https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Frankencoin.sol#L266 https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Frankencoin.sol#L293
Recommendation :- require(isMinter(),"not minter"); if (!isMinter(msg.sender) && !isMinter(positions[msg.sender])) revert NotMinter();
Add above any one code in restricted function instead of minterOnly() modifier to save gas and reduce the code .
code snippet:- https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Position.sol#L329 https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Position.sol#L366
#0 - c4-pre-sort
2023-04-27T09:08:28Z
0xA5DF marked the issue as low quality report
#1 - 0xA5DF
2023-04-27T09:08:50Z
Not very clear. The last one is wrong and the 2 others also don't seem valid
#2 - c4-judge
2023-05-17T03:56:10Z
hansfriese marked the issue as grade-c
#3 - c4-judge
2023-05-18T07:50:18Z
hansfriese marked the issue as grade-b
🌟 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
In bid() function calls the minBid() public function with challenge variable which is initialise by storage only , in minBid() public function uses challenges storage variable array to search given challenge variable which is already found in bid() only then it calls minBid() internal function , in this it will again initialise from storage only, to get challenge.bid .But we can absorb here challenge variable which is already initialise from storage in bid() and try search again and initialise in minBid() functions from storage again .
So Sload consumes 200-800 gas each time , if challenges[] arrays grows large then it consumes 800 gas .
Recommedation :- try to directly call minBid(challenge.bid) in bid() and in internal minBid(challenge.bid) also which saves the gas cost .
change to :- in bid() minBid(challenge.bid)
in minBid( uint challengeBid) public function /// minBid(challenge.bid)
in minBid(uint challengeBid) internal function /// minBid(challenge.bid) // to calculate the minimum bid .
code snippet:- https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/MintingHub.sol#L216
If a function modifier such as onlyOwner is used, the function will revert if a normal user tries to pay the function. Marking the function as payable will lower the gas cost for legitimate callers because the compiler will not include checks for whether a payment was provided. The extra opcodes avoided are CALLVALUE(2),DUP1(3),ISZERO(3),PUSH2(3),JUMPI(10),PUSH1(3),DUP1(3),REVERT(0),JUMPDEST(1),POP(2).
Saves 21 gas per call
code snippet :- https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Position.sol#L132 https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Position.sol#L159 https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Position.sol#L227 https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Position.sol#L249 https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Position.sol#L292
code snippet:- https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Position.sol#L250 https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Position.sol#L121 https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Position.sol#L160 https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Position.sol#L184
Saves a storage slot for the mapping. Depending on the circumstances and sizes of types, can avoid a Gsset (20000 gas) per mapping combined. Reads and subsequent writes can also be cheaper when a function requires both values and they both fit in the same storage slot. Finally, if both fields are accessed in the same function, can save ~42 gas per access due to not having to recalculate the key’s keccak256 hash (Gkeccak256 - 30 gas) and that calculation’s associated stack operations.
saves 42 per access
code snippet:- https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/MintingHub.sol#L37
#0 - 0xA5DF
2023-04-27T12:20:47Z
2 is in automated findings
#1 - c4-judge
2023-05-16T11:49:01Z
hansfriese marked the issue as grade-b