Badger Citadel contest - joshie's results

Bringing BTC to DeFi

General Information

Platform: Code4rena

Start Date: 14/04/2022

Pot Size: $75,000 USDC

Total HM: 8

Participants: 72

Period: 7 days

Judge: Jack the Pug

Total Solo HM: 2

Id: 110

League: ETH

BadgerDAO

Findings Distribution

Researcher Performance

Rank: 65/72

Findings: 1

Award: $54.33

🌟 Selected for report: 0

🚀 Solo Findings: 0

  • save 32 bytes on storing vesting duration
diff --git a/src/StakedCitadelVester.sol b/src/StakedCitadelVester.sol
index a76b496..c8279e5 100644
--- a/src/StakedCitadelVester.sol
+++ b/src/StakedCitadelVester.sol
@@ -21,10 +21,10 @@ contract StakedCitadelVester is
         keccak256("CONTRACT_GOVERNANCE_ROLE");
 
     struct VestingParams {
-        uint256 unlockBegin;
-        uint256 unlockEnd;
         uint256 lockedAmounts;
         uint256 claimedAmounts;
+        uint128 unlockBegin;
+        uint128 unlockEnd;
     }
 
     IERC20Upgradeable public vestingToken;
@@ -140,8 +140,8 @@ contract StakedCitadelVester is
         vesting[recipient].lockedAmounts =
             vesting[recipient].lockedAmounts +
             _amount;
-        vesting[recipient].unlockBegin = _unlockBegin;
-        vesting[recipient].unlockEnd = _unlockBegin + vestingDuration;
+        vesting[recipient].unlockBegin = uint128(_unlockBegin);
+        vesting[recipient].unlockEnd = uint128(_unlockBegin + vestingDuration);
 
         emit Vest(
             recipient,
  • cache saleStart SLOAD
diff --git a/.gas-snapshot b/.gas-snapshot
index 48730dc..d6e94a8 100644
--- a/.gas-snapshot
+++ b/.gas-snapshot
@@ -11,7 +11,7 @@ MintAndDistributeTest:testMintAndDistribute() (gas: 4491731)
 MintingTest:testExampleEpochRates() (gas: 34165)
 MintingTest:testSetCitadelDistributionSplit() (gas: 153248)
 MintingTest:testSetFundingPoolWeight() (gas: 245002)
-KnightingRoundTest:testKnightingRoundIntegration() (gas: 3787844)
+KnightingRoundTest:testKnightingRoundIntegration() (gas: 3787749)
 SupplyScheduleTest:testExampleEpochRates() (gas: 34187)
 SupplyScheduleTest:testSetEpochRate() (gas: 102979)
 SupplyScheduleTest:testSetMintingStart() (gas: 105371)
diff --git a/src/KnightingRound.sol b/src/KnightingRound.sol
index 2679c22..b9403db 100644
--- a/src/KnightingRound.sol
+++ b/src/KnightingRound.sol
@@ -164,9 +164,11 @@ contract KnightingRound is GlobalAccessControlManaged, ReentrancyGuardUpgradeabl
         uint8 _daoId,
         bytes32[] calldata _proof
     ) external gacPausable returns (uint256 tokenOutAmount_) {
-        require(saleStart <= block.timestamp, "KnightingRound: not started");
+        uint256 _saleStart = saleStart;
+
+        require(_saleStart <= block.timestamp, "KnightingRound: not started");
         require(
-            block.timestamp < saleStart + saleDuration,
+            block.timestamp < _saleStart + saleDuration,
             "KnightingRound: already ended"
         );
         require(_tokenInAmount > 0, "_tokenInAmount should be > 0");
  • unchecked loop increment
diff --git a/.gas-snapshot b/.gas-snapshot
index d6e94a8..a1f7842 100644
--- a/.gas-snapshot
+++ b/.gas-snapshot
@@ -7,7 +7,7 @@ FundingTest:testFailClaimAssetToTreasury() (gas: 51815)
 FundingTest:testSetAssetCap() (gas: 510714)
 FundingTest:testSweep() (gas: 54023)
 SetupAndKnightingRoundTest:testFundingOraclesFlow() (gas: 166)
-MintAndDistributeTest:testMintAndDistribute() (gas: 4491731)
+MintAndDistributeTest:testMintAndDistribute() (gas: 4491609)
 MintingTest:testExampleEpochRates() (gas: 34165)
 MintingTest:testSetCitadelDistributionSplit() (gas: 153248)
 MintingTest:testSetFundingPoolWeight() (gas: 245002)
diff --git a/src/CitadelMinter.sol b/src/CitadelMinter.sol
index c4ed18f..78dbc2f 100644
--- a/src/CitadelMinter.sol
+++ b/src/CitadelMinter.sol
@@ -341,7 +341,7 @@ contract CitadelMinter is
         uint256 cachedTotalFundingPoolWeight = totalFundingPoolWeight;
 
         require(length > 0, "CitadelMinter: no funding pools");
-        for (uint256 i; i < length; ++i) {
+        for (uint256 i; i < length; /** See below ++i */) {
             address pool = fundingPools.at(i);
             uint256 weight = fundingPoolWeights[pool];
 
@@ -356,6 +356,7 @@ contract CitadelMinter is
                 pool,
                 amount
             );
+            unchecked { ++i; }
         }
     }
  • add storage pointer for vestingRecipient
