Platform: Code4rena
Start Date: 18/10/2022
Pot Size: $50,000 USDC
Total HM: 13
Participants: 67
Period: 5 days
Judge: Picodes
Total Solo HM: 7
Id: 172
League: ETH
Rank: 25/67
Findings: 2
Award: $63.84
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: berndartmueller
Also found by: 0x1f8b, 0x4non, 0xNazgul, 0xSmartContract, Aymen0909, BClabs, Diana, Jeiwan, Lambda, LeoS, RaoulSchaffranek, RaymondFam, RedOneN, ReyAdmirado, Rolezn, SaharAP, Trust, V_B, __141345__, a12jmx, bharg4v, brgltd, carlitox477, ch0bu, chaduke, cloudjunky, cryptostellar5, cryptphi, csanuragjain, d3e4, delfin454000, erictee, fatherOfBlocks, hansfriese, ignacio, joestakey, karanctf, ladboy233, lukris02, mcwildy, minhtrng, peanuts, ret2basic, seyni, slowmoses, svskaushik, tnevler, yixxas
37.8829 USDC - $37.88
During the audit, 1 low and 9 non-critical issues were found.
â„– | Title | Risk Rating | Instance Count |
---|---|---|---|
L-1 | Possible DoS | Low | 4 |
NC-1 | Order of Functions | Non-Critical | 7 |
NC-2 | Public functions can be external | Non-Critical | 7 |
NC-3 | Comment lines are too long | Non-Critical | 10 |
NC-4 | No error message in require | Non-Critical | 2 |
NC-5 | Unused named return variables | Non-Critical | 4 |
NC-6 | Constants may be used | Non-Critical | 8 |
NC-7 | Missing NatSpec | Non-Critical | 7 |
NC-8 | British English and American English | Non-Critical | 1 |
NC-9 | Typos and grammar errors | Non-Critical | 38 |
If the user adds too many tiers
, four functions can run out of gas.
Add the check in this function to prevent the user from adding too many tiers.
According to Style Guide, ordering helps readers identify which functions they can call and to find the constructor and fallback definitions easier.
Functions should be grouped according to their visibility and ordered:
Within a grouping, place the view and pure functions last.
Constructor after functions:
External functions after public:
External functions between public:
Public functions between external:
Reorder functions where possible.
If functions are not called by the contract where they are defined, they can be declared external.
Make public functions external, where possible.
For readability, split comments across multiple lines.
Both named return variable(s) and return statement are used.
To improve clarity use only named return variables.
For example, change:
function functionName() returns (uint id) { return x;
to
function functionName() returns (uint id) { id = x;
Constants may be used instead of literal values.
For 58:
For 256:
NatSpec is missing for 7 functions in 2 contracts.
Add NatSpec for all functions.
Choose one.
// Convert the hex string to an hash
=> a hash
Convert an hex string to base58
=> a hex
// Forward the recieved weight and memo, and use this contract as a pay delegate.
=> received
@param _interfaceId The ID of the interface to check for adherance to.
=> adherence
A function that will run when a tokens are burned via redemption.
=> when tokens
@param _tokenId The id of the token for which voting units are being transfered.
=> transferred
JBOperatable: Several functions in this contract can only be accessed by a project owner, or an address that has been preconfifigured to be an operator of the project.
=> preconfigured
The contract responsibile for deploying the delegate.
=> responsible
@param _blockNumber the blocknumber to check the voting power at.
=> block number
@param _blockNumber The blocknumber to check the total voting power at. */
=> block number
@param _tierId The ID of the tier for which voting units are being transfered.
=> transferred
@param _tierId The ID of the tier for which voting units are being transfered.
=> transferred
@param _tierId The ID of the tier for which voting units are being transfered.
=> transferred
@param _tokenId The ID of the token for which voting units are being transfered.
=> transferred
assets based based on price floor.
=> based
@return balance The number of tokens owners by the owner accross all tiers.
=> across
@param _interfaceId The ID of the interface to check for adherance to.
=> adherence
// Initialize the sub class.
=> subclass
Sets the beneificiary of the reserved tokens for tiers where a specific beneficiary isn't set.
=> beneficiary
@param _beneficiary The default beneificiary of the reserved tokens.
=> beneficiary
// Keep a reference to the flag indicating if the transaction should revert if all provded funds aren't spent.
=> provided
// Keep a reference to the the specific tier IDs to mint.
=> onethe
A function that will run when a tokens are burned via redemption.
=> when tokens
User the hook to register the first owner if it's not yet regitered.
=> registered
@param _tokenId The ID of the token being transfered.
=> transferred
// Transfered must not be paused when not minting or burning.
=> Transferred
@param _tokenId The ID of the token being transfered.
=> transferred
@param _tokenId The ID of the token for which voting units are being transfered.
=> transferred
_nft The NFT contract to which the tier belong.
=> belongs
// Keep a referecen to the tier being iterated on.
=> reference
// Increment the total supply with the amount used already.
=> already used
@return balance The number of tokens owners by the owner accross all tiers.
=> across
@return The reserved token benficiary.
=> beneficiary
// Keep a reference to the idex to iterate on next.
=> index
@param _beneficiary The reservd token beneficiary.
=> reserved
@param _tierId The ID the tier being transfered
=> transferred
// If the tier is locked throw an error.
=> locked, throw
// Get the number of reserved tokens mintable given the number of non reserved tokens minted. This will round down.
=> non-reserved
#0 - c4-judge
2022-11-04T14:52:29Z
Picodes marked the issue as grade-b
🌟 Selected for report: Jeiwan
Also found by: 0x1f8b, 0x4non, 0x5rings, 0xSmartContract, Awesome, Aymen0909, Bnke0x0, CodingNameKiki, Diana, DimSon, JC, JrNet, LeoS, RaymondFam, ReyAdmirado, Saintcode_, Shinchan, __141345__, berndartmueller, bharg4v, brgltd, carlitox477, ch0bu, chaduke, cryptostellar5, emrekocak, gogo, lukris02, martin, mcwildy, sakman, trustindistrust, zishansami
25.9629 USDC - $25.96
During the audit, 6 gas issues were found.
Total savings ~2030.
In Solidity 0.8+, there’s a default overflow and underflow check on unsigned integers. In the loops, "i" will not overflow because the loop will run out of gas before that.
Change:
for (uint256 i; i < n; ++i) { // ... }
to:
for (uint256 i; i < n;) { // ... unchecked { ++i; } }
This saves ~30-40 gas per iteration.
So, ~35*7 = 245
In Solidity 0.8+, there’s a default overflow and underflow check on unsigned integers. When an overflow or underflow isn’t possible (after require or if-statement), some gas can be saved by using unchecked blocks.
This saves ~35.
So, ~35*1 = 35
calldata
instead of memory for
read-only argumentsSince Solidity v0.6.9, memory and calldata are allowed in all functions regardless of their visibility type (See "Calldata Variables" section here).
When function arguments should not be modified, it is cheaper to use calldata.
Use calldata where possible.
This saves at least 60 gas per iteration.
So, ~60*17 = 1020
Function calls need two extra JUMP instructions and other stack operations.
This saves ~20-40. So, ~30*3 = 90
Stack read is much cheaper than storage read.
This saves ~100.
So, ~100*6 = 600
It saves gas due to not having to perform the same key’s keccak256 hash and/or offset recalculation.
This saves ~40.
So, ~40*1 = 40
#0 - c4-judge
2022-11-08T18:06:40Z
Picodes marked the issue as grade-b