@@ -6,24 +6,28 @@ import {IERC20} from "../token/ERC20/IERC20.sol";
6
6
import {SafeERC20} from "../token/ERC20/utils/SafeERC20.sol " ;
7
7
import {Address} from "../utils/Address.sol " ;
8
8
import {Context} from "../utils/Context.sol " ;
9
+ import {Ownable} from "../access/Ownable.sol " ;
9
10
10
11
/**
11
- * @title VestingWallet
12
- * @dev This contract handles the vesting of Eth and ERC20 tokens for a given beneficiary. Custody of multiple tokens
13
- * can be given to this contract, which will release the token to the beneficiary following a given vesting schedule.
14
- * The vesting schedule is customizable through the {vestedAmount} function.
12
+ * @dev A vesting wallet is an ownable contract that can receive native currency and ERC20 tokens, and release these
13
+ * assets to the wallet owner, also referred to as "beneficiary", according to a vesting schedule.
15
14
*
16
- * Any token transferred to this contract will follow the vesting schedule as if they were locked from the beginning.
15
+ * Any assets transferred to this contract will follow the vesting schedule as if they were locked from the beginning.
17
16
* Consequently, if the vesting has already started, any amount of tokens sent to this contract will (at least partly)
18
17
* be immediately releasable.
19
18
*
20
19
* By setting the duration to 0, one can configure this contract to behave like an asset timelock that hold tokens for
21
20
* a beneficiary until a specified time.
22
21
*
22
+ * NOTE: Since the wallet is {Ownable}, and ownership can be transferred, it is possible to sell unvested tokens.
23
+ * Preventing this in a smart contract is difficult, considering that: 1) a beneficiary address could be a
24
+ * counterfactually deployed contract, 2) there is likely to be a migration path for EOAs to become contracts in the
25
+ * near future.
26
+ *
23
27
* NOTE: When using this contract with any token whose balance is adjusted automatically (i.e. a rebase token), make sure
24
28
* to account the supply/balance adjustment in the vesting schedule to ensure the vested amount is as intended.
25
29
*/
26
- contract VestingWallet is Context {
30
+ contract VestingWallet is Context , Ownable {
27
31
event EtherReleased (uint256 amount );
28
32
event ERC20Released (address indexed token , uint256 amount );
29
33
@@ -34,18 +38,18 @@ contract VestingWallet is Context {
34
38
35
39
uint256 private _released;
36
40
mapping (address => uint256 ) private _erc20Released;
37
- address private immutable _beneficiary;
38
41
uint64 private immutable _start;
39
42
uint64 private immutable _duration;
40
43
41
44
/**
42
- * @dev Set the beneficiary, start timestamp and vesting duration of the vesting wallet.
45
+ * @dev Sets the sender as the initial owner, the beneficiary as the pending owner, the start timestamp and the
46
+ * vesting duration of the vesting wallet.
43
47
*/
44
- constructor (address beneficiaryAddress , uint64 startTimestamp , uint64 durationSeconds ) payable {
45
- if (beneficiaryAddress == address (0 )) {
48
+ constructor (address beneficiary , uint64 startTimestamp , uint64 durationSeconds ) payable Ownable (beneficiary) {
49
+ if (beneficiary == address (0 )) {
46
50
revert VestingWalletInvalidBeneficiary (address (0 ));
47
51
}
48
- _beneficiary = beneficiaryAddress;
52
+
49
53
_start = startTimestamp;
50
54
_duration = durationSeconds;
51
55
}
@@ -55,13 +59,6 @@ contract VestingWallet is Context {
55
59
*/
56
60
receive () external payable virtual {}
57
61
58
- /**
59
- * @dev Getter for the beneficiary address.
60
- */
61
- function beneficiary () public view virtual returns (address ) {
62
- return _beneficiary;
63
- }
64
-
65
62
/**
66
63
* @dev Getter for the start timestamp.
67
64
*/
@@ -121,7 +118,7 @@ contract VestingWallet is Context {
121
118
uint256 amount = releasable ();
122
119
_released += amount;
123
120
emit EtherReleased (amount);
124
- Address.sendValue (payable (beneficiary ()), amount);
121
+ Address.sendValue (payable (owner ()), amount);
125
122
}
126
123
127
124
/**
@@ -133,7 +130,7 @@ contract VestingWallet is Context {
133
130
uint256 amount = releasable (token);
134
131
_erc20Released[token] += amount;
135
132
emit ERC20Released (token, amount);
136
- SafeERC20.safeTransfer (IERC20 (token), beneficiary (), amount);
133
+ SafeERC20.safeTransfer (IERC20 (token), owner (), amount);
137
134
}
138
135
139
136
/**
0 commit comments