Source Code
Overview
MNT Balance
0 MNT
More Info
ContractCreator
Multichain Info
N/A
Loading...
Loading
Contract Name:
TokenVestingManagerFactory
Compiler Version
v0.8.18+commit.87f61d96
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.18; import { Create2 } from "@openzeppelin/contracts/utils/Create2.sol"; import { ITokenVestingManagerFactory } from "../interfaces/ITokenVestingManagerFactory.sol"; import { TokenVestingManager } from "../TokenVestingManager.sol"; /// @title TokenVestingManager Factory /// @notice Allows anyone to reliably deploy a new `TokenVestingManager` contract using deterministic addresses. contract TokenVestingManagerFactory is ITokenVestingManagerFactory { /// @notice Creates a new TokenVestingManager instance /// @param tokenAddress The address of the ERC20 token to be used in the TokenVestingManager /// @return The address of the newly created TokenVestingManager contract function newTokenVestingManager( address tokenAddress ) external override returns (TokenVestingManager) { TokenVestingManager tokenVestingManager = new TokenVestingManager( tokenAddress ); emit TokenVestingManagerCreated(tokenVestingManager); tokenVestingManager.setAdmin(msg.sender, true); tokenVestingManager.setAdmin(address(this), false); return tokenVestingManager; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol) pragma solidity ^0.8.0; import "../token/ERC20/IERC20.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.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; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ 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)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ 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"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @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"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @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). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // 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 cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Create2.sol) pragma solidity ^0.8.0; /** * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer. * `CREATE2` can be used to compute in advance the address where a smart * contract will be deployed, which allows for interesting new mechanisms known * as 'counterfactual interactions'. * * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more * information. */ library Create2 { /** * @dev Deploys a contract using `CREATE2`. The address where the contract * will be deployed can be known in advance via {computeAddress}. * * The bytecode for a contract can be obtained from Solidity with * `type(contractName).creationCode`. * * Requirements: * * - `bytecode` must not be empty. * - `salt` must have not been used for `bytecode` already. * - the factory must have a balance of at least `amount`. * - if `amount` is non-zero, `bytecode` must have a `payable` constructor. */ function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address addr) { require(address(this).balance >= amount, "Create2: insufficient balance"); require(bytecode.length != 0, "Create2: bytecode length is zero"); /// @solidity memory-safe-assembly assembly { addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt) } require(addr != address(0), "Create2: Failed on deploy"); } /** * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the * `bytecodeHash` or `salt` will result in a new destination address. */ function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) { return computeAddress(salt, bytecodeHash, address(this)); } /** * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}. */ function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address addr) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) // Get free memory pointer // | | ↓ ptr ... ↓ ptr + 0x0B (start) ... ↓ ptr + 0x20 ... ↓ ptr + 0x40 ... | // |-------------------|---------------------------------------------------------------------------| // | bytecodeHash | CCCCCCCCCCCCC...CC | // | salt | BBBBBBBBBBBBB...BB | // | deployer | 000000...0000AAAAAAAAAAAAAAAAAAA...AA | // | 0xFF | FF | // |-------------------|---------------------------------------------------------------------------| // | memory | 000000...00FFAAAAAAAAAAAAAAAAAAA...AABBBBBBBBBBBBB...BBCCCCCCCCCCCCC...CC | // | keccak(start, 85) | ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ | mstore(add(ptr, 0x40), bytecodeHash) mstore(add(ptr, 0x20), salt) mstore(ptr, deployer) // Right-aligned with 12 preceding garbage bytes let start := add(ptr, 0x0b) // The hashed data starts at the final garbage byte which we will set to 0xff mstore8(start, 0xff) addr := keccak256(start, 85) } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.18; import "../libraries/TokenVestingLib.sol"; /// @title Interface for the TokenVestingManager contract /// @notice Provides the external functions of the TokenVestingManager contract for managing token vesting schedules interface ITokenVestingManager { struct CreateVestingBatchParams { address[] _recipients; uint32[] _startTimestamps; uint32[] _endTimestamps; uint32[] _timelocks; uint256[] _initialUnlocks; uint32[] _cliffReleaseTimestamps; uint256[] _cliffAmounts; uint32[] _releaseIntervalSecs; uint256[] _linearVestAmounts; } /// @notice Emitted when a new vesting is created /// @param recipient Address of the vesting recipient /// @param vesting Details of the created vesting event VestingCreated( address indexed recipient, bytes32 vestingId, TokenVestingLib.Vesting vesting ); /// @notice Emitted when a claim is made by a vesting recipient /// @param recipient Address of the recipient making the claim /// @param withdrawalAmount Amount of tokens withdrawn in the claim /// @param vestingId Unique identifier of the recipient's vesting arrangement event Claimed( address indexed recipient, uint256 withdrawalAmount, bytes32 vestingId ); /// @notice Emitted when a vesting is revoked /// @param recipient Address of the recipient whose vesting was revoked /// @param numTokensWithheld Amount of tokens withheld during the revocation /// @param vesting Details of the revoked vesting event VestingRevoked( address indexed recipient, uint256 numTokensWithheld, TokenVestingLib.Vesting vesting ); /// @notice Emitted when an admin withdraws tokens not tied up in vesting /// @param recipient Address of the recipient (admin) making the withdrawal /// @param amountRequested Amount of tokens withdrawn by the admin event AdminWithdrawn(address indexed recipient, uint256 amountRequested); error vestingAlreadyExists(bytes32 vestingId); error vestingNotActive(); error insuficientManagerBalance(); error notVestingOwner(); error invalidZeroAddress(); error insufficientBalance(); error arrayLengthMismatch(); error allVestedAmountAlreadyClaimed(); error invalidToken(); /// @notice Create a vesting schedule for a recipient /// @param _recipient Address of the recipient for whom vesting is being created /// @param _startTimestamp Start time of the vesting period as a timestamp /// @param _endTimestamp End time of the vesting period as a timestamp /// @param _timelock Period during which the tokens are locked and cannot be claimed /// @param _initialUnlock Amount of tokens that are initially unlocked and claimable at the start time /// @param _cliffReleaseTimestamp Timestamp after which the cliff amount can be released /// @param _cliffAmount Amount of tokens that are released at once after the cliff period is reached /// @param _releaseIntervalSecs Interval in seconds between subsequent releases /// @param _linearVestAmount Total amount of tokens that will be vested linearly after the cliff function createVesting( address _recipient, uint32 _startTimestamp, uint32 _endTimestamp, uint32 _timelock, uint256 _initialUnlock, uint32 _cliffReleaseTimestamp, uint256 _cliffAmount, uint32 _releaseIntervalSecs, uint256 _linearVestAmount ) external returns (bytes32 vestingId); /// @notice Create vesting schedules in batch for multiple recipients // @param _recipients Array of addresses for whom the vesting is being created // @param _startTimestamps Array of start timestamps for each vesting // @param _endTimestamps Array of end timestamps for each vesting // @param _timelocks Array of timelocks for each vesting // @param _initialUnlocks Array of amounts that are initially unlocked for each vesting // @param _cliffReleaseTimestamps Array of timestamps after which the cliff amounts can be released for each vesting // @param _cliffAmounts Array of cliff amounts for each vesting // @param _releaseIntervalSecs Array of intervals in seconds between subsequent releases for each vesting // @param _linearVestAmounts Array of total amounts of tokens that will be vested linearly after the cliff for each vesting function createVestingBatch( CreateVestingBatchParams memory params ) external returns (bytes32[] memory); /// @notice Allows a recipient to claim their vested tokens /// @param vestingId Unique identifier of the recipient's vesting arrangement function claim(bytes32 vestingId) external; /// @notice Revokes a vesting arrangement before it has been fully claimed /// @param vestingId Unique identifier of the vesting to be revoked function revokeVesting(bytes32 vestingId) external; /// @notice Allows the admin to withdraw ERC20 tokens not locked in vesting /// @param amountRequested Amount of tokens the admin wishes to withdraw function withdrawAdmin(uint256 amountRequested) external; /// @notice Withdraws ERC20 tokens accidentally sent to the contract's address /// @param otherTokenAddress Address of the token to be withdrawn function withdrawOtherToken(address otherTokenAddress) external; /// @notice Returns the amount of tokens that are available for the admin to withdraw /// @return The amount of tokens available to withdraw function amountAvailableToWithdrawByAdmin() external view returns (uint256); /// @notice Retrieves information about a specific vesting arrangement /// @param _vestingId Unique identifier of the vesting /// @return Details of the specified vesting function getVestingInfo( bytes32 _vestingId ) external view returns (TokenVestingLib.Vesting memory); /// @notice Fetches a list of all recipient addresses who have at least one vesting schedule set up in the system /// @return An array of addresses, each representing a recipient with an active or historical vesting schedule. function getAllRecipients() external view returns (address[] memory); /// @notice Checks if a given address is a recipient of any vesting schedule /// @param recipient The address to check against the list of vesting schedule recipients. function isRecipient(address recipient) external view returns (bool); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.18; import { TokenVestingManager } from "../TokenVestingManager.sol"; /// @title Interface for the TokenVestingManagerFactory /// @notice Provides the functionality to deploy TokenVestingManager contracts deterministically using Create2. interface ITokenVestingManagerFactory { /// @notice Emitted when a new TokenVestingManager is created /// @param tokenVestingManager The address of the newly created TokenVestingManager event TokenVestingManagerCreated(TokenVestingManager tokenVestingManager); /// @notice Deploys a new TokenVestingManager contract /// @param tokenAddress The ERC20 token address that will be vested by the newly created TokenVestingManager contract. /// @return The address of the newly created TokenVestingManager contract function newTokenVestingManager( address tokenAddress ) external returns (TokenVestingManager); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.18; import "@openzeppelin/contracts/utils/Context.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; /** @title Access Limiter to multiple owner-specified accounts. @dev Exposes the onlyAdmin modifier, which will revert (ADMIN_ACCESS_REQUIRED) if the caller is not the owner nor the admin. @notice An address with the role admin can grant that role to or revoke that role from any address via the function setAdmin(). */ abstract contract AccessProtected is Context { mapping(address => bool) private _admins; // user address => admin? mapping uint256 public adminCount; event AdminAccessSet(address indexed _admin, bool _enabled); constructor() { _admins[_msgSender()] = true; adminCount = 1; emit AdminAccessSet(_msgSender(), true); } /** * Throws if called by any account that isn't an admin or an owner. */ modifier onlyAdmin() { require(_admins[_msgSender()], "ADMIN_ACCESS_REQUIRED"); _; } function isAdmin(address _addressToCheck) external view returns (bool) { return _admins[_addressToCheck]; } /** * @notice Set/unset Admin Access for a given address. * * @param admin - Address of the new admin (or the one to be removed) * @param isEnabled - Enable/Disable Admin Access */ function setAdmin(address admin, bool isEnabled) public onlyAdmin { require(admin != address(0), "INVALID_ADDRESS"); require( _admins[admin] != isEnabled, "FLAG_ALREADY_PRESENT_FOR_ADDRESS" ); if (isEnabled) { adminCount++; } else { require(adminCount > 1, "AT_LEAST_ONE_ADMIN_REQUIRED"); adminCount--; } _admins[admin] = isEnabled; emit AdminAccessSet(admin, isEnabled); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.18; library TokenVestingLib { error invalidAddress(); error invalidVestedAmount(); error invalidStartTimestamp(); error invalidEndTimestamp(); error invalidReleaseInterval(); error invalidIntervalLength(); error invalidCliffRelease(); error invalidCliffAmount(); error timelockEnabled(); /** @notice A structure representing a Vesting - supporting linear and cliff vesting. @param releaseIntervalSecs used for calculating the vested amount @param linearVestAmount vesting allocation, excluding cliff @param claimedAmount claimed so far, excluding cliff */ struct Vesting { address recipient; // 160 bits 160/256 slot space - 1st slot uint32 startTimestamp; // 32 bits 192/256 slot space - 1st slot uint32 endTimestamp; // 32 bits 224/256 slot space - 1st slot uint32 deactivationTimestamp; // 32 bits 256/256 slot space - 1st slot uint32 timelock; // 32 bits 32/256 slot space - 2nd slot uint32 releaseIntervalSecs; // 32 bits 256/256 slot space - 2nd slot uint32 cliffReleaseTimestamp; // 32 bits 96/256 slot space - 2nd slot uint256 initialUnlock; // 256 bits 64/256 slot space - 3nd slot uint256 cliffAmount; // 256 bits 224/256 slot space - 4nd slots uint256 linearVestAmount; // 256 bits 256/256 slot space - 5rd slot // We could consider using uint128 here since we used 128 for cliffAmount uint256 claimedAmount; // 256 bits 256/256 slot space - 6th slot // We could consider using uint128 here since we used 128 for cliffAmount } /** @notice Calculate the vested amount for a given Vesting, at a given timestamp. @param _vesting The vesting in question @param _referenceTimestamp Timestamp for which we're calculating */ function calculateVestedAmount( Vesting memory _vesting, uint32 _referenceTimestamp ) internal pure returns (uint256) { // Does the Vesting exist? if (_vesting.deactivationTimestamp != 0) { if (_referenceTimestamp > _vesting.deactivationTimestamp) { _referenceTimestamp = _vesting.deactivationTimestamp; } } uint256 vestingAmount; // Has the Vesting ended? if (_referenceTimestamp > _vesting.endTimestamp) { _referenceTimestamp = _vesting.endTimestamp; } // Has the cliff passed? if (_referenceTimestamp >= _vesting.cliffReleaseTimestamp) { vestingAmount += _vesting.cliffAmount; } //Does it has an initial unlock? if (_vesting.initialUnlock > 0) { vestingAmount += _vesting.initialUnlock; } // Has the vesting started? If so, calculate the vested amount linearly uint256 startTimestamp; if (_vesting.cliffReleaseTimestamp != 0) { startTimestamp = _vesting.cliffReleaseTimestamp; } else { startTimestamp = _vesting.startTimestamp; } if (_referenceTimestamp > startTimestamp) { uint256 currentVestingDurationSecs = _referenceTimestamp - startTimestamp; // Round to releaseIntervalSecs uint256 truncatedCurrentVestingDurationSecs = (currentVestingDurationSecs / _vesting.releaseIntervalSecs) * _vesting.releaseIntervalSecs; uint256 finalVestingDurationSecs = _vesting.endTimestamp - startTimestamp; // Calculate vested amount uint256 linearVestAmount = (_vesting.linearVestAmount * truncatedCurrentVestingDurationSecs) / finalVestingDurationSecs; vestingAmount += linearVestAmount; } return vestingAmount; } function generateVestingId( Vesting memory _vesting ) internal pure returns (bytes32) { return keccak256(abi.encode(_vesting)); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.18; import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { AccessProtected } from "./libraries/AccessProtected.sol"; import { TokenVestingLib } from "./libraries/TokenVestingLib.sol"; import { ITokenVestingManager } from "./interfaces/ITokenVestingManager.sol"; /** * @title Token Vesting Manager * @notice Contract to manage token vesting */ contract TokenVestingManager is AccessProtected, ITokenVestingManager { using TokenVestingLib for TokenVestingLib.Vesting; using SafeERC20 for IERC20; /// Address of the token to be vested address public immutable tokenAddress; /// Total number of tokens reserved for vesting uint256 public numTokensReservedForVesting; /// Holds the vesting ids for each recipient mapping(address => bytes32[]) public recipientVestings; /// Holds the vesting information for each vesting id mapping(bytes32 => TokenVestingLib.Vesting) public vestingById; /// List of all recipients address[] public recipients; /** * @notice Sets the token address to be vested * @param _tokenAddress - Address of the token to be vested */ constructor(address _tokenAddress) { if (_tokenAddress == address(0)) { revert TokenVestingLib.invalidAddress(); } tokenAddress = _tokenAddress; } /** * dev Reverts if the vesting is not active */ modifier isVestingActive(bytes32 _vestingId) { if (getVestingInfo(_vestingId).deactivationTimestamp != 0) { revert vestingNotActive(); } _; } /** * @notice Create a new vesting * @param _recipient - Address of the recipient * @param _startTimestamp - Start timestamp of the vesting * @param _endTimestamp - End timestamp of the vesting * @param _timelock - Timelock for the vesting * @param _initialUnlock - Initial unlock amount * @param _cliffReleaseTimestamp - Cliff release timestamp * @param _cliffAmount - Cliff amount * @param _releaseIntervalSecs - Release interval in seconds * @param _linearVestAmount - Linear vest amount * @return vestingId - Identifier of the vesting */ function createVesting( address _recipient, uint32 _startTimestamp, uint32 _endTimestamp, uint32 _timelock, uint256 _initialUnlock, uint32 _cliffReleaseTimestamp, uint256 _cliffAmount, uint32 _releaseIntervalSecs, uint256 _linearVestAmount ) external onlyAdmin returns (bytes32 vestingId) { if (_recipient == address(0)) { revert TokenVestingLib.invalidAddress(); } uint256 totalExpectedAmount = _initialUnlock + _cliffAmount + _linearVestAmount; numTokensReservedForVesting += totalExpectedAmount; vestingId = _createVesting( _recipient, _startTimestamp, _endTimestamp, _timelock, _initialUnlock, _cliffReleaseTimestamp, _cliffAmount, _releaseIntervalSecs, _linearVestAmount ); IERC20(tokenAddress).safeTransferFrom( msg.sender, address(this), totalExpectedAmount ); return vestingId; } /** * @notice Create a batch of vestings * @param params - Parameters for creating the vesting batch * @return vestingIds - Identifiers of the vestings */ function createVestingBatch( CreateVestingBatchParams calldata params ) external onlyAdmin returns (bytes32[] memory) { uint256 length = params._recipients.length; bytes32[] memory vestingIds = new bytes32[](length); uint256 totalExpectedAmount; { if ( params._startTimestamps.length != length || params._endTimestamps.length != length || params._timelocks.length != length || params._initialUnlocks.length != length || params._cliffAmounts.length != length || params._cliffReleaseTimestamps.length != length || params._releaseIntervalSecs.length != length || params._linearVestAmounts.length != length ) { revert arrayLengthMismatch(); } } for (uint256 i; i < params._recipients.length; ) { vestingIds[i] = _createVesting( params._recipients[i], params._startTimestamps[i], params._endTimestamps[i], params._timelocks[i], params._initialUnlocks[i], params._cliffReleaseTimestamps[i], params._cliffAmounts[i], params._releaseIntervalSecs[i], params._linearVestAmounts[i] ); totalExpectedAmount += uint256(params._initialUnlocks[i]) + uint256(params._cliffAmounts[i]) + params._linearVestAmounts[i]; unchecked { ++i; } } numTokensReservedForVesting += totalExpectedAmount; IERC20(tokenAddress).safeTransferFrom( msg.sender, address(this), totalExpectedAmount ); return vestingIds; } /** * @notice Claim vested tokens * @param _vestingId - Identifier of the vesting */ function claim(bytes32 _vestingId) external { TokenVestingLib.Vesting storage vesting = vestingById[_vestingId]; if (msg.sender != vesting.recipient) { revert notVestingOwner(); } if (vesting.timelock > uint32(block.timestamp)) { revert TokenVestingLib.timelockEnabled(); } uint256 vested = TokenVestingLib.calculateVestedAmount( vesting, uint32(block.timestamp) ); uint256 claimable = vested - vesting.claimedAmount; if (claimable == 0) { revert insufficientBalance(); } vesting.claimedAmount += claimable; numTokensReservedForVesting -= claimable; emit Claimed(msg.sender, claimable, _vestingId); IERC20(tokenAddress).safeTransfer(msg.sender, claimable); } /** * @notice Revoke active Vesting * @param _vestingId - Vesting Identifier */ function revokeVesting( bytes32 _vestingId ) external onlyAdmin isVestingActive(_vestingId) { TokenVestingLib.Vesting storage vesting = vestingById[_vestingId]; uint256 finalVestAmount = TokenVestingLib.calculateVestedAmount( vesting, vesting.endTimestamp ); if (vesting.claimedAmount == finalVestAmount) { revert allVestedAmountAlreadyClaimed(); } vesting.deactivationTimestamp = uint32(block.timestamp); uint256 vestedAmountNow = TokenVestingLib.calculateVestedAmount( vesting, uint32(block.timestamp) ); uint256 amountRemaining = finalVestAmount - vestedAmountNow; numTokensReservedForVesting -= amountRemaining; emit VestingRevoked(vesting.recipient, amountRemaining, vesting); } /// INTERNAL FUNCTIONS /** * @dev Internal function to create a new vesting * @param _recipient - Address of the recipient * @param _startTimestamp - Start timestamp of the vesting * @param _endTimestamp - End timestamp of the vesting * @param _timelock - Timelock for the vesting * @param _initialUnlock - Initial unlock amount * @param _cliffReleaseTimestamp - Cliff release timestamp * @param _cliffAmount - Cliff amount * @param _releaseIntervalSecs - Release interval in seconds * @param _linearVestAmount - Linear vest amount * @return vestingId - Identifier of the vesting */ function _createVesting( address _recipient, uint32 _startTimestamp, uint32 _endTimestamp, uint32 _timelock, uint256 _initialUnlock, uint32 _cliffReleaseTimestamp, uint256 _cliffAmount, uint32 _releaseIntervalSecs, uint256 _linearVestAmount ) internal returns (bytes32) { if (_recipient == address(0)) { revert TokenVestingLib.invalidAddress(); } if (_linearVestAmount + _cliffAmount == 0) { revert TokenVestingLib.invalidVestedAmount(); } if (_startTimestamp == 0) { revert TokenVestingLib.invalidStartTimestamp(); } if (_endTimestamp == 0) { revert TokenVestingLib.invalidEndTimestamp(); } if (_startTimestamp > _endTimestamp) { revert TokenVestingLib.invalidEndTimestamp(); } if (_releaseIntervalSecs == 0) { revert TokenVestingLib.invalidReleaseInterval(); } if (_cliffReleaseTimestamp == 0) { if (_cliffAmount != 0) { revert TokenVestingLib.invalidCliffAmount(); } if ((_endTimestamp - _startTimestamp) % _releaseIntervalSecs != 0) { revert TokenVestingLib.invalidIntervalLength(); } } else { if ( ((_startTimestamp > _cliffReleaseTimestamp) || (_cliffReleaseTimestamp >= _endTimestamp)) ) { revert TokenVestingLib.invalidCliffRelease(); } if (_cliffAmount == 0) { revert TokenVestingLib.invalidCliffAmount(); } if ( (_endTimestamp - _cliffReleaseTimestamp) % _releaseIntervalSecs != 0 ) { revert TokenVestingLib.invalidIntervalLength(); } } TokenVestingLib.Vesting memory vesting = TokenVestingLib.Vesting({ recipient: _recipient, startTimestamp: _startTimestamp, endTimestamp: _endTimestamp, deactivationTimestamp: 0, timelock: _timelock, initialUnlock: _initialUnlock, cliffReleaseTimestamp: _cliffReleaseTimestamp, cliffAmount: _cliffAmount, releaseIntervalSecs: _releaseIntervalSecs, linearVestAmount: _linearVestAmount, claimedAmount: 0 }); bytes32 vestingId = TokenVestingLib.generateVestingId(vesting); if (getVestingInfo(vestingId).startTimestamp != 0) { revert vestingAlreadyExists(vestingId); } if (!isRecipient(_recipient)) { recipients.push(_recipient); } vestingById[vestingId] = vesting; recipientVestings[_recipient].push(vestingId); emit VestingCreated(_recipient, vestingId, vesting); return vestingId; } /// ADMIN WITHDRAW HELPER FUNCTIONS /** * @notice Allow the owner to withdraw any balance not currently tied up in Vestings * @param _amountRequested - Amount to withdraw */ function withdrawAdmin(uint256 _amountRequested) external onlyAdmin { uint256 amountRemaining = amountAvailableToWithdrawByAdmin(); if (amountRemaining < _amountRequested) { revert insufficientBalance(); } emit AdminWithdrawn(msg.sender, _amountRequested); IERC20(tokenAddress).safeTransfer(msg.sender, _amountRequested); } /** * @notice Withdraw a token which isn't controlled by the vesting contract. Useful when someone accidentally sends tokens to the contract * @param _otherTokenAddress - the token which we want to withdraw */ function withdrawOtherToken(address _otherTokenAddress) external onlyAdmin { if (_otherTokenAddress == tokenAddress) { // tokenAddress address is already sure to be nonzero due to constructor revert invalidToken(); } uint256 balance = IERC20(_otherTokenAddress).balanceOf(address(this)); IERC20(_otherTokenAddress).safeTransfer(msg.sender, balance); } /// @notice Amount of tokens available to withdraw by the admin function amountAvailableToWithdrawByAdmin() public view returns (uint256) { return IERC20(tokenAddress).balanceOf(address(this)) - numTokensReservedForVesting; } /** * @notice Get the vesting information * @param _vestingId - Identifier of the vesting * @return vesting - Vesting information */ function getVestingInfo( bytes32 _vestingId ) public view returns (TokenVestingLib.Vesting memory) { return vestingById[_vestingId]; } /** * @notice Get all recipients * @return recipients - The list of recipients */ function getAllRecipients() external view returns (address[] memory) { return recipients; } /** * @notice Check if a recipient has vestings * @param recipient - The recipient address * @return isRecipient - True if the recipient has vestings */ function isRecipient(address recipient) public view returns (bool) { return recipientVestings[recipient].length != 0; } /** * @notice Get the length of all recipients * @return length - The length of all recipients */ function getAllRecipientsLength() external view returns (uint256) { return recipients.length; } /** * @notice Get all recipients in a range * @param _from - The start index (inclusive) * @param _to - The end index (exclusive) * @return recipientsSliced - The list of recipients in the range */ function getAllRecipientsSliced( uint256 _from, uint256 _to ) external view returns (address[] memory) { address[] memory recipientsSliced = new address[](_to - _from); for (uint256 i = _from; i < _to; ) { recipientsSliced[i - _from] = recipients[i]; unchecked { ++i; } } return recipientsSliced; } /** * @notice Get all vestings for a recipient * @param _recipient - The recipient address * @return recipientVestings - The list of vestings for the recipient */ function getAllRecipientVestings( address _recipient ) external view returns (bytes32[] memory) { return recipientVestings[_recipient]; } /** * @notice Get all vestings for a recipient in a range * @param _from - The start index (inclusive) * @param _to - The end index (exclusive) * @param _recipient - The recipient address * @return recipientVestingsSliced - The list of vestings for the recipient in the range */ function getAllRecipientVestingsSliced( uint256 _from, uint256 _to, address _recipient ) external view returns (bytes32[] memory) { bytes32[] memory recipientVestingsSliced = new bytes32[](_to - _from); for (uint256 i = _from; i < _to; ) { recipientVestingsSliced[i - _from] = recipientVestings[_recipient][ i ]; unchecked { ++i; } } return recipientVestingsSliced; } /** * @notice Get the length of all vestings for a recipient * @param _recipient - The recipient address * @return length - The length of all vestings for the recipient */ function getAllRecipientVestingsLength( address _recipient ) external view returns (uint256) { return recipientVestings[_recipient].length; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract TokenVestingManager","name":"tokenVestingManager","type":"address"}],"name":"TokenVestingManagerCreated","type":"event"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"newTokenVestingManager","outputs":[{"internalType":"contract TokenVestingManager","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b506129d8806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063bdc30a1214610030575b600080fd5b61004361003e3660046101af565b61005f565b6040516001600160a01b03909116815260200160405180910390f35b6000808260405161006f906101a2565b6001600160a01b039091168152602001604051809103906000f08015801561009b573d6000803e3d6000fd5b506040516001600160a01b03821681529091507f62e1054907fe2d392ee2c75ed24c8653e155f742f01379021594b72d38ebfd329060200160405180910390a1604051632585eee960e11b8152336004820152600160248201526001600160a01b03821690634b0bddd290604401600060405180830381600087803b15801561012357600080fd5b505af1158015610137573d6000803e3d6000fd5b5050604051632585eee960e11b8152306004820152600060248201526001600160a01b0384169250634b0bddd29150604401600060405180830381600087803b15801561018357600080fd5b505af1158015610197573d6000803e3d6000fd5b509295945050505050565b6127c3806101e083390190565b6000602082840312156101c157600080fd5b81356001600160a01b03811681146101d857600080fd5b939250505056fe60a06040523480156200001157600080fd5b50604051620027c3380380620027c38339810160408190526200003491620000c0565b3360008181526020818152604091829020805460ff1916600190811790915580805591519182527fe529461c8529abc0e0fe7c5ee361f74fe22e0b7574df1fc0b7558a282091fb78910160405180910390a26001600160a01b038116620000ae5760405163cbdd34cf60e01b815260040160405180910390fd5b6001600160a01b0316608052620000f2565b600060208284031215620000d357600080fd5b81516001600160a01b0381168114620000eb57600080fd5b9392505050565b60805161268b620001386000396000818161034d0152818161052801528181610d060152818161124e0152818161140f0152818161149c0152611591015261268b6000f3fe608060405234801561001057600080fd5b506004361061014d5760003560e01c8063a1d0ae57116100c3578063d1bc76a11161007c578063d1bc76a1146103fb578063d77836ce1461040e578063d955d6eb14610421578063e50373f914610434578063e5b3248714610447578063e865fbc71461047057600080fd5b8063a1d0ae5714610387578063b74513c1146103a7578063b8900aa7146103af578063ba48042b146103c2578063bd66528a146103d5578063cdc6aa4c146103e857600080fd5b8063451154d111610115578063451154d1146102b55780634b0bddd2146102c8578063661b743d146102dd5780636d63b7ff146102fd5780638c5143ea1461031d5780639d76ea581461034857600080fd5b8063137c68fa1461015257806324d7806c1461016e5780632b7832b3146101aa5780632eb7d434146101b357806343ff9d8d146102ad575b600080fd5b61015b60025481565b6040519081526020015b60405180910390f35b61019a61017c366004611fdb565b6001600160a01b031660009081526020819052604090205460ff1690565b6040519015158152602001610165565b61015b60015481565b61023b6101c1366004611ff6565b60046020819052600091825260409091208054600182015460028301546003840154948401546005909401546001600160a01b0384169563ffffffff600160a01b8604811696600160c01b8704821696600160e01b9004821695808316956401000000008204841695600160401b9092049093169391908b565b604080516001600160a01b03909c168c5263ffffffff9a8b1660208d0152988a16988b019890985295881660608a0152938716608089015291861660a08801529490941660c086015260e085019390935261010084019290925261012083019190915261014082015261016001610165565b60055461015b565b61015b6102c3366004612023565b610478565b6102db6102d63660046120c7565b61055e565b005b6102f06102eb366004611ff6565b610729565b60405161016591906121c7565b61031061030b3660046121d6565b610837565b60405161016591906121f8565b61019a61032b366004611fdb565b6001600160a01b0316600090815260036020526040902054151590565b61036f7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610165565b61039a610395366004612245565b610900565b6040516101659190612281565b610310610d38565b6102db6103bd366004611ff6565b610d9a565b61039a6103d0366004611fdb565b61101e565b6102db6103e3366004611ff6565b61108a565b61039a6103f63660046122b9565b61127b565b61036f610409366004611ff6565b611347565b6102db61041c366004611ff6565b611371565b61015b61042f3660046122ee565b61143a565b6102db610442366004611fdb565b61146b565b61015b610455366004611fdb565b6001600160a01b031660009081526003602052604090205490565b61015b61156d565b3360009081526020819052604081205460ff166104b05760405162461bcd60e51b81526004016104a790612318565b60405180910390fd5b6001600160a01b038a166104d75760405163cbdd34cf60e01b815260040160405180910390fd5b6000826104e4868961235d565b6104ee919061235d565b90508060026000828254610502919061235d565b9091555061051990508b8b8b8b8b8b8b8b8b61160b565b91506105506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333084611b29565b509998505050505050505050565b3360009081526020819052604090205460ff1661058d5760405162461bcd60e51b81526004016104a790612318565b6001600160a01b0382166105d55760405162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b60448201526064016104a7565b6001600160a01b03821660009081526020819052604090205481151560ff9091161515036106455760405162461bcd60e51b815260206004820181905260248201527f464c41475f414c52454144595f50524553454e545f464f525f4144445245535360448201526064016104a7565b8015610665576001805490600061065b83612370565b91905055506106cc565b60018054116106b65760405162461bcd60e51b815260206004820152601b60248201527f41545f4c454153545f4f4e455f41444d494e5f5245515549524544000000000060448201526064016104a7565b600180549060006106c683612389565b91905055505b6001600160a01b03821660008181526020818152604091829020805460ff191685151590811790915591519182527fe529461c8529abc0e0fe7c5ee361f74fe22e0b7574df1fc0b7558a282091fb78910160405180910390a25050565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091525060009081526004602081815260409283902083516101608101855281546001600160a01b038116825263ffffffff600160a01b8204811694830194909452600160c01b8104841695820195909552600160e01b90940482166060850152600181015480831660808601526401000000008104831660a0860152600160401b900490911660c0840152600281015460e08401526003810154610100840152908101546101208301526005015461014082015290565b6060600061084584846123a0565b67ffffffffffffffff81111561085d5761085d6123b3565b604051908082528060200260200182016040528015610886578160200160208202803683370190505b509050835b838110156108f657600581815481106108a6576108a66123c9565b6000918252602090912001546001600160a01b0316826108c687846123a0565b815181106108d6576108d66123c9565b6001600160a01b039092166020928302919091019091015260010161088b565b5090505b92915050565b3360009081526020819052604090205460609060ff166109325760405162461bcd60e51b81526004016104a790612318565b600061093e83806123df565b9050905060008167ffffffffffffffff81111561095d5761095d6123b3565b604051908082528060200260200182016040528015610986578160200160208202803683370190505b50905060008261099960208701876123df565b90501415806109b65750826109b160408701876123df565b905014155b806109cf5750826109ca60608701876123df565b905014155b806109e85750826109e360808701876123df565b905014155b80610a015750826109fc60c08701876123df565b905014155b80610a1a575082610a1560a08701876123df565b905014155b80610a33575082610a2e60e08701876123df565b905014155b80610a4d575082610a486101008701876123df565b905014155b15610a6b5760405163150efcf160e21b815260040160405180910390fd5b60005b610a7886806123df565b9050811015610ce057610c28610a8e87806123df565b83818110610a9e57610a9e6123c9565b9050602002016020810190610ab39190611fdb565b610ac060208901896123df565b84818110610ad057610ad06123c9565b9050602002016020810190610ae59190612430565b610af260408a018a6123df565b85818110610b0257610b026123c9565b9050602002016020810190610b179190612430565b610b2460608b018b6123df565b86818110610b3457610b346123c9565b9050602002016020810190610b499190612430565b610b5660808c018c6123df565b87818110610b6657610b666123c9565b905060200201358b8060a00190610b7d91906123df565b88818110610b8d57610b8d6123c9565b9050602002016020810190610ba29190612430565b610baf60c08e018e6123df565b89818110610bbf57610bbf6123c9565b905060200201358d8060e00190610bd691906123df565b8a818110610be657610be66123c9565b9050602002016020810190610bfb9190612430565b8e806101000190610c0c91906123df565b8b818110610c1c57610c1c6123c9565b9050602002013561160b565b838281518110610c3a57610c3a6123c9565b6020908102919091010152610c536101008701876123df565b82818110610c6357610c636123c9565b90506020020135868060c00190610c7a91906123df565b83818110610c8a57610c8a6123c9565b90506020020135878060800190610ca191906123df565b84818110610cb157610cb16123c9565b90506020020135610cc2919061235d565b610ccc919061235d565b610cd6908361235d565b9150600101610a6e565b508060026000828254610cf3919061235d565b90915550610d2e90506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333084611b29565b509150505b919050565b60606005805480602002602001604051908101604052809291908181526020018280548015610d9057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610d72575b5050505050905090565b3360009081526020819052604090205460ff16610dc95760405162461bcd60e51b81526004016104a790612318565b80610dd381610729565b6060015163ffffffff1615610dfb57604051630ca2c97d60e01b815260040160405180910390fd5b600082815260046020818152604080842081516101608101835281546001600160a01b038116825263ffffffff600160a01b8204811695830195909552600160c01b81048516938201849052600160e01b900484166060820152600182015480851660808301526401000000008104851660a0830152600160401b900490931660c0840152600281015460e08401526003810154610100840152928301546101208301526005830154610140830152919291610eb79190611b94565b905080826005015403610edd57604051630301f5f160e51b815260040160405180910390fd5b815463ffffffff42818116600160e01b9081026001600160e01b038516811780885560408051610160810182526001600160a01b0393841693909716929092178652600160a01b810485166020870152600160c01b81048516918601919091520482166060840152600185015480831660808501526401000000008104831660a0850152600160401b900490911660c0830152600284015460e0830152600384015461010083015260048401546101208301526005840154610140830152600091610fa791611b94565b90506000610fb582846123a0565b90508060026000828254610fc991906123a0565b909155505083546040516001600160a01b03909116907f3dc0eb89db3750b7bd29375f003c6a45783d740de9d631c5f9ef2c2b862496049061100e908490889061244b565b60405180910390a2505050505050565b6001600160a01b03811660009081526003602090815260409182902080548351818402810184019094528084526060939283018282801561107e57602002820191906000526020600020905b81548152602001906001019080831161106a575b50505050509050919050565b600081815260046020526040902080546001600160a01b031633146110c257604051630894bedf60e31b815260040160405180910390fd5b600181015463ffffffff428116911611156110f05760405163b320f6a960e01b815260040160405180910390fd5b604080516101608101825282546001600160a01b038116825263ffffffff600160a01b820481166020840152600160c01b8204811693830193909352600160e01b900482166060820152600183015480831660808301526401000000008104831660a0830152600160401b900490911660c0820152600282015460e082015260038201546101008201526004820154610120820152600582015461014082015260009061119d9042611b94565b905060008260050154826111b191906123a0565b9050806000036111d457604051632388471f60e11b815260040160405180910390fd5b808360050160008282546111e8919061235d565b92505081905550806002600082825461120191906123a0565b9091555050604080518281526020810186905233917fd95107f4584744c6c893a04c43058aadd1ce8aac8ca5d64140eaf277de6c1d57910160405180910390a26112756001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163383611cfa565b50505050565b6060600061128985856123a0565b67ffffffffffffffff8111156112a1576112a16123b3565b6040519080825280602002602001820160405280156112ca578160200160208202803683370190505b509050845b8481101561133c576001600160a01b0384166000908152600360205260409020805482908110611301576113016123c9565b906000526020600020015482878361131991906123a0565b81518110611329576113296123c9565b60209081029190910101526001016112cf565b5090505b9392505050565b6005818154811061135757600080fd5b6000918252602090912001546001600160a01b0316905081565b3360009081526020819052604090205460ff166113a05760405162461bcd60e51b81526004016104a790612318565b60006113aa61156d565b9050818110156113cd57604051632388471f60e11b815260040160405180910390fd5b60405182815233907fca1cf43de312865665f595e88f569f9d5246690c07df26e86aba01147e6d13149060200160405180910390a26114366001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163384611cfa565b5050565b6003602052816000526040600020818154811061145657600080fd5b90600052602060002001600091509150505481565b3360009081526020819052604090205460ff1661149a5760405162461bcd60e51b81526004016104a790612318565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316036114ec57604051630cb45c5d60e31b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015611533573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611557919061250f565b90506114366001600160a01b0383163383611cfa565b6002546040516370a0823160e01b8152306004820152600091906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa1580156115d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fc919061250f565b61160691906123a0565b905090565b60006001600160a01b038a166116345760405163cbdd34cf60e01b815260040160405180910390fd5b61163e848361235d565b60000361165e5760405163c35c7a9d60e01b815260040160405180910390fd5b8863ffffffff166000036116855760405163555c2ec160e11b815260040160405180910390fd5b8763ffffffff166000036116ac5760405163cd2e61c160e01b815260040160405180910390fd5b8763ffffffff168963ffffffff1611156116d95760405163cd2e61c160e01b815260040160405180910390fd5b8263ffffffff1660000361170057604051630bfffc4160e01b815260040160405180910390fd5b8463ffffffff1660000361176b57831561172d5760405163027a165b60e31b815260040160405180910390fd5b826117388a8a612528565b6117429190612562565b63ffffffff1615611766576040516327d84aff60e01b815260040160405180910390fd5b611809565b8463ffffffff168963ffffffff16118061179157508763ffffffff168563ffffffff1610155b156117af57604051632e6ec26160e01b815260040160405180910390fd5b836000036117d05760405163027a165b60e31b815260040160405180910390fd5b826117db868a612528565b6117e59190612562565b63ffffffff1615611809576040516327d84aff60e01b815260040160405180910390fd5b60006040518061016001604052808c6001600160a01b031681526020018b63ffffffff1681526020018a63ffffffff168152602001600063ffffffff1681526020018963ffffffff1681526020018563ffffffff1681526020018763ffffffff16815260200188815260200186815260200184815260200160008152509050600061189382611d2f565b905061189e81610729565b6020015163ffffffff16156118c957604051633dbedca760e01b8152600481018290526024016104a7565b6001600160a01b038c1660009081526003602052604090205461193257600580546001810182556000919091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b0319166001600160a01b038e161790555b816004600083815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160006101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160010160046101000a81548163ffffffff021916908363ffffffff16021790555060c08201518160010160086101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160020155610100820151816003015561012082015181600401556101408201518160050155905050600360008d6001600160a01b03166001600160a01b031681526020019081526020016000208190806001815401808255809150506001900390600052602060002001600090919091909150558b6001600160a01b03167fec5983152f6c11c66222fe210b6341647966bf34d15c564c03251b2a254e21728284604051611b12929190612585565b60405180910390a29b9a5050505050505050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526112759085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611d5f565b6000826060015163ffffffff16600014611bc857826060015163ffffffff168263ffffffff161115611bc857826060015191505b6000836040015163ffffffff168363ffffffff161115611bea57836040015192505b8360c0015163ffffffff168363ffffffff1610611c1457610100840151611c11908261235d565b90505b60e084015115611c305760e0840151611c2d908261235d565b90505b60008460c0015163ffffffff16600014611c55575060c084015163ffffffff16611c62565b50602084015163ffffffff165b808463ffffffff1611156108f6576000611c828263ffffffff87166123a0565b60a087015190915060009063ffffffff16611c9d818461259a565b611ca791906125ae565b9050600083886040015163ffffffff16611cc191906123a0565b9050600081838a6101200151611cd791906125ae565b611ce1919061259a565b9050611ced818761235d565b9998505050505050505050565b6040516001600160a01b038316602482015260448101829052611d2a90849063a9059cbb60e01b90606401611b5d565b505050565b600081604051602001611d4291906121c7565b604051602081830303815290604052805190602001209050919050565b6000611db4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611e349092919063ffffffff16565b9050805160001480611dd5575080806020019051810190611dd591906125c5565b611d2a5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016104a7565b6060611e438484600085611e4b565b949350505050565b606082471015611eac5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016104a7565b600080866001600160a01b03168587604051611ec89190612606565b60006040518083038185875af1925050503d8060008114611f05576040519150601f19603f3d011682016040523d82523d6000602084013e611f0a565b606091505b5091509150611f1b87838387611f26565b979650505050505050565b60608315611f95578251600003611f8e576001600160a01b0385163b611f8e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016104a7565b5081611e43565b611e438383815115611faa5781518083602001fd5b8060405162461bcd60e51b81526004016104a79190612622565b80356001600160a01b0381168114610d3357600080fd5b600060208284031215611fed57600080fd5b61134082611fc4565b60006020828403121561200857600080fd5b5035919050565b803563ffffffff81168114610d3357600080fd5b60008060008060008060008060006101208a8c03121561204257600080fd5b61204b8a611fc4565b985061205960208b0161200f565b975061206760408b0161200f565b965061207560608b0161200f565b955060808a0135945061208a60a08b0161200f565b935060c08a0135925061209f60e08b0161200f565b91506101008a013590509295985092959850929598565b80151581146120c457600080fd5b50565b600080604083850312156120da57600080fd5b6120e383611fc4565b915060208301356120f3816120b6565b809150509250929050565b80516001600160a01b031682526020810151612122602084018263ffffffff169052565b50604081015161213a604084018263ffffffff169052565b506060810151612152606084018263ffffffff169052565b50608081015161216a608084018263ffffffff169052565b5060a081015161218260a084018263ffffffff169052565b5060c081015161219a60c084018263ffffffff169052565b5060e081810151908301526101008082015190830152610120808201519083015261014090810151910152565b61016081016108fa82846120fe565b600080604083850312156121e957600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b818110156122395783516001600160a01b031683529284019291840191600101612214565b50909695505050505050565b60006020828403121561225757600080fd5b813567ffffffffffffffff81111561226e57600080fd5b8201610120818503121561134057600080fd5b6020808252825182820181905260009190848201906040850190845b818110156122395783518352928401929184019160010161229d565b6000806000606084860312156122ce57600080fd5b83359250602084013591506122e560408501611fc4565b90509250925092565b6000806040838503121561230157600080fd5b61230a83611fc4565b946020939093013593505050565b602080825260159082015274105113525397d050d0d154d4d7d491545552549151605a1b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b808201808211156108fa576108fa612347565b60006001820161238257612382612347565b5060010190565b60008161239857612398612347565b506000190190565b818103818111156108fa576108fa612347565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e198436030181126123f657600080fd5b83018035915067ffffffffffffffff82111561241157600080fd5b6020019150600581901b360382131561242957600080fd5b9250929050565b60006020828403121561244257600080fd5b6113408261200f565b82815281546001600160a01b038116602083015261018082019063ffffffff60a082901c8116604085015261248d60608501828460c01c1663ffffffff169052565b60e082901c6080850152600185015463ffffffff8282161660a086015291506124c360c08501828460201c1663ffffffff169052565b6124da60e08501828460401c1663ffffffff169052565b505060028301546101008301526003830154610120830152600483015461014083015260058301546101608301529392505050565b60006020828403121561252157600080fd5b5051919050565b63ffffffff82811682821603908082111561254557612545612347565b5092915050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806125795761257961254c565b92169190910692915050565b828152610180810161134060208301846120fe565b6000826125a9576125a961254c565b500490565b80820281158282048414176108fa576108fa612347565b6000602082840312156125d757600080fd5b8151611340816120b6565b60005b838110156125fd5781810151838201526020016125e5565b50506000910152565b600082516126188184602087016125e2565b9190910192915050565b60208152600082518060208401526126418160408501602087016125e2565b601f01601f1916919091016040019291505056fea264697066735822122021bdba61f5bb09323ecae09641f7cac6c762cb3eb35e60ac85eb580aaafdcfdd64736f6c63430008120033a2646970667358221220a95e4488ed623948260ffd0da31e648ec2d6b0513ea315f66503b4e24483793d64736f6c63430008120033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063bdc30a1214610030575b600080fd5b61004361003e3660046101af565b61005f565b6040516001600160a01b03909116815260200160405180910390f35b6000808260405161006f906101a2565b6001600160a01b039091168152602001604051809103906000f08015801561009b573d6000803e3d6000fd5b506040516001600160a01b03821681529091507f62e1054907fe2d392ee2c75ed24c8653e155f742f01379021594b72d38ebfd329060200160405180910390a1604051632585eee960e11b8152336004820152600160248201526001600160a01b03821690634b0bddd290604401600060405180830381600087803b15801561012357600080fd5b505af1158015610137573d6000803e3d6000fd5b5050604051632585eee960e11b8152306004820152600060248201526001600160a01b0384169250634b0bddd29150604401600060405180830381600087803b15801561018357600080fd5b505af1158015610197573d6000803e3d6000fd5b509295945050505050565b6127c3806101e083390190565b6000602082840312156101c157600080fd5b81356001600160a01b03811681146101d857600080fd5b939250505056fe60a06040523480156200001157600080fd5b50604051620027c3380380620027c38339810160408190526200003491620000c0565b3360008181526020818152604091829020805460ff1916600190811790915580805591519182527fe529461c8529abc0e0fe7c5ee361f74fe22e0b7574df1fc0b7558a282091fb78910160405180910390a26001600160a01b038116620000ae5760405163cbdd34cf60e01b815260040160405180910390fd5b6001600160a01b0316608052620000f2565b600060208284031215620000d357600080fd5b81516001600160a01b0381168114620000eb57600080fd5b9392505050565b60805161268b620001386000396000818161034d0152818161052801528181610d060152818161124e0152818161140f0152818161149c0152611591015261268b6000f3fe608060405234801561001057600080fd5b506004361061014d5760003560e01c8063a1d0ae57116100c3578063d1bc76a11161007c578063d1bc76a1146103fb578063d77836ce1461040e578063d955d6eb14610421578063e50373f914610434578063e5b3248714610447578063e865fbc71461047057600080fd5b8063a1d0ae5714610387578063b74513c1146103a7578063b8900aa7146103af578063ba48042b146103c2578063bd66528a146103d5578063cdc6aa4c146103e857600080fd5b8063451154d111610115578063451154d1146102b55780634b0bddd2146102c8578063661b743d146102dd5780636d63b7ff146102fd5780638c5143ea1461031d5780639d76ea581461034857600080fd5b8063137c68fa1461015257806324d7806c1461016e5780632b7832b3146101aa5780632eb7d434146101b357806343ff9d8d146102ad575b600080fd5b61015b60025481565b6040519081526020015b60405180910390f35b61019a61017c366004611fdb565b6001600160a01b031660009081526020819052604090205460ff1690565b6040519015158152602001610165565b61015b60015481565b61023b6101c1366004611ff6565b60046020819052600091825260409091208054600182015460028301546003840154948401546005909401546001600160a01b0384169563ffffffff600160a01b8604811696600160c01b8704821696600160e01b9004821695808316956401000000008204841695600160401b9092049093169391908b565b604080516001600160a01b03909c168c5263ffffffff9a8b1660208d0152988a16988b019890985295881660608a0152938716608089015291861660a08801529490941660c086015260e085019390935261010084019290925261012083019190915261014082015261016001610165565b60055461015b565b61015b6102c3366004612023565b610478565b6102db6102d63660046120c7565b61055e565b005b6102f06102eb366004611ff6565b610729565b60405161016591906121c7565b61031061030b3660046121d6565b610837565b60405161016591906121f8565b61019a61032b366004611fdb565b6001600160a01b0316600090815260036020526040902054151590565b61036f7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610165565b61039a610395366004612245565b610900565b6040516101659190612281565b610310610d38565b6102db6103bd366004611ff6565b610d9a565b61039a6103d0366004611fdb565b61101e565b6102db6103e3366004611ff6565b61108a565b61039a6103f63660046122b9565b61127b565b61036f610409366004611ff6565b611347565b6102db61041c366004611ff6565b611371565b61015b61042f3660046122ee565b61143a565b6102db610442366004611fdb565b61146b565b61015b610455366004611fdb565b6001600160a01b031660009081526003602052604090205490565b61015b61156d565b3360009081526020819052604081205460ff166104b05760405162461bcd60e51b81526004016104a790612318565b60405180910390fd5b6001600160a01b038a166104d75760405163cbdd34cf60e01b815260040160405180910390fd5b6000826104e4868961235d565b6104ee919061235d565b90508060026000828254610502919061235d565b9091555061051990508b8b8b8b8b8b8b8b8b61160b565b91506105506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333084611b29565b509998505050505050505050565b3360009081526020819052604090205460ff1661058d5760405162461bcd60e51b81526004016104a790612318565b6001600160a01b0382166105d55760405162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b60448201526064016104a7565b6001600160a01b03821660009081526020819052604090205481151560ff9091161515036106455760405162461bcd60e51b815260206004820181905260248201527f464c41475f414c52454144595f50524553454e545f464f525f4144445245535360448201526064016104a7565b8015610665576001805490600061065b83612370565b91905055506106cc565b60018054116106b65760405162461bcd60e51b815260206004820152601b60248201527f41545f4c454153545f4f4e455f41444d494e5f5245515549524544000000000060448201526064016104a7565b600180549060006106c683612389565b91905055505b6001600160a01b03821660008181526020818152604091829020805460ff191685151590811790915591519182527fe529461c8529abc0e0fe7c5ee361f74fe22e0b7574df1fc0b7558a282091fb78910160405180910390a25050565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091525060009081526004602081815260409283902083516101608101855281546001600160a01b038116825263ffffffff600160a01b8204811694830194909452600160c01b8104841695820195909552600160e01b90940482166060850152600181015480831660808601526401000000008104831660a0860152600160401b900490911660c0840152600281015460e08401526003810154610100840152908101546101208301526005015461014082015290565b6060600061084584846123a0565b67ffffffffffffffff81111561085d5761085d6123b3565b604051908082528060200260200182016040528015610886578160200160208202803683370190505b509050835b838110156108f657600581815481106108a6576108a66123c9565b6000918252602090912001546001600160a01b0316826108c687846123a0565b815181106108d6576108d66123c9565b6001600160a01b039092166020928302919091019091015260010161088b565b5090505b92915050565b3360009081526020819052604090205460609060ff166109325760405162461bcd60e51b81526004016104a790612318565b600061093e83806123df565b9050905060008167ffffffffffffffff81111561095d5761095d6123b3565b604051908082528060200260200182016040528015610986578160200160208202803683370190505b50905060008261099960208701876123df565b90501415806109b65750826109b160408701876123df565b905014155b806109cf5750826109ca60608701876123df565b905014155b806109e85750826109e360808701876123df565b905014155b80610a015750826109fc60c08701876123df565b905014155b80610a1a575082610a1560a08701876123df565b905014155b80610a33575082610a2e60e08701876123df565b905014155b80610a4d575082610a486101008701876123df565b905014155b15610a6b5760405163150efcf160e21b815260040160405180910390fd5b60005b610a7886806123df565b9050811015610ce057610c28610a8e87806123df565b83818110610a9e57610a9e6123c9565b9050602002016020810190610ab39190611fdb565b610ac060208901896123df565b84818110610ad057610ad06123c9565b9050602002016020810190610ae59190612430565b610af260408a018a6123df565b85818110610b0257610b026123c9565b9050602002016020810190610b179190612430565b610b2460608b018b6123df565b86818110610b3457610b346123c9565b9050602002016020810190610b499190612430565b610b5660808c018c6123df565b87818110610b6657610b666123c9565b905060200201358b8060a00190610b7d91906123df565b88818110610b8d57610b8d6123c9565b9050602002016020810190610ba29190612430565b610baf60c08e018e6123df565b89818110610bbf57610bbf6123c9565b905060200201358d8060e00190610bd691906123df565b8a818110610be657610be66123c9565b9050602002016020810190610bfb9190612430565b8e806101000190610c0c91906123df565b8b818110610c1c57610c1c6123c9565b9050602002013561160b565b838281518110610c3a57610c3a6123c9565b6020908102919091010152610c536101008701876123df565b82818110610c6357610c636123c9565b90506020020135868060c00190610c7a91906123df565b83818110610c8a57610c8a6123c9565b90506020020135878060800190610ca191906123df565b84818110610cb157610cb16123c9565b90506020020135610cc2919061235d565b610ccc919061235d565b610cd6908361235d565b9150600101610a6e565b508060026000828254610cf3919061235d565b90915550610d2e90506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333084611b29565b509150505b919050565b60606005805480602002602001604051908101604052809291908181526020018280548015610d9057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610d72575b5050505050905090565b3360009081526020819052604090205460ff16610dc95760405162461bcd60e51b81526004016104a790612318565b80610dd381610729565b6060015163ffffffff1615610dfb57604051630ca2c97d60e01b815260040160405180910390fd5b600082815260046020818152604080842081516101608101835281546001600160a01b038116825263ffffffff600160a01b8204811695830195909552600160c01b81048516938201849052600160e01b900484166060820152600182015480851660808301526401000000008104851660a0830152600160401b900490931660c0840152600281015460e08401526003810154610100840152928301546101208301526005830154610140830152919291610eb79190611b94565b905080826005015403610edd57604051630301f5f160e51b815260040160405180910390fd5b815463ffffffff42818116600160e01b9081026001600160e01b038516811780885560408051610160810182526001600160a01b0393841693909716929092178652600160a01b810485166020870152600160c01b81048516918601919091520482166060840152600185015480831660808501526401000000008104831660a0850152600160401b900490911660c0830152600284015460e0830152600384015461010083015260048401546101208301526005840154610140830152600091610fa791611b94565b90506000610fb582846123a0565b90508060026000828254610fc991906123a0565b909155505083546040516001600160a01b03909116907f3dc0eb89db3750b7bd29375f003c6a45783d740de9d631c5f9ef2c2b862496049061100e908490889061244b565b60405180910390a2505050505050565b6001600160a01b03811660009081526003602090815260409182902080548351818402810184019094528084526060939283018282801561107e57602002820191906000526020600020905b81548152602001906001019080831161106a575b50505050509050919050565b600081815260046020526040902080546001600160a01b031633146110c257604051630894bedf60e31b815260040160405180910390fd5b600181015463ffffffff428116911611156110f05760405163b320f6a960e01b815260040160405180910390fd5b604080516101608101825282546001600160a01b038116825263ffffffff600160a01b820481166020840152600160c01b8204811693830193909352600160e01b900482166060820152600183015480831660808301526401000000008104831660a0830152600160401b900490911660c0820152600282015460e082015260038201546101008201526004820154610120820152600582015461014082015260009061119d9042611b94565b905060008260050154826111b191906123a0565b9050806000036111d457604051632388471f60e11b815260040160405180910390fd5b808360050160008282546111e8919061235d565b92505081905550806002600082825461120191906123a0565b9091555050604080518281526020810186905233917fd95107f4584744c6c893a04c43058aadd1ce8aac8ca5d64140eaf277de6c1d57910160405180910390a26112756001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163383611cfa565b50505050565b6060600061128985856123a0565b67ffffffffffffffff8111156112a1576112a16123b3565b6040519080825280602002602001820160405280156112ca578160200160208202803683370190505b509050845b8481101561133c576001600160a01b0384166000908152600360205260409020805482908110611301576113016123c9565b906000526020600020015482878361131991906123a0565b81518110611329576113296123c9565b60209081029190910101526001016112cf565b5090505b9392505050565b6005818154811061135757600080fd5b6000918252602090912001546001600160a01b0316905081565b3360009081526020819052604090205460ff166113a05760405162461bcd60e51b81526004016104a790612318565b60006113aa61156d565b9050818110156113cd57604051632388471f60e11b815260040160405180910390fd5b60405182815233907fca1cf43de312865665f595e88f569f9d5246690c07df26e86aba01147e6d13149060200160405180910390a26114366001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163384611cfa565b5050565b6003602052816000526040600020818154811061145657600080fd5b90600052602060002001600091509150505481565b3360009081526020819052604090205460ff1661149a5760405162461bcd60e51b81526004016104a790612318565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316036114ec57604051630cb45c5d60e31b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015611533573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611557919061250f565b90506114366001600160a01b0383163383611cfa565b6002546040516370a0823160e01b8152306004820152600091906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa1580156115d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fc919061250f565b61160691906123a0565b905090565b60006001600160a01b038a166116345760405163cbdd34cf60e01b815260040160405180910390fd5b61163e848361235d565b60000361165e5760405163c35c7a9d60e01b815260040160405180910390fd5b8863ffffffff166000036116855760405163555c2ec160e11b815260040160405180910390fd5b8763ffffffff166000036116ac5760405163cd2e61c160e01b815260040160405180910390fd5b8763ffffffff168963ffffffff1611156116d95760405163cd2e61c160e01b815260040160405180910390fd5b8263ffffffff1660000361170057604051630bfffc4160e01b815260040160405180910390fd5b8463ffffffff1660000361176b57831561172d5760405163027a165b60e31b815260040160405180910390fd5b826117388a8a612528565b6117429190612562565b63ffffffff1615611766576040516327d84aff60e01b815260040160405180910390fd5b611809565b8463ffffffff168963ffffffff16118061179157508763ffffffff168563ffffffff1610155b156117af57604051632e6ec26160e01b815260040160405180910390fd5b836000036117d05760405163027a165b60e31b815260040160405180910390fd5b826117db868a612528565b6117e59190612562565b63ffffffff1615611809576040516327d84aff60e01b815260040160405180910390fd5b60006040518061016001604052808c6001600160a01b031681526020018b63ffffffff1681526020018a63ffffffff168152602001600063ffffffff1681526020018963ffffffff1681526020018563ffffffff1681526020018763ffffffff16815260200188815260200186815260200184815260200160008152509050600061189382611d2f565b905061189e81610729565b6020015163ffffffff16156118c957604051633dbedca760e01b8152600481018290526024016104a7565b6001600160a01b038c1660009081526003602052604090205461193257600580546001810182556000919091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b0319166001600160a01b038e161790555b816004600083815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160006101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160010160046101000a81548163ffffffff021916908363ffffffff16021790555060c08201518160010160086101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160020155610100820151816003015561012082015181600401556101408201518160050155905050600360008d6001600160a01b03166001600160a01b031681526020019081526020016000208190806001815401808255809150506001900390600052602060002001600090919091909150558b6001600160a01b03167fec5983152f6c11c66222fe210b6341647966bf34d15c564c03251b2a254e21728284604051611b12929190612585565b60405180910390a29b9a5050505050505050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526112759085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611d5f565b6000826060015163ffffffff16600014611bc857826060015163ffffffff168263ffffffff161115611bc857826060015191505b6000836040015163ffffffff168363ffffffff161115611bea57836040015192505b8360c0015163ffffffff168363ffffffff1610611c1457610100840151611c11908261235d565b90505b60e084015115611c305760e0840151611c2d908261235d565b90505b60008460c0015163ffffffff16600014611c55575060c084015163ffffffff16611c62565b50602084015163ffffffff165b808463ffffffff1611156108f6576000611c828263ffffffff87166123a0565b60a087015190915060009063ffffffff16611c9d818461259a565b611ca791906125ae565b9050600083886040015163ffffffff16611cc191906123a0565b9050600081838a6101200151611cd791906125ae565b611ce1919061259a565b9050611ced818761235d565b9998505050505050505050565b6040516001600160a01b038316602482015260448101829052611d2a90849063a9059cbb60e01b90606401611b5d565b505050565b600081604051602001611d4291906121c7565b604051602081830303815290604052805190602001209050919050565b6000611db4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611e349092919063ffffffff16565b9050805160001480611dd5575080806020019051810190611dd591906125c5565b611d2a5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016104a7565b6060611e438484600085611e4b565b949350505050565b606082471015611eac5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016104a7565b600080866001600160a01b03168587604051611ec89190612606565b60006040518083038185875af1925050503d8060008114611f05576040519150601f19603f3d011682016040523d82523d6000602084013e611f0a565b606091505b5091509150611f1b87838387611f26565b979650505050505050565b60608315611f95578251600003611f8e576001600160a01b0385163b611f8e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016104a7565b5081611e43565b611e438383815115611faa5781518083602001fd5b8060405162461bcd60e51b81526004016104a79190612622565b80356001600160a01b0381168114610d3357600080fd5b600060208284031215611fed57600080fd5b61134082611fc4565b60006020828403121561200857600080fd5b5035919050565b803563ffffffff81168114610d3357600080fd5b60008060008060008060008060006101208a8c03121561204257600080fd5b61204b8a611fc4565b985061205960208b0161200f565b975061206760408b0161200f565b965061207560608b0161200f565b955060808a0135945061208a60a08b0161200f565b935060c08a0135925061209f60e08b0161200f565b91506101008a013590509295985092959850929598565b80151581146120c457600080fd5b50565b600080604083850312156120da57600080fd5b6120e383611fc4565b915060208301356120f3816120b6565b809150509250929050565b80516001600160a01b031682526020810151612122602084018263ffffffff169052565b50604081015161213a604084018263ffffffff169052565b506060810151612152606084018263ffffffff169052565b50608081015161216a608084018263ffffffff169052565b5060a081015161218260a084018263ffffffff169052565b5060c081015161219a60c084018263ffffffff169052565b5060e081810151908301526101008082015190830152610120808201519083015261014090810151910152565b61016081016108fa82846120fe565b600080604083850312156121e957600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b818110156122395783516001600160a01b031683529284019291840191600101612214565b50909695505050505050565b60006020828403121561225757600080fd5b813567ffffffffffffffff81111561226e57600080fd5b8201610120818503121561134057600080fd5b6020808252825182820181905260009190848201906040850190845b818110156122395783518352928401929184019160010161229d565b6000806000606084860312156122ce57600080fd5b83359250602084013591506122e560408501611fc4565b90509250925092565b6000806040838503121561230157600080fd5b61230a83611fc4565b946020939093013593505050565b602080825260159082015274105113525397d050d0d154d4d7d491545552549151605a1b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b808201808211156108fa576108fa612347565b60006001820161238257612382612347565b5060010190565b60008161239857612398612347565b506000190190565b818103818111156108fa576108fa612347565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e198436030181126123f657600080fd5b83018035915067ffffffffffffffff82111561241157600080fd5b6020019150600581901b360382131561242957600080fd5b9250929050565b60006020828403121561244257600080fd5b6113408261200f565b82815281546001600160a01b038116602083015261018082019063ffffffff60a082901c8116604085015261248d60608501828460c01c1663ffffffff169052565b60e082901c6080850152600185015463ffffffff8282161660a086015291506124c360c08501828460201c1663ffffffff169052565b6124da60e08501828460401c1663ffffffff169052565b505060028301546101008301526003830154610120830152600483015461014083015260058301546101608301529392505050565b60006020828403121561252157600080fd5b5051919050565b63ffffffff82811682821603908082111561254557612545612347565b5092915050565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff808416806125795761257961254c565b92169190910692915050565b828152610180810161134060208301846120fe565b6000826125a9576125a961254c565b500490565b80820281158282048414176108fa576108fa612347565b6000602082840312156125d757600080fd5b8151611340816120b6565b60005b838110156125fd5781810151838201526020016125e5565b50506000910152565b600082516126188184602087016125e2565b9190910192915050565b60208152600082518060208401526126418160408501602087016125e2565b601f01601f1916919091016040019291505056fea264697066735822122021bdba61f5bb09323ecae09641f7cac6c762cb3eb35e60ac85eb580aaafdcfdd64736f6c63430008120033a2646970667358221220a95e4488ed623948260ffd0da31e648ec2d6b0513ea315f66503b4e24483793d64736f6c63430008120033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.