@@ -4,8 +4,8 @@ pragma solidity ^0.8.20;
4
4
// Based on OpenZeppelin's VestingWallet & VestingWalletCliff contracts:
5
5
// https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/finance
6
6
7
- import { SafeERC20, IERC20 } from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol " ;
8
7
import { Ownable } from "openzeppelin-contracts/access/Ownable.sol " ;
8
+ import { IERC20 , SafeERC20 } from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol " ;
9
9
10
10
contract EnsoVestingWallet is Ownable {
11
11
using SafeERC20 for IERC20 ;
@@ -16,7 +16,7 @@ contract EnsoVestingWallet is Ownable {
16
16
uint256 public released;
17
17
bool public revoked;
18
18
bool public immutable revocable;
19
-
19
+
20
20
IERC20 private immutable _token;
21
21
address private immutable _revoker;
22
22
uint64 private immutable _start;
@@ -28,7 +28,16 @@ contract EnsoVestingWallet is Ownable {
28
28
error NotRevocable ();
29
29
error NotRevoker (address sender , address revoker );
30
30
31
- constructor (IERC20 token , address revoker , address beneficiary , uint64 startTimestamp , uint64 durationSeconds , uint64 cliffSeconds ) Ownable (beneficiary) {
31
+ constructor (
32
+ IERC20 token ,
33
+ address revoker ,
34
+ address beneficiary ,
35
+ uint64 startTimestamp ,
36
+ uint64 durationSeconds ,
37
+ uint64 cliffSeconds
38
+ )
39
+ Ownable (beneficiary)
40
+ {
32
41
if (cliffSeconds > durationSeconds) {
33
42
revert InvalidCliffDuration (cliffSeconds, durationSeconds);
34
43
}
@@ -60,10 +69,11 @@ contract EnsoVestingWallet is Ownable {
60
69
* @dev Getter for the end timestamp.
61
70
*/
62
71
function end () public view returns (uint256 ) {
72
+ // @audit return _start + _duration?
63
73
return start () + duration ();
64
74
}
65
75
66
- /**
76
+ /**
67
77
* @dev Getter for the cliff timestamp.
68
78
*/
69
79
function cliff () public view virtual returns (uint256 ) {
@@ -87,7 +97,8 @@ contract EnsoVestingWallet is Ownable {
87
97
/**
88
98
* @dev Getter for the amount of releasable tokens.
89
99
*/
90
- function releasable () public view returns (uint256 ) {
100
+ function releasable () public view returns (uint256 ) {
101
+ // @audit return `_vestingSchedule(...)`?
91
102
return vestedAmount (uint64 (block .timestamp )) - released;
92
103
}
93
104
@@ -122,6 +133,7 @@ contract EnsoVestingWallet is Ownable {
122
133
if (! revocable) revert NotRevocable ();
123
134
if (msg .sender != _revoker) revert NotRevoker (msg .sender , _revoker);
124
135
release (); // first, release funds beneficiary is entitled to up to this point
136
+ // @audit CEI pattern violated, create a private `_relase()` that skips checking `revoked`
125
137
revoked = true ;
126
138
uint256 amount = _token.balanceOf (address (this ));
127
139
_token.safeTransfer (receiver, amount);
@@ -132,10 +144,7 @@ contract EnsoVestingWallet is Ownable {
132
144
* @dev Implementation of the vesting formula. This returns the amount vested, as a function of time, for
133
145
* an asset given its total historical allocation. Returns 0 if the {cliff} timestamp is not met.
134
146
*/
135
- function _vestingSchedule (
136
- uint256 totalAllocation ,
137
- uint64 timestamp
138
- ) internal view returns (uint256 ) {
147
+ function _vestingSchedule (uint256 totalAllocation , uint64 timestamp ) internal view returns (uint256 ) {
139
148
if (revoked || timestamp < cliff ()) {
140
149
return 0 ;
141
150
} else if (timestamp >= end ()) {
@@ -144,4 +153,4 @@ contract EnsoVestingWallet is Ownable {
144
153
return (totalAllocation * (timestamp - start ())) / duration ();
145
154
}
146
155
}
147
- }
156
+ }
0 commit comments