Forgotten Runes Warrior Guild contest - antonttc's results

16,000 Warrior NFTs sold in a phased Dutch Auction.

General Information

Platform: Code4rena

Start Date: 03/05/2022

Pot Size: $30,000 USDC

Total HM: 6

Participants: 93

Period: 3 days

Judge: gzeon

Id: 118

League: ETH

Forgotten Runes

Findings Distribution

Researcher Performance

Rank: 83/93

Findings: 1

Award: $15.49

🌟 Selected for report: 0

🚀 Solo Findings: 0

Gas optimization:

Here will first introduce 3 tricks to optimize the gas cost for issueRefund, and then several other tricks for overall gas use.

  1. Pack storage variables daAmountPaid, daAmountRefunded and daNumMinted. These 3 variables are read and updated in issueRefud, so if we pack them into single storage slot, you save tons of gas by not using 3 SLOAD instructions. Detail implementation can be found here in forked PR You can see that I pack these 3 vars all into a DARecord struct, (all in uint80 forms so they can fit into 256 bits). The constraint is that non of these values can be higher than 2^80, which is translated to 1208925 eth. This saves you the most gas. From the existing tests, gas reduced from average of 115K to 86K.

The following 2 tricks have minor impacts on issueRefund, but given that you said you expected the function to run for around 3000 loops, it will worth something:

  1. Remove unnecessary internal functions in issueRefund: that is _safeTransferETHWithFallback and _safeTransferETH. The reason is that these 2 functions are only used once by private function refundAddress, and specifying them as separate function will require an additional JUMP instruction to go to the destination, also the EVM will need to go through all the function selectors to find the correct destination. I think from the code readability stand point, merging them together doesn't make it bad. I also had it implemented in the PR, with a @trick2 tag. This saves average of 100 gas based on the gas report .

  2. Optimize the function name. Last trick to ultimately optimize issueRefund is to find better function name for internal functions refundAddress and _refundOwed. The reason is that EVM will go through a list of function selectors and choose what is the correct hash, and the list is sorted by how many leading 0s the hash has. So the more 0s we can put in front of the function selector, the faster it will get selected in the matching phase and save some gas: This tool would be helpful to do such thing: https://emn178.github.io/solidity-optimize-name/ The names I found are:

  • refundAddress => refundAddress_v4W
  • refundOwed => change to internal and use _refundOwed_vBw This saves dozens of gas.

This is all the idea I had to optimize issueRefund, the rest of the report will be gas saving around other functions.


AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter