Platform: Code4rena
Start Date: 31/10/2023
Pot Size: $60,500 USDC
Total HM: 9
Participants: 65
Period: 10 days
Judge: gzeon
Total Solo HM: 2
Id: 301
League: ETH
Rank: 57/65
Findings: 1
Award: $23.81
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0xVolcano
Also found by: 0x11singh99, 0xAnah, 0xhacksmithh, 0xhex, 0xta, DavidGiladi, K42, Topmark, arjun16, dharma09, hunter_w3b, lsaudit, pavankv, tabriz, tala7985, ybansal2403
23.8054 USDC - $23.81
The batchRefund() function currently refunds token owners individually by calling refund() on each one sequentially:
for (uint256 i; i < numRefunds; ++i) { (bool s, bytes memory r) = address(this).call( abi.encodeCall(this.refund, (tokenIds[i])) ); // ... }
This repeats the base cost for each refund call.
It could be optimized by batching the transfers into a single call to an ERC20/ERC721's transfer()/transferFrom()function.
For example, loop through all recipients and amounts, build arrays, then call:
party.batchTransfer(recipients, amounts);
This would consolidate the costs and reduce total gas usage, especially for many refunds.
When users contribute to the crowdfund, a new party card is minted for them individually:
function _contribute(contributor, delegate, amount) { //... if (tokenId == 0) { party.mint(contributor, votingPower, delegate); } //... }
This repeats the cost of minting for each contribution.
It could be optimized by collecting the list of contributors and voting powers, then calling a batched mint function:
contributors = []; powers = []; // collect in loop party.batchMint(contributors, powers);
The party contract would implement a batchMint() that mints all cards in one call.
This avoids repeating the base minting cost and improves gas scaling for multiple contributions.
The OffChainSignatureValidator.sol contract currently performs storage lookups each time common references like addresses and selector values are used. This wastes gas by repeating the lookup cost unnecessarily.
Declare common references like the EIP-1271 signature validator selector and address types as public immutable variables initialized directly from storage.
Each storage lookup costs approx 200 gas. By declaring references immutable, their value is hardcoded at deployment saving repeated lookup costs.
For example:
bytes4 public immutable eip1271Validator = IERC1271.isValidSignature.selector; function isValidSignature() external view returns(bytes4) { return eip1271Validator; }
Vs original repeated lookups.
Expected Savings 200 gas saved per usage, scaling with number of reference lookups. Significant for common references.
So Initializing immutable references from storage improves gas efficiency by avoiding repeated lookups for fixed values.
The current OffChainSignatureValidator.sol
contract stores party specific data like signing thresholds in a mapping within the main contract. This wastes storage gas as the data grows with number of parties.
Extract party specific data storage and logic into a separate nested contract that manages individual thresholds.
The main contract then simply delegates to these threshold managers.
// Current approach contract Validator { mapping(Party => uint) thresholds; //... } // Optimized approach contract Validator { mapping(Party => ThresholdManager) public managers; //... } contract ThresholdManager { uint public threshold; //... }
Storage costs are 20,000 - 30,000 gas per slot. Splitting data saves this cost per party over long term growth.
The OffChainSignatureValidator.sol
contract currently recalculates the signer's voting power from the party on each validation by querying storage.Cache previously calculated voting powers in a mapping to avoid repeated lookups. Only recalculate if signer's power has changed.
For-Example
function validate() { uint96 power = cachedPowers[signer]; if(power == 0) { power = party.getVotingPower(signer); cachedPowers[signer] = power; } // use cached power }
Each storage read costs ~200 gas. This avoids a read per validation.
Problem
Solution
Implementation
Benefits
Estimates
#0 - c4-pre-sort
2023-11-13T06:55:57Z
ydspa marked the issue as sufficient quality report
#1 - c4-judge
2023-11-19T18:26:00Z
gzeon-c4 marked the issue as grade-b