VestingWallet.sol 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v4.8.0-rc.0) (finance/VestingWallet.sol)
  3. pragma solidity ^0.8.0;
  4. import "../token/ERC20/utils/SafeERC20.sol";
  5. import "../utils/Address.sol";
  6. import "../utils/Context.sol";
  7. /**
  8. * @title VestingWallet
  9. * @dev This contract handles the vesting of Eth and ERC20 tokens for a given beneficiary. Custody of multiple tokens
  10. * can be given to this contract, which will release the token to the beneficiary following a given vesting schedule.
  11. * The vesting schedule is customizable through the {vestedAmount} function.
  12. *
  13. * Any token transferred to this contract will follow the vesting schedule as if they were locked from the beginning.
  14. * Consequently, if the vesting has already started, any amount of tokens sent to this contract will (at least partly)
  15. * be immediately releasable.
  16. */
  17. contract VestingWallet is Context {
  18. event EtherReleased(uint256 amount);
  19. event ERC20Released(address indexed token, uint256 amount);
  20. uint256 private _released;
  21. mapping(address => uint256) private _erc20Released;
  22. address private immutable _beneficiary;
  23. uint64 private immutable _start;
  24. uint64 private immutable _duration;
  25. /**
  26. * @dev Set the beneficiary, start timestamp and vesting duration of the vesting wallet.
  27. */
  28. constructor(
  29. address beneficiaryAddress,
  30. uint64 startTimestamp,
  31. uint64 durationSeconds
  32. ) payable {
  33. require(beneficiaryAddress != address(0), "VestingWallet: beneficiary is zero address");
  34. _beneficiary = beneficiaryAddress;
  35. _start = startTimestamp;
  36. _duration = durationSeconds;
  37. }
  38. /**
  39. * @dev The contract should be able to receive Eth.
  40. */
  41. receive() external payable virtual {}
  42. /**
  43. * @dev Getter for the beneficiary address.
  44. */
  45. function beneficiary() public view virtual returns (address) {
  46. return _beneficiary;
  47. }
  48. /**
  49. * @dev Getter for the start timestamp.
  50. */
  51. function start() public view virtual returns (uint256) {
  52. return _start;
  53. }
  54. /**
  55. * @dev Getter for the vesting duration.
  56. */
  57. function duration() public view virtual returns (uint256) {
  58. return _duration;
  59. }
  60. /**
  61. * @dev Amount of eth already released
  62. */
  63. function released() public view virtual returns (uint256) {
  64. return _released;
  65. }
  66. /**
  67. * @dev Amount of token already released
  68. */
  69. function released(address token) public view virtual returns (uint256) {
  70. return _erc20Released[token];
  71. }
  72. /**
  73. * @dev Getter for the amount of releasable eth.
  74. */
  75. function releasable() public view virtual returns (uint256) {
  76. return vestedAmount(uint64(block.timestamp)) - released();
  77. }
  78. /**
  79. * @dev Getter for the amount of releasable `token` tokens. `token` should be the address of an
  80. * IERC20 contract.
  81. */
  82. function releasable(address token) public view virtual returns (uint256) {
  83. return vestedAmount(token, uint64(block.timestamp)) - released(token);
  84. }
  85. /**
  86. * @dev Release the native token (ether) that have already vested.
  87. *
  88. * Emits a {EtherReleased} event.
  89. */
  90. function release() public virtual {
  91. uint256 amount = releasable();
  92. _released += amount;
  93. emit EtherReleased(amount);
  94. Address.sendValue(payable(beneficiary()), amount);
  95. }
  96. /**
  97. * @dev Release the tokens that have already vested.
  98. *
  99. * Emits a {ERC20Released} event.
  100. */
  101. function release(address token) public virtual {
  102. uint256 amount = releasable(token);
  103. _erc20Released[token] += amount;
  104. emit ERC20Released(token, amount);
  105. SafeERC20.safeTransfer(IERC20(token), beneficiary(), amount);
  106. }
  107. /**
  108. * @dev Calculates the amount of ether that has already vested. Default implementation is a linear vesting curve.
  109. */
  110. function vestedAmount(uint64 timestamp) public view virtual returns (uint256) {
  111. return _vestingSchedule(address(this).balance + released(), timestamp);
  112. }
  113. /**
  114. * @dev Calculates the amount of tokens that has already vested. Default implementation is a linear vesting curve.
  115. */
  116. function vestedAmount(address token, uint64 timestamp) public view virtual returns (uint256) {
  117. return _vestingSchedule(IERC20(token).balanceOf(address(this)) + released(token), timestamp);
  118. }
  119. /**
  120. * @dev Virtual implementation of the vesting formula. This returns the amount vested, as a function of time, for
  121. * an asset given its total historical allocation.
  122. */
  123. function _vestingSchedule(uint256 totalAllocation, uint64 timestamp) internal view virtual returns (uint256) {
  124. if (timestamp < start()) {
  125. return 0;
  126. } else if (timestamp > start() + duration()) {
  127. return totalAllocation;
  128. } else {
  129. return (totalAllocation * (timestamp - start())) / duration();
  130. }
  131. }
  132. }