VestingWallet.sol 4.6 KB

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