Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- SlothVesting
- Optimization enabled
- true
- Compiler version
- v0.8.19+commit.7dd6d404
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2024-09-26T15:34:03.495668Z
Constructor Arguments
0x000000000000000000000000586c52dbb6600b8a96f5bff5b664a4ffa76663d1
Arg [0] (address) : 0x586c52dbb6600b8a96f5bff5b664a4ffa76663d1
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; } } interface IERC223 { function mint(address _to, uint256 _amount) external; function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); function burnFrom(address sender, uint256 amount) external returns (bool); function transfer(address recipient, uint256 amount) external returns (bool); function balanceOf(address account) external view returns (uint256); } interface IERC223Recipient { /** * @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, uint _value, bytes memory _data) external; } contract SlothVesting is Ownable { address constant public vestingToken = address(0x7873d09AF3d6965988831C60c7D38DBbd2eAEAB0); // Sloth token uint256 constant public EndReward = 1769904000; // end time to pay APR 1 February 2026 00:00:00 UTC struct Allocation { uint256 amount; // amount of token uint256 startVesting; // Timestamp (unix time) when starts vesting. uint256 lastClaimed; // Timestamp when tokens were claimed last time uint256 alreadyClaimed; // amount that were claimed already } uint256 public vestingPeriod = 9 minutes;//0 days; // vesting period, before first tokens release uint256 public vestingInterval = 3 minutes;//0 days; // interval (in seconds) of vesting (i.e. 30 days) uint256 public vestingPercentage = 5; // percentage of tokens will be unlocked every interval (i.e. 10% per 30 days) uint256 public vestingAPR = 15; // APR on locked amount of tokens uint256 public totalAllocated; uint256 public totalClaimed; uint256 public totalAPR; mapping(address => Allocation) public beneficiaries; // beneficiary => Allocation 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"); _; } event SetDepositor(address depositor, bool enable); event Claim(address indexed beneficiary, uint256 amount, uint256 reward); event AddAllocation( address indexed to, // beneficiary of tokens uint256 amount, // amount of token uint256 startVesting // Timestamp (unix time) when starts vesting. ); event Rescue(address _token, uint256 _amount); constructor (address _depositor) { if (_depositor != address(0)) { depositors[_depositor] = true; emit SetDepositor(_depositor, true); } } // 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 setVestingParameters(uint256 _vestingPercentage, uint256 _vestingInterval, uint256 _vestingPeriod, uint256 _vestingAPR) external onlyOwner { vestingPercentage = _vestingPercentage; vestingInterval = _vestingInterval; vestingPeriod = _vestingPeriod; vestingAPR = _vestingAPR; } function allocateTokens( address to, // beneficiary of tokens uint256 amount // amount of token ) external onlyDepositor { IERC223(vestingToken).mint(address(this), amount); // mint vesting token if (beneficiaries[to].startVesting == 0) { // new allocation beneficiaries[to].amount = amount; beneficiaries[to].startVesting = block.timestamp; beneficiaries[to].lastClaimed = block.timestamp; // Check ERC223 compatibility of the beneficiary safeTransfer(vestingToken, to, 0); } else beneficiaries[to].amount += amount; totalAllocated += amount; emit AddAllocation(to, amount, beneficiaries[to].startVesting); } function claim() external { claimBehalf(msg.sender); } function claimBehalf(address beneficiary) public { (uint256 unlockedAmount, uint256 reward) = getUnlockedAmount(beneficiary); require(unlockedAmount != 0, "No unlocked tokens"); beneficiaries[beneficiary].alreadyClaimed += unlockedAmount; beneficiaries[beneficiary].lastClaimed = block.timestamp; totalClaimed += unlockedAmount; totalAPR += reward; if (unlockedAmount != 0) { safeTransfer(vestingToken, beneficiary, unlockedAmount); if (reward != 0) IERC223(vestingToken).mint(beneficiary, reward); // mint reward to beneficiary } emit Claim(beneficiary, unlockedAmount, reward); } function getUnlockedAmount(address beneficiary) public view returns(uint256 unlockedAmount, uint256 reward) { Allocation memory b = beneficiaries[beneficiary]; uint256 startRelease = b.startVesting + vestingPeriod; if (startRelease < block.timestamp) { uint256 rewardEnd = (block.timestamp < EndReward) ? block.timestamp : EndReward; if (b.lastClaimed < rewardEnd) // APR for locked tokens reward = (b.amount - b.alreadyClaimed) * vestingAPR * (rewardEnd - b.lastClaimed) / (100 * 365 days); uint256 intervals = (block.timestamp - startRelease) / vestingInterval; // number of full intervals passed after startVesting unlockedAmount = b.amount * intervals * vestingPercentage / 100; if (unlockedAmount > b.amount) unlockedAmount = b.amount; unlockedAmount = unlockedAmount - b.alreadyClaimed; } } function rescueTokens(address _token) onlyOwner external { require(_token != vestingToken, "vestingToken not allowed"); uint256 amount = IERC223(_token).balanceOf(address(this)); safeTransfer(_token, msg.sender, amount); emit Rescue(_token, amount); } function safeTransfer(address token, address to, uint value) internal { // bytes4(keccak256(bytes('transfer(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED'); } }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_depositor","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":"startVesting","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},{"type":"uint256","name":"reward","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":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"EndReward","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"allocateTokens","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"startVesting","internalType":"uint256"},{"type":"uint256","name":"lastClaimed","internalType":"uint256"},{"type":"uint256","name":"alreadyClaimed","internalType":"uint256"}],"name":"beneficiaries","inputs":[{"type":"address","name":"","internalType":"address"}]},{"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":"bool","name":"","internalType":"bool"}],"name":"depositors","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"unlockedAmount","internalType":"uint256"},{"type":"uint256","name":"reward","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":"setVestingParameters","inputs":[{"type":"uint256","name":"_vestingPercentage","internalType":"uint256"},{"type":"uint256","name":"_vestingInterval","internalType":"uint256"},{"type":"uint256","name":"_vestingPeriod","internalType":"uint256"},{"type":"uint256","name":"_vestingAPR","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalAPR","inputs":[]},{"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":"uint256","name":"","internalType":"uint256"}],"name":"vestingAPR","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"vestingInterval","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"vestingPercentage","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"vestingPeriod","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"vestingToken","inputs":[]}]
Contract Creation Code
0x608060405261021c60015560b46002556005600355600f60045534801561002557600080fd5b5060405161103f38038061103f833981016040819052610044916100f7565b600080546001600160a01b0319163390811782556040519091907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a36001600160a01b038116156100f1576001600160a01b038116600081815260096020908152604091829020805460ff191660019081179091558251938452908301527fb1252fa67b4c05afbdaadfae34890b205103c0212a9e062b3978e8cd573631a9910160405180910390a15b50610127565b60006020828403121561010957600080fd5b81516001600160a01b038116811461012057600080fd5b9392505050565b610f09806101366000396000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c8063715018a6116100b8578063b8e50cab1161007c578063b8e50cab1461029a578063d54ad2a1146102a3578063d89d6d78146102ac578063dbd533da146102bf578063eed75f6d146102ca578063f2fde38b146102fd57600080fd5b8063715018a6146102525780637313ee5a1461025a57806386ce02851461026357806388901496146102765780638da5cb5b1461028957600080fd5b8063420d4a02116100ff578063420d4a02146101fd57806345f7f249146102255780634e71d92d1461022e5780636d2883d3146102365780636f860d741461023f57600080fd5b8062ae3bf81461013b5780630156773914610150578063106f3bbb146101aa5780631839e92e146101c157806319d152fa146101ca575b600080fd5b61014e610149366004610cf8565b610310565b005b61018561015e366004610cf8565b60086020526000908152604090208054600182015460028301546003909301549192909184565b6040805194855260208501939093529183015260608201526080015b60405180910390f35b6101b360035481565b6040519081526020016101a1565b6101b360045481565b6101e5737873d09af3d6965988831c60c7d38dbbd2eaeab081565b6040516001600160a01b0390911681526020016101a1565b61021061020b366004610cf8565b61047e565b604080519283526020830191909152016101a1565b6101b360055481565b61014e6105c3565b6101b360075481565b61014e61024d366004610d2b565b6105ce565b61014e610663565b6101b360015481565b61014e610271366004610d62565b6106e6565b61014e610284366004610cf8565b6108be565b6000546001600160a01b03166101e5565b6101b360025481565b6101b360065481565b61014e6102ba366004610d8c565b610a7b565b6101b363697e978081565b6102ed6102d8366004610cf8565b60096020526000908152604090205460ff1681565b60405190151581526020016101a1565b61014e61030b366004610cf8565b610ac8565b336103236000546001600160a01b031690565b6001600160a01b0316146103525760405162461bcd60e51b815260040161034990610dbe565b60405180910390fd5b737873d09af3d6965988831c60c7d38dbbd2eaeaaf196001600160a01b038216016103bf5760405162461bcd60e51b815260206004820152601860248201527f76657374696e67546f6b656e206e6f7420616c6c6f77656400000000000000006044820152606401610349565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610406573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061042a9190610df3565b9050610437823383610bc1565b604080516001600160a01b0384168152602081018390527f542fa6bfee3b4746210fbdd1d83f9e49b65adde3639f8d8f165dd18347938af291015b60405180910390a15050565b6001600160a01b038116600090815260086020908152604080832081516080810183528154815260018083015494820185905260028301549382019390935260039091015460608201529054839283916104d791610e22565b9050428110156105bc57600063697e978042106104f85763697e97806104fa565b425b905080836040015110156105525763bbf81e0083604001518261051d9190610e3b565b600454606086015186516105319190610e3b565b61053b9190610e4e565b6105459190610e4e565b61054f9190610e65565b93505b6002546000906105628442610e3b565b61056c9190610e65565b905060646003548286600001516105839190610e4e565b61058d9190610e4e565b6105979190610e65565b84519096508611156105a857835195505b60608401516105b79087610e3b565b955050505b5050915091565b6105cc336108be565b565b336105e16000546001600160a01b031690565b6001600160a01b0316146106075760405162461bcd60e51b815260040161034990610dbe565b6001600160a01b038216600081815260096020908152604091829020805460ff19168515159081179091558251938452908301527fb1252fa67b4c05afbdaadfae34890b205103c0212a9e062b3978e8cd573631a99101610472565b336106766000546001600160a01b031690565b6001600160a01b03161461069c5760405162461bcd60e51b815260040161034990610dbe565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b3360009081526009602052604090205460ff166107455760405162461bcd60e51b815260206004820152601760248201527f4f6e6c79206465706f7369746f727320616c6c6f7765640000000000000000006044820152606401610349565b6040516340c10f1960e01b815230600482015260248101829052737873d09af3d6965988831c60c7d38dbbd2eaeab0906340c10f1990604401600060405180830381600087803b15801561079857600080fd5b505af11580156107ac573d6000803e3d6000fd5b505050506001600160a01b0382166000908152600860205260408120600101549003610821576001600160a01b0382166000908152600860205260408120828155426001820181905560029091015561081c90737873d09af3d6965988831c60c7d38dbbd2eaeab0908490610bc1565b61084f565b6001600160a01b03821660009081526008602052604081208054839290610849908490610e22565b90915550505b80600560008282546108619190610e22565b90915550506001600160a01b038216600081815260086020908152604091829020600101548251858152918201527fc8fb5cb702e27b0b1c69943779531dfad2648533e125393dc98a0dccf648ab61910160405180910390a25050565b6000806108ca8361047e565b91509150816000036109135760405162461bcd60e51b81526020600482015260126024820152714e6f20756e6c6f636b656420746f6b656e7360701b6044820152606401610349565b6001600160a01b0383166000908152600860205260408120600301805484929061093e908490610e22565b90915550506001600160a01b03831660009081526008602052604081204260029091015560068054849290610974908490610e22565b92505081905550806007600082825461098d9190610e22565b90915550508115610a32576109b7737873d09af3d6965988831c60c7d38dbbd2eaeab08484610bc1565b8015610a32576040516340c10f1960e01b81526001600160a01b038416600482015260248101829052737873d09af3d6965988831c60c7d38dbbd2eaeab0906340c10f1990604401600060405180830381600087803b158015610a1957600080fd5b505af1158015610a2d573d6000803e3d6000fd5b505050505b60408051838152602081018390526001600160a01b038516917f34fcbac0073d7c3d388e51312faf357774904998eeb8fca628b9e6f65ee1cbf7910160405180910390a2505050565b33610a8e6000546001600160a01b031690565b6001600160a01b031614610ab45760405162461bcd60e51b815260040161034990610dbe565b600393909355600291909155600155600455565b33610adb6000546001600160a01b031690565b6001600160a01b031614610b015760405162461bcd60e51b815260040161034990610dbe565b6001600160a01b038116610b665760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610349565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691610c1d9190610e87565b6000604051808303816000865af19150503d8060008114610c5a576040519150601f19603f3d011682016040523d82523d6000602084013e610c5f565b606091505b5091509150818015610c89575080511580610c89575080806020019051810190610c899190610eb6565b610cd55760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610349565b5050505050565b80356001600160a01b0381168114610cf357600080fd5b919050565b600060208284031215610d0a57600080fd5b610d1382610cdc565b9392505050565b8015158114610d2857600080fd5b50565b60008060408385031215610d3e57600080fd5b610d4783610cdc565b91506020830135610d5781610d1a565b809150509250929050565b60008060408385031215610d7557600080fd5b610d7e83610cdc565b946020939093013593505050565b60008060008060808587031215610da257600080fd5b5050823594602084013594506040840135936060013592509050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600060208284031215610e0557600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610e3557610e35610e0c565b92915050565b81810381811115610e3557610e35610e0c565b8082028115828204841417610e3557610e35610e0c565b600082610e8257634e487b7160e01b600052601260045260246000fd5b500490565b6000825160005b81811015610ea85760208186018101518583015201610e8e565b506000920191825250919050565b600060208284031215610ec857600080fd5b8151610d1381610d1a56fea2646970667358221220fb9f50b85e748f2f3cfa6c32ecda488a3e37d9f96130d76e7d2cd03ff892e9cb64736f6c63430008130033000000000000000000000000586c52dbb6600b8a96f5bff5b664a4ffa76663d1
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106101365760003560e01c8063715018a6116100b8578063b8e50cab1161007c578063b8e50cab1461029a578063d54ad2a1146102a3578063d89d6d78146102ac578063dbd533da146102bf578063eed75f6d146102ca578063f2fde38b146102fd57600080fd5b8063715018a6146102525780637313ee5a1461025a57806386ce02851461026357806388901496146102765780638da5cb5b1461028957600080fd5b8063420d4a02116100ff578063420d4a02146101fd57806345f7f249146102255780634e71d92d1461022e5780636d2883d3146102365780636f860d741461023f57600080fd5b8062ae3bf81461013b5780630156773914610150578063106f3bbb146101aa5780631839e92e146101c157806319d152fa146101ca575b600080fd5b61014e610149366004610cf8565b610310565b005b61018561015e366004610cf8565b60086020526000908152604090208054600182015460028301546003909301549192909184565b6040805194855260208501939093529183015260608201526080015b60405180910390f35b6101b360035481565b6040519081526020016101a1565b6101b360045481565b6101e5737873d09af3d6965988831c60c7d38dbbd2eaeab081565b6040516001600160a01b0390911681526020016101a1565b61021061020b366004610cf8565b61047e565b604080519283526020830191909152016101a1565b6101b360055481565b61014e6105c3565b6101b360075481565b61014e61024d366004610d2b565b6105ce565b61014e610663565b6101b360015481565b61014e610271366004610d62565b6106e6565b61014e610284366004610cf8565b6108be565b6000546001600160a01b03166101e5565b6101b360025481565b6101b360065481565b61014e6102ba366004610d8c565b610a7b565b6101b363697e978081565b6102ed6102d8366004610cf8565b60096020526000908152604090205460ff1681565b60405190151581526020016101a1565b61014e61030b366004610cf8565b610ac8565b336103236000546001600160a01b031690565b6001600160a01b0316146103525760405162461bcd60e51b815260040161034990610dbe565b60405180910390fd5b737873d09af3d6965988831c60c7d38dbbd2eaeaaf196001600160a01b038216016103bf5760405162461bcd60e51b815260206004820152601860248201527f76657374696e67546f6b656e206e6f7420616c6c6f77656400000000000000006044820152606401610349565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610406573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061042a9190610df3565b9050610437823383610bc1565b604080516001600160a01b0384168152602081018390527f542fa6bfee3b4746210fbdd1d83f9e49b65adde3639f8d8f165dd18347938af291015b60405180910390a15050565b6001600160a01b038116600090815260086020908152604080832081516080810183528154815260018083015494820185905260028301549382019390935260039091015460608201529054839283916104d791610e22565b9050428110156105bc57600063697e978042106104f85763697e97806104fa565b425b905080836040015110156105525763bbf81e0083604001518261051d9190610e3b565b600454606086015186516105319190610e3b565b61053b9190610e4e565b6105459190610e4e565b61054f9190610e65565b93505b6002546000906105628442610e3b565b61056c9190610e65565b905060646003548286600001516105839190610e4e565b61058d9190610e4e565b6105979190610e65565b84519096508611156105a857835195505b60608401516105b79087610e3b565b955050505b5050915091565b6105cc336108be565b565b336105e16000546001600160a01b031690565b6001600160a01b0316146106075760405162461bcd60e51b815260040161034990610dbe565b6001600160a01b038216600081815260096020908152604091829020805460ff19168515159081179091558251938452908301527fb1252fa67b4c05afbdaadfae34890b205103c0212a9e062b3978e8cd573631a99101610472565b336106766000546001600160a01b031690565b6001600160a01b03161461069c5760405162461bcd60e51b815260040161034990610dbe565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b3360009081526009602052604090205460ff166107455760405162461bcd60e51b815260206004820152601760248201527f4f6e6c79206465706f7369746f727320616c6c6f7765640000000000000000006044820152606401610349565b6040516340c10f1960e01b815230600482015260248101829052737873d09af3d6965988831c60c7d38dbbd2eaeab0906340c10f1990604401600060405180830381600087803b15801561079857600080fd5b505af11580156107ac573d6000803e3d6000fd5b505050506001600160a01b0382166000908152600860205260408120600101549003610821576001600160a01b0382166000908152600860205260408120828155426001820181905560029091015561081c90737873d09af3d6965988831c60c7d38dbbd2eaeab0908490610bc1565b61084f565b6001600160a01b03821660009081526008602052604081208054839290610849908490610e22565b90915550505b80600560008282546108619190610e22565b90915550506001600160a01b038216600081815260086020908152604091829020600101548251858152918201527fc8fb5cb702e27b0b1c69943779531dfad2648533e125393dc98a0dccf648ab61910160405180910390a25050565b6000806108ca8361047e565b91509150816000036109135760405162461bcd60e51b81526020600482015260126024820152714e6f20756e6c6f636b656420746f6b656e7360701b6044820152606401610349565b6001600160a01b0383166000908152600860205260408120600301805484929061093e908490610e22565b90915550506001600160a01b03831660009081526008602052604081204260029091015560068054849290610974908490610e22565b92505081905550806007600082825461098d9190610e22565b90915550508115610a32576109b7737873d09af3d6965988831c60c7d38dbbd2eaeab08484610bc1565b8015610a32576040516340c10f1960e01b81526001600160a01b038416600482015260248101829052737873d09af3d6965988831c60c7d38dbbd2eaeab0906340c10f1990604401600060405180830381600087803b158015610a1957600080fd5b505af1158015610a2d573d6000803e3d6000fd5b505050505b60408051838152602081018390526001600160a01b038516917f34fcbac0073d7c3d388e51312faf357774904998eeb8fca628b9e6f65ee1cbf7910160405180910390a2505050565b33610a8e6000546001600160a01b031690565b6001600160a01b031614610ab45760405162461bcd60e51b815260040161034990610dbe565b600393909355600291909155600155600455565b33610adb6000546001600160a01b031690565b6001600160a01b031614610b015760405162461bcd60e51b815260040161034990610dbe565b6001600160a01b038116610b665760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610349565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691610c1d9190610e87565b6000604051808303816000865af19150503d8060008114610c5a576040519150601f19603f3d011682016040523d82523d6000602084013e610c5f565b606091505b5091509150818015610c89575080511580610c89575080806020019051810190610c899190610eb6565b610cd55760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610349565b5050505050565b80356001600160a01b0381168114610cf357600080fd5b919050565b600060208284031215610d0a57600080fd5b610d1382610cdc565b9392505050565b8015158114610d2857600080fd5b50565b60008060408385031215610d3e57600080fd5b610d4783610cdc565b91506020830135610d5781610d1a565b809150509250929050565b60008060408385031215610d7557600080fd5b610d7e83610cdc565b946020939093013593505050565b60008060008060808587031215610da257600080fd5b5050823594602084013594506040840135936060013592509050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600060208284031215610e0557600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610e3557610e35610e0c565b92915050565b81810381811115610e3557610e35610e0c565b8082028115828204841417610e3557610e35610e0c565b600082610e8257634e487b7160e01b600052601260045260246000fd5b500490565b6000825160005b81811015610ea85760208186018101518583015201610e8e565b506000920191825250919050565b600060208284031215610ec857600080fd5b8151610d1381610d1a56fea2646970667358221220fb9f50b85e748f2f3cfa6c32ecda488a3e37d9f96130d76e7d2cd03ff892e9cb64736f6c63430008130033