mirror of https://github.com/logos-co/staking.git
refactor(StakeManager): Abstact out codehash verification to better code reusability
chore(StakeManager): move out storage contract and rename it
This commit is contained in:
parent
769f32f718
commit
509383ccd8
94
.gas-report
94
.gas-report
|
@ -1,51 +1,42 @@
|
||||||
| contracts/StakeManager.sol:StakeManager contract | | | | | |
|
| contracts/StakeManager.sol:StakeManager contract | | | | | |
|
||||||
|--------------------------------------------------|-----------------|--------|--------|--------|---------|
|
|--------------------------------------------------|-----------------|--------|--------|--------|---------|
|
||||||
| Deployment Cost | Deployment Size | | | | |
|
| Deployment Cost | Deployment Size | | | | |
|
||||||
| 2465702 | 13041 | | | | |
|
| 2489660 | 13152 | | | | |
|
||||||
| Function Name | min | avg | median | max | # calls |
|
| Function Name | min | avg | median | max | # calls |
|
||||||
| EPOCH_SIZE | 307 | 307 | 307 | 307 | 1498 |
|
| EPOCH_SIZE | 263 | 263 | 263 | 263 | 1498 |
|
||||||
| MAX_BOOST | 285 | 285 | 285 | 285 | 637 |
|
| MAX_BOOST | 264 | 264 | 264 | 264 | 637 |
|
||||||
| MAX_LOCKUP_PERIOD | 361 | 361 | 361 | 361 | 4 |
|
| MAX_LOCKUP_PERIOD | 383 | 383 | 383 | 383 | 4 |
|
||||||
| MIN_LOCKUP_PERIOD | 264 | 264 | 264 | 264 | 12 |
|
| MIN_LOCKUP_PERIOD | 264 | 264 | 264 | 264 | 12 |
|
||||||
| YEAR | 263 | 263 | 263 | 263 | 637 |
|
| YEAR | 263 | 263 | 263 | 263 | 637 |
|
||||||
| accounts | 1597 | 1597 | 1597 | 1597 | 144273 |
|
| accounts | 1616 | 1616 | 1616 | 1616 | 144249 |
|
||||||
| calculateMPToMint | 740 | 740 | 740 | 740 | 1276 |
|
| calculateMPToMint | 740 | 740 | 740 | 740 | 1276 |
|
||||||
| currentEpoch | 384 | 1050 | 384 | 2384 | 54 |
|
| currentEpoch | 384 | 1050 | 384 | 2384 | 54 |
|
||||||
| epochEnd | 627 | 627 | 627 | 2627 | 23675 |
|
| epochEnd | 649 | 649 | 649 | 2649 | 23671 |
|
||||||
| epochReward | 1425 | 2925 | 1425 | 5925 | 3 |
|
| epochReward | 1381 | 2881 | 1381 | 5881 | 3 |
|
||||||
| executeAccount(address) | 151152 | 151152 | 151152 | 151152 | 2 |
|
| executeAccount(address) | 151167 | 151167 | 151167 | 151167 | 2 |
|
||||||
| executeAccount(address,uint256) | 26562 | 72616 | 74122 | 217879 | 141860 |
|
| executeAccount(address,uint256) | 26562 | 72617 | 74122 | 217855 | 141836 |
|
||||||
| executeEpoch() | 23458 | 120800 | 121956 | 938985 | 23564 |
|
| executeEpoch() | 23480 | 120821 | 121978 | 939007 | 23560 |
|
||||||
| executeEpoch(uint256) | 23861 | 24497 | 23861 | 26090 | 7 |
|
| executeEpoch(uint256) | 23861 | 24497 | 23861 | 26090 | 7 |
|
||||||
| isVault | 540 | 948 | 540 | 2540 | 680 |
|
| expiredStakeStorage | 437 | 2346 | 2437 | 2437 | 22 |
|
||||||
| lock | 23862 | 23862 | 23862 | 23862 | 1 |
|
| isTrustedCodehash | 541 | 949 | 541 | 2541 | 680 |
|
||||||
| migrateTo | 23891 | 23897 | 23897 | 23903 | 2 |
|
| lock | 23818 | 23818 | 23818 | 23818 | 1 |
|
||||||
| migration | 395 | 1395 | 1395 | 2395 | 4 |
|
| migrateTo | 23922 | 23928 | 23928 | 23934 | 2 |
|
||||||
| migrationInitialize | 24602 | 24602 | 24602 | 24602 | 1 |
|
| migration | 417 | 1417 | 1417 | 2417 | 4 |
|
||||||
|
| migrationInitialize | 24624 | 24624 | 24624 | 24624 | 1 |
|
||||||
| newEpoch | 441 | 441 | 441 | 441 | 5 |
|
| newEpoch | 441 | 441 | 441 | 441 | 5 |
|
||||||
| owner | 2432 | 2432 | 2432 | 2432 | 13 |
|
| owner | 2432 | 2432 | 2432 | 2432 | 13 |
|
||||||
| pendingMPToBeMinted | 364 | 364 | 364 | 364 | 46432 |
|
| pendingMPToBeMinted | 363 | 363 | 363 | 363 | 46424 |
|
||||||
| pendingReward | 386 | 1420 | 2386 | 2386 | 29 |
|
| pendingReward | 408 | 1442 | 2408 | 2408 | 29 |
|
||||||
| previousManager | 275 | 275 | 275 | 275 | 13 |
|
| previousManager | 275 | 275 | 275 | 275 | 13 |
|
||||||
| setVault | 46239 | 46239 | 46239 | 46239 | 139 |
|
| setTrustedCodehash | 47960 | 47960 | 47960 | 47960 | 139 |
|
||||||
| stake | 23983 | 23983 | 23983 | 23983 | 1 |
|
| stake | 23983 | 23983 | 23983 | 23983 | 1 |
|
||||||
| stakeRewardEstimate | 436 | 2345 | 2436 | 2436 | 22 |
|
| stakedToken | 272 | 272 | 272 | 272 | 696 |
|
||||||
| stakedToken | 295 | 295 | 295 | 295 | 696 |
|
| startMigration | 103602 | 103610 | 103614 | 103614 | 3 |
|
||||||
| startMigration | 103580 | 103588 | 103592 | 103592 | 3 |
|
|
||||||
| startTime | 306 | 306 | 306 | 306 | 21 |
|
| startTime | 306 | 306 | 306 | 306 | 21 |
|
||||||
| totalSupply | 762 | 1943 | 2762 | 2762 | 22 |
|
| totalSupply | 784 | 1965 | 2784 | 2784 | 22 |
|
||||||
| totalSupplyBalance | 407 | 1807 | 2407 | 2407 | 20 |
|
| totalSupplyBalance | 407 | 1807 | 2407 | 2407 | 20 |
|
||||||
| totalSupplyMP | 362 | 362 | 362 | 2362 | 46453 |
|
| totalSupplyMP | 384 | 384 | 384 | 2384 | 46445 |
|
||||||
| unstake | 23819 | 23819 | 23819 | 23819 | 1 |
|
| unstake | 23841 | 23841 | 23841 | 23841 | 1 |
|
||||||
|
|
||||||
|
|
||||||
| contracts/StakeManager.sol:StakeRewardEstimate contract | | | | | |
|
|
||||||
|---------------------------------------------------------|-----------------|-------|--------|-------|---------|
|
|
||||||
| Deployment Cost | Deployment Size | | | | |
|
|
||||||
| 0 | 0 | | | | |
|
|
||||||
| Function Name | min | avg | median | max | # calls |
|
|
||||||
| getExpiredMP | 2427 | 2427 | 2427 | 2427 | 23725 |
|
|
||||||
| transferOwnership | 28533 | 28533 | 28533 | 28533 | 1 |
|
|
||||||
|
|
||||||
|
|
||||||
| contracts/StakeVault.sol:StakeVault contract | | | | | |
|
| contracts/StakeVault.sol:StakeVault contract | | | | | |
|
||||||
|
@ -53,13 +44,13 @@
|
||||||
| Deployment Cost | Deployment Size | | | | |
|
| Deployment Cost | Deployment Size | | | | |
|
||||||
| 0 | 0 | | | | |
|
| 0 | 0 | | | | |
|
||||||
| Function Name | min | avg | median | max | # calls |
|
| Function Name | min | avg | median | max | # calls |
|
||||||
| acceptMigration | 35280 | 35280 | 35280 | 35280 | 2 |
|
| acceptMigration | 35311 | 35311 | 35311 | 35311 | 2 |
|
||||||
| leave | 35266 | 35266 | 35266 | 35266 | 1 |
|
| leave | 35297 | 35297 | 35297 | 35297 | 1 |
|
||||||
| lock | 43329 | 96146 | 64421 | 204745 | 7 |
|
| lock | 43285 | 96103 | 64379 | 204703 | 7 |
|
||||||
| owner | 362 | 362 | 362 | 362 | 679 |
|
| owner | 362 | 362 | 362 | 362 | 679 |
|
||||||
| stake | 27265 | 282079 | 265719 | 351866 | 684 |
|
| stake | 27265 | 282007 | 265700 | 351859 | 684 |
|
||||||
| stakedToken | 212 | 212 | 212 | 212 | 2 |
|
| stakedToken | 212 | 212 | 212 | 212 | 2 |
|
||||||
| unstake | 40167 | 95818 | 78688 | 233549 | 11 |
|
| unstake | 40180 | 97074 | 78700 | 233556 | 11 |
|
||||||
|
|
||||||
|
|
||||||
| contracts/VaultFactory.sol:VaultFactory contract | | | | | |
|
| contracts/VaultFactory.sol:VaultFactory contract | | | | | |
|
||||||
|
@ -67,34 +58,43 @@
|
||||||
| Deployment Cost | Deployment Size | | | | |
|
| Deployment Cost | Deployment Size | | | | |
|
||||||
| 0 | 0 | | | | |
|
| 0 | 0 | | | | |
|
||||||
| Function Name | min | avg | median | max | # calls |
|
| Function Name | min | avg | median | max | # calls |
|
||||||
| createVault | 696553 | 696553 | 696553 | 696553 | 683 |
|
| createVault | 696530 | 696530 | 696530 | 696530 | 683 |
|
||||||
| setStakeManager | 23710 | 26669 | 26076 | 30222 | 3 |
|
| setStakeManager | 23710 | 26669 | 26076 | 30222 | 3 |
|
||||||
| stakeManager | 368 | 1868 | 2368 | 2368 | 4 |
|
| stakeManager | 368 | 1868 | 2368 | 2368 | 4 |
|
||||||
|
|
||||||
|
|
||||||
|
| contracts/storage/ExpiredStakeStorage.sol:ExpiredStakeStorage contract | | | | | |
|
||||||
|
|------------------------------------------------------------------------|-----------------|-------|--------|-------|---------|
|
||||||
|
| Deployment Cost | Deployment Size | | | | |
|
||||||
|
| 0 | 0 | | | | |
|
||||||
|
| Function Name | min | avg | median | max | # calls |
|
||||||
|
| getExpiredMP | 2427 | 2427 | 2427 | 2427 | 23721 |
|
||||||
|
| transferOwnership | 28533 | 28533 | 28533 | 28533 | 1 |
|
||||||
|
|
||||||
|
|
||||||
| lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol:ERC20 contract | | | | | |
|
| lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol:ERC20 contract | | | | | |
|
||||||
|---------------------------------------------------------------------------|-----------------|-------|--------|-------|---------|
|
|---------------------------------------------------------------------------|-----------------|-------|--------|-------|---------|
|
||||||
| Deployment Cost | Deployment Size | | | | |
|
| Deployment Cost | Deployment Size | | | | |
|
||||||
| 0 | 0 | | | | |
|
| 0 | 0 | | | | |
|
||||||
| Function Name | min | avg | median | max | # calls |
|
| Function Name | min | avg | median | max | # calls |
|
||||||
| approve | 46175 | 46239 | 46199 | 46367 | 679 |
|
| approve | 46175 | 46238 | 46199 | 46367 | 679 |
|
||||||
| balanceOf | 561 | 2107 | 2561 | 2561 | 30744 |
|
| balanceOf | 561 | 2107 | 2561 | 2561 | 30740 |
|
||||||
|
|
||||||
|
|
||||||
| script/Deploy.s.sol:Deploy contract | | | | | |
|
| script/Deploy.s.sol:Deploy contract | | | | | |
|
||||||
|-------------------------------------|-----------------|---------|---------|---------|---------|
|
|-------------------------------------|-----------------|---------|---------|---------|---------|
|
||||||
| Deployment Cost | Deployment Size | | | | |
|
| Deployment Cost | Deployment Size | | | | |
|
||||||
| 6118940 | 29538 | | | | |
|
| 6142896 | 29649 | | | | |
|
||||||
| Function Name | min | avg | median | max | # calls |
|
| Function Name | min | avg | median | max | # calls |
|
||||||
| run | 5316305 | 5316305 | 5316305 | 5316305 | 66 |
|
| run | 5338557 | 5338557 | 5338557 | 5338557 | 66 |
|
||||||
|
|
||||||
|
|
||||||
| script/DeployMigrationStakeManager.s.sol:DeployMigrationStakeManager contract | | | | | |
|
| script/DeployMigrationStakeManager.s.sol:DeployMigrationStakeManager contract | | | | | |
|
||||||
|-------------------------------------------------------------------------------|-----------------|---------|---------|---------|---------|
|
|-------------------------------------------------------------------------------|-----------------|---------|---------|---------|---------|
|
||||||
| Deployment Cost | Deployment Size | | | | |
|
| Deployment Cost | Deployment Size | | | | |
|
||||||
| 3282471 | 16306 | | | | |
|
| 3306430 | 16417 | | | | |
|
||||||
| Function Name | min | avg | median | max | # calls |
|
| Function Name | min | avg | median | max | # calls |
|
||||||
| run | 2302633 | 2302633 | 2302633 | 2302633 | 19 |
|
| run | 2324886 | 2324886 | 2324886 | 2324886 | 19 |
|
||||||
|
|
||||||
|
|
||||||
| script/DeploymentConfig.s.sol:DeploymentConfig contract | | | | | |
|
| script/DeploymentConfig.s.sol:DeploymentConfig contract | | | | | |
|
||||||
|
@ -117,9 +117,9 @@
|
||||||
| test/script/DeployBroken.s.sol:DeployBroken contract | | | | | |
|
| test/script/DeployBroken.s.sol:DeployBroken contract | | | | | |
|
||||||
|------------------------------------------------------|-----------------|---------|---------|---------|---------|
|
|------------------------------------------------------|-----------------|---------|---------|---------|---------|
|
||||||
| Deployment Cost | Deployment Size | | | | |
|
| Deployment Cost | Deployment Size | | | | |
|
||||||
| 4803693 | 23336 | | | | |
|
| 4827656 | 23447 | | | | |
|
||||||
| Function Name | min | avg | median | max | # calls |
|
| Function Name | min | avg | median | max | # calls |
|
||||||
| run | 4156127 | 4156127 | 4156127 | 4156127 | 1 |
|
| run | 4178379 | 4178379 | 4178379 | 4178379 | 1 |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
118
.gas-snapshot
118
.gas-snapshot
|
@ -1,67 +1,67 @@
|
||||||
CreateVaultTest:testDeployment() (gas: 9774)
|
CreateVaultTest:testDeployment() (gas: 9774)
|
||||||
CreateVaultTest:test_createVault() (gas: 714022)
|
CreateVaultTest:test_createVault() (gas: 713999)
|
||||||
ExecuteAccountTest:testDeployment() (gas: 28785)
|
ExecuteAccountTest:testDeployment() (gas: 28828)
|
||||||
ExecuteAccountTest:test_ExecuteAccountLimit() (gas: 1580255)
|
ExecuteAccountTest:test_ExecuteAccountLimit() (gas: 1582018)
|
||||||
ExecuteAccountTest:test_ExecuteAccountMintMP() (gas: 5297777)
|
ExecuteAccountTest:test_ExecuteAccountMintMP() (gas: 5299985)
|
||||||
ExecuteAccountTest:test_RevertWhen_InvalidLimitEpoch() (gas: 1788412)
|
ExecuteAccountTest:test_RevertWhen_InvalidLimitEpoch() (gas: 1790139)
|
||||||
ExecuteAccountTest:test_ShouldNotMintMoreThanCap() (gas: 321397553)
|
ExecuteAccountTest:test_ShouldNotMintMoreThanCap() (gas: 321470949)
|
||||||
ExecuteEpochTest:testDeployment() (gas: 28786)
|
ExecuteEpochTest:testDeployment() (gas: 28829)
|
||||||
ExecuteEpochTest:testNewDeployment() (gas: 30858)
|
ExecuteEpochTest:testNewDeployment() (gas: 30901)
|
||||||
ExecuteEpochTest:test_ExecuteEpochExecuteAccountAfterEpochEnd() (gas: 1366211)
|
ExecuteEpochTest:test_ExecuteEpochExecuteAccountAfterEpochEnd() (gas: 1367896)
|
||||||
ExecuteEpochTest:test_ExecuteEpochExecuteAccountAfterManyEpochsJumoMany() (gas: 1385045)
|
ExecuteEpochTest:test_ExecuteEpochExecuteAccountAfterManyEpochsJumoMany() (gas: 1386983)
|
||||||
ExecuteEpochTest:test_ExecuteEpochExecuteAccountAfterManyEpochsWithBrokenTime() (gas: 1629507)
|
ExecuteEpochTest:test_ExecuteEpochExecuteAccountAfterManyEpochsWithBrokenTime() (gas: 1630994)
|
||||||
ExecuteEpochTest:test_ExecuteEpochExecuteAccountAfterManyEpochsWithBrokenTimeJumpMany() (gas: 1395200)
|
ExecuteEpochTest:test_ExecuteEpochExecuteAccountAfterManyEpochsWithBrokenTimeJumpMany() (gas: 1396698)
|
||||||
ExecuteEpochTest:test_ExecuteEpochExecuteEpochAfterEnd() (gas: 1936210)
|
ExecuteEpochTest:test_ExecuteEpochExecuteEpochAfterEnd() (gas: 1937948)
|
||||||
ExecuteEpochTest:test_ExecuteEpochExecuteEpochExecuteAccountAfterManyEpochs() (gas: 2523553)
|
ExecuteEpochTest:test_ExecuteEpochExecuteEpochExecuteAccountAfterManyEpochs() (gas: 2525682)
|
||||||
ExecuteEpochTest:test_ExecuteEpochExecuteEpochExecuteAccountAfterManyEpochsJumoMany() (gas: 1479491)
|
ExecuteEpochTest:test_ExecuteEpochExecuteEpochExecuteAccountAfterManyEpochsJumoMany() (gas: 1481437)
|
||||||
ExecuteEpochTest:test_ExecuteEpochExecuteEpochExecuteAccountAfterManyEpochsWithBrokenTime() (gas: 2533729)
|
ExecuteEpochTest:test_ExecuteEpochExecuteEpochExecuteAccountAfterManyEpochsWithBrokenTime() (gas: 2535418)
|
||||||
ExecuteEpochTest:test_ExecuteEpochExecuteEpochExecuteAccountAfterManyEpochsWithBrokenTimeJumpMany() (gas: 1489623)
|
ExecuteEpochTest:test_ExecuteEpochExecuteEpochExecuteAccountAfterManyEpochsWithBrokenTimeJumpMany() (gas: 1491129)
|
||||||
ExecuteEpochTest:test_ExecuteEpochNewEpoch() (gas: 1122339)
|
ExecuteEpochTest:test_ExecuteEpochNewEpoch() (gas: 1122427)
|
||||||
ExecuteEpochTest:test_ExecuteEpochShouldIncreaseEpoch() (gas: 92413)
|
ExecuteEpochTest:test_ExecuteEpochShouldIncreaseEpoch() (gas: 92457)
|
||||||
ExecuteEpochTest:test_ExecuteEpochShouldIncreasePendingReward() (gas: 256446)
|
ExecuteEpochTest:test_ExecuteEpochShouldIncreasePendingReward() (gas: 256428)
|
||||||
ExecuteEpochTest:test_ExecuteEpochShouldNotIncreaseEpochBeforeEnd() (gas: 38984)
|
ExecuteEpochTest:test_ExecuteEpochShouldNotIncreaseEpochBeforeEnd() (gas: 39028)
|
||||||
ExecuteEpochTest:test_ExecuteEpochShouldNotIncreaseEpochInMigration() (gas: 149638)
|
ExecuteEpochTest:test_ExecuteEpochShouldNotIncreaseEpochInMigration() (gas: 149748)
|
||||||
LeaveTest:testDeployment() (gas: 28763)
|
LeaveTest:testDeployment() (gas: 28806)
|
||||||
LeaveTest:test_RevertWhen_NoPendingMigration() (gas: 1327993)
|
LeaveTest:test_RevertWhen_NoPendingMigration() (gas: 1329762)
|
||||||
LeaveTest:test_RevertWhen_SenderIsNotVault() (gas: 31964)
|
LeaveTest:test_RevertWhen_SenderIsNotVault() (gas: 31995)
|
||||||
LockTest:testDeployment() (gas: 28763)
|
LockTest:testDeployment() (gas: 28806)
|
||||||
LockTest:test_NewLockupPeriod() (gas: 1329045)
|
LockTest:test_NewLockupPeriod() (gas: 1330751)
|
||||||
LockTest:test_RevertWhen_InvalidNewLockupPeriod() (gas: 1301374)
|
LockTest:test_RevertWhen_InvalidNewLockupPeriod() (gas: 1303059)
|
||||||
LockTest:test_RevertWhen_InvalidUpdateLockupPeriod() (gas: 1545884)
|
LockTest:test_RevertWhen_InvalidUpdateLockupPeriod() (gas: 1547562)
|
||||||
LockTest:test_RevertWhen_SenderIsNotVault() (gas: 31856)
|
LockTest:test_RevertWhen_SenderIsNotVault() (gas: 31812)
|
||||||
LockTest:test_ShouldIncreaseBonusMP() (gas: 1311575)
|
LockTest:test_ShouldIncreaseBonusMP() (gas: 1313344)
|
||||||
LockTest:test_UpdateLockupPeriod() (gas: 1634540)
|
LockTest:test_UpdateLockupPeriod() (gas: 1636200)
|
||||||
MigrateTest:testDeployment() (gas: 28763)
|
MigrateTest:testDeployment() (gas: 28806)
|
||||||
MigrateTest:test_RevertWhen_NoPendingMigration() (gas: 1292046)
|
MigrateTest:test_RevertWhen_NoPendingMigration() (gas: 1293784)
|
||||||
MigrateTest:test_RevertWhen_SenderIsNotVault() (gas: 31976)
|
MigrateTest:test_RevertWhen_SenderIsNotVault() (gas: 32007)
|
||||||
MigrationInitializeTest:testDeployment() (gas: 28763)
|
MigrationInitializeTest:testDeployment() (gas: 28806)
|
||||||
MigrationInitializeTest:test_RevertWhen_MigrationPending() (gas: 5181388)
|
MigrationInitializeTest:test_RevertWhen_MigrationPending() (gas: 5229403)
|
||||||
MigrationStakeManagerTest:testDeployment() (gas: 28763)
|
MigrationStakeManagerTest:testDeployment() (gas: 28806)
|
||||||
MigrationStakeManagerTest:testNewDeployment() (gas: 30902)
|
MigrationStakeManagerTest:testNewDeployment() (gas: 30945)
|
||||||
MigrationStakeManagerTest:test_ExecuteEpochShouldNotIncreaseEpochInMigration() (gas: 149603)
|
MigrationStakeManagerTest:test_ExecuteEpochShouldNotIncreaseEpochInMigration() (gas: 149713)
|
||||||
SetStakeManagerTest:testDeployment() (gas: 9774)
|
SetStakeManagerTest:testDeployment() (gas: 9774)
|
||||||
SetStakeManagerTest:test_RevertWhen_InvalidStakeManagerAddress() (gas: 63105)
|
SetStakeManagerTest:test_RevertWhen_InvalidStakeManagerAddress() (gas: 63105)
|
||||||
SetStakeManagerTest:test_SetStakeManager() (gas: 41301)
|
SetStakeManagerTest:test_SetStakeManager() (gas: 41301)
|
||||||
StakeManagerTest:testDeployment() (gas: 28535)
|
StakeManagerTest:testDeployment() (gas: 28578)
|
||||||
StakeTest:testDeployment() (gas: 28741)
|
StakeTest:testDeployment() (gas: 28784)
|
||||||
StakeTest:test_RevertWhen_InvalidLockupPeriod() (gas: 1080635)
|
StakeTest:test_RevertWhen_InvalidLockupPeriod() (gas: 1082353)
|
||||||
StakeTest:test_RevertWhen_Restake() (gas: 1316847)
|
StakeTest:test_RevertWhen_Restake() (gas: 1318545)
|
||||||
StakeTest:test_RevertWhen_RestakeWithLock() (gas: 1320861)
|
StakeTest:test_RevertWhen_RestakeWithLock() (gas: 1322559)
|
||||||
StakeTest:test_RevertWhen_SenderIsNotVault() (gas: 32018)
|
StakeTest:test_RevertWhen_SenderIsNotVault() (gas: 32018)
|
||||||
StakeTest:test_RevertWhen_StakeIsTooLow() (gas: 817762)
|
StakeTest:test_RevertWhen_StakeIsTooLow() (gas: 819467)
|
||||||
StakeTest:test_RevertWhen_StakeTokenTransferFails() (gas: 211363)
|
StakeTest:test_RevertWhen_StakeTokenTransferFails() (gas: 211363)
|
||||||
StakeTest:test_StakeWithLockBonusMP() (gas: 2357564)
|
StakeTest:test_StakeWithLockBonusMP() (gas: 2359257)
|
||||||
StakeTest:test_StakeWithoutLockUpTimeMintsMultiplierPoints() (gas: 1322003)
|
StakeTest:test_StakeWithoutLockUpTimeMintsMultiplierPoints() (gas: 1314761)
|
||||||
StakedTokenTest:testStakeToken() (gas: 7616)
|
StakedTokenTest:testStakeToken() (gas: 7616)
|
||||||
UnstakeTest:testDeployment() (gas: 28785)
|
UnstakeTest:testDeployment() (gas: 28828)
|
||||||
UnstakeTest:test_RevertWhen_AmountMoreThanBalance() (gas: 1297407)
|
UnstakeTest:test_RevertWhen_AmountMoreThanBalance() (gas: 1299127)
|
||||||
UnstakeTest:test_RevertWhen_FundsLocked() (gas: 1342144)
|
UnstakeTest:test_RevertWhen_FundsLocked() (gas: 1343877)
|
||||||
UnstakeTest:test_RevertWhen_SenderIsNotVault() (gas: 31857)
|
UnstakeTest:test_RevertWhen_SenderIsNotVault() (gas: 31879)
|
||||||
UnstakeTest:test_UnstakeShouldBurnMultiplierPoints() (gas: 6526945)
|
UnstakeTest:test_UnstakeShouldBurnMultiplierPoints() (gas: 6529254)
|
||||||
UnstakeTest:test_UnstakeShouldReturnFund_NoLockUp() (gas: 1319573)
|
UnstakeTest:test_UnstakeShouldReturnFund_NoLockUp() (gas: 1321289)
|
||||||
UnstakeTest:test_UnstakeShouldReturnFund_WithLockUp() (gas: 1440205)
|
UnstakeTest:test_UnstakeShouldReturnFund_WithLockUp() (gas: 1441917)
|
||||||
UserFlowsTest:testDeployment() (gas: 28763)
|
UserFlowsTest:testDeployment() (gas: 28806)
|
||||||
UserFlowsTest:test_PendingMPToBeMintedCannotBeGreaterThanTotalSupplyMP(uint8,uint128) (runs: 106, μ: 131402731, ~: 130856521)
|
UserFlowsTest:test_PendingMPToBeMintedCannotBeGreaterThanTotalSupplyMP(uint8,uint128) (runs: 106, μ: 131427031, ~: 130900495)
|
||||||
UserFlowsTest:test_StakeWithLockUpTimeLocksStake() (gas: 1481301)
|
UserFlowsTest:test_StakeWithLockUpTimeLocksStake() (gas: 1483026)
|
||||||
UserFlowsTest:test_StakedSupplyShouldIncreaseAndDecreaseAgain() (gas: 2494771)
|
UserFlowsTest:test_StakedSupplyShouldIncreaseAndDecreaseAgain() (gas: 2496473)
|
||||||
VaultFactoryTest:testDeployment() (gas: 9774)
|
VaultFactoryTest:testDeployment() (gas: 9774)
|
|
@ -43,7 +43,7 @@ To install the system on the blockchain, follow these steps:
|
||||||
|
|
||||||
1. **Deploy StakeManager**: Begin by deploying the `StakeManager` contract.
|
1. **Deploy StakeManager**: Begin by deploying the `StakeManager` contract.
|
||||||
2. **Deploy Sample VaultManager**: Next, deploy a sample `VaultManager` contract on any chain (this can be on a development network or a testnet).
|
2. **Deploy Sample VaultManager**: Next, deploy a sample `VaultManager` contract on any chain (this can be on a development network or a testnet).
|
||||||
3. **Configure Codehash**: Once the `VaultManager` is deployed, retrieve its codehash and configure it in the `StakeManager` using the `setVault(bytes32)` function.
|
3. **Configure Codehash**: Once the `VaultManager` is deployed, retrieve its codehash and configure it in the `StakeManager` using the `setTrustedCodehash(bytes32, bool)` function.
|
||||||
4. **Optional - Use VaultFactory**: The `VaultFactory` contract can be optionally used to optimize gas costs during deployments and to facilitate the creation of valid vaults.
|
4. **Optional - Use VaultFactory**: The `VaultFactory` contract can be optionally used to optimize gas costs during deployments and to facilitate the creation of valid vaults.
|
||||||
|
|
||||||
### Staking Tokens
|
### Staking Tokens
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"files":
|
"files":
|
||||||
["contracts/StakeManager.sol",
|
["contracts/StakeManager.sol",
|
||||||
"certora/helpers/StakeRewardEstimateA.sol",
|
"certora/helpers/ExpiredStakeStorageA.sol",
|
||||||
"certora/helpers/ERC20A.sol"
|
"certora/helpers/ERC20A.sol"
|
||||||
],
|
],
|
||||||
"link" : [
|
"link" : [
|
||||||
"StakeManager:stakedToken=ERC20A",
|
"StakeManager:stakedToken=ERC20A",
|
||||||
"StakeManager:stakeRewardEstimate=StakeRewardEstimateA"
|
"StakeManager:expiredStakeStorage=ExpiredStakeStorageA"
|
||||||
],
|
],
|
||||||
"msg": "Verifying StakeManager.sol",
|
"msg": "Verifying StakeManager.sol",
|
||||||
"rule_sanity": "basic",
|
"rule_sanity": "basic",
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
"files":
|
"files":
|
||||||
["contracts/StakeManager.sol",
|
["contracts/StakeManager.sol",
|
||||||
"certora/helpers/ERC20A.sol",
|
"certora/helpers/ERC20A.sol",
|
||||||
"certora/helpers/StakeRewardEstimateA.sol"
|
"certora/helpers/ExpiredStakeStorageA.sol"
|
||||||
],
|
],
|
||||||
"link" : [
|
"link" : [
|
||||||
"StakeManager:stakedToken=ERC20A",
|
"StakeManager:stakedToken=ERC20A",
|
||||||
"StakeManager:stakeRewardEstimate=StakeRewardEstimateA"
|
"StakeManager:expiredStakeStorage=ExpiredStakeStorageA"
|
||||||
],
|
],
|
||||||
"msg": "Verifying StakeManager ProcessAccount",
|
"msg": "Verifying StakeManager ProcessAccount",
|
||||||
"rule_sanity": "basic",
|
"rule_sanity": "basic",
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
"files":
|
"files":
|
||||||
[ "contracts/StakeManager.sol",
|
[ "contracts/StakeManager.sol",
|
||||||
"certora/harness/StakeManagerNew.sol",
|
"certora/harness/StakeManagerNew.sol",
|
||||||
"certora/helpers/StakeRewardEstimateA.sol",
|
"certora/helpers/ExpiredStakeStorageA.sol",
|
||||||
"certora/helpers/ERC20A.sol"
|
"certora/helpers/ERC20A.sol"
|
||||||
],
|
],
|
||||||
"link" : [
|
"link" : [
|
||||||
"StakeManager:stakedToken=ERC20A",
|
"StakeManager:stakedToken=ERC20A",
|
||||||
"StakeManager:stakeRewardEstimate=StakeRewardEstimateA",
|
"StakeManager:expiredStakeStorage=ExpiredStakeStorageA",
|
||||||
],
|
],
|
||||||
"msg": "Verifying StakeManager.sol",
|
"msg": "Verifying StakeManager.sol",
|
||||||
"rule_sanity": "basic",
|
"rule_sanity": "basic",
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
"files": [
|
"files": [
|
||||||
"contracts/StakeManager.sol",
|
"contracts/StakeManager.sol",
|
||||||
"contracts/StakeVault.sol",
|
"contracts/StakeVault.sol",
|
||||||
"certora/helpers/StakeRewardEstimateA.sol",
|
"certora/helpers/ExpiredStakeStorageA.sol",
|
||||||
"certora/helpers/ERC20A.sol"
|
"certora/helpers/ERC20A.sol"
|
||||||
],
|
],
|
||||||
"link" : [
|
"link" : [
|
||||||
"StakeVault:STAKED_TOKEN=ERC20A",
|
"StakeVault:STAKED_TOKEN=ERC20A",
|
||||||
"StakeManager:stakedToken=ERC20A",
|
"StakeManager:stakedToken=ERC20A",
|
||||||
"StakeManager:stakeRewardEstimate=StakeRewardEstimateA",
|
"StakeManager:expiredStakeStorage=ExpiredStakeStorageA",
|
||||||
"StakeVault:stakeManager=StakeManager"
|
"StakeVault:stakeManager=StakeManager"
|
||||||
],
|
],
|
||||||
"msg": "Verifying StakeVault.sol",
|
"msg": "Verifying StakeVault.sol",
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
pragma solidity ^0.8.19;
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
import { StakeRewardEstimate } from "./../../contracts/StakeManager.sol";
|
import { ExpiredStakeStorage } from "./../../contracts/StakeManager.sol";
|
||||||
|
|
||||||
contract StakeRewardEstimateA is StakeRewardEstimate {}
|
|
||||||
|
|
||||||
|
contract ExpiredStakeStorageA is ExpiredStakeStorage { }
|
||||||
|
|
|
@ -198,7 +198,7 @@ rule epochOnlyIncreases(method f) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//TODO codehash / isVault
|
//TODO codehash / isTrustedCodehash
|
||||||
/*
|
/*
|
||||||
ghost mapping(address => bytes32) codehash;
|
ghost mapping(address => bytes32) codehash;
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ rule checksCodeHash(method f) filtered {
|
||||||
} {
|
} {
|
||||||
env e;
|
env e;
|
||||||
|
|
||||||
bool isWhitelisted = isVault(codehash[e.msg.sender]);
|
bool isWhitelisted = isTrustedCodehash(codehash[e.msg.sender]);
|
||||||
f(e);
|
f(e);
|
||||||
|
|
||||||
assert isWhitelisted;
|
assert isWhitelisted;
|
||||||
|
|
|
@ -3,33 +3,13 @@
|
||||||
pragma solidity ^0.8.18;
|
pragma solidity ^0.8.18;
|
||||||
|
|
||||||
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
||||||
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
|
|
||||||
import { Math } from "@openzeppelin/contracts/utils/math/Math.sol";
|
import { Math } from "@openzeppelin/contracts/utils/math/Math.sol";
|
||||||
|
|
||||||
|
import { TrustedCodehashAccess } from "./access/TrustedCodehashAccess.sol";
|
||||||
|
import { ExpiredStakeStorage } from "./storage/ExpiredStakeStorage.sol";
|
||||||
import { StakeVault } from "./StakeVault.sol";
|
import { StakeVault } from "./StakeVault.sol";
|
||||||
|
|
||||||
contract StakeRewardEstimate is Ownable {
|
contract StakeManager is TrustedCodehashAccess {
|
||||||
mapping(uint256 epochId => uint256 balance) public expiredMPPerEpoch;
|
|
||||||
|
|
||||||
function getExpiredMP(uint256 epochId) public view returns (uint256) {
|
|
||||||
return expiredMPPerEpoch[epochId];
|
|
||||||
}
|
|
||||||
|
|
||||||
function incrementExpiredMP(uint256 epochId, uint256 amount) public onlyOwner {
|
|
||||||
expiredMPPerEpoch[epochId] += amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
function decrementExpiredMP(uint256 epochId, uint256 amount) public onlyOwner {
|
|
||||||
expiredMPPerEpoch[epochId] -= amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteExpiredMP(uint256 epochId) public onlyOwner {
|
|
||||||
delete expiredMPPerEpoch[epochId];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
contract StakeManager is Ownable {
|
|
||||||
error StakeManager__SenderIsNotVault();
|
|
||||||
error StakeManager__FundsLocked();
|
error StakeManager__FundsLocked();
|
||||||
error StakeManager__InvalidLockTime();
|
error StakeManager__InvalidLockTime();
|
||||||
error StakeManager__NoPendingMigration();
|
error StakeManager__NoPendingMigration();
|
||||||
|
@ -70,7 +50,6 @@ contract StakeManager is Ownable {
|
||||||
|
|
||||||
mapping(address index => Account value) public accounts;
|
mapping(address index => Account value) public accounts;
|
||||||
mapping(uint256 index => Epoch value) public epochs;
|
mapping(uint256 index => Epoch value) public epochs;
|
||||||
mapping(bytes32 codehash => bool approved) public isVault;
|
|
||||||
|
|
||||||
uint256 public currentEpoch;
|
uint256 public currentEpoch;
|
||||||
uint256 public pendingReward;
|
uint256 public pendingReward;
|
||||||
|
@ -81,7 +60,7 @@ contract StakeManager is Ownable {
|
||||||
uint256 public totalSupplyBalance;
|
uint256 public totalSupplyBalance;
|
||||||
uint256 public totalMPPerEpoch;
|
uint256 public totalMPPerEpoch;
|
||||||
|
|
||||||
StakeRewardEstimate public stakeRewardEstimate;
|
ExpiredStakeStorage public expiredStakeStorage;
|
||||||
|
|
||||||
uint256 public currentEpochTotalExpiredMP;
|
uint256 public currentEpochTotalExpiredMP;
|
||||||
|
|
||||||
|
@ -89,16 +68,6 @@ contract StakeManager is Ownable {
|
||||||
StakeManager public immutable previousManager;
|
StakeManager public immutable previousManager;
|
||||||
ERC20 public immutable stakedToken;
|
ERC20 public immutable stakedToken;
|
||||||
|
|
||||||
/**
|
|
||||||
* @notice Only callable by vaults
|
|
||||||
*/
|
|
||||||
modifier onlyVault() {
|
|
||||||
if (!isVault[msg.sender.codehash]) {
|
|
||||||
revert StakeManager__SenderIsNotVault();
|
|
||||||
}
|
|
||||||
_;
|
|
||||||
}
|
|
||||||
|
|
||||||
modifier onlyAccountInitialized(address account) {
|
modifier onlyAccountInitialized(address account) {
|
||||||
if (accounts[account].lockUntil == 0) {
|
if (accounts[account].lockUntil == 0) {
|
||||||
revert StakeManager__AccountNotInitialized();
|
revert StakeManager__AccountNotInitialized();
|
||||||
|
@ -144,10 +113,10 @@ contract StakeManager is Ownable {
|
||||||
uint256 tempCurrentEpoch = currentEpoch;
|
uint256 tempCurrentEpoch = currentEpoch;
|
||||||
while (tempCurrentEpoch < _limitEpoch) {
|
while (tempCurrentEpoch < _limitEpoch) {
|
||||||
Epoch storage thisEpoch = epochs[tempCurrentEpoch];
|
Epoch storage thisEpoch = epochs[tempCurrentEpoch];
|
||||||
uint256 expiredMP = stakeRewardEstimate.getExpiredMP(tempCurrentEpoch);
|
uint256 expiredMP = expiredStakeStorage.getExpiredMP(tempCurrentEpoch);
|
||||||
if (expiredMP > 0) {
|
if (expiredMP > 0) {
|
||||||
totalMPPerEpoch -= expiredMP;
|
totalMPPerEpoch -= expiredMP;
|
||||||
stakeRewardEstimate.deleteExpiredMP(tempCurrentEpoch);
|
expiredStakeStorage.deleteExpiredMP(tempCurrentEpoch);
|
||||||
}
|
}
|
||||||
thisEpoch.estimatedMP = totalMPPerEpoch - currentEpochTotalExpiredMP;
|
thisEpoch.estimatedMP = totalMPPerEpoch - currentEpochTotalExpiredMP;
|
||||||
delete currentEpochTotalExpiredMP;
|
delete currentEpochTotalExpiredMP;
|
||||||
|
@ -171,9 +140,9 @@ contract StakeManager is Ownable {
|
||||||
previousManager = StakeManager(_previousManager);
|
previousManager = StakeManager(_previousManager);
|
||||||
stakedToken = ERC20(_stakedToken);
|
stakedToken = ERC20(_stakedToken);
|
||||||
if (address(previousManager) != address(0)) {
|
if (address(previousManager) != address(0)) {
|
||||||
stakeRewardEstimate = previousManager.stakeRewardEstimate();
|
expiredStakeStorage = previousManager.expiredStakeStorage();
|
||||||
} else {
|
} else {
|
||||||
stakeRewardEstimate = new StakeRewardEstimate();
|
expiredStakeStorage = new ExpiredStakeStorage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,7 +155,7 @@ contract StakeManager is Ownable {
|
||||||
* @dev Reverts when account has already staked funds.
|
* @dev Reverts when account has already staked funds.
|
||||||
* @dev Reverts when amount staked results in less than 1 MP per epoch.
|
* @dev Reverts when amount staked results in less than 1 MP per epoch.
|
||||||
*/
|
*/
|
||||||
function stake(uint256 _amount, uint256 _secondsToLock) external onlyVault noPendingMigration {
|
function stake(uint256 _amount, uint256 _secondsToLock) external onlyTrustedCodehash noPendingMigration {
|
||||||
finalizeEpoch(newEpoch());
|
finalizeEpoch(newEpoch());
|
||||||
Account storage account = accounts[msg.sender];
|
Account storage account = accounts[msg.sender];
|
||||||
if (account.balance > 0 || account.lockUntil != 0) {
|
if (account.balance > 0 || account.lockUntil != 0) {
|
||||||
|
@ -219,14 +188,19 @@ contract StakeManager is Ownable {
|
||||||
totalSupplyBalance += _amount;
|
totalSupplyBalance += _amount;
|
||||||
currentEpochTotalExpiredMP += currentEpochExpiredMP;
|
currentEpochTotalExpiredMP += currentEpochExpiredMP;
|
||||||
totalMPPerEpoch += mpPerEpoch;
|
totalMPPerEpoch += mpPerEpoch;
|
||||||
stakeRewardEstimate.incrementExpiredMP(mpLimitEpoch, lastEpochAmountToMint);
|
expiredStakeStorage.incrementExpiredMP(mpLimitEpoch, lastEpochAmountToMint);
|
||||||
stakeRewardEstimate.incrementExpiredMP(mpLimitEpoch + 1, mpPerEpoch - lastEpochAmountToMint);
|
expiredStakeStorage.incrementExpiredMP(mpLimitEpoch + 1, mpPerEpoch - lastEpochAmountToMint);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* leaves the staking pool and withdraws all funds;
|
* leaves the staking pool and withdraws all funds;
|
||||||
*/
|
*/
|
||||||
function unstake(uint256 _amount) external onlyVault onlyAccountInitialized(msg.sender) noPendingMigration {
|
function unstake(uint256 _amount)
|
||||||
|
external
|
||||||
|
onlyTrustedCodehash
|
||||||
|
onlyAccountInitialized(msg.sender)
|
||||||
|
noPendingMigration
|
||||||
|
{
|
||||||
finalizeEpoch(newEpoch());
|
finalizeEpoch(newEpoch());
|
||||||
Account storage account = accounts[msg.sender];
|
Account storage account = accounts[msg.sender];
|
||||||
if (_amount > account.balance) {
|
if (_amount > account.balance) {
|
||||||
|
@ -241,7 +215,7 @@ contract StakeManager is Ownable {
|
||||||
uint256 reducedInitialMP = Math.mulDiv(_amount, account.bonusMP, account.balance);
|
uint256 reducedInitialMP = Math.mulDiv(_amount, account.bonusMP, account.balance);
|
||||||
|
|
||||||
uint256 mpPerEpoch = _getMPToMint(account.balance, EPOCH_SIZE);
|
uint256 mpPerEpoch = _getMPToMint(account.balance, EPOCH_SIZE);
|
||||||
stakeRewardEstimate.decrementExpiredMP(account.mpLimitEpoch, mpPerEpoch);
|
expiredStakeStorage.decrementExpiredMP(account.mpLimitEpoch, mpPerEpoch);
|
||||||
if (account.mpLimitEpoch < currentEpoch) {
|
if (account.mpLimitEpoch < currentEpoch) {
|
||||||
totalMPPerEpoch -= mpPerEpoch;
|
totalMPPerEpoch -= mpPerEpoch;
|
||||||
}
|
}
|
||||||
|
@ -263,7 +237,7 @@ contract StakeManager is Ownable {
|
||||||
*/
|
*/
|
||||||
function lock(uint256 _secondsToIncreaseLock)
|
function lock(uint256 _secondsToIncreaseLock)
|
||||||
external
|
external
|
||||||
onlyVault
|
onlyTrustedCodehash
|
||||||
onlyAccountInitialized(msg.sender)
|
onlyAccountInitialized(msg.sender)
|
||||||
noPendingMigration
|
noPendingMigration
|
||||||
{
|
{
|
||||||
|
@ -331,14 +305,6 @@ contract StakeManager is Ownable {
|
||||||
_processAccount(accounts[_vault], _limitEpoch);
|
_processAccount(accounts[_vault], _limitEpoch);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @notice Enables a contract class to interact with staking functions
|
|
||||||
* @param _codehash bytecode hash of contract
|
|
||||||
*/
|
|
||||||
function setVault(bytes32 _codehash) external onlyOwner {
|
|
||||||
isVault[_codehash] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @notice starts migration to new StakeManager
|
* @notice starts migration to new StakeManager
|
||||||
* @param _migration new StakeManager
|
* @param _migration new StakeManager
|
||||||
|
@ -350,7 +316,7 @@ contract StakeManager is Ownable {
|
||||||
}
|
}
|
||||||
migration = _migration;
|
migration = _migration;
|
||||||
stakedToken.transfer(address(migration), epochReward());
|
stakedToken.transfer(address(migration), epochReward());
|
||||||
stakeRewardEstimate.transferOwnership(address(_migration));
|
expiredStakeStorage.transferOwnership(address(_migration));
|
||||||
migration.migrationInitialize(
|
migration.migrationInitialize(
|
||||||
currentEpoch,
|
currentEpoch,
|
||||||
totalSupplyMP,
|
totalSupplyMP,
|
||||||
|
@ -410,7 +376,7 @@ contract StakeManager is Ownable {
|
||||||
*/
|
*/
|
||||||
function migrateTo(bool _acceptMigration)
|
function migrateTo(bool _acceptMigration)
|
||||||
external
|
external
|
||||||
onlyVault
|
onlyTrustedCodehash
|
||||||
onlyAccountInitialized(msg.sender)
|
onlyAccountInitialized(msg.sender)
|
||||||
onlyPendingMigration
|
onlyPendingMigration
|
||||||
returns (StakeManager newManager)
|
returns (StakeManager newManager)
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
pragma solidity ^0.8.18;
|
||||||
|
|
||||||
|
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title TrustedCodehashAccess
|
||||||
|
* @author Ricardo Guilherme Schmidt <ricardo3@status.im>
|
||||||
|
* @notice Ensures that only specific contract bytecode hashes are trusted to
|
||||||
|
* interact with the functions using the `onlyTrustedCodehash` modifier.
|
||||||
|
*/
|
||||||
|
contract TrustedCodehashAccess is Ownable {
|
||||||
|
error TrustedCodehashAccess__UnauthorizedCodehash();
|
||||||
|
|
||||||
|
event TrustedCodehashUpdated(bytes32 indexed codehash, bool trusted);
|
||||||
|
|
||||||
|
mapping(bytes32 codehash => bool permission) private trustedCodehashes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @notice Restricts access based on the codehash of the caller.
|
||||||
|
* Only contracts with trusted codehashes can execute functions using this modifier.
|
||||||
|
*/
|
||||||
|
modifier onlyTrustedCodehash() {
|
||||||
|
bytes32 codehash = msg.sender.codehash;
|
||||||
|
if (!trustedCodehashes[codehash]) {
|
||||||
|
revert TrustedCodehashAccess__UnauthorizedCodehash();
|
||||||
|
}
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @notice Allows the owner to set or update the trust status for a contract's codehash.
|
||||||
|
* @dev Emits the `TrustedCodehashUpdated` event whenever a codehash is updated.
|
||||||
|
* @param _codehash The bytecode hash of the contract.
|
||||||
|
* @param _trusted Boolean flag to designate the contract as trusted or not.
|
||||||
|
*/
|
||||||
|
function setTrustedCodehash(bytes32 _codehash, bool _trusted) external onlyOwner {
|
||||||
|
trustedCodehashes[_codehash] = _trusted;
|
||||||
|
emit TrustedCodehashUpdated(_codehash, _trusted);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @notice Checks if a contract's codehash is trusted to interact with protected functions.
|
||||||
|
* @param _codehash The bytecode hash of the contract.
|
||||||
|
* @return bool True if the codehash is trusted, false otherwise.
|
||||||
|
*/
|
||||||
|
function isTrustedCodehash(bytes32 _codehash) external view returns (bool) {
|
||||||
|
return trustedCodehashes[_codehash];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
pragma solidity ^0.8.18;
|
||||||
|
|
||||||
|
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
|
||||||
|
|
||||||
|
contract ExpiredStakeStorage is Ownable {
|
||||||
|
mapping(uint256 epochId => uint256 balance) public expiredMPPerEpoch;
|
||||||
|
|
||||||
|
function getExpiredMP(uint256 epochId) public view returns (uint256) {
|
||||||
|
return expiredMPPerEpoch[epochId];
|
||||||
|
}
|
||||||
|
|
||||||
|
function incrementExpiredMP(uint256 epochId, uint256 amount) public onlyOwner {
|
||||||
|
expiredMPPerEpoch[epochId] += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
function decrementExpiredMP(uint256 epochId, uint256 amount) public onlyOwner {
|
||||||
|
expiredMPPerEpoch[epochId] -= amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteExpiredMP(uint256 epochId) public onlyOwner {
|
||||||
|
delete expiredMPPerEpoch[epochId];
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ import { Test, console } from "forge-std/Test.sol";
|
||||||
import { Deploy } from "../script/Deploy.s.sol";
|
import { Deploy } from "../script/Deploy.s.sol";
|
||||||
import { DeployMigrationStakeManager } from "../script/DeployMigrationStakeManager.s.sol";
|
import { DeployMigrationStakeManager } from "../script/DeployMigrationStakeManager.s.sol";
|
||||||
import { DeploymentConfig } from "../script/DeploymentConfig.s.sol";
|
import { DeploymentConfig } from "../script/DeploymentConfig.s.sol";
|
||||||
import { StakeManager, StakeRewardEstimate } from "../contracts/StakeManager.sol";
|
import { TrustedCodehashAccess, StakeManager, ExpiredStakeStorage } from "../contracts/StakeManager.sol";
|
||||||
import { StakeVault } from "../contracts/StakeVault.sol";
|
import { StakeVault } from "../contracts/StakeVault.sol";
|
||||||
import { VaultFactory } from "../contracts/VaultFactory.sol";
|
import { VaultFactory } from "../contracts/VaultFactory.sol";
|
||||||
|
|
||||||
|
@ -42,9 +42,9 @@ contract StakeManagerTest is Test {
|
||||||
vm.prank(owner);
|
vm.prank(owner);
|
||||||
vault = vaultFactory.createVault();
|
vault = vaultFactory.createVault();
|
||||||
|
|
||||||
if (!stakeManager.isVault(address(vault).codehash)) {
|
if (!stakeManager.isTrustedCodehash(address(vault).codehash)) {
|
||||||
vm.prank(deployer);
|
vm.prank(deployer);
|
||||||
stakeManager.setVault(address(vault).codehash);
|
stakeManager.setTrustedCodehash(address(vault).codehash, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ contract StakeManagerTest is Test {
|
||||||
|
|
||||||
contract StakeTest is StakeManagerTest {
|
contract StakeTest is StakeManagerTest {
|
||||||
function test_RevertWhen_SenderIsNotVault() public {
|
function test_RevertWhen_SenderIsNotVault() public {
|
||||||
vm.expectRevert(StakeManager.StakeManager__SenderIsNotVault.selector);
|
vm.expectRevert(TrustedCodehashAccess.TrustedCodehashAccess__UnauthorizedCodehash.selector);
|
||||||
stakeManager.stake(100, 1);
|
stakeManager.stake(100, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,8 +169,8 @@ contract StakeTest is StakeManagerTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_StakeWithoutLockUpTimeMintsMultiplierPoints() public {
|
function test_StakeWithoutLockUpTimeMintsMultiplierPoints() public {
|
||||||
uint256 stakeAmount = 100;
|
uint256 stakeAmount = 54;
|
||||||
StakeVault userVault = _createStakingAccount(testUser, stakeAmount, 0, stakeAmount * 10);
|
StakeVault userVault = _createStakingAccount(testUser, stakeAmount, 0, stakeAmount);
|
||||||
|
|
||||||
(,, uint256 totalMP,,,,,) = stakeManager.accounts(address(userVault));
|
(,, uint256 totalMP,,,,,) = stakeManager.accounts(address(userVault));
|
||||||
assertEq(stakeManager.totalSupplyMP(), stakeAmount, "total multiplier point supply");
|
assertEq(stakeManager.totalSupplyMP(), stakeAmount, "total multiplier point supply");
|
||||||
|
@ -187,7 +187,7 @@ contract StakeTest is StakeManagerTest {
|
||||||
|
|
||||||
contract UnstakeTest is StakeManagerTest {
|
contract UnstakeTest is StakeManagerTest {
|
||||||
function test_RevertWhen_SenderIsNotVault() public {
|
function test_RevertWhen_SenderIsNotVault() public {
|
||||||
vm.expectRevert(StakeManager.StakeManager__SenderIsNotVault.selector);
|
vm.expectRevert(TrustedCodehashAccess.TrustedCodehashAccess__UnauthorizedCodehash.selector);
|
||||||
stakeManager.unstake(1);
|
stakeManager.unstake(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,7 +289,7 @@ contract UnstakeTest is StakeManagerTest {
|
||||||
|
|
||||||
contract LockTest is StakeManagerTest {
|
contract LockTest is StakeManagerTest {
|
||||||
function test_RevertWhen_SenderIsNotVault() public {
|
function test_RevertWhen_SenderIsNotVault() public {
|
||||||
vm.expectRevert(StakeManager.StakeManager__SenderIsNotVault.selector);
|
vm.expectRevert(TrustedCodehashAccess.TrustedCodehashAccess__UnauthorizedCodehash.selector);
|
||||||
stakeManager.lock(100);
|
stakeManager.lock(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,7 +371,7 @@ contract LockTest is StakeManagerTest {
|
||||||
|
|
||||||
contract LeaveTest is StakeManagerTest {
|
contract LeaveTest is StakeManagerTest {
|
||||||
function test_RevertWhen_SenderIsNotVault() public {
|
function test_RevertWhen_SenderIsNotVault() public {
|
||||||
vm.expectRevert(StakeManager.StakeManager__SenderIsNotVault.selector);
|
vm.expectRevert(TrustedCodehashAccess.TrustedCodehashAccess__UnauthorizedCodehash.selector);
|
||||||
stakeManager.migrateTo(false);
|
stakeManager.migrateTo(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,7 +393,7 @@ contract LeaveTest is StakeManagerTest {
|
||||||
|
|
||||||
contract MigrateTest is StakeManagerTest {
|
contract MigrateTest is StakeManagerTest {
|
||||||
function test_RevertWhen_SenderIsNotVault() public {
|
function test_RevertWhen_SenderIsNotVault() public {
|
||||||
vm.expectRevert(StakeManager.StakeManager__SenderIsNotVault.selector);
|
vm.expectRevert(TrustedCodehashAccess.TrustedCodehashAccess__UnauthorizedCodehash.selector);
|
||||||
stakeManager.migrateTo(true);
|
stakeManager.migrateTo(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,7 +423,7 @@ contract MigrationInitializeTest is StakeManagerTest {
|
||||||
vm.stopPrank();
|
vm.stopPrank();
|
||||||
|
|
||||||
// first, ensure `secondStakeManager` is in migration mode itself
|
// first, ensure `secondStakeManager` is in migration mode itself
|
||||||
StakeRewardEstimate db = stakeManager.stakeRewardEstimate();
|
ExpiredStakeStorage db = stakeManager.expiredStakeStorage();
|
||||||
vm.prank(address(stakeManager));
|
vm.prank(address(stakeManager));
|
||||||
db.transferOwnership(address(secondStakeManager));
|
db.transferOwnership(address(secondStakeManager));
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue