Update docs
This commit is contained in:
99
contracts/token/ERC20/utils/SafeERC20.sol
Normal file
99
contracts/token/ERC20/utils/SafeERC20.sol
Normal file
@ -0,0 +1,99 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import "../IERC20.sol";
|
||||
import "../../../utils/Address.sol";
|
||||
|
||||
/**
|
||||
* @title SafeERC20
|
||||
* @dev Wrappers around ERC20 operations that throw on failure (when the token
|
||||
* contract returns false). Tokens that return no value (and instead revert or
|
||||
* throw on failure) are also supported, non-reverting calls are assumed to be
|
||||
* successful.
|
||||
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
|
||||
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
|
||||
*/
|
||||
library SafeERC20 {
|
||||
using Address for address;
|
||||
|
||||
function safeTransfer(
|
||||
IERC20 token,
|
||||
address to,
|
||||
uint256 value
|
||||
) internal {
|
||||
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
|
||||
}
|
||||
|
||||
function safeTransferFrom(
|
||||
IERC20 token,
|
||||
address from,
|
||||
address to,
|
||||
uint256 value
|
||||
) internal {
|
||||
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Deprecated. This function has issues similar to the ones found in
|
||||
* {IERC20-approve}, and its usage is discouraged.
|
||||
*
|
||||
* Whenever possible, use {safeIncreaseAllowance} and
|
||||
* {safeDecreaseAllowance} instead.
|
||||
*/
|
||||
function safeApprove(
|
||||
IERC20 token,
|
||||
address spender,
|
||||
uint256 value
|
||||
) internal {
|
||||
// safeApprove should only be called when setting an initial allowance,
|
||||
// or when resetting it to zero. To increase and decrease it, use
|
||||
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
|
||||
require(
|
||||
(value == 0) || (token.allowance(address(this), spender) == 0),
|
||||
"SafeERC20: approve from non-zero to non-zero allowance"
|
||||
);
|
||||
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
|
||||
}
|
||||
|
||||
function safeIncreaseAllowance(
|
||||
IERC20 token,
|
||||
address spender,
|
||||
uint256 value
|
||||
) internal {
|
||||
uint256 newAllowance = token.allowance(address(this), spender) + value;
|
||||
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
|
||||
}
|
||||
|
||||
function safeDecreaseAllowance(
|
||||
IERC20 token,
|
||||
address spender,
|
||||
uint256 value
|
||||
) internal {
|
||||
unchecked {
|
||||
uint256 oldAllowance = token.allowance(address(this), spender);
|
||||
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
|
||||
uint256 newAllowance = oldAllowance - value;
|
||||
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
|
||||
* on the return value: the return value is optional (but if data is returned, it must not be false).
|
||||
* @param token The token targeted by the call.
|
||||
* @param data The call data (encoded using abi.encode or one of its variants).
|
||||
*/
|
||||
function _callOptionalReturn(IERC20 token, bytes memory data) private {
|
||||
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
|
||||
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
|
||||
// the target address contains contract code and also asserts for success in the low-level call.
|
||||
|
||||
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
|
||||
if (returndata.length > 0) {
|
||||
// Return data is optional
|
||||
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
|
||||
}
|
||||
}
|
||||
}
|
||||
70
contracts/token/ERC20/utils/TokenTimelock.sol
Normal file
70
contracts/token/ERC20/utils/TokenTimelock.sol
Normal file
@ -0,0 +1,70 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/TokenTimelock.sol)
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import "./SafeERC20.sol";
|
||||
|
||||
/**
|
||||
* @dev A token holder contract that will allow a beneficiary to extract the
|
||||
* tokens after a given release time.
|
||||
*
|
||||
* Useful for simple vesting schedules like "advisors get all of their tokens
|
||||
* after 1 year".
|
||||
*/
|
||||
contract TokenTimelock {
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
// ERC20 basic token contract being held
|
||||
IERC20 private immutable _token;
|
||||
|
||||
// beneficiary of tokens after they are released
|
||||
address private immutable _beneficiary;
|
||||
|
||||
// timestamp when token release is enabled
|
||||
uint256 private immutable _releaseTime;
|
||||
|
||||
constructor(
|
||||
IERC20 token_,
|
||||
address beneficiary_,
|
||||
uint256 releaseTime_
|
||||
) {
|
||||
require(releaseTime_ > block.timestamp, "TokenTimelock: release time is before current time");
|
||||
_token = token_;
|
||||
_beneficiary = beneficiary_;
|
||||
_releaseTime = releaseTime_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the token being held.
|
||||
*/
|
||||
function token() public view virtual returns (IERC20) {
|
||||
return _token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the beneficiary of the tokens.
|
||||
*/
|
||||
function beneficiary() public view virtual returns (address) {
|
||||
return _beneficiary;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the time when the tokens are released.
|
||||
*/
|
||||
function releaseTime() public view virtual returns (uint256) {
|
||||
return _releaseTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Transfers tokens held by timelock to beneficiary.
|
||||
*/
|
||||
function release() public virtual {
|
||||
require(block.timestamp >= releaseTime(), "TokenTimelock: current time is before release time");
|
||||
|
||||
uint256 amount = token().balanceOf(address(this));
|
||||
require(amount > 0, "TokenTimelock: no tokens to release");
|
||||
|
||||
token().safeTransfer(beneficiary(), amount);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user