Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- Vesting
- Optimization enabled
- true
- Compiler version
- v0.8.7+commit.e28d00a7
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2024-09-26T15:35:28.448576Z
Constructor Arguments
0x0000000000000000000000009fae2529863bd691b4a7171bdfcf33c7ebb10a65
Arg [0] (address) : 0x9fae2529863bd691b4a7171bdfcf33c7ebb10a65
Contract source code
// SPDX-License-Identifier: No License (None)
pragma solidity ^0.8.0;
/**
* @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 {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor () {
_owner = msg.sender;
emit OwnershipTransferred(address(0), msg.sender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == msg.sender, "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = 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");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
/**
* @dev Interface of the ERC223 standard as defined in the EIP.
*/
interface IERC223 {
/**
* @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 `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
function transfer(address recipient, uint256 amount, bytes calldata data) 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 `sender` to `recipient` 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 sender, address recipient, uint256 amount) external returns (bool);
/**
* @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 Additional event that is fired on successful transfer and logs transfer metadata,
* this event is implemented to keep Transfer event compatible with ERC20.
*/
event TransferData(bytes data);
}
abstract contract ERC223Recipient {
address public vestedToken;
mapping(address => bool) public depositors; // address of users who has right to deposit and allocate tokens
modifier onlyDepositor() {
require(depositors[msg.sender], "Only depositors allowed");
_;
}
/**
* @dev Standard ERC223 function that will handle incoming token transfers.
*
* @param _from Token sender address.
* @param _value Amount of tokens.
* @param _data Transaction metadata.
*/
function tokenReceived(address _from, uint256 _value, bytes memory _data) external virtual {
require(depositors[_from], "Only depositors allowed");
}
constructor (address _token) {
require(_token != address(0));
vestedToken = _token;
}
}
contract Vesting is Ownable, ERC223Recipient {
struct Allocation {
uint256 amount; // amount of token
uint256 unlockPercentage; // percentage of initially unlocked token
uint256 startVesting; // Timestamp (unix time) when starts vesting. First vesting will be at this time
uint256 vestingPercentage; // percentage of tokens will be unlocked every interval (i.e. 10% per 30 days)
uint256 vestingInterval; // interval (in seconds) of vesting (i.e. 30 days)
}
uint256 public totalAllocated;
uint256 public totalClaimed;
mapping(address => Allocation[]) public beneficiaries; // beneficiary => Allocation
mapping(address => uint256) public claimedAmount; // beneficiary => already claimed amount
event SetDepositor(address depositor, bool enable);
event Claim(address indexed beneficiary, uint256 amount);
event AddAllocation(
address indexed to, // beneficiary of tokens
uint256 amount, // amount of token
uint256 unlockPercentage, // percentage of initially unlocked token
uint256 startVesting, // Timestamp (unix time) when starts vesting. First vesting will be at this time
uint256 vestingPercentage, // percentage of tokens will be unlocked every interval (i.e. 10% per 30 days)
uint256 vestingInterval // interval (in seconds) of vesting (i.e. 30 days)
);
event Rescue(address _token, uint256 _amount);
constructor (address _token) ERC223Recipient(_token) {
}
// Depositor has right to transfer token to contract and allocate token to the beneficiary
function setDepositor(address depositor, bool enable) external onlyOwner {
depositors[depositor] = enable;
emit SetDepositor(depositor, enable);
}
function allocateTokens(
address to, // beneficiary of tokens
uint256 amount, // amount of token
uint256 unlockPercentage, // percentage of initially unlocked token
uint256 startVesting, // Timestamp (unix time) when starts vesting. First vesting will be at this time
uint256 vestingPercentage, // percentage of tokens will be unlocked every interval (i.e. 10% per 30 days)
uint256 vestingInterval // interval (in seconds) of vesting (i.e. 30 days)
)
external
onlyDepositor
{
require(amount <= getUnallocatedAmount(), "Not enough tokens");
require(startVesting > block.timestamp, "startVesting in the past");
beneficiaries[to].push(Allocation(amount, unlockPercentage, startVesting, vestingPercentage, vestingInterval));
totalAllocated += amount;
// Check ERC223 compatibility of the beneficiary
if (isContract(to)) {
bytes memory _empty = hex"00000000";
ERC223Recipient(to).tokenReceived(address(this), 0, _empty);
}
emit AddAllocation(to, amount, unlockPercentage, startVesting, vestingPercentage, vestingInterval);
}
function claim() external {
claimBehalf(msg.sender);
}
function claimBehalf(address beneficiary) public {
uint256 unlockedAmount = getUnlockedAmount(beneficiary);
require(unlockedAmount != 0, "No unlocked tokens");
claimedAmount[beneficiary] += unlockedAmount;
totalClaimed += unlockedAmount;
IERC223(vestedToken).transfer(beneficiary, unlockedAmount);
emit Claim(beneficiary, unlockedAmount);
}
function getUnlockedAmount(address beneficiary) public view returns(uint256 unlockedAmount) {
for (uint256 i = 0; i < beneficiaries[beneficiary].length; i++) {
Allocation storage b = beneficiaries[beneficiary][i];
uint256 amount = b.amount;
uint256 unlocked = amount * b.unlockPercentage / 100;
if (b.startVesting <= block.timestamp) {
uint256 intervals = (block.timestamp - b.startVesting) / b.vestingInterval + 1;
unlocked = unlocked + (amount * intervals * b.vestingPercentage / 100);
}
if (unlocked > amount) unlocked = amount;
unlockedAmount += unlocked;
}
unlockedAmount = unlockedAmount - claimedAmount[beneficiary];
}
function getUnallocatedAmount() public view returns(uint256 amount) {
amount = IERC223(vestedToken).balanceOf(address(this));
uint256 unclaimed = totalAllocated - totalClaimed;
amount = amount - unclaimed;
}
function rescueTokens(address _token) onlyOwner external {
uint256 amount;
if (_token == vestedToken) {
amount = getUnallocatedAmount();
} else {
amount = IERC223(_token).balanceOf(address(this));
}
IERC223(_token).transfer(msg.sender, amount);
emit Rescue(_token, amount);
}
/**
* @dev Returns true if `account` is a contract.
*
* This test is non-exhaustive, and there may be false-negatives: during the
* execution of a contract's constructor, its address will be reported as
* not containing a contract.
*
* > It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*/
function isContract(address account) internal view returns (bool) {
// This method relies in extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly { size := extcodesize(account) }
return size > 0;
}
}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_token","internalType":"address"}]},{"type":"event","name":"AddAllocation","inputs":[{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"unlockPercentage","internalType":"uint256","indexed":false},{"type":"uint256","name":"startVesting","internalType":"uint256","indexed":false},{"type":"uint256","name":"vestingPercentage","internalType":"uint256","indexed":false},{"type":"uint256","name":"vestingInterval","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Claim","inputs":[{"type":"address","name":"beneficiary","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Rescue","inputs":[{"type":"address","name":"_token","internalType":"address","indexed":false},{"type":"uint256","name":"_amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"SetDepositor","inputs":[{"type":"address","name":"depositor","internalType":"address","indexed":false},{"type":"bool","name":"enable","internalType":"bool","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"allocateTokens","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"unlockPercentage","internalType":"uint256"},{"type":"uint256","name":"startVesting","internalType":"uint256"},{"type":"uint256","name":"vestingPercentage","internalType":"uint256"},{"type":"uint256","name":"vestingInterval","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"unlockPercentage","internalType":"uint256"},{"type":"uint256","name":"startVesting","internalType":"uint256"},{"type":"uint256","name":"vestingPercentage","internalType":"uint256"},{"type":"uint256","name":"vestingInterval","internalType":"uint256"}],"name":"beneficiaries","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claim","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claimBehalf","inputs":[{"type":"address","name":"beneficiary","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"claimedAmount","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"depositors","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amount","internalType":"uint256"}],"name":"getUnallocatedAmount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"unlockedAmount","internalType":"uint256"}],"name":"getUnlockedAmount","inputs":[{"type":"address","name":"beneficiary","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"rescueTokens","inputs":[{"type":"address","name":"_token","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setDepositor","inputs":[{"type":"address","name":"depositor","internalType":"address"},{"type":"bool","name":"enable","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"tokenReceived","inputs":[{"type":"address","name":"_from","internalType":"address"},{"type":"uint256","name":"_value","internalType":"uint256"},{"type":"bytes","name":"_data","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalAllocated","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalClaimed","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"vestedToken","inputs":[]}]
Contract Creation Code
0x608060405234801561001057600080fd5b5060405161115338038061115383398101604081905261002f916100a7565b600080546001600160a01b0319163390811782556040518392907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a36001600160a01b03811661008157600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055506100d7565b6000602082840312156100b957600080fd5b81516001600160a01b03811681146100d057600080fd5b9392505050565b61106d806100e66000396000f3fe608060405234801561001057600080fd5b506004361061010a5760003560e01c80636bd7a97a116100a25780638943ec02116100715780638943ec021461022a5780638da5cb5b1461023d578063d54ad2a11461024e578063eed75f6d14610257578063f2fde38b1461028a57600080fd5b80636bd7a97a146101e95780636f860d74146101fc578063715018a61461020f578063889014961461021757600080fd5b806345f7f249116100de57806345f7f249146101725780634e71d92d1461017b578063529849e9146101835780635de29741146101be57600080fd5b8062ae3bf81461010f57806304e869031461012457806328733bb714610157578063420d4a021461015f575b600080fd5b61012261011d366004610cea565b61029d565b005b610144610132366004610cea565b60066020526000908152604090205481565b6040519081526020015b60405180910390f35b610144610449565b61014461016d366004610cea565b6104eb565b61014460035481565b610122610632565b610196610191366004610d43565b61063d565b604080519586526020860194909452928401919091526060830152608082015260a00161014e565b6001546101d1906001600160a01b031681565b6040516001600160a01b03909116815260200161014e565b6101226101f7366004610e38565b61068b565b61012261020a366004610d0c565b6108f3565b610122610988565b610122610225366004610cea565b610a0b565b610122610238366004610d6d565b610b6e565b6000546001600160a01b03166101d1565b61014460045481565b61027a610265366004610cea565b60026020526000908152604090205460ff1681565b604051901515815260200161014e565b610122610298366004610cea565b610bd5565b336102b06000546001600160a01b031690565b6001600160a01b0316146102df5760405162461bcd60e51b81526004016102d690610f24565b60405180910390fd5b6001546000906001600160a01b038381169116141561030757610300610449565b9050610381565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a082319060240160206040518083038186803b15801561034657600080fd5b505afa15801561035a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037e9190610e9f565b90505b60405163a9059cbb60e01b8152336004820152602481018290526001600160a01b0383169063a9059cbb90604401602060405180830381600087803b1580156103c957600080fd5b505af11580156103dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104019190610e82565b50604080516001600160a01b0384168152602081018390527f542fa6bfee3b4746210fbdd1d83f9e49b65adde3639f8d8f165dd18347938af291015b60405180910390a15050565b6001546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b15801561048d57600080fd5b505afa1580156104a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c59190610e9f565b905060006004546003546104d99190610fb2565b90506104e58183610fb2565b91505090565b6000805b6001600160a01b038316600090815260056020526040902054811015610608576001600160a01b038316600090815260056020526040812080548390811061053957610539610ffa565b6000918252602082206005909102018054600182015491935091906064906105619084610f93565b61056b9190610f71565b9050428360020154116105db576000836004015484600201544261058f9190610fb2565b6105999190610f71565b6105a4906001610f59565b90506064846003015482856105b99190610f93565b6105c39190610f93565b6105cd9190610f71565b6105d79083610f59565b9150505b818111156105e65750805b6105f08186610f59565b9450505050808061060090610fc9565b9150506104ef565b506001600160a01b03821660009081526006602052604090205461062c9082610fb2565b92915050565b61063b33610a0b565b565b6005602052816000526040600020818154811061065957600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919085565b3360009081526002602052604090205460ff166106e45760405162461bcd60e51b815260206004820152601760248201527613db9b1e4819195c1bdcda5d1bdc9cc8185b1b1bddd959604a1b60448201526064016102d6565b6106ec610449565b85111561072f5760405162461bcd60e51b81526020600482015260116024820152704e6f7420656e6f75676820746f6b656e7360781b60448201526064016102d6565b42831161077e5760405162461bcd60e51b815260206004820152601860248201527f737461727456657374696e6720696e207468652070617374000000000000000060448201526064016102d6565b6001600160a01b0386166000908152600560208181526040808420815160a0810183528a81528084018a81529281018981526060820189815260808301898152845460018181018755958a5296892093519690970290920194855592519184019190915590516002830155516003808301919091559151600490910155805487929061080b908490610f59565b9091555050853b1561089157604080518082018252600480825260006020830181905292516344a1f60160e11b815291926001600160a01b038a1692638943ec029261085d9230929091879101610eb8565b600060405180830381600087803b15801561087757600080fd5b505af115801561088b573d6000803e3d6000fd5b50505050505b604080518681526020810186905290810184905260608101839052608081018290526001600160a01b038716907f585acc8130c6cd35ae5bb61237605676cd4ec0a81dc2bf91a06b37270e81c3929060a00160405180910390a2505050505050565b336109066000546001600160a01b031690565b6001600160a01b03161461092c5760405162461bcd60e51b81526004016102d690610f24565b6001600160a01b038216600081815260026020908152604091829020805460ff19168515159081179091558251938452908301527fb1252fa67b4c05afbdaadfae34890b205103c0212a9e062b3978e8cd573631a9910161043d565b3361099b6000546001600160a01b031690565b6001600160a01b0316146109c15760405162461bcd60e51b81526004016102d690610f24565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000610a16826104eb565b905080610a5a5760405162461bcd60e51b81526020600482015260126024820152714e6f20756e6c6f636b656420746f6b656e7360701b60448201526064016102d6565b6001600160a01b03821660009081526006602052604081208054839290610a82908490610f59565b925050819055508060046000828254610a9b9190610f59565b909155505060015460405163a9059cbb60e01b81526001600160a01b038481166004830152602482018490529091169063a9059cbb90604401602060405180830381600087803b158015610aee57600080fd5b505af1158015610b02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b269190610e82565b50816001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d482604051610b6291815260200190565b60405180910390a25050565b6001600160a01b03831660009081526002602052604090205460ff16610bd05760405162461bcd60e51b815260206004820152601760248201527613db9b1e4819195c1bdcda5d1bdc9cc8185b1b1bddd959604a1b60448201526064016102d6565b505050565b33610be86000546001600160a01b031690565b6001600160a01b031614610c0e5760405162461bcd60e51b81526004016102d690610f24565b6001600160a01b038116610c735760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016102d6565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b80356001600160a01b0381168114610ce557600080fd5b919050565b600060208284031215610cfc57600080fd5b610d0582610cce565b9392505050565b60008060408385031215610d1f57600080fd5b610d2883610cce565b91506020830135610d3881611026565b809150509250929050565b60008060408385031215610d5657600080fd5b610d5f83610cce565b946020939093013593505050565b600080600060608486031215610d8257600080fd5b610d8b84610cce565b925060208401359150604084013567ffffffffffffffff80821115610daf57600080fd5b818601915086601f830112610dc357600080fd5b813581811115610dd557610dd5611010565b604051601f8201601f19908116603f01168101908382118183101715610dfd57610dfd611010565b81604052828152896020848701011115610e1657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b60008060008060008060c08789031215610e5157600080fd5b610e5a87610cce565b9860208801359850604088013597606081013597506080810135965060a00135945092505050565b600060208284031215610e9457600080fd5b8151610d0581611026565b600060208284031215610eb157600080fd5b5051919050565b60018060a01b038416815260006020848184015260606040840152835180606085015260005b81811015610efa57858101830151858201608001528201610ede565b81811115610f0c576000608083870101525b50601f01601f19169290920160800195945050505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60008219821115610f6c57610f6c610fe4565b500190565b600082610f8e57634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615610fad57610fad610fe4565b500290565b600082821015610fc457610fc4610fe4565b500390565b6000600019821415610fdd57610fdd610fe4565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b801515811461103457600080fd5b5056fea26469706673582212208dabc3861fd170fdf8c2055a60b01e83344311e553c3298d414e82e3856538cd64736f6c634300080700330000000000000000000000009fae2529863bd691b4a7171bdfcf33c7ebb10a65
Deployed ByteCode
0x608060405234801561001057600080fd5b506004361061010a5760003560e01c80636bd7a97a116100a25780638943ec02116100715780638943ec021461022a5780638da5cb5b1461023d578063d54ad2a11461024e578063eed75f6d14610257578063f2fde38b1461028a57600080fd5b80636bd7a97a146101e95780636f860d74146101fc578063715018a61461020f578063889014961461021757600080fd5b806345f7f249116100de57806345f7f249146101725780634e71d92d1461017b578063529849e9146101835780635de29741146101be57600080fd5b8062ae3bf81461010f57806304e869031461012457806328733bb714610157578063420d4a021461015f575b600080fd5b61012261011d366004610cea565b61029d565b005b610144610132366004610cea565b60066020526000908152604090205481565b6040519081526020015b60405180910390f35b610144610449565b61014461016d366004610cea565b6104eb565b61014460035481565b610122610632565b610196610191366004610d43565b61063d565b604080519586526020860194909452928401919091526060830152608082015260a00161014e565b6001546101d1906001600160a01b031681565b6040516001600160a01b03909116815260200161014e565b6101226101f7366004610e38565b61068b565b61012261020a366004610d0c565b6108f3565b610122610988565b610122610225366004610cea565b610a0b565b610122610238366004610d6d565b610b6e565b6000546001600160a01b03166101d1565b61014460045481565b61027a610265366004610cea565b60026020526000908152604090205460ff1681565b604051901515815260200161014e565b610122610298366004610cea565b610bd5565b336102b06000546001600160a01b031690565b6001600160a01b0316146102df5760405162461bcd60e51b81526004016102d690610f24565b60405180910390fd5b6001546000906001600160a01b038381169116141561030757610300610449565b9050610381565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a082319060240160206040518083038186803b15801561034657600080fd5b505afa15801561035a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037e9190610e9f565b90505b60405163a9059cbb60e01b8152336004820152602481018290526001600160a01b0383169063a9059cbb90604401602060405180830381600087803b1580156103c957600080fd5b505af11580156103dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104019190610e82565b50604080516001600160a01b0384168152602081018390527f542fa6bfee3b4746210fbdd1d83f9e49b65adde3639f8d8f165dd18347938af291015b60405180910390a15050565b6001546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b15801561048d57600080fd5b505afa1580156104a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c59190610e9f565b905060006004546003546104d99190610fb2565b90506104e58183610fb2565b91505090565b6000805b6001600160a01b038316600090815260056020526040902054811015610608576001600160a01b038316600090815260056020526040812080548390811061053957610539610ffa565b6000918252602082206005909102018054600182015491935091906064906105619084610f93565b61056b9190610f71565b9050428360020154116105db576000836004015484600201544261058f9190610fb2565b6105999190610f71565b6105a4906001610f59565b90506064846003015482856105b99190610f93565b6105c39190610f93565b6105cd9190610f71565b6105d79083610f59565b9150505b818111156105e65750805b6105f08186610f59565b9450505050808061060090610fc9565b9150506104ef565b506001600160a01b03821660009081526006602052604090205461062c9082610fb2565b92915050565b61063b33610a0b565b565b6005602052816000526040600020818154811061065957600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919085565b3360009081526002602052604090205460ff166106e45760405162461bcd60e51b815260206004820152601760248201527613db9b1e4819195c1bdcda5d1bdc9cc8185b1b1bddd959604a1b60448201526064016102d6565b6106ec610449565b85111561072f5760405162461bcd60e51b81526020600482015260116024820152704e6f7420656e6f75676820746f6b656e7360781b60448201526064016102d6565b42831161077e5760405162461bcd60e51b815260206004820152601860248201527f737461727456657374696e6720696e207468652070617374000000000000000060448201526064016102d6565b6001600160a01b0386166000908152600560208181526040808420815160a0810183528a81528084018a81529281018981526060820189815260808301898152845460018181018755958a5296892093519690970290920194855592519184019190915590516002830155516003808301919091559151600490910155805487929061080b908490610f59565b9091555050853b1561089157604080518082018252600480825260006020830181905292516344a1f60160e11b815291926001600160a01b038a1692638943ec029261085d9230929091879101610eb8565b600060405180830381600087803b15801561087757600080fd5b505af115801561088b573d6000803e3d6000fd5b50505050505b604080518681526020810186905290810184905260608101839052608081018290526001600160a01b038716907f585acc8130c6cd35ae5bb61237605676cd4ec0a81dc2bf91a06b37270e81c3929060a00160405180910390a2505050505050565b336109066000546001600160a01b031690565b6001600160a01b03161461092c5760405162461bcd60e51b81526004016102d690610f24565b6001600160a01b038216600081815260026020908152604091829020805460ff19168515159081179091558251938452908301527fb1252fa67b4c05afbdaadfae34890b205103c0212a9e062b3978e8cd573631a9910161043d565b3361099b6000546001600160a01b031690565b6001600160a01b0316146109c15760405162461bcd60e51b81526004016102d690610f24565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000610a16826104eb565b905080610a5a5760405162461bcd60e51b81526020600482015260126024820152714e6f20756e6c6f636b656420746f6b656e7360701b60448201526064016102d6565b6001600160a01b03821660009081526006602052604081208054839290610a82908490610f59565b925050819055508060046000828254610a9b9190610f59565b909155505060015460405163a9059cbb60e01b81526001600160a01b038481166004830152602482018490529091169063a9059cbb90604401602060405180830381600087803b158015610aee57600080fd5b505af1158015610b02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b269190610e82565b50816001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d482604051610b6291815260200190565b60405180910390a25050565b6001600160a01b03831660009081526002602052604090205460ff16610bd05760405162461bcd60e51b815260206004820152601760248201527613db9b1e4819195c1bdcda5d1bdc9cc8185b1b1bddd959604a1b60448201526064016102d6565b505050565b33610be86000546001600160a01b031690565b6001600160a01b031614610c0e5760405162461bcd60e51b81526004016102d690610f24565b6001600160a01b038116610c735760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016102d6565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b80356001600160a01b0381168114610ce557600080fd5b919050565b600060208284031215610cfc57600080fd5b610d0582610cce565b9392505050565b60008060408385031215610d1f57600080fd5b610d2883610cce565b91506020830135610d3881611026565b809150509250929050565b60008060408385031215610d5657600080fd5b610d5f83610cce565b946020939093013593505050565b600080600060608486031215610d8257600080fd5b610d8b84610cce565b925060208401359150604084013567ffffffffffffffff80821115610daf57600080fd5b818601915086601f830112610dc357600080fd5b813581811115610dd557610dd5611010565b604051601f8201601f19908116603f01168101908382118183101715610dfd57610dfd611010565b81604052828152896020848701011115610e1657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b60008060008060008060c08789031215610e5157600080fd5b610e5a87610cce565b9860208801359850604088013597606081013597506080810135965060a00135945092505050565b600060208284031215610e9457600080fd5b8151610d0581611026565b600060208284031215610eb157600080fd5b5051919050565b60018060a01b038416815260006020848184015260606040840152835180606085015260005b81811015610efa57858101830151858201608001528201610ede565b81811115610f0c576000608083870101525b50601f01601f19169290920160800195945050505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60008219821115610f6c57610f6c610fe4565b500190565b600082610f8e57634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615610fad57610fad610fe4565b500290565b600082821015610fc457610fc4610fe4565b500390565b6000600019821415610fdd57610fdd610fe4565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b801515811461103457600080fd5b5056fea26469706673582212208dabc3861fd170fdf8c2055a60b01e83344311e553c3298d414e82e3856538cd64736f6c63430008070033