feat(RewardsStreamerMP): allow for staking multiple times with lock

This commit enables users to stake multiple times into the same vault
with a lock increase.

If their total lock increase goes beyond the maximum lock period,
staking will revert. In this case users will have to create a new vault.

Closes #152

Co-authored-by: Andrea Franz <andrea@gravityblast.com>
This commit is contained in:
r4bbit
2025-03-14 15:44:12 +01:00
parent 2de338c673
commit 4fa3eb06e0
7 changed files with 278 additions and 142 deletions

View File

@@ -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 |
╰---------------------------------------------+-----------------+-------+--------+-------+---------╯
╭-----------------------------------------------------------------------------+-----------------+--------+--------+--------+---------╮

View File

@@ -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)
WithdrawTest:test_CannotWithdrawStakedFunds() (gas: 368259)

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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

View File

@@ -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));