diff --git a/.gas-snapshot b/.gas-snapshot
index 9e8c399..a67d5c5 100644
--- a/.gas-snapshot
+++ b/.gas-snapshot
@@ -7,7 +7,7 @@ FundingTest:testFailClaimAssetToTreasury() (gas: 51815)
 FundingTest:testSetAssetCap() (gas: 510714)
 FundingTest:testSweep() (gas: 54023)
 SetupAndKnightingRoundTest:testFundingOraclesFlow() (gas: 166)
-GasTest:testGas_Vest() (gas: 61826)
+GasTest:testGas_Vest() (gas: 61678)
 MintAndDistributeTest:testMintAndDistribute() (gas: 4491609)
 MintingTest:testExampleEpochRates() (gas: 34165)
 MintingTest:testSetCitadelDistributionSplit() (gas: 153248)
diff --git a/src/StakedCitadelVester.sol b/src/StakedCitadelVester.sol
index c8279e5..ce0375e 100644
--- a/src/StakedCitadelVester.sol
+++ b/src/StakedCitadelVester.sol
@@ -106,15 +106,17 @@ contract StakedCitadelVester is
      * @return The number of tokens currently claimable.
      */
     function claimableBalance(address recipient) public view returns (uint256) {
-        uint256 locked = vesting[recipient].lockedAmounts;
-        uint256 claimed = vesting[recipient].claimedAmounts;
-        if (block.timestamp >= vesting[recipient].unlockEnd) {
+        VestingParams storage vestingRecipient = vesting[recipient];
+        
+        uint256 locked = vestingRecipient.lockedAmounts;
+        uint256 claimed = vestingRecipient.claimedAmounts;
+        if (block.timestamp >= vestingRecipient.unlockEnd) {
             return locked - claimed;
         }
         return
-            ((locked * (block.timestamp - vesting[recipient].unlockBegin)) /
-                (vesting[recipient].unlockEnd -
-                    vesting[recipient].unlockBegin)) - claimed;
+            ((locked * (block.timestamp - vestingRecipient.unlockBegin)) /
+                (vestingRecipient.unlockEnd -
+                    vestingRecipient.unlockBegin)) - claimed;
     }
 
     /// =========================
@@ -136,18 +138,20 @@ contract StakedCitadelVester is
     ) external {
         require(msg.sender == vault, "StakedCitadelVester: only xCTDL vault");
         require(_amount > 0, "StakedCitadelVester: cannot vest 0");
+        
+        VestingParams storage vestingRecipient = vesting[recipient];
 
-        vesting[recipient].lockedAmounts =
-            vesting[recipient].lockedAmounts +
+        vestingRecipient.lockedAmounts =
+            vestingRecipient.lockedAmounts +
             _amount;
-        vesting[recipient].unlockBegin = uint128(_unlockBegin);
-        vesting[recipient].unlockEnd = uint128(_unlockBegin + vestingDuration);
+        vestingRecipient.unlockBegin = uint128(_unlockBegin);
+        vestingRecipient.unlockEnd = uint128(_unlockBegin + vestingDuration);
 
         emit Vest(
             recipient,
-            vesting[recipient].lockedAmounts,
+            vestingRecipient.lockedAmounts,
             _unlockBegin,
-            vesting[recipient].unlockEnd
+            vestingRecipient.unlockEnd
         );
     }
 
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