Skip to content

Commit 9ac1a6a

Browse files
committed
address comment
1 parent 117230c commit 9ac1a6a

File tree

6 files changed

+71
-38
lines changed

6 files changed

+71
-38
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ $ anvil
4848
### Deploy
4949

5050
```shell
51-
$ forge script script/Counter.s.sol:CounterScript --rpc-url <your_rpc_url> --private-key <your_private_key>
51+
$ TGE=$timestamp forge script script/NubilaNetwork.s.sol:NubilaNetworkScript --rpc-url <your_rpc_url> --private-key <your_private_key>
5252
```
5353

5454
### Cast

script/Counter.s.sol

Lines changed: 0 additions & 19 deletions
This file was deleted.

script/NubilaNetwork.s.sol

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity ^0.8.13;
3+
4+
import {Script, console} from "forge-std/Script.sol";
5+
import {NubilaNetwork} from "../src/NubilaNetwork.sol";
6+
import {VestingManager} from "../src/VestingManager.sol";
7+
contract NubilaNetworkScript is Script {
8+
9+
function setUp() public {}
10+
11+
function run() public {
12+
vm.startBroadcast();
13+
uint256 tge = uint256(vm.envUint("TGE"));
14+
console.log("TGE read from env:", tge);
15+
NubilaNetwork nubilaNetwork = new NubilaNetwork(msg.sender);
16+
console.log("NubilaNetwork deployed to:", address(nubilaNetwork));
17+
address[] memory beneficiaries = new address[](12);
18+
for (uint256 i = 0; i < 12; i++) {
19+
beneficiaries[i] = msg.sender;
20+
}
21+
VestingManager vestingManager = new VestingManager(address(nubilaNetwork), tge, beneficiaries);
22+
console.log("VestingManager deployed to:", address(vestingManager));
23+
vm.assertTrue(nubilaNetwork.transfer(address(vestingManager), nubilaNetwork.balanceOf(msg.sender)));
24+
25+
vm.stopBroadcast();
26+
}
27+
}

src/Counter.sol

Lines changed: 0 additions & 14 deletions
This file was deleted.

src/VestingManager.sol

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ pragma solidity ^0.8.20;
33

44
import "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
55
import "openzeppelin-contracts/contracts/access/Ownable.sol";
6+
import "openzeppelin-contracts/contracts/utils/Pausable.sol";
67

