commit
f2c352366a
@ -0,0 +1,135 @@ |
||||
// SPDX-License-Identifier: MIT |
||||
// OpenZeppelin Contracts v4.3.2 (finance/VestingWallet.sol) |
||||
pragma solidity ^0.8.0; |
||||
|
||||
import "../token/ERC20/utils/SafeERC20.sol"; |
||||
import "../utils/Address.sol"; |
||||
import "../utils/Context.sol"; |
||||
import "../utils/math/Math.sol"; |
||||
|
||||
/** |
||||
* @title VestingWallet |
||||
* @dev This contract handles the vesting of Eth and ERC20 tokens for a given beneficiary. Custody of multiple tokens |
||||
* can be given to this contract, which will release the token to the beneficiary following a given vesting schedule. |
||||
* The vesting schedule is customizable through the {vestedAmount} function. |
||||
* |
||||
* Any token transferred to this contract will follow the vesting schedule as if they were locked from the beginning. |
||||
* Consequently, if the vesting has already started, any amount of tokens sent to this contract will (at least partly) |
||||
* be immediately releasable. |
||||
*/ |
||||
contract VestingWallet is Context { |
||||
event EtherReleased(uint256 amount); |
||||
event ERC20Released(address token, uint256 amount); |
||||
|
||||
uint256 private _released; |
||||
mapping(address => uint256) private _erc20Released; |
||||
address private immutable _beneficiary; |
||||
uint64 private immutable _start; |
||||
uint64 private immutable _duration; |
||||
|
||||
/** |
||||
* @dev Set the beneficiary, start timestamp and vesting duration of the vesting wallet. |
||||
*/ |
||||
constructor( |
||||
address beneficiaryAddress, |
||||
uint64 startTimestamp, |
||||
uint64 durationSeconds |
||||
) { |
||||
require(beneficiaryAddress != address(0), "VestingWallet: beneficiary is zero address"); |
||||
_beneficiary = beneficiaryAddress; |
||||
_start = startTimestamp; |
||||
_duration = durationSeconds; |
||||
} |
||||
|
||||
/** |
||||
* @dev The contract should be able to receive Eth. |
||||
*/ |
||||
receive() external payable virtual {} |
||||
|
||||
/** |
||||
* @dev Getter for the beneficiary address. |
||||
*/ |
||||
function beneficiary() public view virtual returns (address) { |
||||
return _beneficiary; |
||||
} |
||||
|
||||
/** |
||||
* @dev Getter for the start timestamp. |
||||
*/ |
||||
function start() public view virtual returns (uint256) { |
||||
return _start; |
||||
} |
||||
|
||||
/** |
||||
* @dev Getter for the vesting duration. |
||||
*/ |
||||
function duration() public view virtual returns (uint256) { |
||||
return _duration; |
||||
} |
||||
|
||||
/** |
||||
* @dev Amount of eth already released |
||||
*/ |
||||
function released() public view virtual returns (uint256) { |
||||
return _released; |
||||
} |
||||
|
||||
/** |
||||
* @dev Amount of token already released |
||||
*/ |
||||
function released(address token) public view virtual returns (uint256) { |
||||
return _erc20Released[token]; |
||||
} |
||||
|
||||
/** |
||||
* @dev Release the native token (ether) that have already vested. |
||||
* |
||||
* Emits a {TokensReleased} event. |
||||
*/ |
||||
function release() public virtual { |
||||
uint256 releasable = vestedAmount(uint64(block.timestamp)) - released(); |
||||
_released += releasable; |
||||
emit EtherReleased(releasable); |
||||
Address.sendValue(payable(beneficiary()), releasable); |
||||
} |
||||
|
||||
/** |
||||
* @dev Release the tokens that have already vested. |
||||
* |
||||
* Emits a {TokensReleased} event. |
||||
*/ |
||||
function release(address token) public virtual { |
||||
uint256 releasable = vestedAmount(token, uint64(block.timestamp)) - released(token); |
||||
_erc20Released[token] += releasable; |
||||
emit ERC20Released(token, releasable); |
||||
SafeERC20.safeTransfer(IERC20(token), beneficiary(), releasable); |
||||
} |
||||
|
||||
/** |
||||
* @dev Calculates the amount of ether that has already vested. Default implementation is a linear vesting curve. |
||||
*/ |
||||
function vestedAmount(uint64 timestamp) public view virtual returns (uint256) { |
||||
return _vestingSchedule(address(this).balance + released(), timestamp); |
||||
} |
||||
|
||||
/** |
||||
* @dev Calculates the amount of tokens that has already vested. Default implementation is a linear vesting curve. |
||||
*/ |
||||
function vestedAmount(address token, uint64 timestamp) public view virtual returns (uint256) { |
||||
return _vestingSchedule(IERC20(token).balanceOf(address(this)) + released(token), timestamp); |
||||
} |
||||
|
||||
/** |
||||
* @dev Virtual implementation of the vesting formula. This returns the amout vested, as a function of time, for |
||||
* an asset given its total historical allocation. |
||||
*/ |
||||
function _vestingSchedule(uint256 totalAllocation, uint64 timestamp) internal view virtual returns (uint256) { |
||||
if (timestamp < start()) { |
||||
return 0; |
||||
} else if (timestamp > start() + duration()) { |
||||
return totalAllocation; |
||||
} else { |
||||
return (totalAllocation * (timestamp - start())) / duration(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,114 @@ |
||||
// SPDX-License-Identifier: MIT |
||||
// OpenZeppelin Contracts v4.3.2 (governance/extensions/GovernorSettings.sol) |
||||
|
||||
pragma solidity ^0.8.0; |
||||
|
||||
import "../Governor.sol"; |
||||
|
||||
/** |
||||
* @dev Extension of {Governor} for settings updatable through governance. |
||||
* |
||||
* _Available since v4.4._ |
||||
*/ |
||||
abstract contract GovernorSettings is Governor { |
||||
uint256 private _votingDelay; |
||||
uint256 private _votingPeriod; |
||||
uint256 private _proposalThreshold; |
||||
|
||||
event VotingDelaySet(uint256 oldVotingDelay, uint256 newVotingDelay); |
||||
event VotingPeriodSet(uint256 oldVotingPeriod, uint256 newVotingPeriod); |
||||
event ProposalThresholdSet(uint256 oldProposalThreshold, uint256 newProposalThreshold); |
||||
|
||||
/** |
||||
* @dev Initialize the governance parameters. |
||||
*/ |
||||
constructor( |
||||
uint256 initialVotingDelay, |
||||
uint256 initialVotingPeriod, |
||||
uint256 initialProposalThreshold |
||||
) { |
||||
_setVotingDelay(initialVotingDelay); |
||||
_setVotingPeriod(initialVotingPeriod); |
||||
_setProposalThreshold(initialProposalThreshold); |
||||
} |
||||
|
||||
/** |
||||
* @dev See {IGovernor-votingDelay}. |
||||
*/ |
||||
function votingDelay() public view virtual override returns (uint256) { |
||||
return _votingDelay; |
||||
} |
||||
|
||||
/** |
||||
* @dev See {IGovernor-votingPeriod}. |
||||
*/ |
||||
function votingPeriod() public view virtual override returns (uint256) { |
||||
return _votingPeriod; |
||||
} |
||||
|
||||
/** |
||||
* @dev See {Governor-proposalThreshold}. |
||||
*/ |
||||
function proposalThreshold() public view virtual override returns (uint256) { |
||||
return _proposalThreshold; |
||||
} |
||||
|
||||
/** |
||||
* @dev Update the voting delay. This operation can only be performed through a governance proposal. |
||||
* |
||||
* Emits a {VotingDelaySet} event. |
||||
*/ |
||||
function setVotingDelay(uint256 newVotingDelay) public onlyGovernance { |
||||
_setVotingDelay(newVotingDelay); |
||||
} |
||||
|
||||
/** |
||||
* @dev Update the voting period. This operation can only be performed through a governance proposal. |
||||
* |
||||
* Emits a {VotingPeriodSet} event. |
||||
*/ |
||||
function setVotingPeriod(uint256 newVotingPeriod) public onlyGovernance { |
||||
_setVotingPeriod(newVotingPeriod); |
||||
} |
||||
|
||||
/** |
||||
* @dev Update the proposal threshold. This operation can only be performed through a governance proposal. |
||||
* |
||||
* Emits a {ProposalThresholdSet} event. |
||||
*/ |
||||
function setProposalThreshold(uint256 newProposalThreshold) public onlyGovernance { |
||||
_setProposalThreshold(newProposalThreshold); |
||||
} |
||||
|
||||
/** |
||||
* @dev Internal setter for the voting delay. |
||||
* |
||||
* Emits a {VotingDelaySet} event. |
||||
*/ |
||||
function _setVotingDelay(uint256 newVotingDelay) internal virtual { |
||||
emit VotingDelaySet(_votingDelay, newVotingDelay); |
||||
_votingDelay = newVotingDelay; |
||||
} |
||||
|
||||
/** |
||||
* @dev Internal setter for the voting period. |
||||
* |
||||
* Emits a {VotingPeriodSet} event. |
||||
*/ |
||||
function _setVotingPeriod(uint256 newVotingPeriod) internal virtual { |
||||
// voting period must be at least one block long |
||||
require(newVotingPeriod > 0, "GovernorSettings: voting period too low"); |
||||
emit VotingPeriodSet(_votingPeriod, newVotingPeriod); |
||||
_votingPeriod = newVotingPeriod; |
||||
} |
||||
|
||||
/** |
||||
* @dev Internal setter for the proposal threshold. |
||||
* |
||||
* Emits a {ProposalThresholdSet} event. |
||||
*/ |
||||
function _setProposalThreshold(uint256 newProposalThreshold) internal virtual { |
||||
emit ProposalThresholdSet(_proposalThreshold, newProposalThreshold); |
||||
_proposalThreshold = newProposalThreshold; |
||||
} |
||||
} |
@ -0,0 +1,96 @@ |
||||
// SPDX-License-Identifier: MIT |
||||
pragma solidity ^0.8.2; |
||||
|
||||
import "../../governance/Governor.sol"; |
||||
import "../../governance/extensions/GovernorCountingSimple.sol"; |
||||
import "../../governance/extensions/GovernorVotes.sol"; |
||||
import "../../governance/extensions/GovernorVotesQuorumFraction.sol"; |
||||
import "../../governance/extensions/GovernorTimelockControl.sol"; |
||||
|
||||
contract MyGovernor1 is |
||||
Governor, |
||||
GovernorTimelockControl, |
||||
GovernorVotes, |
||||
GovernorVotesQuorumFraction, |
||||
GovernorCountingSimple |
||||
{ |
||||
constructor(ERC20Votes _token, TimelockController _timelock) |
||||
Governor("MyGovernor") |
||||
GovernorVotes(_token) |
||||
GovernorVotesQuorumFraction(4) |
||||
GovernorTimelockControl(_timelock) |
||||
{} |
||||
|
||||
function votingDelay() public pure override returns (uint256) { |
||||
return 1; // 1 block |
||||
} |
||||
|
||||
function votingPeriod() public pure override returns (uint256) { |
||||
return 45818; // 1 week |
||||
} |
||||
|
||||
// The following functions are overrides required by Solidity. |
||||
|
||||
function quorum(uint256 blockNumber) |
||||
public |
||||
view |
||||
override(IGovernor, GovernorVotesQuorumFraction) |
||||
returns (uint256) |
||||
{ |
||||
return super.quorum(blockNumber); |
||||
} |
||||
|
||||
function getVotes(address account, uint256 blockNumber) |
||||
public |
||||
view |
||||
override(IGovernor, GovernorVotes) |
||||
returns (uint256) |
||||
{ |
||||
return super.getVotes(account, blockNumber); |
||||
} |
||||
|
||||
function state(uint256 proposalId) public view override(Governor, GovernorTimelockControl) returns (ProposalState) { |
||||
return super.state(proposalId); |
||||
} |
||||
|
||||
function propose( |
||||
address[] memory targets, |
||||
uint256[] memory values, |
||||
bytes[] memory calldatas, |
||||
string memory description |
||||
) public override(Governor, IGovernor) returns (uint256) { |
||||
return super.propose(targets, values, calldatas, description); |
||||
} |
||||
|
||||
function _execute( |
||||
uint256 proposalId, |
||||
address[] memory targets, |
||||
uint256[] memory values, |
||||
bytes[] memory calldatas, |
||||
bytes32 descriptionHash |
||||
) internal override(Governor, GovernorTimelockControl) { |
||||
super._execute(proposalId, targets, values, calldatas, descriptionHash); |
||||
} |
||||
|
||||
function _cancel( |
||||
address[] memory targets, |
||||
uint256[] memory values, |
||||
bytes[] memory calldatas, |
||||
bytes32 descriptionHash |
||||
) internal override(Governor, GovernorTimelockControl) returns (uint256) { |
||||
return super._cancel(targets, values, calldatas, descriptionHash); |
||||
} |
||||
|
||||
function _executor() internal view override(Governor, GovernorTimelockControl) returns (address) { |
||||
return super._executor(); |
||||
} |
||||
|
||||
function supportsInterface(bytes4 interfaceId) |
||||
public |
||||
view |
||||
override(Governor, GovernorTimelockControl) |
||||
returns (bool) |
||||
{ |
||||
return super.supportsInterface(interfaceId); |
||||
} |
||||
} |
@ -0,0 +1,102 @@ |
||||
// SPDX-License-Identifier: MIT |
||||
pragma solidity ^0.8.2; |
||||
|
||||
import "../../governance/Governor.sol"; |
||||
import "../../governance/extensions/GovernorProposalThreshold.sol"; |
||||
import "../../governance/extensions/GovernorCountingSimple.sol"; |
||||
import "../../governance/extensions/GovernorVotes.sol"; |
||||
import "../../governance/extensions/GovernorVotesQuorumFraction.sol"; |
||||
import "../../governance/extensions/GovernorTimelockControl.sol"; |
||||
|
||||
contract MyGovernor2 is |
||||
Governor, |
||||
GovernorTimelockControl, |
||||
GovernorProposalThreshold, |
||||
GovernorVotes, |
||||
GovernorVotesQuorumFraction, |
||||
GovernorCountingSimple |
||||
{ |
||||
constructor(ERC20Votes _token, TimelockController _timelock) |
||||
Governor("MyGovernor") |
||||
GovernorVotes(_token) |
||||
GovernorVotesQuorumFraction(4) |
||||
GovernorTimelockControl(_timelock) |
||||
{} |
||||
|
||||
function votingDelay() public pure override returns (uint256) { |
||||
return 1; // 1 block |
||||
} |
||||
|
||||
function votingPeriod() public pure override returns (uint256) { |
||||
return 45818; // 1 week |
||||
} |
||||
|
||||
function proposalThreshold() public pure override returns (uint256) { |
||||
return 1000e18; |
||||
} |
||||
|
||||
// The following functions are overrides required by Solidity. |
||||
|
||||
function quorum(uint256 blockNumber) |
||||
public |
||||
view |
||||
override(IGovernor, GovernorVotesQuorumFraction) |
||||
returns (uint256) |
||||
{ |
||||
return super.quorum(blockNumber); |
||||
} |
||||
|
||||
function getVotes(address account, uint256 blockNumber) |
||||
public |
||||
view |
||||
override(IGovernor, GovernorVotes) |
||||
returns (uint256) |
||||
{ |
||||
return super.getVotes(account, blockNumber); |
||||
} |
||||
|
||||
function state(uint256 proposalId) public view override(Governor, GovernorTimelockControl) returns (ProposalState) { |
||||
return super.state(proposalId); |
||||
} |
||||
|
||||
function propose( |
||||
address[] memory targets, |
||||
uint256[] memory values, |
||||
bytes[] memory calldatas, |
||||
string memory description |
||||
) public override(Governor, GovernorProposalThreshold, IGovernor) returns (uint256) { |
||||
return super.propose(targets, values, calldatas, description); |
||||
} |
||||
|
||||
function _execute( |
||||
uint256 proposalId, |
||||
address[] memory targets, |
||||
uint256[] memory values, |
||||
bytes[] memory calldatas, |
||||
bytes32 descriptionHash |
||||
) internal override(Governor, GovernorTimelockControl) { |
||||
super._execute(proposalId, targets, values, calldatas, descriptionHash); |
||||
} |
||||
|
||||
function _cancel( |
||||
address[] memory targets, |
||||
uint256[] memory values, |
||||
bytes[] memory calldatas, |
||||
bytes32 descriptionHash |
||||
) internal override(Governor, GovernorTimelockControl) returns (uint256) { |
||||
return super._cancel(targets, values, calldatas, descriptionHash); |
||||
} |
||||
|
||||
function _executor() internal view override(Governor, GovernorTimelockControl) returns (address) { |
||||
return super._executor(); |
||||
} |
||||
|
||||
function supportsInterface(bytes4 interfaceId) |
||||
public |
||||
view |
||||
override(Governor, GovernorTimelockControl) |
||||
returns (bool) |
||||
{ |
||||
return super.supportsInterface(interfaceId); |
||||
} |
||||
} |
@ -0,0 +1,105 @@ |
||||
// SPDX-License-Identifier: MIT |
||||
pragma solidity ^0.8.2; |
||||
|
||||
import "../../governance/Governor.sol"; |
||||
import "../../governance/compatibility/GovernorCompatibilityBravo.sol"; |
||||
import "../../governance/extensions/GovernorVotes.sol"; |
||||
import "../../governance/extensions/GovernorVotesQuorumFraction.sol"; |
||||
import "../../governance/extensions/GovernorTimelockControl.sol"; |
||||
|
||||
contract MyGovernor is |
||||
Governor, |
||||
GovernorTimelockControl, |
||||
GovernorCompatibilityBravo, |
||||
GovernorVotes, |
||||
GovernorVotesQuorumFraction |
||||
{ |
||||
constructor(ERC20Votes _token, TimelockController _timelock) |
||||
Governor("MyGovernor") |
||||
GovernorVotes(_token) |
||||
GovernorVotesQuorumFraction(4) |
||||
GovernorTimelockControl(_timelock) |
||||
{} |
||||
|
||||
function votingDelay() public pure override returns (uint256) { |
||||
return 1; // 1 block |
||||
} |
||||
|
||||
function votingPeriod() public pure override returns (uint256) { |
||||
return 45818; // 1 week |
||||
} |
||||
|
||||
function proposalThreshold() public pure override returns (uint256) { |
||||
return 1000e18; |
||||
} |
||||
|
||||
// The following functions are overrides required by Solidity. |
||||
|
||||
function quorum(uint256 blockNumber) |
||||
public |
||||
view |
||||
override(IGovernor, GovernorVotesQuorumFraction) |
||||
returns (uint256) |
||||
{ |
||||
return super.quorum(blockNumber); |
||||
} |
||||
|
||||
function getVotes(address account, uint256 blockNumber) |
||||
public |
||||
view |
||||
override(IGovernor, GovernorVotes) |
||||
returns (uint256) |
||||
{ |
||||
return super.getVotes(account, blockNumber); |
||||
} |
||||
|
||||
function state(uint256 proposalId) |
||||
public |
||||
view |
||||
override(Governor, IGovernor, GovernorTimelockControl) |
||||
returns (ProposalState) |
||||
{ |
||||
return super.state(proposalId); |
||||
} |
||||
|
||||
function propose( |
||||
address[] memory targets, |
||||
uint256[] memory values, |
||||
bytes[] memory calldatas, |
||||
string memory description |
||||
) public override(Governor, GovernorCompatibilityBravo, IGovernor) returns (uint256) { |
||||
return super.propose(targets, values, calldatas, description); |
||||
} |
||||
|
||||
function _execute( |
||||
uint256 proposalId, |
||||
address[] memory targets, |
||||
uint256[] memory values, |
||||
bytes[] memory calldatas, |
||||
bytes32 descriptionHash |
||||
) internal override(Governor, GovernorTimelockControl) { |
||||
super._execute(proposalId, targets, values, calldatas, descriptionHash); |
||||
} |
||||
|
||||
function _cancel( |
||||
address[] memory targets, |
||||
uint256[] memory values, |
||||
bytes[] memory calldatas, |
||||
bytes32 descriptionHash |
||||
) internal override(Governor, GovernorTimelockControl) returns (uint256) { |
||||
return super._cancel(targets, values, calldatas, descriptionHash); |
||||
} |
||||
|
||||
function _executor() internal view override(Governor, GovernorTimelockControl) returns (address) { |
||||
return super._executor(); |
||||
} |
||||
|
||||
function supportsInterface(bytes4 interfaceId) |
||||
public |
||||
view |
||||
override(Governor, IERC165, GovernorTimelockControl) |
||||
returns (bool) |
||||
{ |
||||
return super.supportsInterface(interfaceId); |
||||
} |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue