Platform: Code4rena
Start Date: 11/11/2022
Pot Size: $36,500 USDC
Total HM: 5
Participants: 62
Period: 3 days
Judge: berndartmueller
Id: 181
League: ETH
Rank: 50/62
Findings: 1
Award: $22.22
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: ReyAdmirado
Also found by: 0x4non, 0xRoxas, 0xab00, Awesome, Aymen0909, Bnke0x0, Deivitto, Diana, IllIllI, Rahoz, RaymondFam, Rolezn, Sathish9098, ajtra, aphak5010, aviggiano, c3phas, carlitox477, ch0bu, cryptostellar5, erictee, lukris02, martin, rotcivegaf, saian, shark, trustindistrust, zaskoh
22.2155 USDC - $22.22
Save 6 gas when assembly is used to check for zero address. e.g:
assembly { if iszero(_addr) { mstore(0x00, "zero address") revert(0x00, 0x20) }
contracts/Exchange.sol:L630 require(to != address(0), "Transfer to zero address");
The code should be refactored such that they no longer exist, or the block should do something useful, such as emitting an event or reverting.
contracts/Exchange.sol:L66 function _authorizeUpgrade(address) internal override onlyOwner {} contracts/Pool.sol:L15 function _authorizeUpgrade(address) internal override onlyOwner {}
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), which costs an average of about 21 gas per call to the function, in addition to the extra deployment cost.
contracts/Exchange.sol:L56 function open() external onlyOwner { contracts/Exchange.sol:L60 function close() external onlyOwner { contracts/Exchange.sol:L66 function _authorizeUpgrade(address) internal override onlyOwner {} contracts/Pool.sol:L15 function _authorizeUpgrade(address) internal override onlyOwner {}
X += Y
costs more gas than X = X + Y
for state variables.Consider changing X += Y
to X = X + Y
to save gas.
contracts/Exchange.sol:L574 remainingETH -= price; contracts/Exchange.sol:L601 totalFee += fee;
Keep revert message lower than or equal to 32 bytes to save gas.
contracts/Exchange.sol:L49 require(isInternal, "This function should not be called directly"); contracts/Exchange.sol:L295 require(!cancelledOrFilled[hash], "Order already cancelled or filled"); contracts/Exchange.sol:L604 require(totalFee <= price, "Total amount of fees are more than the price");
++i
/i++
should be unchecked{++i}
/unchecked{i++}
when it is not possible for them to overflow, as is the case when used in for- and while-loops.The unchecked
keyword is new in solidity version 0.8.0, so this only applies to that version or higher, which these instances are. This saves 30-40 gas per loop.
contracts/Exchange.sol:L177 for (uint8 i=0; i < executionsLength; i++) { contracts/Exchange.sol:L184 for (uint8 i = 0; i < executionsLength; i++) { contracts/Exchange.sol:L307 for (uint8 i = 0; i < orders.length; i++) { contracts/Exchange.sol:L598 for (uint8 i = 0; i < fees.length; i++) {
#0 - c4-judge
2022-11-17T14:15:18Z
berndartmueller marked the issue as grade-b