78
/// @title Vesting Manager with Vesting Schedules
8-
contract VestingManager is Ownable {
9+
contract VestingManager is Ownable, Pausable {
910
IERC20 public immutable token;
1011
uint256 public immutable tgeTimestamp;
1112

@@ -38,6 +39,7 @@ contract VestingManager is Ownable {
3839

3940
constructor(address _token, uint256 _tgeTimestamp, address[] memory beneficiaries) Ownable(msg.sender) {
4041
require(_token != address(0), "token zero");
42+
require(_tgeTimestamp > block.timestamp, "tge in past");
4143
require(beneficiaries.length == 12, "need 12 addresses");
4244
token = IERC20(_token);
4345
tgeTimestamp = _tgeTimestamp;
@@ -126,6 +128,7 @@ contract VestingManager is Ownable {
126128
require(scheduleId < schedules.length, "invalid index");
127129
require(newBeneficiary != address(0), "new beneficiary is zero");
128130
VestingSchedule storage s = schedules[scheduleId];
131+
require(s.beneficiary != newBeneficiary, "same beneficiary");
129132
s.beneficiary = newBeneficiary;
130133
emit BeneficiaryUpdated(scheduleId, newBeneficiary);
131134
}
@@ -134,7 +137,8 @@ contract VestingManager is Ownable {
134137
address beneficiary,
135138
uint256 totalAmount,
136139
Term[] memory terms
137-
) internal {
140+
) internal {
141+
require(beneficiary != address(0), "beneficiary is zero");
138142
uint256 sumWeight = 0;
139143
for (uint i = 0; i < terms.length; ++i) {
140144
if (terms[i].period == 0) {
@@ -159,7 +163,7 @@ contract VestingManager is Ownable {
159163
emit BeneficiaryUpdated(schedules.length - 1, beneficiary);
160164
}
161165

162-
function claim(uint256 scheduleId) external {
166+
function claim(uint256 scheduleId) external whenNotPaused {
163167
require(scheduleId < schedules.length, "invalid index");
164168
VestingSchedule storage s = schedules[scheduleId];
165169
require(s.termIndex < s.terms.length, "invalid term index");
@@ -182,6 +186,20 @@ contract VestingManager is Ownable {
182186
emit Vested(scheduleId, termIdx, periodIdx, s.beneficiary, amount);
183187
}
184188

189+
function pause() external onlyOwner {
190+
_pause();
191+
}
192+
193+
function unpause() external onlyOwner {
194+
_unpause();
195+
}
196+
197+
function emergencyWithdraw(uint256 amount) external onlyOwner {
198+
uint256 balance = token.balanceOf(address(this));
199+
require(amount > 0 && amount <= balance, "invalid amount");
200+
require(token.transfer(owner(), amount), "transfer failed");
201+
}
202+
185203
function numOfSchedules() external view returns (uint256) {
186204
return schedules.length;
187205
}

test/VestingManager.t.sol

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ contract VestingManagerTest is Test {
1515
event ScheduleCreated(uint256 indexed id, uint256 totalAmount);
1616
event Vested(uint256 indexed id, uint256 indexed termIndex, uint256 indexed periodIdx, address beneficiary, uint256 amount);
1717
event BeneficiaryUpdated(uint256 indexed id, address indexed newBeneficiary);
18+
event Paused(address account);
19+
event Unpaused(address account);
1820

1921
function setUp() public {
2022
beneficiaries.push(address(0x1));
@@ -28,11 +30,20 @@ contract VestingManagerTest is Test {
2830
beneficiaries.push(address(0x9));
2931
beneficiaries.push(address(0xA));
3032
beneficiaries.push(address(0xB));
31-
beneficiaries.push(address(0xC));
3233
vm.expectEmit(true, true, false, true);
3334
emit Transfer(address(0), address(this), 1_000_000_000 ether);
3435
token = new NubilaNetwork(address(this));
36+
tge = block.timestamp;
37+
vm.expectRevert("tge in past");
38+
vm.warp(block.timestamp + 30 seconds);
39+
manager = new VestingManager(address(token), tge, beneficiaries);
40+
vm.expectRevert("need 12 addresses");
3541
tge = block.timestamp + 1 minutes;
42+
manager = new VestingManager(address(token), tge, beneficiaries);
43+
beneficiaries.push(address(0x0));
44+
vm.expectRevert("beneficiary is zero");
45+
manager = new VestingManager(address(token), tge, beneficiaries);
46+
beneficiaries[11] = address(0xC);
3647
vm.expectEmit(true, false, false, true);
3748
emit ScheduleCreated(0, 210_000_000 ether);
3849
emit BeneficiaryUpdated(0, address(0x1));
@@ -73,6 +84,8 @@ contract VestingManagerTest is Test {
7384
manager.updateBeneficiary(12, address(0x456));
7485
vm.expectRevert("new beneficiary is zero");
7586
manager.updateBeneficiary(0, address(0));
87+
vm.expectRevert("same beneficiary");
88+
manager.updateBeneficiary(0, address(0x1));
7689

7790
vm.expectEmit(true, true, false, true, address(manager));
7891
emit BeneficiaryUpdated(0, address(0x456));
@@ -274,6 +287,14 @@ contract VestingManagerTest is Test {
274287
assertEq(manager.claimable(10), 18_750_000 ether);
275288
assertEq(manager.claimable(11), 62_000_000 ether);
276289
vm.expectEmit(true, true, true, true, address(manager));
290+
emit Paused(address(this));
291+
manager.pause();
292+
vm.expectRevert();
293+
manager.claim(0);
294+
vm.expectEmit(true, true, true, true, address(manager));
295+
emit Unpaused(address(this));
296+
manager.unpause();
297+
vm.expectEmit(true, true, true, true, address(manager));
277298
emit Vested(0, 0, 0, beneficiaries[0], 10_500_000 ether);
278299
manager.claim(0);
279300
vm.expectEmit(true, true, true, true, address(manager));

0 commit comments

Comments
 (0)