Skip to content

Commit c5eb1f0

Browse files
committed
Addressed review feedback from @jrhea and @sean392
1 parent e10bd36 commit c5eb1f0

2 files changed

Lines changed: 36 additions & 48 deletions

File tree

src/MigrationVestingVault.sol

Lines changed: 18 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,11 @@ import { VestingVaultStorage } from "council/libraries/VestingVaultStorage.sol";
88
import { Storage } from "council/libraries/Storage.sol";
99
import { AbstractVestingVault } from "council/vaults/VestingVault.sol";
1010

11-
// FIXME: Scrutinize this.
12-
//
13-
// FIXME: Test this.
14-
//
15-
// FIXME: We can retrofit this to pull funds from the treasury instead of needing
16-
// to be funded directly by the treasury. This would be more flexible since we'll
17-
// have two migration vaults.
18-
//
19-
// FIXME: What should happen to the ELFI? Should it be burned?
20-
//
21-
// FIXME: We should avoid setting the manager roll. We don't want grants to be
22-
// revoked.
23-
//
2411
/// @title MigrationVestingVault
2512
/// @notice A migration vault that converts ELFI tokens to HD tokens. Migrated
26-
/// tokens are granted with a linear vesting schedule of three months.
27-
/// The grant is created at a destination address provided by the
28-
/// migrator. This contract inherits full voting power tracking from
13+
/// tokens are granted with a linear vesting schedule. The grant is
14+
/// created at a destination address provided by the migrator. This
15+
/// contract inherits full voting power tracking from
2916
/// `AbstractVestingVault`.
3017
contract MigrationVestingVault is AbstractVestingVault {
3118
using History for History.HistoricalBalances;
@@ -45,11 +32,14 @@ contract MigrationVestingVault is AbstractVestingVault {
4532
/// @dev The ELFI token to migrate from.
4633
IERC20 public immutable elfiToken;
4734

48-
// The conversion rate from ELFI to HD.
35+
/// @dev The conversion rate from ELFI to HD.
4936
uint256 public immutable conversionMultiplier;
5037

51-
// The global expiration block at which all grants fully vest.
52-
uint256 public immutable globalExpiration;
38+
/// @dev The global start block at which all grants start vesting.
39+
uint256 public immutable startBlock;
40+
41+
/// @dev The global expiration block at which all grants fully vest.
42+
uint256 public immutable expiration;
5343

5444
/// @notice Constructs the migration vault.
5545
/// @param _hdTreasury The HD treasury that is funding this migration
@@ -58,19 +48,22 @@ contract MigrationVestingVault is AbstractVestingVault {
5848
/// @param _elfiToken The ERC20 token to migrate from (ELFI token).
5949
/// @param _stale The stale block lag used in voting power calculations.
6050
/// @param _conversionMultiplier The conversion multiplier from ELFI to HD.
61-
/// @param _globalExpiration The global expiration block for all grants.
51+
/// @param _startBlock The global start block for all grants.
52+
/// @param _expiration The global expiration block for all grants.
6253
constructor(
6354
address _hdTreasury,
6455
IERC20 _hdToken,
6556
IERC20 _elfiToken,
6657
uint256 _stale,
6758
uint256 _conversionMultiplier,
68-
uint256 _globalExpiration
59+
uint256 _startBlock,
60+
uint256 _expiration
6961
) AbstractVestingVault(_hdToken, _stale) {
7062
hdTreasury = _hdTreasury;
7163
elfiToken = _elfiToken;
7264
conversionMultiplier = _conversionMultiplier;
73-
globalExpiration = _globalExpiration;
65+
startBlock = _startBlock;
66+
expiration = _expiration;
7467
}
7568

7669
/// @notice Migrates a specified amount of ELFI tokens into a vesting grant of HD tokens.
@@ -98,12 +91,6 @@ contract MigrationVestingVault is AbstractVestingVault {
9891
revert InsufficientHDTokens();
9992
}
10093

101-
// Set the vesting parameters. We use the global expiration for all
102-
// grants, and the vesting starts immediately.
103-
uint128 startBlock = uint128(block.number);
104-
uint128 expiration = uint128(globalExpiration);
105-
uint128 cliff = startBlock;
106-
10794
// Calculate the initial voting power using the current unvested multiplier.
10895
Storage.Uint256 memory unvestedMultiplier = _unvestedMultiplier();
10996
uint128 initialVotingPower = uint128((hdAmount * uint128(unvestedMultiplier.data)) / 100);
@@ -112,9 +99,9 @@ contract MigrationVestingVault is AbstractVestingVault {
11299
_grants()[destination] = VestingVaultStorage.Grant({
113100
allocation: uint128(hdAmount),
114101
withdrawn: 0,
115-
created: startBlock,
116-
expiration: expiration,
117-
cliff: cliff,
102+
created: uint128(startBlock),
103+
expiration: uint128(expiration),
104+
cliff: uint128(startBlock), // vesting starts immediately
118105
latestVotingPower: initialVotingPower,
119106
delegatee: destination,
120107
range: [uint256(0), uint256(0)]

test/MigrationVestingVaultTest.t.sol

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,16 @@ contract MigrationVestingVaultTest is Test {
5858
);
5959

6060
// Deploy migration vault
61-
uint256 globalExpiration = block.number + (VESTING_DURATION / 12);
61+
uint256 startBlock = block.number;
62+
uint256 expiration = block.number + (VESTING_DURATION / 12);
6263
vault = new MigrationVestingVault(
6364
deployer,
6465
IERC20(address(hdToken)), // Cast HDToken to IERC20
6566
ELFI,
6667
STALE_BLOCKS,
6768
CONVERSION_MULTIPLIER,
68-
globalExpiration
69+
startBlock,
70+
expiration
6971
);
7072
vault.initialize(deployer, deployer);
7173

@@ -153,7 +155,7 @@ contract MigrationVestingVaultTest is Test {
153155
assertEq(grant.allocation, amount * CONVERSION_MULTIPLIER, "Wrong allocation");
154156
assertEq(grant.withdrawn, 0, "Should not have withdrawals");
155157
assertEq(grant.cliff, grant.created, "Cliff should equal creation block");
156-
assertEq(grant.expiration, vault.globalExpiration(), "Wrong expiration");
158+
assertEq(grant.expiration, vault.expiration(), "Wrong expiration");
157159
assertEq(grant.delegatee, bob, "Wrong delegatee");
158160

159161
// Verify token transfers.
@@ -174,7 +176,7 @@ contract MigrationVestingVaultTest is Test {
174176
uint256 vaultHDBalanceBefore = hdToken.balanceOf(address(vault));
175177
uint256 votingPowerBefore = vault.queryVotePower(bob, block.number, "");
176178
vm.startPrank(bob);
177-
uint256 halfwayBlock = (block.number + vault.globalExpiration()) / 2;
179+
uint256 halfwayBlock = (block.number + vault.expiration()) / 2;
178180
vm.roll(halfwayBlock);
179181
vault.claim();
180182

@@ -189,7 +191,7 @@ contract MigrationVestingVaultTest is Test {
189191

190192
// The other half of the three months passes.
191193
vm.startPrank(bob);
192-
vm.roll(vault.globalExpiration());
194+
vm.roll(vault.expiration());
193195
vault.claim();
194196

195197
// Ensure that Bob received the other half of the HD grant and that his
@@ -211,6 +213,10 @@ contract MigrationVestingVaultTest is Test {
211213
uint256 vaultElfiBalanceBefore = ELFI.balanceOf(address(vault));
212214
uint256 aliceElfiBalanceBefore = ELFI.balanceOf(alice);
213215

216+
// Half of the three months passes and Alice migrates her ELFI.
217+
uint256 halfwayBlock = (block.number + vault.expiration()) / 2;
218+
vm.roll(halfwayBlock);
219+
214220
// Alice migrates some of her ELFI tokens. She sets Bob as the destination
215221
// address.
216222
vm.startPrank(alice);
@@ -219,15 +225,11 @@ contract MigrationVestingVaultTest is Test {
219225
emit Transfer(alice, address(vault), amount);
220226
vault.migrate(amount, bob);
221227
vm.stopPrank();
222-
223-
// Half of the three months passes and Alice migrates her ELFI.
224-
uint256 halfwayBlock = (block.number + vault.globalExpiration()) / 2;
225-
vm.roll(halfwayBlock);
226228
VestingVaultStorage.Grant memory grant = vault.getGrant(bob);
227229
assertEq(grant.allocation, amount * CONVERSION_MULTIPLIER, "Wrong allocation");
228230
assertEq(grant.withdrawn, 0, "Should not have withdrawals");
229231
assertEq(grant.cliff, grant.created, "Cliff should equal creation block");
230-
assertEq(grant.expiration, vault.globalExpiration(), "Wrong expiration");
232+
assertEq(grant.expiration, vault.expiration(), "Wrong expiration");
231233
assertEq(grant.delegatee, bob, "Wrong delegatee");
232234

233235
// Verify token transfers.
@@ -260,7 +262,7 @@ contract MigrationVestingVaultTest is Test {
260262

261263
// The other half of the three months passes.
262264
vm.startPrank(bob);
263-
vm.roll(vault.globalExpiration());
265+
vm.roll(vault.expiration());
264266
vault.claim();
265267

266268
// Ensure that Bob received the other half of the HD grant and that his
@@ -282,6 +284,9 @@ contract MigrationVestingVaultTest is Test {
282284
uint256 vaultElfiBalanceBefore = ELFI.balanceOf(address(vault));
283285
uint256 aliceElfiBalanceBefore = ELFI.balanceOf(alice);
284286

287+
// Four months passes and Alice migrates her ELFI.
288+
vm.roll(vault.expiration());
289+
285290
// Alice migrates some of her ELFI tokens. She sets Bob as the destination
286291
// address.
287292
vm.startPrank(alice);
@@ -290,14 +295,11 @@ contract MigrationVestingVaultTest is Test {
290295
emit Transfer(alice, address(vault), amount);
291296
vault.migrate(amount, bob);
292297
vm.stopPrank();
293-
294-
// Four months passes and Alice migrates her ELFI.
295-
vm.roll(vault.globalExpiration());
296298
VestingVaultStorage.Grant memory grant = vault.getGrant(bob);
297299
assertEq(grant.allocation, amount * CONVERSION_MULTIPLIER, "Wrong allocation");
298300
assertEq(grant.withdrawn, 0, "Should not have withdrawals");
299301
assertEq(grant.cliff, grant.created, "Cliff should equal creation block");
300-
assertEq(grant.expiration, vault.globalExpiration(), "Wrong expiration");
302+
assertEq(grant.expiration, vault.expiration(), "Wrong expiration");
301303
assertEq(grant.delegatee, bob, "Wrong delegatee");
302304

303305
// Verify token transfers.
@@ -315,7 +317,6 @@ contract MigrationVestingVaultTest is Test {
315317
// Bob can claim all of the tokens immediately.
316318
uint256 bobHDBalanceBefore = hdToken.balanceOf(address(bob));
317319
uint256 vaultHDBalanceBefore = hdToken.balanceOf(address(vault));
318-
uint256 votingPowerBefore = vault.queryVotePower(bob, block.number, "");
319320
vm.startPrank(bob);
320321
vault.claim();
321322

@@ -396,7 +397,7 @@ contract MigrationVestingVaultTest is Test {
396397
vm.stopPrank();
397398

398399
// Move to middle of vesting period
399-
uint256 halfwayBlock = (block.number + vault.globalExpiration()) / 2;
400+
uint256 halfwayBlock = (block.number + vault.expiration()) / 2;
400401
vm.roll(halfwayBlock);
401402

402403
// Check voting power is maintained through vesting

0 commit comments

Comments
 (0)