Platform: Code4rena
Start Date: 07/01/2022
Pot Size: $80,000 USDC
Total HM: 21
Participants: 37
Period: 7 days
Judge: 0xean
Total Solo HM: 14
Id: 71
League: ETH
Rank: 19/37
Findings: 2
Award: $732.37
🌟 Selected for report: 8
🚀 Solo Findings: 0
🌟 Selected for report: TomFrenchBlockchain
379.9514 INSURE - $132.98
230.6848 USDC - $230.68
TomFrenchBlockchain
Gas costs
When transferring any of the market tokens, a check is performed to see if they have a pending withdrawal and reduce it if their balance falls below the requested amount.
In the case where a user has no pending withdrawal we then perform an unnecessary check on their balance. We could save an SLOAD by changing it to the below
if (from != address(0)) { uint256 reqAmount = withdrawalReq[from].amount if (reqAmount > 0){ uint256 _after = balanceOf(from) - amount; if (_after < reqAmount) { withdrawalReq[from].amount = _after; } } }
As above
#0 - oishun1112
2022-01-12T07:15:38Z
sponsor confirmed
🌟 Selected for report: Jujic
Also found by: TomFrenchBlockchain, WatchPug
16.8132 INSURE - $5.88
8.8269 USDC - $8.83
TomFrenchBlockchain
Gas costs
PoolTemplate.sol
has an Insurance
struct which looks as below:
struct Insurance { uint256 id; uint256 startTime; uint256 endTime; uint256 amount; bytes32 target; address insured; bool status; }
id
, startTime
and endTime
and potentially amount
are all good candidates to be packed to save SSTORES when taking out insurance. A potential (conservative) packing is
struct Insurance { uint128 id; uint64 startTime; uint64 endTime; uint256 amount; bytes32 target; address insured; bool status; }
which eliminates 2 SSTORES (40k) gas when taking out insurance.
Determine the optimal packing for this struct (take into account which fields are read together when paying out for extra savings)
#0 - oishun1112
2022-01-12T07:12:00Z
sponsor confirmed
#1 - oishun1112
2022-01-12T07:12:54Z
@kohshiba
#2 - 0xean
2022-01-28T02:29:44Z
dupe of #253
🌟 Selected for report: TomFrenchBlockchain
62.2711 INSURE - $21.79
32.6923 USDC - $32.69
TomFrenchBlockchain
gas costs
In the sqrt function it is known that the while loop will not overflow so it can be safely left unchecked to save gas.
function sqrt(uint256 x) internal pure returns (uint256 y) { uint256 z = (x + 1) / 2; unchecked { y = x; while (z < y) { y = z; z = (x / z + z) / 2; } } }
wrap entire function body in a unchecked block as above
#0 - oishun1112
2022-01-12T06:19:52Z
sponsor confirmed
#1 - oishun1112
2022-01-16T07:17:46Z
contract Storage { function sqrt_1(uint256 x) external pure returns (uint256 y) { uint256 z = (x + 1) / 2; y = x; while (z < y) { y = z; z = (x / z + z) / 2; } } function sqrt_2(uint256 x) external pure returns (uint256 y) { uint256 z = (x + 1) / 2; unchecked { y = x; while (z < y) { y = z; z = (x / z + z) / 2; } } } }
sqrt_1(100) => 24635 gas sqrt_2(100) => 22657 gas diff = 1978
sqrt_1(100467583) => 31979 gas (+7344, +29.8%) sqrt_2(100467583) => 24001 gas (+1344, +5.93%) diff = 7978
#2 - oishun1112
2022-01-16T07:17:57Z
This reduces a lot of gas
🌟 Selected for report: TomFrenchBlockchain
62.2711 INSURE - $21.79
32.6923 USDC - $32.69
TomFrenchBlockchain
Detailed description of the impact of this finding.
The Withdrawal
struct in IndexTemplate.sol
contains a timestamp and the amount of tokens which the user requests to withdraw.
If we make the safe assumption that the user's balance does not exceed 2^192 then we can pack this struct into a single storage slot to save an SLOAD by changing the definition to:
struct Withdrawal { uint64 timestamp; uint192 amount; }
As above
#0 - oishun1112
2022-01-12T07:23:22Z
@kohshiba
🌟 Selected for report: TomFrenchBlockchain
62.2711 INSURE - $21.79
32.6923 USDC - $32.69
TomFrenchBlockchain
gas costs
Here on L563 we check the market status however we have already done this on L558
Remove redundant check (check other market templates as well)
🌟 Selected for report: TomFrenchBlockchain
62.2711 INSURE - $21.79
32.6923 USDC - $32.69
TomFrenchBlockchain
Gas costs
It seems that we always want to get a pool's allocatedCredit
and availableBalance
together, suggesting that these values are tightly coupled.
If we're regularly going to be requesting these values together it may be worth considering having a single function in the pool template which returns both of these values. This would save gas costs of performing an extra external call to the pool contract.
Consider having a function which returns both of these values to avoid repeated calls into the same contract for related info.
#0 - oishun1112
2022-01-12T07:48:37Z
@kohshiba
#1 - blue32captain
2022-01-22T05:24:09Z
For this, each individual function will be removed and new function that returns both value will be created.
#2 - oishun1112
2022-01-24T08:35:54Z
Yes, you can proceed with this if there is no problem. In this case, please fix the test code as well. https://github.com/code-423n4/2022-01-insure/blob/main/test/unitary/test-utils.js#L55 https://github.com/code-423n4/2022-01-insure/blob/main/test/unitary/test-utils.js#L73
#3 - blue32captain
2022-01-28T01:12:03Z
This issue should be checked again to find the optimization.
🌟 Selected for report: TomFrenchBlockchain
62.2711 INSURE - $21.79
32.6923 USDC - $32.69
TomFrenchBlockchain
Gas costs
Here we push a new market onto an array in the factory whilst we just added the market to the registry.
This array on the factory seems redundant and so it can be removed.
#0 - oishun1112
2022-01-12T07:56:40Z
@kohshiba
🌟 Selected for report: TomFrenchBlockchain
Also found by: defsec
28.022 INSURE - $9.81
14.7115 USDC - $14.71
TomFrenchBlockchain
Gas costs
Solidity 0.8.10 has a useful change which reduced gas costs of external calls which expect a return value: https://blog.soliditylang.org/2021/11/09/solidity-0.8.10-release-announcement/
Code Generator: Skip existence check for external contract if return data is expected. In this case, the ABI decoder will revert if the contract does not exist
InsureDAO is using 0.8.7: https://github.com/code-423n4/2022-01-insure/blob/19d1a7819fe7ce795e6d4814e7ddf8b8e1323df3/contracts/Factory.sol#L8
Updating to the newer version of solc will allow InsureDAO to take advantage of these lower costs for external calls.
Update to solc 0.8.10 or above
🌟 Selected for report: Dravee
Also found by: 0x1f8b, Jujic, TomFrenchBlockchain, csanuragjain, defsec, gzeon, loop, robee
2.9784 INSURE - $1.04
1.5637 USDC - $1.56
TomFrenchBlockchain
gas costs
We only set this field on construction so it can be safely made immutable.
add immutable keyword
#0 - oishun1112
2022-01-13T14:23:06Z
#1 - oishun1112
2022-01-13T14:34:31Z
🌟 Selected for report: TomFrenchBlockchain
62.2711 INSURE - $21.79
32.6923 USDC - $32.69
TomFrenchBlockchain
gas costs
Here if the lengths of these arrays are zero we'll fall straight through the for loops so there's no need for the if statements.
Remove if statements