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