Popcorn contest - 0xdaydream's results

A multi-chain regenerative yield-optimizing protocol.

General Information

Platform: Code4rena

Start Date: 31/01/2023

Pot Size: $90,500 USDC

Total HM: 47

Participants: 169

Period: 7 days

Judge: LSDan

Total Solo HM: 9

Id: 211

League: ETH

Popcorn

Findings Distribution

Researcher Performance

Rank: 81/169

Findings: 1

Award: $69.82

Gas:
grade-b

๐ŸŒŸ Selected for report: 0

๐Ÿš€ Solo Findings: 0

Awards

69.8247 USDC - $69.82

Labels

bug
G (Gas Optimization)
grade-b
G-01

External Links

Gas optimizations

IssueInstancesTotal Gas Saved
[G-01]++i costs less gas than i++, especially when itโ€™s used in for loops (--i/i-- too)15
[G-02]Using private rather than public for constants, saves gas5-
[G-03]Functions guaranteed to revert when called by normal users can be marked payable13168
[G-04]Use assembly to check for address(0)4-
[G-05]<x> += <y> costs more gas than <x> = <x> + <y> for state variables8104
Total 36 instances with 277 gas saved.

++i costs less gas than i++, especially when itโ€™s used in for loops (--i/i-- too)

Saves 5 gas per loop

There is 1 instance of this issue:

File: src/vault/adapter/abstracts/AdapterBase.sol
659:    nonces[owner]++,

https://github.com/code-423n4/2023-01-popcorn/blob/main/src/vault/adapter/abstracts/AdapterBase.sol#L659

Using private rather than public for constants, saves gas

If needed, the values can be read from the verified contract source code, or if there are multiple values there can be a single getter function that returns a tuple of the values of all currently-public constants. Saves 3406-3606 gas in deployment gas due to the compiler not having to create non-payable getter functions for deployment calldata, not having to store the bytes of the value outside of where itโ€™s used, and not adding another entry to the method ID table.

There are 5 instances of this issue:

File: src/vault/VaultController.sol
36:    bytes32 public immutable VAULT = "Vault";
37:    bytes32 public immutable ADAPTER = "Adapter";
38:    bytes32 public immutable STRATEGY = "Strategy";
39:    bytes32 public immutable STAKING = "Staking";

https://github.com/code-423n4/2023-01-popcorn/blob/main/src/vault/VaultController.sol#L36

File: src/vault/adapter/beefy/BeefyAdapter.sol
31:    uint256 public constant BPS_DENOMINATOR = 10_000;

https://github.com/code-423n4/2023-01-popcorn/blob/main/src/vault/adapter/beefy/BeefyAdapter.sol#L31

Functions guaranteed to revert when called by normal users can be marked payable

Functions guaranteed to revert when called by normal users can be marked payable 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

There are 13 instances of this issue:

File: src/utils/MultiRewardStaking.sol
243:    function addRewardToken(
244:      IERC20 rewardToken,
245:      uint160 rewardsPerSecond,
246:      uint256 amount,
247:      bool useEscrow,
248:      uint192 escrowPercentage,
249:      uint32 escrowDuration,
250:      uint32 offset
251:    ) external onlyOwner {

https://github.com/code-423n4/2023-01-popcorn/blob/main/src/utils/MultiRewardStaking.sol#L243

File: src/vault/AdminProxy.sol
21:    function execute(address target, bytes calldata callData)
20:      external
21:      onlyOwner

https://github.com/code-423n4/2023-01-popcorn/blob/main/src/vault/AdminProxy.sol#L21

File: src/vault/CloneRegistry.sol
41:    function addClone(
42:      bytes32 templateCategory,
43:      bytes32 templateId,
44:      address clone
45:    ) external onlyOwner {

https://github.com/code-423n4/2023-01-popcorn/blob/main/src/vault/CloneRegistry.sol#L41

File: src/vault/DeploymentController.sol
99:    function deploy(
100:      bytes32 templateCategory,
101:      bytes32 templateId,
102:      bytes calldata data
103:    ) external onlyOwner returns (address clone) {

https://github.com/code-423n4/2023-01-popcorn/blob/main/src/vault/DeploymentController.sol#L99

File: src/vault/TemplateRegistry.sol
67:    function addTemplate(
68:      bytes32 templateCategory,
69:      bytes32 templateId,
70:      Template memory template
71:    ) external onlyOwner {

https://github.com/code-423n4/2023-01-popcorn/blob/main/src/vault/TemplateRegistry.sol#L67

File: src/vault/VaultController.sol
579:    function toggleTemplateEndorsements(bytes32[] calldata templateCategories, bytes32[] calldata templateIds)
580:      external
581:      onlyOwner

https://github.com/code-423n4/2023-01-popcorn/blob/main/src/vault/VaultController.sol#L579

File: src/vault/adapter/abstracts/AdapterBase.sol
55:    function __AdapterBase_init(bytes memory popERC4626InitData)
56:      internal
57:      onlyInitializing
456:    function strategyDeposit(uint256 amount, uint256 shares)
457:      public
458:      onlyStrategy
467:    function strategyWithdraw(uint256 amount, uint256 shares)
468:      public
469:      onlyStrategy
500:    function setHarvestCooldown(uint256 newCooldown) external onlyOwner {
549:    function setPerformanceFee(uint256 newFee) public onlyOwner {
574:    function pause() external onlyOwner {
582:    function unpause() external onlyOwner {

https://github.com/code-423n4/2023-01-popcorn/blob/main/src/vault/adapter/abstracts/AdapterBase.sol#L55

Use assembly to check for address(0)

Saves 6 gas per instance There are 4 instances of this issue:

File: src/utils/MultiRewardEscrow.sol
95:    if (token == IERC20(address(0))) revert ZeroAddress();

https://github.com/code-423n4/2023-01-popcorn/blob/main/src/utils/MultiRewardEscrow.sol#L95

File: src/vault/adapter/abstracts/AdapterBase.sol
83:    if (_strategy != address(0)) _verifyAndSetupStrategy(_requiredSigs);
440:    address(strategy) != address(0) &&
670:    if (recoveredAddress == address(0) || recoveredAddress != owner)

https://github.com/code-423n4/2023-01-popcorn/blob/main/src/vault/adapter/abstracts/AdapterBase.sol#L83

<x> += <y> costs more gas than <x> = <x> + <y> for state variables

There are 8 instances of this issue:

File: src/vault/adapter/abstracts/AdapterBase.sol
158:    underlyingBalance += _underlyingBalance() - underlyingBalance_;
225:    underlyingBalance -= underlyingBalance_ - _underlyingBalance();

https://github.com/code-423n4/2023-01-popcorn/blob/main/src/vault/adapter/abstracts/AdapterBase.sol#L158

File: src/vault/Vault.sol
228:    shares += feeShares;
357:    amount += uint256(rewardsPerSecond) * (rewardsEndTimestamp - block.timestamp

https://github.com/code-423n4/2023-01-popcorn/blob/main/src/vault/Vault.sol#L228

File: src/utils/MultiRewardStaking.sol
408:    rewardInfos[_rewardToken].index += deltaIndex;
431:    accruedRewards[_user][_rewardToken] += supplierDelta;

https://github.com/code-423n4/2023-01-popcorn/blob/main/src/utils/MultiRewardStaking.sol#L408

File: src/utils/MultiRewardEscrow.sol
110:    amount -= fee;
162:    escrows[escrowId].balance -= claimable;

https://github.com/code-423n4/2023-01-popcorn/blob/main/src/utils/MultiRewardEscrow.sol#L110

#0 - c4-judge

2023-02-28T13:17:46Z

dmvt marked the issue as grade-b

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