Skip to content

Commit db74969

Browse files
committed
fix(StakeManager): add checks for whether lockup period is in range
This commit introduces `MIN_LOCKUP_PERIOD` and `MAX_LOCKUP_PERIOD` and makes use of them within `StakeManager.stake()` and `StakeManager.lock()` accordingly. When users deposit tokens into their vault via `stake()`, they can provide an optional lockup time. If the value is `0` it implies users do not want to lock their stake. If the value is `> 0` it has to be within the range of `MIN_LOCKUP_PERIOD` and `MAX_LOCKUP_PERIOD`. Properly addresses #15
1 parent f259286 commit db74969

File tree

3 files changed

+66
-19
lines changed

3 files changed

+66
-19
lines changed

.gas-snapshot

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
11
CreateVaultTest:testDeployment() (gas: 9774)
2-
CreateVaultTest:test_createVault() (gas: 650992)
3-
ExecuteAccountTest:testDeployment() (gas: 26400)
4-
ExecuteAccountTest:test_RevertWhen_InvalidLimitEpoch() (gas: 991602)
5-
LeaveTest:testDeployment() (gas: 26172)
6-
LeaveTest:test_RevertWhen_NoPendingMigration() (gas: 678051)
7-
LeaveTest:test_RevertWhen_SenderIsNotVault() (gas: 10562)
8-
LockTest:testDeployment() (gas: 26400)
9-
LockTest:test_RevertWhen_DecreasingLockTime() (gas: 994528)
10-
LockTest:test_RevertWhen_SenderIsNotVault() (gas: 10607)
11-
MigrateTest:testDeployment() (gas: 26172)
12-
MigrateTest:test_RevertWhen_NoPendingMigration() (gas: 677890)
2+
CreateVaultTest:test_createVault() (gas: 650970)
3+
ExecuteAccountTest:testDeployment() (gas: 26421)
4+
ExecuteAccountTest:test_RevertWhen_InvalidLimitEpoch() (gas: 992511)
5+
LeaveTest:testDeployment() (gas: 26193)
6+
LeaveTest:test_RevertWhen_NoPendingMigration() (gas: 678007)
7+
LeaveTest:test_RevertWhen_SenderIsNotVault() (gas: 10540)
8+
LockTest:testDeployment() (gas: 26421)
9+
LockTest:test_RevertWhen_DecreasingLockTime() (gas: 995651)
10+
LockTest:test_RevertWhen_InvalidLockupPeriod() (gas: 815891)
11+
LockTest:test_RevertWhen_SenderIsNotVault() (gas: 10652)
12+
MigrateTest:testDeployment() (gas: 26193)
13+
MigrateTest:test_RevertWhen_NoPendingMigration() (gas: 677868)
1314
MigrateTest:test_RevertWhen_SenderIsNotVault() (gas: 10629)
1415
SetStakeManagerTest:testDeployment() (gas: 9774)
1516
SetStakeManagerTest:test_RevertWhen_InvalidStakeManagerAddress() (gas: 20481)
1617
SetStakeManagerTest:test_SetStakeManager() (gas: 19869)
17-
StakeManagerTest:testDeployment() (gas: 26172)
18-
StakeTest:testDeployment() (gas: 26172)
19-
StakeTest:test_RevertWhen_SenderIsNotVault() (gas: 10638)
18+
StakeManagerTest:testDeployment() (gas: 26193)
19+
StakeTest:testDeployment() (gas: 26421)
20+
StakeTest:test_RevertWhen_InvalidLockupPeriod() (gas: 827181)
21+
StakeTest:test_RevertWhen_SenderIsNotVault() (gas: 10672)
2022
StakedTokenTest:testStakeToken() (gas: 7638)
21-
UnstakeTest:testDeployment() (gas: 26355)
22-
UnstakeTest:test_RevertWhen_FundsLocked() (gas: 990991)
23+
UnstakeTest:testDeployment() (gas: 26376)
24+
UnstakeTest:test_RevertWhen_FundsLocked() (gas: 991901)
2325
UnstakeTest:test_RevertWhen_SenderIsNotVault() (gas: 10609)
2426
VaultFactoryTest:testDeployment() (gas: 9774)

contracts/StakeManager.sol

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ contract StakeManager is Ownable {
1414
error StakeManager__PendingMigration();
1515
error StakeManager__SenderIsNotPreviousStakeManager();
1616
error StakeManager__InvalidLimitEpoch();
17+
error StakeManager__InvalidLockupPeriod();
1718

1819
struct Account {
1920
uint256 lockUntil;
@@ -32,6 +33,8 @@ contract StakeManager is Ownable {
3233

3334
uint256 public constant EPOCH_SIZE = 1 weeks;
3435
uint256 public constant YEAR = 365 days;
36+
uint256 public constant MIN_LOCKUP_PERIOD = 12 weeks; // 3 months
37+
uint256 public constant MAX_LOCKUP_PERIOD = 4 * YEAR; // 4 years
3538
uint256 public constant MP_APY = 1;
3639
uint256 public constant MAX_BOOST = 4;
3740

@@ -64,8 +67,13 @@ contract StakeManager is Ownable {
6467
* Increases balance of msg.sender;
6568
* @param _amount Amount of balance to be decreased.
6669
* @param _time Seconds from block.timestamp to lock balance.
70+
*
71+
* @dev Reverts when `_time` is not in range of [MIN_LOCKUP_PERIOD, MAX_LOCKUP_PERIOD]
6772
*/
6873
function stake(uint256 _amount, uint256 _time) external onlyVault {
74+
if (_time > 0 && (_time < MIN_LOCKUP_PERIOD || _time > MAX_LOCKUP_PERIOD)) {
75+
revert StakeManager__InvalidLockupPeriod();
76+
}
6977
Account storage account = accounts[msg.sender];
7078
processAccount(account, currentEpoch);
7179
account.balance += _amount;
@@ -94,8 +102,14 @@ contract StakeManager is Ownable {
94102
/**
95103
* @notice Locks entire balance for more amount of time.
96104
* @param _time amount of time to lock from now.
105+
*
106+
* @dev Reverts when `_time` is bigger than `MAX_LOCKUP_PERIOD`
107+
* @dev Reverts when `_time + block.timestamp` is smaller than current lock time.
97108
*/
98109
function lock(uint256 _time) external onlyVault {
110+
if (_time > MAX_LOCKUP_PERIOD) {
111+
revert StakeManager__InvalidLockupPeriod();
112+
}
99113
Account storage account = accounts[msg.sender];
100114
processAccount(account, currentEpoch);
101115
if (block.timestamp + _time < account.lockUntil) {

test/StakeManager.t.sol

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,23 @@ contract StakeTest is StakeManagerTest {
5454
vm.expectRevert(StakeManager.StakeManager__SenderIsNotVault.selector);
5555
stakeManager.stake(100, 1);
5656
}
57+
58+
function test_RevertWhen_InvalidLockupPeriod() public {
59+
// ensure user has funds
60+
deal(stakeToken, testUser, 1000);
61+
StakeVault userVault = _createTestVault(testUser);
62+
63+
vm.startPrank(testUser);
64+
ERC20(stakeToken).approve(address(userVault), 100);
65+
66+
uint256 lockTime = stakeManager.MIN_LOCKUP_PERIOD() - 1;
67+
vm.expectRevert(StakeManager.StakeManager__InvalidLockupPeriod.selector);
68+
userVault.stake(100, lockTime);
69+
70+
lockTime = stakeManager.MAX_LOCKUP_PERIOD() + 1;
71+
vm.expectRevert(StakeManager.StakeManager__InvalidLockupPeriod.selector);
72+
userVault.stake(100, lockTime);
73+
}
5774
}
5875

5976
contract UnstakeTest is StakeManagerTest {
@@ -74,7 +91,7 @@ contract UnstakeTest is StakeManagerTest {
7491
vm.startPrank(testUser);
7592
ERC20(stakeToken).approve(address(userVault), 100);
7693

77-
uint256 lockTime = 1 days;
94+
uint256 lockTime = stakeManager.MIN_LOCKUP_PERIOD();
7895
userVault.stake(100, lockTime);
7996

8097
vm.expectRevert(StakeManager.StakeManager__FundsLocked.selector);
@@ -92,6 +109,20 @@ contract LockTest is StakeManagerTest {
92109
stakeManager.lock(100);
93110
}
94111

112+
function test_RevertWhen_InvalidLockupPeriod() public {
113+
// ensure user has funds
114+
deal(stakeToken, testUser, 1000);
115+
StakeVault userVault = _createTestVault(testUser);
116+
117+
vm.startPrank(testUser);
118+
// ensure user vault can spend user tokens
119+
ERC20(stakeToken).approve(address(userVault), 100);
120+
121+
uint256 lockTime = stakeManager.MAX_LOCKUP_PERIOD() + 1;
122+
vm.expectRevert(StakeManager.StakeManager__InvalidLockupPeriod.selector);
123+
userVault.stake(100, lockTime);
124+
}
125+
95126
function test_RevertWhen_DecreasingLockTime() public {
96127
// ensure user has funds
97128
deal(stakeToken, testUser, 1000);
@@ -101,7 +132,7 @@ contract LockTest is StakeManagerTest {
101132
// ensure user vault can spend user tokens
102133
ERC20(stakeToken).approve(address(userVault), 100);
103134

104-
uint256 lockTime = 1 days;
135+
uint256 lockTime = stakeManager.MIN_LOCKUP_PERIOD() + 1;
105136
userVault.stake(100, lockTime);
106137

107138
vm.expectRevert(StakeManager.StakeManager__DecreasingLockTime.selector);
@@ -157,7 +188,7 @@ contract ExecuteAccountTest is StakeManagerTest {
157188
vm.startPrank(testUser);
158189
ERC20(stakeToken).approve(address(userVault), 100);
159190

160-
uint256 lockTime = 1 days;
191+
uint256 lockTime = stakeManager.MIN_LOCKUP_PERIOD();
161192
userVault.stake(100, lockTime);
162193

163194
uint256 currentEpoch = stakeManager.currentEpoch();

0 commit comments

Comments
 (0)