Skip to content

Commit 117230c

Browse files
committed
owner to update beneficiaries
1 parent 4858a5a commit 117230c

File tree

2 files changed

+170
-8
lines changed

2 files changed

+170
-8
lines changed

src/VestingManager.sol

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
pragma solidity ^0.8.20;
33

44
import "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
5+
import "openzeppelin-contracts/contracts/access/Ownable.sol";
56

67
/// @title Vesting Manager with Vesting Schedules
7-
contract VestingManager {
8+
contract VestingManager is Ownable {
89
IERC20 public immutable token;
910
uint256 public immutable tgeTimestamp;
1011

@@ -31,10 +32,11 @@ contract VestingManager {
3132

3233
VestingSchedule[] private schedules;
3334

34-
event ScheduleCreated(uint256 indexed id, address indexed beneficiary, uint256 totalAmount);
35-
event Vested(uint256 indexed id, address indexed beneficiary, uint256 indexed termIndex, uint256 periodIdx, uint256 amount);
35+
event ScheduleCreated(uint256 indexed id, uint256 totalAmount);
36+
event Vested(uint256 indexed id, uint256 indexed termIndex, uint256 indexed periodIdx, address beneficiary, uint256 amount);
37+
event BeneficiaryUpdated(uint256 indexed id, address indexed newBeneficiary);
3638

37-
constructor(address _token, uint256 _tgeTimestamp, address[] memory beneficiaries) {
39+
constructor(address _token, uint256 _tgeTimestamp, address[] memory beneficiaries) Ownable(msg.sender) {
3840
require(_token != address(0), "token zero");
3941
require(beneficiaries.length == 12, "need 12 addresses");
4042
token = IERC20(_token);
@@ -120,6 +122,14 @@ contract VestingManager {
120122
}
121123
}
122124

125+
function updateBeneficiary(uint256 scheduleId, address newBeneficiary) external onlyOwner {
126+
require(scheduleId < schedules.length, "invalid index");
127+
require(newBeneficiary != address(0), "new beneficiary is zero");
128+
VestingSchedule storage s = schedules[scheduleId];
129+
s.beneficiary = newBeneficiary;
130+
emit BeneficiaryUpdated(scheduleId, newBeneficiary);
131+
}
132+
123133
function _createScheduleInternal(
124134
address beneficiary,
125135
uint256 totalAmount,
@@ -145,7 +155,8 @@ contract VestingManager {
145155
s.terms.push(terms[i]);
146156
}
147157

148-
emit ScheduleCreated(schedules.length - 1, beneficiary, totalAmount);
158+
emit ScheduleCreated(schedules.length - 1, totalAmount);
159+
emit BeneficiaryUpdated(schedules.length - 1, beneficiary);
149160
}
150161

151162
function claim(uint256 scheduleId) external {
@@ -168,7 +179,7 @@ contract VestingManager {
168179
}
169180
require(token.transfer(s.beneficiary, amount), "transfer failed");
170181

171-
emit Vested(scheduleId, s.beneficiary, termIdx, periodIdx, amount);
182+
emit Vested(scheduleId, termIdx, periodIdx, s.beneficiary, amount);
172183
}
173184

174185
function numOfSchedules() external view returns (uint256) {

test/VestingManager.t.sol

Lines changed: 153 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ contract VestingManagerTest is Test {
1111
address[] public beneficiaries;
1212
uint256 public tge;
1313

14+
event Transfer(address indexed from, address indexed to, uint256 amount);
15+
event ScheduleCreated(uint256 indexed id, uint256 totalAmount);
16+
event Vested(uint256 indexed id, uint256 indexed termIndex, uint256 indexed periodIdx, address beneficiary, uint256 amount);
17+
event BeneficiaryUpdated(uint256 indexed id, address indexed newBeneficiary);
18+
1419
function setUp() public {
1520
beneficiaries.push(address(0x1));
1621
beneficiaries.push(address(0x2));
@@ -24,16 +29,62 @@ contract VestingManagerTest is Test {
2429
beneficiaries.push(address(0xA));
2530
beneficiaries.push(address(0xB));
2631
beneficiaries.push(address(0xC));
32+
vm.expectEmit(true, true, false, true);
33+
emit Transfer(address(0), address(this), 1_000_000_000 ether);
2734
token = new NubilaNetwork(address(this));
2835
tge = block.timestamp + 1 minutes;
36+
vm.expectEmit(true, false, false, true);
37+
emit ScheduleCreated(0, 210_000_000 ether);
38+
emit BeneficiaryUpdated(0, address(0x1));
39+
emit ScheduleCreated(1, 200_000_000 ether);
40+
emit BeneficiaryUpdated(1, address(0x2));
41+
emit ScheduleCreated(2, 62_500_000 ether);
42+
emit BeneficiaryUpdated(2, address(0x3));
43+
emit ScheduleCreated(3, 80_000_000 ether);
44+
emit BeneficiaryUpdated(3, address(0x4));
45+
emit ScheduleCreated(4, 5_000_000 ether);
46+
emit BeneficiaryUpdated(4, address(0x5));
47+
emit ScheduleCreated(5, 65_000_000 ether);
48+
emit BeneficiaryUpdated(5, address(0x6));
49+
emit ScheduleCreated(6, 78_000_000 ether);
50+
emit BeneficiaryUpdated(6, address(0x7));
51+
emit ScheduleCreated(7, 120_000_000 ether);
52+
emit BeneficiaryUpdated(7, address(0x8));
53+
emit ScheduleCreated(8, 20_000_000 ether);
54+
emit BeneficiaryUpdated(8, address(0x9));
55+
emit ScheduleCreated(9, 22_500_000 ether);
56+
emit BeneficiaryUpdated(9, address(0xA));
57+
emit ScheduleCreated(10, 75_000_000 ether);
58+
emit BeneficiaryUpdated(10, address(0xB));
59+
emit ScheduleCreated(11, 62_000_000 ether);
60+
emit BeneficiaryUpdated(11, address(0xC));
2961
manager = new VestingManager(address(token), tge, beneficiaries);
62+
vm.expectEmit(true, true, false, true, address(token));
63+
emit Transfer(address(this), address(manager), 1_000_000_000 ether);
3064
assertTrue(token.transfer(address(manager), token.totalSupply()));
3165
}
3266

3367
function testNumOfSchedules() public view {
3468
assertEq(manager.numOfSchedules(), 12);
3569
}
3670

71+
function testUpdateBeneficiary() public {
72+
vm.expectRevert("invalid index");
73+
manager.updateBeneficiary(12, address(0x456));
74+
vm.expectRevert("new beneficiary is zero");
75+
manager.updateBeneficiary(0, address(0));
76+
77+
vm.expectEmit(true, true, false, true, address(manager));
78+
emit BeneficiaryUpdated(0, address(0x456));
79+
manager.updateBeneficiary(0, address(0x456));
80+
(address beneficiary,,,,) = manager.getSchedule(0);
81+
assertEq(beneficiary, address(0x456));
82+
83+
vm.expectRevert();
84+
vm.prank(address(0x123));
85+
manager.updateBeneficiary(0, address(0x654));
86+
}
87+
3788
function testGetSchedule() public view {
3889
{
3990
(address beneficiary, uint256 totalAmount, uint256 vestedAmount, uint256 termIndex, VestingManager.Term[] memory terms) = manager.getSchedule(0);
@@ -222,13 +273,29 @@ contract VestingManagerTest is Test {
222273
assertEq(manager.claimable(9), 22_500_000 ether);
223274
assertEq(manager.claimable(10), 18_750_000 ether);
224275
assertEq(manager.claimable(11), 62_000_000 ether);
276+
vm.expectEmit(true, true, true, true, address(manager));
277+
emit Vested(0, 0, 0, beneficiaries[0], 10_500_000 ether);
225278
manager.claim(0);
279+
vm.expectEmit(true, true, true, true, address(manager));
280+
emit Vested(1, 0, 0, beneficiaries[1], 10_000_000 ether);
226281
manager.claim(1);
282+
vm.expectEmit(true, true, true, true, address(manager));
283+
emit Vested(4, 0, 0, beneficiaries[4], 5_000_000 ether);
227284
manager.claim(4);
285+
vm.expectEmit(true, true, true, true, address(manager));
286+
emit Vested(5, 0, 0, beneficiaries[5], 16_250_000 ether);
228287
manager.claim(5);
288+
vm.expectEmit(true, true, true, true, address(manager));
289+
emit Vested(6, 0, 0, beneficiaries[6], 31_200_000 ether);
229290
manager.claim(6);
291+
vm.expectEmit(true, true, true, true, address(manager));
292+
emit Vested(9, 0, 0, beneficiaries[9], 22_500_000 ether);
230293
manager.claim(9);
294+
vm.expectEmit(true, true, true, true, address(manager));
295+
emit Vested(10, 0, 0, beneficiaries[10], 18_750_000 ether);
231296
manager.claim(10);
297+
vm.expectEmit(true, true, true, true, address(manager));
298+
emit Vested(11, 0, 0, beneficiaries[11], 62_000_000 ether);
232299
manager.claim(11);
233300
assertEq(token.balanceOf(beneficiaries[0]), 10_500_000 ether);
234301
assertEq(token.balanceOf(beneficiaries[1]), 10_000_000 ether);
@@ -261,10 +328,20 @@ contract VestingManagerTest is Test {
261328
assertEq(manager.claimable(9), 0 ether);
262329
assertEq(manager.claimable(10), 18_750_000 ether);
263330
assertEq(manager.claimable(11), 0 ether);
331+
vm.expectEmit(true, true, true, true, address(manager));
332+
emit Vested(0, 0, 1, beneficiaries[0], 10_500_000 ether);
264333
manager.claim(0);
334+
vm.expectEmit(true, true, true, true, address(manager));
335+
emit Vested(1, 0, 1, beneficiaries[1], 10_000_000 ether);
265336
manager.claim(1);
337+
vm.expectEmit(true, true, true, true, address(manager));
338+
emit Vested(5, 1, 0, beneficiaries[5], 2_437_500 ether);
266339
manager.claim(5);
340+
vm.expectEmit(true, true, true, true, address(manager));
341+
emit Vested(6, 1, 0, beneficiaries[6], 11_700_000 ether);
267342
manager.claim(6);
343+
vm.expectEmit(true, true, true, true, address(manager));
344+
emit Vested(10, 1, 0, beneficiaries[10], 18_750_000 ether);
268345
manager.claim(10);
269346
assertEq(token.balanceOf(beneficiaries[0]), 21_000_000 ether);
270347
assertEq(token.balanceOf(beneficiaries[1]), 20_000_000 ether);
@@ -297,10 +374,20 @@ contract VestingManagerTest is Test {
297374
assertEq(manager.claimable(9), 0 ether);
298375
assertEq(manager.claimable(10), 37_500_000 ether);
299376
assertEq(manager.claimable(11), 0 ether);
377+
vm.expectEmit(true, true, true, true, address(manager));
378+
emit Vested(0, 0, 2, beneficiaries[0], 10_500_000 ether);
300379
manager.claim(0);
380+
vm.expectEmit(true, true, true, true, address(manager));
381+
emit Vested(1, 0, 2, beneficiaries[1], 10_000_000 ether);
301382
manager.claim(1);
383+
vm.expectEmit(true, true, true, true, address(manager));
384+
emit Vested(5, 1, 1, beneficiaries[5], 2_437_500 ether);
302385
manager.claim(5);
386+
vm.expectEmit(true, true, true, true, address(manager));
387+
emit Vested(6, 1, 1, beneficiaries[6], 11_700_000 ether);
303388
manager.claim(6);
389+
vm.expectEmit(true, true, true, true, address(manager));
390+
emit Vested(10, 2, 0, beneficiaries[10], 37_500_000 ether);
304391
manager.claim(10);
305392
assertEq(token.balanceOf(beneficiaries[0]), 31_500_000 ether);
306393
assertEq(token.balanceOf(beneficiaries[1]), 30_000_000 ether);
@@ -333,13 +420,29 @@ contract VestingManagerTest is Test {
333420
assertEq(manager.claimable(9), 0 ether);
334421
assertEq(manager.claimable(10), 0 ether);
335422
assertEq(manager.claimable(11), 0 ether);
423+
vm.expectEmit(true, true, true, true, address(manager));
424+
emit Vested(0, 0, 3, beneficiaries[0], 10_500_000 ether);
336425
manager.claim(0);
426+
vm.expectEmit(true, true, true, true, address(manager));
427+
emit Vested(1, 0, 3, beneficiaries[1], 10_000_000 ether);
337428
manager.claim(1);
429+
vm.expectEmit(true, true, true, true, address(manager));
430+
emit Vested(2, 0, 0, beneficiaries[2], 5_208_333 ether + 333_333_333_333_333_333);
338431
manager.claim(2);
432+
vm.expectEmit(true, true, true, true, address(manager));
433+
emit Vested(3, 0, 0, beneficiaries[3], 10_000_000 ether);
339434
manager.claim(3);
435+
vm.expectEmit(true, true, true, true, address(manager));
436+
emit Vested(5, 1, 2, beneficiaries[5], 2_437_500 ether);
340437
manager.claim(5);
438+
vm.expectEmit(true, true, true, true, address(manager));
439+
emit Vested(6, 1, 2, beneficiaries[6], 11_700_000 ether);
341440
manager.claim(6);
441+
vm.expectEmit(true, true, true, true, address(manager));
442+
emit Vested(7, 0, 0, beneficiaries[7], 10_000_000 ether);
342443
manager.claim(7);
444+
vm.expectEmit(true, true, true, true, address(manager));
445+
emit Vested(8, 0, 0, beneficiaries[8], 1_666_666 ether + 666_666_666_666_666_666);
343446
manager.claim(8);
344447
assertEq(token.balanceOf(beneficiaries[0]), 42_000_000 ether);
345448
assertEq(token.balanceOf(beneficiaries[1]), 40_000_000 ether);
@@ -357,9 +460,17 @@ contract VestingManagerTest is Test {
357460
assertEq(manager.claimable(1), 10_000_000 ether);
358461
assertEq(manager.claimable(5), 2_437_500 ether);
359462
assertEq(manager.claimable(6), 11_700_000 ether);
463+
vm.expectEmit(true, true, true, true, address(manager));
464+
emit Vested(0, 0, 4, beneficiaries[0], 10_500_000 ether);
360465
manager.claim(0);
466+
vm.expectEmit(true, true, true, true, address(manager));
467+
emit Vested(1, 0, 4, beneficiaries[1], 10_000_000 ether);
361468
manager.claim(1);
469+
vm.expectEmit(true, true, true, true, address(manager));
470+
emit Vested(5, 1, 3, beneficiaries[5], 2_437_500 ether);
362471
manager.claim(5);
472+
vm.expectEmit(true, true, true, true, address(manager));
473+
emit Vested(6, 1, 3, beneficiaries[6], 11_700_000 ether);
363474
manager.claim(6);
364475
assertEq(token.balanceOf(beneficiaries[0]), 52_500_000 ether);
365476
assertEq(token.balanceOf(beneficiaries[1]), 50_000_000 ether);
@@ -385,12 +496,26 @@ contract VestingManagerTest is Test {
385496
assertEq(manager.claimable(9), 0 ether);
386497
assertEq(manager.claimable(10), 0 ether);
387498
assertEq(manager.claimable(11), 0 ether);
499+
vm.expectEmit(true, true, true, true, address(manager));
500+
emit Vested(0, 0, i, beneficiaries[0], 10_500_000 ether);
388501
manager.claim(0);
502+
vm.expectEmit(true, true, true, true, address(manager));
503+
emit Vested(1, 0, i, beneficiaries[1], 10_000_000 ether);
389504
manager.claim(1);
505+
vm.expectEmit(true, true, true, true, address(manager));
506+
emit Vested(2, 0, i - 4, beneficiaries[2], 5_208_333 ether + 333_333_333_333_333_333);
390507
manager.claim(2);
508+
vm.expectEmit(true, true, true, true, address(manager));
509+
emit Vested(3, 0, i - 4, beneficiaries[3], 10_000_000 ether);
391510
manager.claim(3);
511+
vm.expectEmit(true, true, true, true, address(manager));
512+
emit Vested(5, 1, i - 1, beneficiaries[5], 2_437_500 ether);
392513
manager.claim(5);
514+
vm.expectEmit(true, true, true, true, address(manager));
515+
emit Vested(7, 0, i - 4, beneficiaries[7], 10_000_000 ether);
393516
manager.claim(7);
517+
vm.expectEmit(true, true, true, true, address(manager));
518+
emit Vested(8, 0, i - 4, beneficiaries[8], 1_666_666 ether + 666_666_666_666_666_666);
394519
manager.claim(8);
395520
}
396521
assertEq(token.balanceOf(beneficiaries[0]), 126_000_000 ether);
@@ -423,19 +548,37 @@ contract VestingManagerTest is Test {
423548
if (i == 15) {
424549
assertEq(manager.claimable(8), 1_666_666 ether + 666_666_666_666_666_666 + 8);
425550
assertEq(manager.claimable(2), 5_208_333 ether + 333_333_333_333_333_333 + 4);
551+
vm.expectEmit(true, true, true, true, address(manager));
552+
emit Vested(2, 0, i - 4, beneficiaries[2], 5_208_333 ether + 333_333_333_333_333_333 + 4);
553+
manager.claim(2);
554+
vm.expectEmit(true, true, true, true, address(manager));
555+
emit Vested(8, 0, i - 4, beneficiaries[8], 1_666_666 ether + 666_666_666_666_666_666 + 8);
556+
manager.claim(8);
426557
} else {
427558
assertEq(manager.claimable(8), 1_666_666 ether + 666_666_666_666_666_666);
428559
assertEq(manager.claimable(2), 5_208_333 ether + 333_333_333_333_333_333);
560+
vm.expectEmit(true, true, true, true, address(manager));
561+
emit Vested(2, 0, i - 4, beneficiaries[2], 5_208_333 ether + 333_333_333_333_333_333);
562+
manager.claim(2);
563+
vm.expectEmit(true, true, true, true, address(manager));
564+
emit Vested(8, 0, i - 4, beneficiaries[8], 1_666_666 ether + 666_666_666_666_666_666);
565+
manager.claim(8);
429566
}
430567
assertEq(manager.claimable(9), 0 ether);
431568
assertEq(manager.claimable(10), 0 ether);
432569
assertEq(manager.claimable(11), 0 ether);
570+
vm.expectEmit(true, true, true, true, address(manager));
571+
emit Vested(0, 0, i, beneficiaries[0], 10_500_000 ether);
433572
manager.claim(0);
573+
vm.expectEmit(true, true, true, true, address(manager));
574+
emit Vested(1, 0, i, beneficiaries[1], 10_000_000 ether);
434575
manager.claim(1);
435-
manager.claim(2);
576+
vm.expectEmit(true, true, true, true, address(manager));
577+
emit Vested(5, 1, i - 1, beneficiaries[5], 2_437_500 ether);
436578
manager.claim(5);
579+
vm.expectEmit(true, true, true, true, address(manager));
580+
emit Vested(7, 0, i - 4, beneficiaries[7], 10_000_000 ether);
437581
manager.claim(7);
438-
manager.claim(8);
439582
}
440583
assertEq(token.balanceOf(beneficiaries[0]), 168_000_000 ether);
441584
assertEq(token.balanceOf(beneficiaries[1]), 160_000_000 ether);
@@ -469,8 +612,14 @@ contract VestingManagerTest is Test {
469612
assertEq(manager.claimable(9), 0 ether);
470613
assertEq(manager.claimable(10), 0 ether);
471614
assertEq(manager.claimable(11), 0 ether);
615+
vm.expectEmit(true, true, true, true, address(manager));
616+
emit Vested(0, 0, i, beneficiaries[0], 10_500_000 ether);
472617
manager.claim(0);
618+
vm.expectEmit(true, true, true, true, address(manager));
619+
emit Vested(1, 0, i, beneficiaries[1], 10_000_000 ether);
473620
manager.claim(1);
621+
vm.expectEmit(true, true, true, true, address(manager));
622+
emit Vested(5, 1, i - 1, beneficiaries[5], 2_437_500 ether);
474623
manager.claim(5);
475624
}
476625
assertEq(token.balanceOf(beneficiaries[0]), 210_000_000 ether);
@@ -499,6 +648,8 @@ contract VestingManagerTest is Test {
499648
for (uint i = 6; i < 12; i++) {
500649
assertEq(manager.claimable(i), 0 ether);
501650
}
651+
vm.expectEmit(true, true, true, true, address(manager));
652+
emit Vested(5, 1, 19, beneficiaries[5], 2_437_500 ether);
502653
manager.claim(5);
503654
assertEq(token.balanceOf(beneficiaries[5]), 65_000_000 ether);
504655
vm.warp(tge + 5000 days);

0 commit comments

Comments
 (0)