Transactions
Token Transfers
Tokens
Internal Transactions
Coin Balance History
Logs
Code
Read Contract
Write Contract
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- PromoVault2
- Optimization enabled
- true
- Compiler version
- v0.8.19+commit.7dd6d404
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2024-09-26T15:33:48.826780Z
Contract source code
// SPDX-License-Identifier: No License (None) pragma solidity 0.8.19; // helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false library TransferHelper { function safeApprove(address token, address to, uint value) internal { // bytes4(keccak256(bytes('approve(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED'); } 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'); } function safeTransferFrom(address token, address from, address to, uint value) internal { // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED'); } function safeTransferETH(address to, uint value) internal { (bool success,) = to.call{value:value}(new bytes(0)); require(success, 'TransferHelper: ETH_TRANSFER_FAILED'); } } abstract contract Ownable { address internal _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 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 IERC20 { function balanceOf(address account) external view returns (uint256); } contract PromoVault2 is Ownable { using TransferHelper for address; struct Airdrop { uint128 balance; // available airdrop balance uint64 vestingDate; // after this date tokens can be claimed uint64 deadline; // until this date tokens can be claimed, 0 means "without deadline" address token; // airdrop token } mapping(address signer => Airdrop) public airdrops; mapping(bytes32 messageHash => bool processed) public isProcessed; // record processed messages event VaultTransfer(address indexed token, address indexed signer, address indexed from, address to, uint256 value, uint256 nonce); event CreateAirdrop(address signer, address token, uint256 amount); event CloseAirdrop(address signer, address receiver, uint256 amount); event Rescue(address _token, uint256 _amount); bool public isPaused; modifier isNotPaused() { require(!isPaused, "is paused"); _; } function setPause(bool pause) external onlyOwner { isPaused = pause; } function createAirdrop( address token, // airdrop token uint256 amount, // amount of tokens for airdrop address signer, // unique signer for this airdrop uint64 vestingDate, // after this date tokens can be claimed uint64 deadline // until this date tokens can be claimed, 0 means "without deadline" ) external isNotPaused { require(signer != address(0) && airdrops[signer].token == address(0), "signer already was used"); uint256 balance = IERC20(token).balanceOf(address(this)); token.safeTransferFrom(msg.sender, address(this), amount); amount = IERC20(token).balanceOf(address(this)) - balance; require(amount < 2**128, "too big amount"); airdrops[signer] = Airdrop(uint128(amount), vestingDate, deadline, token); emit CreateAirdrop(signer, token, amount); } /* // to sign message on the server-side use: var vault = new web3.eth.Contract(VaultContractABI, VaultContractAddress); var nonce = await vault.methods.nonces(from).call(); var messageHash = web3.utils.soliditySha3(signer, token, from, value, nonce, ChainId, VaultContractAddress); var signature = web3.eth.accounts.sign(messageHash, PrivateKey); */ // claim promo tokens from vault to user's address. Can be called by any wallet function claimTokens( address signer, // signer of airdrop address to, // transfer to address (user's address who received airdrop) uint256 value, // amount of tokens to transfer uint256 nonce, // nonce is used to if you need to airdrop tokens to the same user many times bytes memory signature ) external isNotPaused { claim(signer, to, to, value, nonce, signature); } // user transfers promo tokens from vault to some address. Must be called by user who received airdrop function transferTokens( address signer, // signer of airdrop address to, // transfer to address (any address) uint256 value, // amount of tokens to transfer uint256 nonce, // nonce is used to if you need to airdrop tokens to the same user many times bytes memory signature ) external isNotPaused { claim(signer, msg.sender, to, value, nonce, signature); } function claim( address signer, // signer of airdrop address from, // transfer from address address to, // transfer to address uint256 value, // amount of tokens to transfer uint256 nonce, // nonce is used to if you need to airdrop tokens to the same user many times bytes memory signature ) internal { Airdrop memory a = airdrops[signer]; require(a.token != address(0) && signer != address(0), "closed"); require(a.balance >= value, "Not enough tokens"); require(a.vestingDate <= block.timestamp, "under vesting"); require(a.deadline == 0 || a.deadline >= block.timestamp, "expired"); bytes32 messageHash = keccak256( abi.encodePacked( signer, a.token, from, value, nonce, block.chainid, address(this) ) ); messageHash = prefixed(messageHash); require(!isProcessed[messageHash], "already claimed"); require(signer == recoverSigner(messageHash, signature), "wrong signature"); isProcessed[messageHash] = true; airdrops[signer].balance = a.balance - uint128(value); a.token.safeTransfer(to, value); emit VaultTransfer(a.token, signer, from, to, value, nonce); } function splitSignature(bytes memory sig) internal pure returns ( uint8 v, bytes32 r, bytes32 s ) { require(sig.length == 65); assembly { // first 32 bytes, after the length prefix r := mload(add(sig, 32)) // second 32 bytes s := mload(add(sig, 64)) // final byte (first byte of the next 32 bytes) v := byte(0, mload(add(sig, 96))) } } function recoverSigner(bytes32 message, bytes memory sig) internal pure returns (address) { uint8 v; bytes32 r; bytes32 s; (v, r, s) = splitSignature(sig); return ecrecover(message, v, r, s); } // Builds a prefixed hash to mimic the behavior of eth_sign. function prefixed(bytes32 hash) internal pure returns (bytes32) { return keccak256( abi.encodePacked("\x19Ethereum Signed Message:\n32", hash) ); } /* // ERC223 callback function tokenReceived(address, uint, bytes calldata) external pure returns(bytes4) { return this.tokenReceived.selector; } */ // owner can close airdrop before all tokens is claimed and transfer leftover tokens to receiver address function closeAirdrop(address signer, address receiver) external onlyOwner { Airdrop memory a = airdrops[signer]; require(a.token != address(0) && signer != address(0), "closed"); require(a.balance != 0, "Not enough tokens"); a.token.safeTransfer(receiver, uint256(a.balance)); airdrops[signer].balance = 0; emit CloseAirdrop(signer, receiver, uint256(a.balance)); } // allow owner to rescue tokens from contract function rescueTokens(address token, uint256 amount) onlyOwner external { if (token == address(0)) { msg.sender.safeTransferETH(amount); } else { token.safeTransfer(msg.sender, amount); } emit Rescue(token, amount); } }
Contract ABI
[{"type":"event","name":"CloseAirdrop","inputs":[{"type":"address","name":"signer","internalType":"address","indexed":false},{"type":"address","name":"receiver","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"CreateAirdrop","inputs":[{"type":"address","name":"signer","internalType":"address","indexed":false},{"type":"address","name":"token","internalType":"address","indexed":false},{"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":"VaultTransfer","inputs":[{"type":"address","name":"token","internalType":"address","indexed":true},{"type":"address","name":"signer","internalType":"address","indexed":true},{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":false},{"type":"uint256","name":"value","internalType":"uint256","indexed":false},{"type":"uint256","name":"nonce","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint128","name":"balance","internalType":"uint128"},{"type":"uint64","name":"vestingDate","internalType":"uint64"},{"type":"uint64","name":"deadline","internalType":"uint64"},{"type":"address","name":"token","internalType":"address"}],"name":"airdrops","inputs":[{"type":"address","name":"signer","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claimTokens","inputs":[{"type":"address","name":"signer","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"uint256","name":"nonce","internalType":"uint256"},{"type":"bytes","name":"signature","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"closeAirdrop","inputs":[{"type":"address","name":"signer","internalType":"address"},{"type":"address","name":"receiver","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"createAirdrop","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"address","name":"signer","internalType":"address"},{"type":"uint64","name":"vestingDate","internalType":"uint64"},{"type":"uint64","name":"deadline","internalType":"uint64"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isPaused","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"processed","internalType":"bool"}],"name":"isProcessed","inputs":[{"type":"bytes32","name":"messageHash","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"rescueTokens","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setPause","inputs":[{"type":"bool","name":"pause","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferTokens","inputs":[{"type":"address","name":"signer","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"uint256","name":"nonce","internalType":"uint256"},{"type":"bytes","name":"signature","internalType":"bytes"}]}]
Contract Creation Code
0x608060405234801561001057600080fd5b50600080546001600160a01b0319163390811782556040519091907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a36114a28061005f6000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80638da5cb5b116100715780638da5cb5b146101ba578063b187bd26146101d5578063bedb86fb146101e2578063cbc20fe0146101f5578063f2fde38b14610208578063f6368f7b1461021b57600080fd5b806311c16896146100ae57806355c81293146100e657806357376198146100fb578063690e6cc21461010e5780638c86f0a714610121575b600080fd5b6100d16100bc36600461110b565b60026020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6100f96100f4366004611158565b61022e565b005b6100f96101093660046111b6565b610514565b6100f961011c3660046111e0565b6105c4565b61017961012f366004611213565b600160208190526000918252604090912080549101546001600160801b0382169167ffffffffffffffff600160801b8204811692600160c01b90920416906001600160a01b031684565b604080516001600160801b0395909516855267ffffffffffffffff938416602086015291909216908301526001600160a01b031660608201526080016100dd565b6000546040516001600160a01b0390911681526020016100dd565b6003546100d19060ff1681565b6100f96101f0366004611246565b6107a0565b6100f9610203366004611279565b6107ec565b6100f9610216366004611213565b610824565b6100f9610229366004611279565b61091d565b60035460ff161561025a5760405162461bcd60e51b81526004016102519061135f565b60405180910390fd5b6001600160a01b0383161580159061028e57506001600160a01b038381166000908152600160208190526040909120015416155b6102da5760405162461bcd60e51b815260206004820152601760248201527f7369676e657220616c72656164792077617320757365640000000000000000006044820152606401610251565b6040516370a0823160e01b81523060048201526000906001600160a01b038716906370a0823190602401602060405180830381865afa158015610321573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103459190611382565b905061035c6001600160a01b03871633308861094e565b6040516370a0823160e01b815230600482015281906001600160a01b038816906370a0823190602401602060405180830381865afa1580156103a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103c69190611382565b6103d091906113b1565b9450600160801b85106104165760405162461bcd60e51b815260206004820152600e60248201526d1d1bdbc8189a59c8185b5bdd5b9d60921b6044820152606401610251565b604080516080810182526001600160801b03878116825267ffffffffffffffff86811660208085019182528783168587019081526001600160a01b038d811660608089018281528e841660008181526001808952908d90209b518c54995197518b16600160c01b026001600160c01b0398909b16600160801b026001600160c01b0319909a169b169a909a1797909717949094169690961788559151969095018054969095166001600160a01b0319909616959095179093558451908152918201929092529182018790527f8bb035a14e427c40fc1fb7f442d2a84d053d2cf217513ca816ca3a8af748c56c910160405180910390a1505050505050565b336105276000546001600160a01b031690565b6001600160a01b03161461054d5760405162461bcd60e51b8152600401610251906113c4565b6001600160a01b03821661056a576105653382610a7e565b61057e565b61057e6001600160a01b0383163383610b4c565b604080516001600160a01b0384168152602081018390527f542fa6bfee3b4746210fbdd1d83f9e49b65adde3639f8d8f165dd18347938af2910160405180910390a15050565b336105d76000546001600160a01b031690565b6001600160a01b0316146105fd5760405162461bcd60e51b8152600401610251906113c4565b6001600160a01b03808316600090815260016020818152604092839020835160808101855281546001600160801b038116825267ffffffffffffffff600160801b8204811694830194909452600160c01b900490921693820193909352910154909116606082018190521580159061067d57506001600160a01b03831615155b6106b25760405162461bcd60e51b815260206004820152600660248201526518db1bdcd95960d21b6044820152606401610251565b80516001600160801b03166000036107005760405162461bcd60e51b81526020600482015260116024820152704e6f7420656e6f75676820746f6b656e7360781b6044820152606401610251565b80516060820151610727916001600160a01b039091169084906001600160801b0316610b4c565b6001600160a01b0383811660008181526001602090815260409182902080546001600160801b031916905584518251938452938616908301526001600160801b039092168183015290517f3ec192272fa9cf7c91850e76dbc4eb1665ed08972b0eca02adcfa50a875ed3d09181900360600190a1505050565b336107b36000546001600160a01b031690565b6001600160a01b0316146107d95760405162461bcd60e51b8152600401610251906113c4565b6003805460ff1916911515919091179055565b60035460ff161561080f5760405162461bcd60e51b81526004016102519061135f565b61081d853386868686610c60565b5050505050565b336108376000546001600160a01b031690565b6001600160a01b03161461085d5760405162461bcd60e51b8152600401610251906113c4565b6001600160a01b0381166108c25760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610251565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60035460ff16156109405760405162461bcd60e51b81526004016102519061135f565b61081d858586868686610c60565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916109b291906113f9565b6000604051808303816000865af19150503d80600081146109ef576040519150601f19603f3d011682016040523d82523d6000602084013e6109f4565b606091505b5091509150818015610a1e575080511580610a1e575080806020019051810190610a1e9190611428565b610a765760405162461bcd60e51b8152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f46416044820152631253115160e21b6064820152608401610251565b505050505050565b604080516000808252602082019092526001600160a01b038416908390604051610aa891906113f9565b60006040518083038185875af1925050503d8060008114610ae5576040519150601f19603f3d011682016040523d82523d6000602084013e610aea565b606091505b5050905080610b475760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b6064820152608401610251565b505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691610ba891906113f9565b6000604051808303816000865af19150503d8060008114610be5576040519150601f19603f3d011682016040523d82523d6000602084013e610bea565b606091505b5091509150818015610c14575080511580610c14575080806020019051810190610c149190611428565b61081d5760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610251565b6001600160a01b03808716600090815260016020818152604092839020835160808101855281546001600160801b038116825267ffffffffffffffff600160801b8204811694830194909452600160c01b9004909216938201939093529101549091166060820181905215801590610ce057506001600160a01b03871615155b610d155760405162461bcd60e51b815260206004820152600660248201526518db1bdcd95960d21b6044820152606401610251565b80516001600160801b0316841115610d635760405162461bcd60e51b81526020600482015260116024820152704e6f7420656e6f75676820746f6b656e7360781b6044820152606401610251565b42816020015167ffffffffffffffff161115610db15760405162461bcd60e51b815260206004820152600d60248201526c756e6465722076657374696e6760981b6044820152606401610251565b604081015167ffffffffffffffff161580610dda575042816040015167ffffffffffffffff1610155b610e105760405162461bcd60e51b8152602060048201526007602482015266195e1c1a5c995960ca1b6044820152606401610251565b6060808201516040516bffffffffffffffffffffffff198a841b8116602083015291831b8216603482015288831b82166048820152605c8101879052607c810186905246609c8201523090921b1660bc82015260009060d001604051602081830303815290604052805190602001209050610ed8816040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b60008181526002602052604090205490915060ff1615610f2c5760405162461bcd60e51b815260206004820152600f60248201526e185b1c9958591e4818db185a5b5959608a1b6044820152606401610251565b610f36818461105c565b6001600160a01b0316886001600160a01b031614610f885760405162461bcd60e51b815260206004820152600f60248201526e77726f6e67207369676e617475726560881b6044820152606401610251565b6000818152600260205260409020805460ff191660011790558151610fae908690611445565b6001600160a01b03898116600090815260016020526040902080546001600160801b0319166001600160801b0393909316929092179091556060830151610ff791168787610b4c565b606080830151604080516001600160a01b038a81168252602082018a9052918101889052818b16938c831693909216917f9940b13f828ca3c69d28f507d3d8a43250000e65b24a5f15b99c37333f37831f910160405180910390a45050505050505050565b60008060008061106b856110dc565b6040805160008152602081018083528b905260ff8516918101919091526060810183905260808101829052929550909350915060019060a0016020604051602081039080840390855afa1580156110c6573d6000803e3d6000fd5b5050506020604051035193505050505b92915050565b600080600083516041146110ef57600080fd5b5050506020810151604082015160609092015160001a92909190565b60006020828403121561111d57600080fd5b5035919050565b80356001600160a01b038116811461113b57600080fd5b919050565b803567ffffffffffffffff8116811461113b57600080fd5b600080600080600060a0868803121561117057600080fd5b61117986611124565b94506020860135935061118e60408701611124565b925061119c60608701611140565b91506111aa60808701611140565b90509295509295909350565b600080604083850312156111c957600080fd5b6111d283611124565b946020939093013593505050565b600080604083850312156111f357600080fd5b6111fc83611124565b915061120a60208401611124565b90509250929050565b60006020828403121561122557600080fd5b61122e82611124565b9392505050565b801515811461124357600080fd5b50565b60006020828403121561125857600080fd5b813561122e81611235565b634e487b7160e01b600052604160045260246000fd5b600080600080600060a0868803121561129157600080fd5b61129a86611124565b94506112a860208701611124565b93506040860135925060608601359150608086013567ffffffffffffffff808211156112d357600080fd5b818801915088601f8301126112e757600080fd5b8135818111156112f9576112f9611263565b604051601f8201601f19908116603f0116810190838211818310171561132157611321611263565b816040528281528b602084870101111561133a57600080fd5b8260208601602083013760006020848301015280955050505050509295509295909350565b6020808252600990820152681a5cc81c185d5cd95960ba1b604082015260600190565b60006020828403121561139457600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b818103818111156110d6576110d661139b565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6000825160005b8181101561141a5760208186018101518583015201611400565b506000920191825250919050565b60006020828403121561143a57600080fd5b815161122e81611235565b6001600160801b038281168282160390808211156114655761146561139b565b509291505056fea2646970667358221220bd3802557a5b18457081bd679fee8eb5ccd26645c108167fe372928964b02d9964736f6c63430008130033
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106100a95760003560e01c80638da5cb5b116100715780638da5cb5b146101ba578063b187bd26146101d5578063bedb86fb146101e2578063cbc20fe0146101f5578063f2fde38b14610208578063f6368f7b1461021b57600080fd5b806311c16896146100ae57806355c81293146100e657806357376198146100fb578063690e6cc21461010e5780638c86f0a714610121575b600080fd5b6100d16100bc36600461110b565b60026020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6100f96100f4366004611158565b61022e565b005b6100f96101093660046111b6565b610514565b6100f961011c3660046111e0565b6105c4565b61017961012f366004611213565b600160208190526000918252604090912080549101546001600160801b0382169167ffffffffffffffff600160801b8204811692600160c01b90920416906001600160a01b031684565b604080516001600160801b0395909516855267ffffffffffffffff938416602086015291909216908301526001600160a01b031660608201526080016100dd565b6000546040516001600160a01b0390911681526020016100dd565b6003546100d19060ff1681565b6100f96101f0366004611246565b6107a0565b6100f9610203366004611279565b6107ec565b6100f9610216366004611213565b610824565b6100f9610229366004611279565b61091d565b60035460ff161561025a5760405162461bcd60e51b81526004016102519061135f565b60405180910390fd5b6001600160a01b0383161580159061028e57506001600160a01b038381166000908152600160208190526040909120015416155b6102da5760405162461bcd60e51b815260206004820152601760248201527f7369676e657220616c72656164792077617320757365640000000000000000006044820152606401610251565b6040516370a0823160e01b81523060048201526000906001600160a01b038716906370a0823190602401602060405180830381865afa158015610321573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103459190611382565b905061035c6001600160a01b03871633308861094e565b6040516370a0823160e01b815230600482015281906001600160a01b038816906370a0823190602401602060405180830381865afa1580156103a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103c69190611382565b6103d091906113b1565b9450600160801b85106104165760405162461bcd60e51b815260206004820152600e60248201526d1d1bdbc8189a59c8185b5bdd5b9d60921b6044820152606401610251565b604080516080810182526001600160801b03878116825267ffffffffffffffff86811660208085019182528783168587019081526001600160a01b038d811660608089018281528e841660008181526001808952908d90209b518c54995197518b16600160c01b026001600160c01b0398909b16600160801b026001600160c01b0319909a169b169a909a1797909717949094169690961788559151969095018054969095166001600160a01b0319909616959095179093558451908152918201929092529182018790527f8bb035a14e427c40fc1fb7f442d2a84d053d2cf217513ca816ca3a8af748c56c910160405180910390a1505050505050565b336105276000546001600160a01b031690565b6001600160a01b03161461054d5760405162461bcd60e51b8152600401610251906113c4565b6001600160a01b03821661056a576105653382610a7e565b61057e565b61057e6001600160a01b0383163383610b4c565b604080516001600160a01b0384168152602081018390527f542fa6bfee3b4746210fbdd1d83f9e49b65adde3639f8d8f165dd18347938af2910160405180910390a15050565b336105d76000546001600160a01b031690565b6001600160a01b0316146105fd5760405162461bcd60e51b8152600401610251906113c4565b6001600160a01b03808316600090815260016020818152604092839020835160808101855281546001600160801b038116825267ffffffffffffffff600160801b8204811694830194909452600160c01b900490921693820193909352910154909116606082018190521580159061067d57506001600160a01b03831615155b6106b25760405162461bcd60e51b815260206004820152600660248201526518db1bdcd95960d21b6044820152606401610251565b80516001600160801b03166000036107005760405162461bcd60e51b81526020600482015260116024820152704e6f7420656e6f75676820746f6b656e7360781b6044820152606401610251565b80516060820151610727916001600160a01b039091169084906001600160801b0316610b4c565b6001600160a01b0383811660008181526001602090815260409182902080546001600160801b031916905584518251938452938616908301526001600160801b039092168183015290517f3ec192272fa9cf7c91850e76dbc4eb1665ed08972b0eca02adcfa50a875ed3d09181900360600190a1505050565b336107b36000546001600160a01b031690565b6001600160a01b0316146107d95760405162461bcd60e51b8152600401610251906113c4565b6003805460ff1916911515919091179055565b60035460ff161561080f5760405162461bcd60e51b81526004016102519061135f565b61081d853386868686610c60565b5050505050565b336108376000546001600160a01b031690565b6001600160a01b03161461085d5760405162461bcd60e51b8152600401610251906113c4565b6001600160a01b0381166108c25760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610251565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60035460ff16156109405760405162461bcd60e51b81526004016102519061135f565b61081d858586868686610c60565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916109b291906113f9565b6000604051808303816000865af19150503d80600081146109ef576040519150601f19603f3d011682016040523d82523d6000602084013e6109f4565b606091505b5091509150818015610a1e575080511580610a1e575080806020019051810190610a1e9190611428565b610a765760405162461bcd60e51b8152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f46416044820152631253115160e21b6064820152608401610251565b505050505050565b604080516000808252602082019092526001600160a01b038416908390604051610aa891906113f9565b60006040518083038185875af1925050503d8060008114610ae5576040519150601f19603f3d011682016040523d82523d6000602084013e610aea565b606091505b5050905080610b475760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b6064820152608401610251565b505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691610ba891906113f9565b6000604051808303816000865af19150503d8060008114610be5576040519150601f19603f3d011682016040523d82523d6000602084013e610bea565b606091505b5091509150818015610c14575080511580610c14575080806020019051810190610c149190611428565b61081d5760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610251565b6001600160a01b03808716600090815260016020818152604092839020835160808101855281546001600160801b038116825267ffffffffffffffff600160801b8204811694830194909452600160c01b9004909216938201939093529101549091166060820181905215801590610ce057506001600160a01b03871615155b610d155760405162461bcd60e51b815260206004820152600660248201526518db1bdcd95960d21b6044820152606401610251565b80516001600160801b0316841115610d635760405162461bcd60e51b81526020600482015260116024820152704e6f7420656e6f75676820746f6b656e7360781b6044820152606401610251565b42816020015167ffffffffffffffff161115610db15760405162461bcd60e51b815260206004820152600d60248201526c756e6465722076657374696e6760981b6044820152606401610251565b604081015167ffffffffffffffff161580610dda575042816040015167ffffffffffffffff1610155b610e105760405162461bcd60e51b8152602060048201526007602482015266195e1c1a5c995960ca1b6044820152606401610251565b6060808201516040516bffffffffffffffffffffffff198a841b8116602083015291831b8216603482015288831b82166048820152605c8101879052607c810186905246609c8201523090921b1660bc82015260009060d001604051602081830303815290604052805190602001209050610ed8816040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b60008181526002602052604090205490915060ff1615610f2c5760405162461bcd60e51b815260206004820152600f60248201526e185b1c9958591e4818db185a5b5959608a1b6044820152606401610251565b610f36818461105c565b6001600160a01b0316886001600160a01b031614610f885760405162461bcd60e51b815260206004820152600f60248201526e77726f6e67207369676e617475726560881b6044820152606401610251565b6000818152600260205260409020805460ff191660011790558151610fae908690611445565b6001600160a01b03898116600090815260016020526040902080546001600160801b0319166001600160801b0393909316929092179091556060830151610ff791168787610b4c565b606080830151604080516001600160a01b038a81168252602082018a9052918101889052818b16938c831693909216917f9940b13f828ca3c69d28f507d3d8a43250000e65b24a5f15b99c37333f37831f910160405180910390a45050505050505050565b60008060008061106b856110dc565b6040805160008152602081018083528b905260ff8516918101919091526060810183905260808101829052929550909350915060019060a0016020604051602081039080840390855afa1580156110c6573d6000803e3d6000fd5b5050506020604051035193505050505b92915050565b600080600083516041146110ef57600080fd5b5050506020810151604082015160609092015160001a92909190565b60006020828403121561111d57600080fd5b5035919050565b80356001600160a01b038116811461113b57600080fd5b919050565b803567ffffffffffffffff8116811461113b57600080fd5b600080600080600060a0868803121561117057600080fd5b61117986611124565b94506020860135935061118e60408701611124565b925061119c60608701611140565b91506111aa60808701611140565b90509295509295909350565b600080604083850312156111c957600080fd5b6111d283611124565b946020939093013593505050565b600080604083850312156111f357600080fd5b6111fc83611124565b915061120a60208401611124565b90509250929050565b60006020828403121561122557600080fd5b61122e82611124565b9392505050565b801515811461124357600080fd5b50565b60006020828403121561125857600080fd5b813561122e81611235565b634e487b7160e01b600052604160045260246000fd5b600080600080600060a0868803121561129157600080fd5b61129a86611124565b94506112a860208701611124565b93506040860135925060608601359150608086013567ffffffffffffffff808211156112d357600080fd5b818801915088601f8301126112e757600080fd5b8135818111156112f9576112f9611263565b604051601f8201601f19908116603f0116810190838211818310171561132157611321611263565b816040528281528b602084870101111561133a57600080fd5b8260208601602083013760006020848301015280955050505050509295509295909350565b6020808252600990820152681a5cc81c185d5cd95960ba1b604082015260600190565b60006020828403121561139457600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b818103818111156110d6576110d661139b565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6000825160005b8181101561141a5760208186018101518583015201611400565b506000920191825250919050565b60006020828403121561143a57600080fd5b815161122e81611235565b6001600160801b038281168282160390808211156114655761146561139b565b509291505056fea2646970667358221220bd3802557a5b18457081bd679fee8eb5ccd26645c108167fe372928964b02d9964736f6c63430008130033