diff --git a/.gas-report b/.gas-report index 0780214..21d210e 100644 --- a/.gas-report +++ b/.gas-report @@ -10,7 +10,7 @@ |-------------------------------------------------------------------------------------------+-----------------+--------+--------+--------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |-------------------------------------------------------------------------------------------+-----------------+--------+--------+--------+---------| -| fallback | 746 | 132762 | 190951 | 190987 | 509 | +| fallback | 746 | 132207 | 190939 | 190987 | 517 | ╰-------------------------------------------------------------------------------------------+-----------------+--------+--------+--------+---------╯ ╭-----------------------------------------------------+-----------------+---------+---------+---------+---------╮ @@ -24,7 +24,7 @@ |-----------------------------------------------------+-----------------+---------+---------+---------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |-----------------------------------------------------+-----------------+---------+---------+---------+---------| -| run | 4020680 | 4020680 | 4020680 | 4020680 | 111 | +| run | 4020680 | 4020680 | 4020680 | 4020680 | 119 | ╰-----------------------------------------------------+-----------------+---------+---------+---------+---------╯ ╭-----------------------------------------------------------+-----------------+---------+---------+---------+---------╮ @@ -46,13 +46,13 @@ +=======================================================================================================================================+ | Deployment Cost | Deployment Size | | | | | |-----------------------------------------------------------------------------+-----------------+---------+---------+---------+---------| -| 8455440 | 40315 | | | | | +| 8515453 | 40596 | | | | | |-----------------------------------------------------------------------------+-----------------+---------+---------+---------+---------| | | | | | | | |-----------------------------------------------------------------------------+-----------------+---------+---------+---------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |-----------------------------------------------------------------------------+-----------------+---------+---------+---------+---------| -| run | 7371804 | 7371804 | 7371804 | 7371804 | 86 | +| run | 7428140 | 7428140 | 7428140 | 7428140 | 94 | ╰-----------------------------------------------------------------------------+-----------------+---------+---------+---------+---------╯ ╭---------------------------------------------------------+-----------------+-----+--------+-----+---------╮ @@ -66,7 +66,7 @@ |---------------------------------------------------------+-----------------+-----+--------+-----+---------| | Function Name | Min | Avg | Median | Max | # Calls | |---------------------------------------------------------+-----------------+-----+--------+-----+---------| -| activeNetworkConfig | 597 | 597 | 597 | 597 | 323 | +| activeNetworkConfig | 597 | 597 | 597 | 597 | 347 | ╰---------------------------------------------------------+-----------------+-----+--------+-----+---------╯ ╭-------------------------------------------------------------------------------+-----------------+---------+---------+---------+---------╮ @@ -74,13 +74,13 @@ +=========================================================================================================================================+ | Deployment Cost | Deployment Size | | | | | |-------------------------------------------------------------------------------+-----------------+---------+---------+---------+---------| -| 5905912 | 28406 | | | | | +| 5965902 | 28687 | | | | | |-------------------------------------------------------------------------------+-----------------+---------+---------+---------+---------| | | | | | | | |-------------------------------------------------------------------------------+-----------------+---------+---------+---------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |-------------------------------------------------------------------------------+-----------------+---------+---------+---------+---------| -| runWithAdminAndProxy | 3334666 | 3334666 | 3334666 | 3334666 | 3 | +| runWithAdminAndProxy | 3391002 | 3391002 | 3391002 | 3391002 | 3 | ╰-------------------------------------------------------------------------------+-----------------+---------+---------+---------+---------╯ ╭------------------------------+-----------------+--------+--------+--------+---------╮ @@ -96,7 +96,7 @@ |------------------------------+-----------------+--------+--------+--------+---------| | acceptOwnership | 12020 | 12020 | 12020 | 12020 | 1 | |------------------------------+-----------------+--------+--------+--------+---------| -| addRewardDistributor | 2589 | 65359 | 70586 | 70586 | 147 | +| addRewardDistributor | 2589 | 65629 | 70586 | 70586 | 155 | |------------------------------+-----------------+--------+--------+--------+---------| | allowance | 482 | 482 | 482 | 482 | 3 | |------------------------------+-----------------+--------+--------+--------+---------| @@ -106,7 +106,7 @@ |------------------------------+-----------------+--------+--------+--------+---------| | getRewardDistributors | 1140 | 3384 | 3384 | 5628 | 6 | |------------------------------+-----------------+--------+--------+--------+---------| -| initialize | 95872 | 95872 | 95872 | 95872 | 111 | +| initialize | 95872 | 95872 | 95872 | 95872 | 119 | |------------------------------+-----------------+--------+--------+--------+---------| | mint | 2654 | 58515 | 74916 | 74916 | 18 | |------------------------------+-----------------+--------+--------+--------+---------| @@ -164,7 +164,7 @@ +=============================================================================================================+ | Deployment Cost | Deployment Size | | | | | |------------------------------------------------------+-----------------+--------+--------+--------+---------| -| 3542921 | 16412 | | | | | +| 3602901 | 16693 | | | | | |------------------------------------------------------+-----------------+--------+--------+--------+---------| | | | | | | | |------------------------------------------------------+-----------------+--------+--------+--------+---------| @@ -172,7 +172,7 @@ |------------------------------------------------------+-----------------+--------+--------+--------+---------| | MAX_LOCKUP_PERIOD | 383 | 383 | 383 | 383 | 4 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| -| MAX_MULTIPLIER | 263 | 263 | 263 | 263 | 16 | +| MAX_MULTIPLIER | 263 | 263 | 263 | 263 | 20 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| | MIN_LOCKUP_PERIOD | 309 | 309 | 309 | 309 | 15 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| @@ -192,17 +192,17 @@ |------------------------------------------------------+-----------------+--------+--------+--------+---------| | getStakedBalance | 2643 | 2643 | 2643 | 2643 | 1 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| -| getVault | 1970 | 1970 | 1970 | 1970 | 2130 | +| getVault | 2139 | 2795 | 2139 | 4139 | 2130 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| -| initialize | 92753 | 92753 | 92753 | 92753 | 86 | +| initialize | 92753 | 92753 | 92753 | 92753 | 94 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| | lastRewardTime | 429 | 1429 | 1429 | 2429 | 2 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| -| leave | 92893 | 92893 | 92893 | 92893 | 1 | +| leave | 95108 | 95108 | 95108 | 95108 | 1 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| -| lock | 7062 | 68846 | 71363 | 88476 | 1032 | +| lock | 7062 | 74851 | 76770 | 110983 | 1034 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| -| migrateToVault | 13505 | 72060 | 15712 | 186964 | 3 | +| migrateToVault | 13505 | 72798 | 15712 | 189179 | 3 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| | mpBalanceOf | 917 | 2361 | 2316 | 7063 | 12 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| @@ -212,45 +212,45 @@ |------------------------------------------------------+-----------------+--------+--------+--------+---------| | proxiableUUID | 342 | 342 | 342 | 342 | 3 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| -| registerVault | 2539 | 74350 | 74970 | 74970 | 338 | +| registerVault | 2539 | 74404 | 74970 | 74970 | 370 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| | rewardEndTime | 385 | 1385 | 1385 | 2385 | 2 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| | rewardStartTime | 430 | 1430 | 1430 | 2430 | 2 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| -| rewardsBalanceOf | 2340 | 3550 | 3953 | 6340 | 268 | +| rewardsBalanceOf | 2340 | 3544 | 3953 | 6340 | 268 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| | rewardsBalanceOfAccount | 10242 | 10242 | 10242 | 10242 | 1 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| | setReward | 2530 | 105587 | 107098 | 107098 | 265 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| -| setRewardsSupplier | 26831 | 26831 | 26831 | 26831 | 81 | +| setRewardsSupplier | 26831 | 26831 | 26831 | 26831 | 89 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| -| setTrustedCodehash | 24194 | 24194 | 24194 | 24194 | 86 | +| setTrustedCodehash | 24194 | 24194 | 24194 | 24194 | 94 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| -| stake | 2639 | 234216 | 225267 | 246054 | 2381 | +| stake | 2639 | 243775 | 225186 | 268574 | 2409 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| | totalMP | 805 | 1257 | 1257 | 1710 | 6 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| -| totalMPAccrued | 385 | 385 | 385 | 385 | 2132 | +| totalMPAccrued | 385 | 385 | 385 | 385 | 2136 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| -| totalMPStaked | 429 | 429 | 429 | 429 | 2135 | +| totalMPStaked | 429 | 429 | 429 | 429 | 2139 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| -| totalMaxMP | 407 | 407 | 407 | 407 | 2132 | +| totalMaxMP | 407 | 407 | 407 | 407 | 2136 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| | totalRewardsAccrued | 429 | 429 | 429 | 429 | 3 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| -| totalRewardsSupply | 1020 | 1649 | 1814 | 6759 | 290 | +| totalRewardsSupply | 1020 | 1646 | 1814 | 6759 | 290 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| | totalShares | 662 | 662 | 662 | 662 | 6 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| -| totalStaked | 430 | 430 | 430 | 430 | 2139 | +| totalStaked | 430 | 430 | 430 | 430 | 2143 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| -| unstake | 50497 | 75863 | 75818 | 83186 | 269 | +| unstake | 50497 | 75848 | 75818 | 83186 | 269 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| -| updateGlobalState | 15820 | 27819 | 29230 | 29521 | 277 | +| updateGlobalState | 15820 | 27786 | 29230 | 29521 | 277 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| -| updateVaultMP | 25083 | 34611 | 36494 | 36785 | 277 | +| updateVaultMP | 25083 | 34625 | 36494 | 36785 | 277 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| | upgradeTo | 10235 | 10857 | 10235 | 12723 | 4 | |------------------------------------------------------+-----------------+--------+--------+--------+---------| @@ -274,25 +274,25 @@ |----------------------------------------+-----------------+--------+--------+--------+---------| | emergencyExit | 15045 | 31485 | 31483 | 48583 | 263 | |----------------------------------------+-----------------+--------+--------+--------+---------| -| initialize | 97660 | 97660 | 97660 | 97660 | 338 | +| initialize | 97660 | 97660 | 97660 | 97660 | 370 | |----------------------------------------+-----------------+--------+--------+--------+---------| -| leave | 12161 | 127523 | 68545 | 360844 | 4 | +| leave | 12161 | 128077 | 69652 | 360844 | 4 | |----------------------------------------+-----------------+--------+--------+--------+---------| -| lock | 12091 | 84240 | 86826 | 103939 | 1033 | +| lock | 12091 | 90239 | 92233 | 126446 | 1035 | |----------------------------------------+-----------------+--------+--------+--------+---------| -| migrateToVault | 28993 | 98742 | 31200 | 236034 | 3 | +| migrateToVault | 28993 | 99480 | 31200 | 238249 | 3 | |----------------------------------------+-----------------+--------+--------+--------+---------| -| owner | 379 | 413 | 379 | 2379 | 346 | +| owner | 379 | 410 | 379 | 2379 | 378 | |----------------------------------------+-----------------+--------+--------+--------+---------| -| register | 12674 | 78000 | 78600 | 78600 | 338 | +| register | 12674 | 78052 | 78600 | 78600 | 370 | |----------------------------------------+-----------------+--------+--------+--------+---------| -| stake | 12071 | 289651 | 280835 | 301622 | 2382 | +| stake | 12071 | 298989 | 280754 | 324142 | 2410 | |----------------------------------------+-----------------+--------+--------+--------+---------| -| stakeManager | 369 | 369 | 369 | 369 | 337 | +| stakeManager | 369 | 369 | 369 | 369 | 369 | |----------------------------------------+-----------------+--------+--------+--------+---------| | trustStakeManager | 7580 | 7580 | 7580 | 7580 | 1 | |----------------------------------------+-----------------+--------+--------+--------+---------| -| unstake | 12048 | 106326 | 106840 | 114208 | 270 | +| unstake | 12048 | 106311 | 106840 | 114208 | 270 | |----------------------------------------+-----------------+--------+--------+--------+---------| | withdraw | 20754 | 20754 | 20754 | 20754 | 1 | ╰----------------------------------------+-----------------+--------+--------+--------+---------╯ @@ -308,9 +308,9 @@ |----------------------------------------------------+-----------------+------+--------+--------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |----------------------------------------------------+-----------------+------+--------+--------+---------| -| fallback | 708 | 5344 | 874 | 396039 | 12505 | +| fallback | 708 | 5508 | 874 | 396039 | 12533 | |----------------------------------------------------+-----------------+------+--------+--------+---------| -| implementation | 346 | 2345 | 2346 | 2346 | 4031 | +| implementation | 346 | 2345 | 2346 | 2346 | 4093 | ╰----------------------------------------------------+-----------------+------+--------+--------+---------╯ ╭--------------------------------------------+-----------------+--------+--------+--------+---------╮ @@ -324,7 +324,7 @@ |--------------------------------------------+-----------------+--------+--------+--------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |--------------------------------------------+-----------------+--------+--------+--------+---------| -| createVault | 230924 | 247618 | 248024 | 248024 | 337 | +| createVault | 230924 | 247653 | 248024 | 248024 | 369 | ╰--------------------------------------------+-----------------+--------+--------+--------+---------╯ ╭------------------------------------------------------------------------------------------+-----------------+-------+--------+-------+---------╮ @@ -412,11 +412,11 @@ |---------------------------------------------+-----------------+-------+--------+-------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |---------------------------------------------+-----------------+-------+--------+-------+---------| -| approve | 29075 | 31635 | 29243 | 46259 | 2384 | +| approve | 29075 | 31831 | 29255 | 46259 | 2416 | |---------------------------------------------+-----------------+-------+--------+-------+---------| | balanceOf | 561 | 924 | 561 | 2561 | 2930 | |---------------------------------------------+-----------------+-------+--------+-------+---------| -| mint | 33964 | 37308 | 34132 | 68248 | 2393 | +| mint | 33964 | 37549 | 34144 | 68248 | 2425 | ╰---------------------------------------------+-----------------+-------+--------+-------+---------╯ ╭-----------------------------------------------------------------------------+-----------------+--------+--------+--------+---------╮ diff --git a/.gas-snapshot b/.gas-snapshot index 55e8438..0982922 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,22 +1,22 @@ -CompoundTest:test_CompoundForAccount() (gas: 2494062) -CompoundTest:test_RevertWhenInsufficientMPBalance() (gas: 382215) +CompoundTest:test_CompoundForAccount() (gas: 2493738) +CompoundTest:test_RevertWhenInsufficientMPBalance() (gas: 382134) EmergencyExitTest:test_CannotEnableEmergencyModeTwice() (gas: 93420) -EmergencyExitTest:test_CannotLeaveBeforeEmergencyMode() (gas: 355534) -EmergencyExitTest:test_EmergencyExitBasic() (gas: 448200) -EmergencyExitTest:test_EmergencyExitMultipleUsers() (gas: 771903) -EmergencyExitTest:test_EmergencyExitToAlternateAddress() (gas: 453707) -EmergencyExitTest:test_EmergencyExitWithLock() (gas: 450628) -EmergencyExitTest:test_EmergencyExitWithRewards() (gas: 438686) +EmergencyExitTest:test_CannotLeaveBeforeEmergencyMode() (gas: 355453) +EmergencyExitTest:test_EmergencyExitBasic() (gas: 450328) +EmergencyExitTest:test_EmergencyExitMultipleUsers() (gas: 776160) +EmergencyExitTest:test_EmergencyExitToAlternateAddress() (gas: 455835) +EmergencyExitTest:test_EmergencyExitWithLock() (gas: 473148) +EmergencyExitTest:test_EmergencyExitWithRewards() (gas: 438605) EmergencyExitTest:test_OnlyOwnerCanEnableEmergencyMode() (gas: 39066) -FuzzTests:testFuzz_AccrueMP(uint256,uint256,uint16) (runs: 1000, μ: 524477, ~: 518624) -FuzzTests:testFuzz_AccrueMP_Relock(uint256,uint256,uint16) (runs: 1000, μ: 547715, ~: 549740) -FuzzTests:testFuzz_EmergencyExit(uint256,uint256) (runs: 1000, μ: 514320, ~: 505292) -FuzzTests:testFuzz_Lock(uint256,uint256) (runs: 1000, μ: 526042, ~: 526055) -FuzzTests:testFuzz_Relock(uint256,uint256,uint256) (runs: 1000, μ: 546547, ~: 553470) -FuzzTests:testFuzz_Rewards(uint256,uint256,uint256,uint16,uint16) (runs: 1000, μ: 612288, ~: 613606) -FuzzTests:testFuzz_Stake(uint256,uint256) (runs: 1000, μ: 407676, ~: 398648) -FuzzTests:testFuzz_Unstake(uint256,uint256,uint16,uint256) (runs: 1000, μ: 533829, ~: 533277) -IntegrationTest:testStakeFoo() (gas: 1425226) +FuzzTests:testFuzz_AccrueMP(uint256,uint256,uint16) (runs: 1000, μ: 536369, ~: 521373) +FuzzTests:testFuzz_AccrueMP_Relock(uint256,uint256,uint16) (runs: 1001, μ: 575868, ~: 577876) +FuzzTests:testFuzz_EmergencyExit(uint256,uint256) (runs: 1000, μ: 526503, ~: 507384) +FuzzTests:testFuzz_Lock(uint256,uint256) (runs: 1000, μ: 548676, ~: 548689) +FuzzTests:testFuzz_Relock(uint256,uint256,uint256) (runs: 1002, μ: 575751, ~: 581815) +FuzzTests:testFuzz_Rewards(uint256,uint256,uint256,uint16,uint16) (runs: 1000, μ: 634275, ~: 636130) +FuzzTests:testFuzz_Stake(uint256,uint256) (runs: 1000, μ: 419858, ~: 400739) +FuzzTests:testFuzz_Unstake(uint256,uint256,uint16,uint256) (runs: 1000, μ: 535949, ~: 535405) +IntegrationTest:testStakeFoo() (gas: 1434411) KarmaMintAllowanceTest:testAddKarmaDistributorOnlyOwner() (gas: 364780) KarmaMintAllowanceTest:testBalanceOf() (gas: 444028) KarmaMintAllowanceTest:testBalanceOfWithNoSystemTotalKarma() (gas: 49501) @@ -57,76 +57,84 @@ KarmaTest:testRemoveKarmaDistributorOnlyOwner() (gas: 88798) KarmaTest:testRemoveUnknownKarmaDistributor() (gas: 41398) KarmaTest:testTotalSupply() (gas: 352175) KarmaTest:testTransfersNotAllowed() (gas: 40241) -LeaveTest:test_LeaveShouldProperlyUpdateAccounting() (gas: 9727511) -LeaveTest:test_RevertWhenStakeManagerIsTrusted() (gas: 352606) -LeaveTest:test_TrustNewStakeManager() (gas: 9780109) -LockTest:test_LockFailsWithInvalidPeriod(uint256) (runs: 1000, μ: 401668, ~: 401692) -LockTest:test_LockFailsWithNoStake() (gas: 87158) -LockTest:test_LockFailsWithZero() (gas: 362755) -LockTest:test_LockMultipleTimesExceedMaxLock() (gas: 685105) -LockTest:test_LockWithPriorLock() (gas: 590263) -LockTest:test_LockWithoutPriorLock() (gas: 468573) -LockTest:test_RevertWhenVaultToLockIsEmpty() (gas: 87116) -MaliciousUpgradeTest:test_UpgradeStackOverflowStakeManager() (gas: 2018890) +LeaveTest:test_LeaveShouldProperlyUpdateAccounting() (gas: 9845373) +LeaveTest:test_RevertWhenStakeManagerIsTrusted() (gas: 352525) +LeaveTest:test_TrustNewStakeManager() (gas: 9896439) +LockTest:test_LockFailsWithInvalidPeriod(uint256) (runs: 1002, μ: 389382, ~: 366689) +LockTest:test_LockFailsWithNoStake() (gas: 109665) +LockTest:test_LockFailsWithZero() (gas: 362674) +LockTest:test_LockMultipleTimesExceedMaxLock() (gas: 673937) +LockTest:test_LockWithPriorLock() (gas: 620723) +LockTest:test_LockWithoutPriorLock() (gas: 493416) +LockTest:test_RevertWhenVaultToLockIsEmpty() (gas: 109623) +MaliciousUpgradeTest:test_UpgradeStackOverflowStakeManager() (gas: 2018809) MathTest:test_CalcAbsoluteMaxTotalMP() (gas: 5196) MathTest:test_CalcAccrueMP() (gas: 8511) MathTest:test_CalcBonusMP() (gas: 19112) MathTest:test_CalcInitialMP() (gas: 5728) MathTest:test_CalcMaxAccruedMP() (gas: 4842) MathTest:test_CalcMaxTotalMP() (gas: 19852) -MultipleVaultsStakeTest:test_StakeMultipleVaults() (gas: 860354) +MultipleVaultsStakeTest:test_StakeMultipleVaults() (gas: 860111) NFTMetadataGeneratorSVGTest:testGenerateMetadata() (gas: 92580) NFTMetadataGeneratorSVGTest:testSetImageStrings() (gas: 60081) NFTMetadataGeneratorSVGTest:testSetImageStringsRevert() (gas: 35891) NFTMetadataGeneratorURLTest:testGenerateMetadata() (gas: 108341) NFTMetadataGeneratorURLTest:testSetBaseURL() (gas: 50631) NFTMetadataGeneratorURLTest:testSetBaseURLRevert() (gas: 36066) -RewardsStreamerMP_RewardsTest:testRewardsBalanceOf() (gas: 1326572) +RewardsStreamerMP_RewardsTest:testRewardsBalanceOf() (gas: 1326410) RewardsStreamerMP_RewardsTest:testSetRewards() (gas: 224746) RewardsStreamerMP_RewardsTest:testSetRewards_RevertsBadAmount() (gas: 61304) RewardsStreamerMP_RewardsTest:testSetRewards_RevertsBadDuration() (gas: 101081) RewardsStreamerMP_RewardsTest:testSetRewards_RevertsNotAuthorized() (gas: 39366) -RewardsStreamerMP_RewardsTest:testTotalRewardsSupply() (gas: 761485) -StakeTest:test_StakeMultipleAccounts() (gas: 597304) -StakeTest:test_StakeMultipleAccountsAndRewards() (gas: 605774) -StakeTest:test_StakeMultipleAccountsMPIncreasesMaxMPDoesNotChange() (gas: 1033828) -StakeTest:test_StakeMultipleAccountsWithMinLockUp() (gas: 607850) -StakeTest:test_StakeMultipleAccountsWithRandomLockUp() (gas: 629860) -StakeTest:test_StakeOneAccount() (gas: 336859) -StakeTest:test_StakeOneAccountAndRewards() (gas: 345325) -StakeTest:test_StakeOneAccountMPIncreasesMaxMPDoesNotChange() (gas: 612302) -StakeTest:test_StakeOneAccountReachingMPLimit() (gas: 600369) -StakeTest:test_StakeOneAccountWithMaxLockUp() (gas: 354886) -StakeTest:test_StakeOneAccountWithMinLockUp() (gas: 355460) -StakeTest:test_StakeOneAccountWithRandomLockUp() (gas: 355549) -StakeVaultMigrationTest:testMigrateToVault() (gas: 950946) -StakeVaultMigrationTest:test_RevertWhenMigrationVaultNotEmpty() (gas: 648652) +RewardsStreamerMP_RewardsTest:testTotalRewardsSupply() (gas: 761404) +StakeTest:test_RevertWhenStakeMultipleTimesExceedsMaxLockUpTime() (gas: 776821) +StakeTest:test_RevertWhenStakeMultipleTimesWithGapsExceedsMaxLockUpTime() (gas: 828961) +StakeTest:test_StakeMultipleAccounts() (gas: 601560) +StakeTest:test_StakeMultipleAccountsAndRewards() (gas: 610075) +StakeTest:test_StakeMultipleAccountsMPIncreasesMaxMPDoesNotChange() (gas: 1038928) +StakeTest:test_StakeMultipleAccountsWithMinLockUp() (gas: 630289) +StakeTest:test_StakeMultipleAccountsWithRandomLockUp() (gas: 674900) +StakeTest:test_StakeMultipleTimesWithLockIncreaseAtSameBlock() (gas: 625486) +StakeTest:test_StakeMultipleTimesWithLockZeroAfterMaxLock() (gas: 593616) +StakeTest:test_StakeOneAccount() (gas: 338986) +StakeTest:test_StakeOneAccountAndRewards() (gas: 347498) +StakeTest:test_StakeOneAccountMPIncreasesMaxMPDoesNotChange() (gas: 614617) +StakeTest:test_StakeOneAccountReachingMPLimit() (gas: 602770) +StakeTest:test_StakeOneAccountWithMaxLockUp() (gas: 377406) +StakeTest:test_StakeOneAccountWithMinLockUp() (gas: 378002) +StakeTest:test_StakeOneAccountWithRandomLockUp() (gas: 378069) +StakeVaultMigrationTest:testMigrateToVault() (gas: 957919) +StakeVaultMigrationTest:test_RevertWhenMigrationVaultNotEmpty() (gas: 648571) StakeVaultMigrationTest:test_RevertWhenNotOwnerOfMigrationVault() (gas: 68066) StakeVaultTest:testOwner() (gas: 15262) StakingTokenTest:testOwner() (gas: 15262) StakingTokenTest:testStakeToken() (gas: 13144) TrustedCodehashAccessTest:test_RevertWhenProxyCloneCodehashNotTrusted() (gas: 2023401) -UnstakeTest:test_StakeMultipleAccounts() (gas: 597348) -UnstakeTest:test_StakeMultipleAccountsAndRewards() (gas: 605818) -UnstakeTest:test_StakeMultipleAccountsMPIncreasesMaxMPDoesNotChange() (gas: 1033805) -UnstakeTest:test_StakeMultipleAccountsWithMinLockUp() (gas: 607827) -UnstakeTest:test_StakeMultipleAccountsWithRandomLockUp() (gas: 629837) -UnstakeTest:test_StakeOneAccount() (gas: 336859) -UnstakeTest:test_StakeOneAccountAndRewards() (gas: 345369) -UnstakeTest:test_StakeOneAccountMPIncreasesMaxMPDoesNotChange() (gas: 612279) -UnstakeTest:test_StakeOneAccountReachingMPLimit() (gas: 600413) -UnstakeTest:test_StakeOneAccountWithMaxLockUp() (gas: 354908) -UnstakeTest:test_StakeOneAccountWithMinLockUp() (gas: 355482) -UnstakeTest:test_StakeOneAccountWithRandomLockUp() (gas: 355527) -UnstakeTest:test_UnstakeBonusMPAndAccuredMP() (gas: 639439) -UnstakeTest:test_UnstakeMultipleAccounts() (gas: 836970) -UnstakeTest:test_UnstakeMultipleAccountsAndRewards() (gas: 950387) -UnstakeTest:test_UnstakeOneAccount() (gas: 571924) -UnstakeTest:test_UnstakeOneAccountAndAccruedMP() (gas: 597361) -UnstakeTest:test_UnstakeOneAccountAndRewards() (gas: 493417) -UnstakeTest:test_UnstakeOneAccountWithLockUpAndAccruedMP() (gas: 627061) -UpgradeTest:test_RevertWhenNotOwner() (gas: 3619323) -UpgradeTest:test_UpgradeStakeManager() (gas: 9616123) +UnstakeTest:test_RevertWhenStakeMultipleTimesExceedsMaxLockUpTime() (gas: 776843) +UnstakeTest:test_RevertWhenStakeMultipleTimesWithGapsExceedsMaxLockUpTime() (gas: 829005) +UnstakeTest:test_StakeMultipleAccounts() (gas: 601604) +UnstakeTest:test_StakeMultipleAccountsAndRewards() (gas: 610030) +UnstakeTest:test_StakeMultipleAccountsMPIncreasesMaxMPDoesNotChange() (gas: 1038905) +UnstakeTest:test_StakeMultipleAccountsWithMinLockUp() (gas: 630244) +UnstakeTest:test_StakeMultipleAccountsWithRandomLockUp() (gas: 674877) +UnstakeTest:test_StakeMultipleTimesWithLockIncreaseAtSameBlock() (gas: 625508) +UnstakeTest:test_StakeMultipleTimesWithLockZeroAfterMaxLock() (gas: 593616) +UnstakeTest:test_StakeOneAccount() (gas: 338986) +UnstakeTest:test_StakeOneAccountAndRewards() (gas: 347475) +UnstakeTest:test_StakeOneAccountMPIncreasesMaxMPDoesNotChange() (gas: 614594) +UnstakeTest:test_StakeOneAccountReachingMPLimit() (gas: 602728) +UnstakeTest:test_StakeOneAccountWithMaxLockUp() (gas: 377428) +UnstakeTest:test_StakeOneAccountWithMinLockUp() (gas: 378002) +UnstakeTest:test_StakeOneAccountWithRandomLockUp() (gas: 378047) +UnstakeTest:test_UnstakeBonusMPAndAccuredMP() (gas: 662587) +UnstakeTest:test_UnstakeMultipleAccounts() (gas: 841649) +UnstakeTest:test_UnstakeMultipleAccountsAndRewards() (gas: 955345) +UnstakeTest:test_UnstakeOneAccount() (gas: 574242) +UnstakeTest:test_UnstakeOneAccountAndAccruedMP() (gas: 599490) +UnstakeTest:test_UnstakeOneAccountAndRewards() (gas: 495755) +UnstakeTest:test_UnstakeOneAccountWithLockUpAndAccruedMP() (gas: 649560) +UpgradeTest:test_RevertWhenNotOwner() (gas: 3679375) +UpgradeTest:test_UpgradeStakeManager() (gas: 9732455) VaultRegistrationTest:test_VaultRegistration() (gas: 63050) WithdrawTest:testOwner() (gas: 15296) -WithdrawTest:test_CannotWithdrawStakedFunds() (gas: 368340) \ No newline at end of file +WithdrawTest:test_CannotWithdrawStakedFunds() (gas: 368259) \ No newline at end of file diff --git a/certora/specs/RewardsStreamerMP.spec b/certora/specs/RewardsStreamerMP.spec index 713484a..72d7e3c 100644 --- a/certora/specs/RewardsStreamerMP.spec +++ b/certora/specs/RewardsStreamerMP.spec @@ -7,7 +7,7 @@ methods { function ERC20A.allowance(address, address) external returns(uint256) envfree; function ERC20A.totalSupply() external returns(uint256) envfree; function totalStaked() external returns (uint256) envfree; - function vaultData(address) external returns (uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256) envfree; + function vaultData(address) external returns (uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256) envfree; function lastMPUpdatedTime() external returns (uint256) envfree; function updateGlobalState() external; function updateVaultMP(address vaultAddress) external; @@ -31,19 +31,19 @@ hook Sstore vaultData[KEY address vault].stakedBalance uint256 newValue (uint256 function getVaultMaxMP(address vault) returns uint256 { uint256 maxMP; - _, _, _, maxMP, _, _, _, _ = streamer.vaultData(vault); + _, _, _, maxMP, _, _, _, _, _ = streamer.vaultData(vault); return maxMP; } function getVaultMPAccrued(address vault) returns uint256 { uint256 vaultMPAccrued; - _, _, vaultMPAccrued, _, _, _, _, _ = streamer.vaultData(vault); + _, _, vaultMPAccrued, _, _, _, _, _, _ = streamer.vaultData(vault); return vaultMPAccrued; } function getVaultLockUntil(address vault) returns uint256 { uint256 lockUntil; - _, _, _, _, _, lockUntil, _, _ = streamer.vaultData(vault); + _, _, _, _, _, lockUntil, _, _, _ = streamer.vaultData(vault); return lockUntil; } diff --git a/certora/specs/shared.spec b/certora/specs/shared.spec index a5d2bd8..aa6bde2 100644 --- a/certora/specs/shared.spec +++ b/certora/specs/shared.spec @@ -2,7 +2,7 @@ using RewardsStreamerMP as streamer; function getVaultStakedBalance(address vault) returns uint256 { uint256 stakedBalance; - stakedBalance, _, _, _, _, _, _, _ = streamer.vaultData(vault); + stakedBalance, _, _, _, _, _, _, _, _ = streamer.vaultData(vault); return stakedBalance; } diff --git a/src/RewardsStreamerMP.sol b/src/RewardsStreamerMP.sol index 09aed93..60e5338 100644 --- a/src/RewardsStreamerMP.sol +++ b/src/RewardsStreamerMP.sol @@ -35,6 +35,7 @@ contract RewardsStreamerMP is uint256 lockUntil; uint256 mpStaked; uint256 rewardsAccrued; + uint256 totalLockTime; } /*////////////////////////////////////////////////////////////////////////// @@ -186,9 +187,21 @@ contract RewardsStreamerMP is _updateVault(msg.sender, true); VaultData storage vault = vaultData[msg.sender]; - if (vault.lockUntil != 0 && vault.lockUntil > block.timestamp) { - revert StakingManager__CannotRestakeWithLockedFunds(); + + bool isCurrentlyLocked = vault.lockUntil > block.timestamp; + + // Can't have `lockPeriod = 0` if vault is currently locked + if (lockPeriod == 0 && isCurrentlyLocked) { + revert StakingManager__InvalidLockPeriod(); } + + if (lockPeriod > 0) { + if (vault.totalLockTime + lockPeriod > MAX_LOCKUP_PERIOD) { + revert StakingManager__InvalidLockPeriod(); + } + vault.totalLockTime += lockPeriod; + } + (uint256 _deltaMpTotal, uint256 _deltaMPMax, uint256 _newLockEnd) = _calculateStake(vault.stakedBalance, vault.maxMP, vault.lockUntil, block.timestamp, amount, lockPeriod); @@ -198,8 +211,6 @@ contract RewardsStreamerMP is if (lockPeriod != 0) { vault.lockUntil = _newLockEnd; - } else { - vault.lockUntil = 0; } vault.mpAccrued += _deltaMpTotal; @@ -228,6 +239,11 @@ contract RewardsStreamerMP is revert StakingManager__DurationCannotBeZero(); } + if (vault.totalLockTime + lockPeriod > MAX_LOCKUP_PERIOD) { + revert StakingManager__InvalidLockPeriod(); + } + vault.totalLockTime += lockPeriod; + _updateGlobalState(); _updateVault(msg.sender, false); (uint256 deltaMp, uint256 newLockEnd) = @@ -281,6 +297,7 @@ contract RewardsStreamerMP is vault.rewardIndex = 0; vault.lockUntil = 0; vault.lastMPUpdateTime = 0; + vault.totalLockTime = 0; } emit AccountLeft(msg.sender); diff --git a/src/interfaces/IStakeManager.sol b/src/interfaces/IStakeManager.sol index b1c344a..4ca765e 100644 --- a/src/interfaces/IStakeManager.sol +++ b/src/interfaces/IStakeManager.sol @@ -22,9 +22,7 @@ interface IStakeManager is ITrustedCodehashAccess, IStakeConstants { /// @notice Emitted when the amount to stake is zero. error StakingManager__AmountCannotBeZero(); /// @notice Emitted when the lock period is not zero. - error StakingManager__CannotRestakeWithLockedFunds(); - /// @notice Emitted when the vault is already locked. - error StakingManager__AlreadyLocked(); + error StakingManager__InvalidLockPeriod(); /// @notice Emitted when emergency mode is enabled. error StakingManager__EmergencyModeEnabled(); /// @notice Emitted trying to migrate to non empty vault diff --git a/test/RewardsStreamerMP.t.sol b/test/RewardsStreamerMP.t.sol index fd30701..9864a90 100644 --- a/test/RewardsStreamerMP.t.sol +++ b/test/RewardsStreamerMP.t.sol @@ -7,7 +7,6 @@ import { DeployKarmaScript } from "../script/DeployKarma.s.sol"; import { DeployRewardsStreamerMPScript } from "../script/DeployRewardsStreamerMP.s.sol"; import { UpgradeRewardsStreamerMPScript } from "../script/UpgradeRewardsStreamerMP.s.sol"; import { DeploymentConfig } from "../script/DeploymentConfig.s.sol"; -import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import { Clones } from "@openzeppelin/contracts/proxy/Clones.sol"; import { IStakeManager } from "../src/interfaces/IStakeManager.sol"; @@ -101,13 +100,10 @@ contract RewardsStreamerMPTest is StakeMath, Test { } function checkVault(CheckVaultParams memory p) public view { - // assertEq(rewardToken.balanceOf(p.account), p.rewardBalance, "wrong account reward balance"); - RewardsStreamerMP.VaultData memory vaultData = streamer.getVault(p.account); assertEq(vaultData.stakedBalance, p.stakedBalance, "wrong account staked balance"); assertEq(stakingToken.balanceOf(p.account), p.vaultBalance, "wrong vault balance"); - // assertEq(vaultData.accountRewardIndex, p.rewardIndex, "wrong account reward index"); assertEq(vaultData.mpStaked, p.mpStaked, "wrong account MP staked"); assertEq(vaultData.mpAccrued, p.mpAccrued, "wrong account MP accrued"); assertEq(vaultData.maxMP, p.maxMP, "wrong account max MP"); @@ -149,6 +145,12 @@ contract RewardsStreamerMPTest is StakeMath, Test { vault.unstake(amount); } + function _lock(address account, uint256 lockPeriod) internal { + StakeVault vault = StakeVault(vaults[account]); + vm.prank(account); + vault.lock(lockPeriod); + } + function _emergencyExit(address account) public { StakeVault vault = StakeVault(vaults[account]); vm.prank(account); @@ -959,6 +961,131 @@ contract StakeTest is RewardsStreamerMPTest { ); } + function test_StakeMultipleTimesWithLockZeroAfterMaxLock() public { + uint256 stakeAmount = 10e18; + + // stake and lock 4 years + _stake(alice, stakeAmount, 4 * YEAR); + vm.warp(vm.getBlockTimestamp() + 4 * YEAR); + + // staking with lock 0 should now work because the previous + // lock up has expired + _stake(alice, stakeAmount, 0); + + // staking with lock > 0 should revert as max lock time was reached + vm.expectRevert(IStakeManager.StakingManager__InvalidLockPeriod.selector); + _stake(alice, stakeAmount, MIN_LOCKUP_PERIOD); + } + + function test_StakeMultipleTimesWithLockIncreaseAtSameBlock() public { + uint256 stakeAmount = 10e18; + uint256 expectedStake = stakeAmount; + uint256 lockUpIncrease = YEAR; + uint256 expectedBonus = _bonusMP(stakeAmount, lockUpIncrease); + uint256 expectedMP = stakeAmount; + uint256 expectedMaxMP = expectedMP + expectedBonus + (stakeAmount * streamer.MAX_MULTIPLIER()); + + // Alice stakes 10 tokens, locks for 1 year + _stake(alice, stakeAmount, lockUpIncrease); + + checkStreamer( + CheckStreamerParams({ + totalStaked: expectedStake, + totalMPStaked: expectedMP + expectedBonus, + totalMPAccrued: expectedMP + expectedBonus, + totalMaxMP: expectedMaxMP, + stakingBalance: stakeAmount, + rewardBalance: 0, + rewardIndex: 0 + }) + ); + + // Alice stakes again 10 tokens and increases lock by 3 years + // Since time hasn't passed yet, we essentially have a total lock up + // of 4 years + lockUpIncrease = 3 * YEAR; + + // new bonus = old bonus + bonus increase for old stake + bonus for new stake + bonus for new stake + expectedBonus = expectedBonus + _bonusMP(stakeAmount, lockUpIncrease) + _bonusMP(stakeAmount, lockUpIncrease) + // This is the bonus for the new stake on the previous lock up + + _bonusMP(stakeAmount, YEAR); + expectedMP = expectedMP + stakeAmount; + expectedMaxMP = expectedMP + expectedBonus + ((stakeAmount * 2) * streamer.MAX_MULTIPLIER()); + + _stake(alice, stakeAmount, lockUpIncrease); + + expectedStake = expectedStake + stakeAmount; + + checkStreamer( + CheckStreamerParams({ + totalStaked: expectedStake, + totalMPStaked: expectedMP + expectedBonus, + totalMPAccrued: expectedMP + expectedBonus, + totalMaxMP: expectedMaxMP, + stakingBalance: expectedStake, + rewardBalance: 0, + rewardIndex: 0 + }) + ); + + // any lock up beyond the max lock up period should revert + vm.expectRevert(IStakeManager.StakingManager__InvalidLockPeriod.selector); + _stake(alice, 1, MIN_LOCKUP_PERIOD); + } + + function test_RevertWhenStakeMultipleTimesExceedsMaxLockUpTime() public { + // stake and lock 1 year + uint256 stakeAmount = 10e18; + _stake(alice, stakeAmount, YEAR); + + vm.warp(vm.getBlockTimestamp() + YEAR); + + // stake and lock another year + _stake(alice, stakeAmount, YEAR); + + vm.warp(vm.getBlockTimestamp() + YEAR); + + // stake and lock another 2 * year + _stake(alice, stakeAmount, 2 * YEAR); + + vm.warp(vm.getBlockTimestamp() + (2 * YEAR)); + + // we have now a total lock up of 4 years, + // so the next stake/or lock attempt should revert + vm.expectRevert(IStakeManager.StakingManager__InvalidLockPeriod.selector); + _stake(alice, stakeAmount, MIN_LOCKUP_PERIOD); + } + + function test_RevertWhenStakeMultipleTimesWithGapsExceedsMaxLockUpTime() public { + uint256 stakeAmount = 10e18; + + // stake and lock 1 year + _stake(alice, stakeAmount, YEAR); + vm.warp(vm.getBlockTimestamp() + YEAR); + + // wait for 1 year + vm.warp(vm.getBlockTimestamp() + YEAR); + + // stake and lock another year + _stake(alice, stakeAmount, YEAR); + vm.warp(vm.getBlockTimestamp() + YEAR); + + // wait for 2 years + vm.warp(vm.getBlockTimestamp() + 2 * YEAR); + + // stake and lock another 2 * year + _stake(alice, stakeAmount, 2 * YEAR); + vm.warp(vm.getBlockTimestamp() + (2 * YEAR)); + + // we have now staked for 7 years but locked up for 4 years, + // so the next stake/or lock attempt should revert + vm.expectRevert(IStakeManager.StakingManager__InvalidLockPeriod.selector); + _stake(alice, stakeAmount, MIN_LOCKUP_PERIOD); + + vm.expectRevert(IStakeManager.StakingManager__InvalidLockPeriod.selector); + _lock(alice, MIN_LOCKUP_PERIOD); + } + function test_StakeMultipleAccounts() public { // Alice stakes 10 tokens _stake(alice, 10e18, 0); @@ -1715,12 +1842,6 @@ contract LockTest is RewardsStreamerMPTest { super.setUp(); } - function _lock(address account, uint256 lockPeriod) internal { - StakeVault vault = StakeVault(vaults[account]); - vm.prank(account); - vault.lock(lockPeriod); - } - function test_LockWithPriorLock() public { // Setup - alice stakes 10 tokens without lock uint256 stakeAmount = 10e18; @@ -1898,7 +2019,7 @@ contract LockTest is RewardsStreamerMPTest { ); // lock for another year should fail as 4 years is the maximum of total lock time - vm.expectRevert(StakeMath.StakeMath__AbsoluteMaxMPOverflow.selector); + vm.expectRevert(IStakeManager.StakingManager__InvalidLockPeriod.selector); _lock(alice, YEAR); } @@ -1909,8 +2030,6 @@ contract LockTest is RewardsStreamerMPTest { function test_LockFailsWithZero() public { _stake(alice, 10e18, 0); - - // Test with period = 0 vm.expectRevert(IStakeManager.StakingManager__DurationCannotBeZero.selector); _lock(alice, 0); } @@ -1922,7 +2041,7 @@ contract LockTest is RewardsStreamerMPTest { _stake(alice, 10e18, 0); - vm.expectRevert(StakeMath.StakeMath__InvalidLockingPeriod.selector); + vm.expectRevert(); _lock(alice, _lockPeriod); } @@ -2799,12 +2918,6 @@ contract FuzzTests is RewardsStreamerMPTest { super._stake(account, amount, lockPeriod); } - function _lock(address account, uint256 lockPeriod) internal { - StakeVault vault = StakeVault(vaults[account]); - vm.prank(account); - vault.lock(lockPeriod); - } - function testFuzz_Stake(uint256 stakeAmount, uint256 lockUpPeriod) public { vm.assume(stakeAmount > 0 && stakeAmount <= MAX_BALANCE); vm.assume(lockUpPeriod == 0 || (lockUpPeriod >= MIN_LOCKUP_PERIOD && lockUpPeriod <= MAX_LOCKUP_PERIOD));