Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- Launchpad
- Optimization enabled
- true
- Compiler version
- v0.8.19+commit.7dd6d404
- Optimization runs
- 200
- EVM Version
- paris
- Verified at
- 2025-01-26T20:02:52.922365Z
Launchpad.sol
// SPDX-License-Identifier: No License (None)
pragma solidity 0.8.19;
/**
* @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 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 totalSupply() external view returns (uint256);
function decimals() external view returns (uint8);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function approve(address spender, uint256 amount) external returns (bool);
}
interface IVesting {
function initialize(address owner_, address vestedToken_) external;
function allocateTokens(
address to, // beneficiary of tokens
uint256 amount, // amount of token to lock on vesting contract
uint256 cliffFinish, // Timestamp (unix time) when starts vesting. First vesting will be at this time
uint256 vestingPercentage, // percentage (with 2 decimals) 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;
}
contract Launchpad is Ownable {
address public vestingImplementation;
struct VestingParams {
uint256 unlockPercentage; // percentage (with 2 decimals) of initially unlocked token. I.e. 500 means 5% unlocked and 95% will go to vesting, 10000 means 100% unlocked (vesting will not be used)
uint256 cliffPeriod; // cliff period (in seconds). The first release will be after this time.
uint256 vestingPercentage; // percentage (with 2 decimals) of locked tokens will be unlocked every interval I.e. 500 means 5% per vestingInterval
uint256 vestingInterval; // interval (in seconds) of vesting (i.e. 2592000 = 30 days)
}
struct ICOParams {
address token; // ICO token
address paymentToken; // if address(0) - native coin
uint256 amount; // amount of token to sell
uint256 startPrice; // price of 1 token in paymentTokens
uint256 endPrice; // if 0 then price is fixed, else price grows liner from startPrice to endPrice based on sold tokens.
uint256 startDate; // timestamp when ICO starts. The date must be in future.
uint256 endDate; // timestamp when ICO ends, if 0 then ICO will be active until sell all tokens
uint256 bonusReserve; // amount of tokens that will be used for bonus. Bonus will be paid until it's available
uint256 bonusPercentage; // percent of bonus (with 2 decimals) which will be added to bought amount. I.e. 2500 = 25%
uint256 bonusActivator; // percent of total ICO tokens that should be bought to activate bonus (with 2 decimals). I.e. 1000 = 10%
// Let say total amount of tokens on this ICO is 1,000,000, so to receive bonus a user should buy at least 100,000 tokens at ones (10%)
VestingParams vestingParams; // parameters of vesting
}
struct ICOState {
address ICOOwner; // address of ICO owner (creator) who will receive payment tokens
uint8 icoTokenDecimals; // number decimals of ICO token (get from token.decimals())
address vestingContract; // address of vesting contract
bool isClosed; // ICO is closed
uint256 totalSold; // total amount of sold tokens
uint256 totalReceived; // total amount received (in paymentToken)
}
mapping (address token => address vestingContract) public vestingContracts;
mapping (uint256 ICOid => ICOParams) public icoParams;
mapping (uint256 ICOid => ICOState) public icoState;
uint256 public counter; // counter of ICOs
bool public isPaused; // launchpad is paused
event BuyToken(address buyer, uint256 ICO_id, uint256 amountPaid, uint256 amountBought, uint256 bonus);
event ICOCreated(uint256 ICO_id, address token, address owner, address vestingContract);
event CloseICO(uint256 ICO_id, address owner, address token, uint256 refund);
// initialize if use upgradable proxy
function initialize(address vestingImplementation_) external {
require(_owner == address(0), "Already init");
_owner = msg.sender;
emit OwnershipTransferred(address(0), msg.sender);
vestingImplementation = vestingImplementation_;
}
modifier checkICO(uint256 id) {
require(block.timestamp >= icoParams[id].startDate, "ICO is not started yet");
require(block.timestamp <= icoParams[id].endDate || icoParams[id].endDate == 0, "ICO is finished");
require(!icoState[id].isClosed, "ICO is closed");
require(!isPaused, "Launchpad is paused");
_;
}
// returns ICO details by ICO id
function getICO(uint256 id) external view returns(ICOParams memory params, ICOState memory state) {
params = icoParams[id];
state = icoState[id];
}
// returns value of tokens to pay for tokens amount
function getValue(
uint256 id, // ICO id
uint256 amount // amount of ICO tokens to buy
) public view returns(
uint256 availableAmount, // amount of available tokens (in case if ICO has less tokens then requested)
uint256 value // value that user have to pay in paymentToken for availableAmount
) {
uint256 total = icoParams[id].amount;
uint256 sold = icoState[id].totalSold;
availableAmount = total - sold;
if (amount < availableAmount) availableAmount = amount;
uint256 endPrice = icoParams[id].endPrice;
if (endPrice == 0) { // fix price
value = availableAmount * icoParams[id].startPrice / (10**icoState[id].icoTokenDecimals);
} else { // liner growing price
uint256 startPrice = icoParams[id].startPrice;
uint256 currentPrice = startPrice + ((endPrice - startPrice) * sold / total);
endPrice = startPrice + ((endPrice - startPrice) * (sold + availableAmount) / total); // price after purchase
value = availableAmount * (currentPrice + endPrice) / (2 * 10**icoState[id].icoTokenDecimals);
}
}
// create new ICO. User should approve ICO tokens (amount + bonusReserve)
function createICO(ICOParams memory params) external {
safeTransferFrom(params.token, msg.sender, address(this), params.amount + params.bonusReserve);
uint256 id = counter;
++counter;
icoParams[id] = params;
icoState[id].ICOOwner = msg.sender;
icoState[id].icoTokenDecimals = IERC20(params.token).decimals();
require(params.vestingParams.unlockPercentage <= 10000, "Incorrect unlockPercentage");
address vc;
if (params.vestingParams.unlockPercentage < 10000) {
// use vesting
vc = vestingContracts[params.token];
if(vc == address(0)) {
vc = clone(vestingImplementation);
IVesting(vc).initialize(msg.sender, params.token);
vestingContracts[params.token] = vc;
}
icoState[id].vestingContract = vc;
}
emit ICOCreated(id, params.token, msg.sender, vc);
}
// Buy ICO tokens. The value of paymentToken should be approved to ICO contract
function buyToken(
uint256 id, // ICO id
uint256 amountToBuy, // amount of token to buy
address buyer // buyer address
) external payable checkICO(id) {
require(buyer != address(0), "Incorrect buyer");
uint256 amountToPay;
(amountToBuy, amountToPay) = getValue(id, amountToBuy);
require(amountToBuy != 0, "sold out");
ICOParams storage p = icoParams[id];
ICOState storage s = icoState[id];
address paymentToken = p.paymentToken;
if(paymentToken == address(0)) { // pay with native coin
require(msg.value >= amountToPay, "Low payment");
if (msg.value > amountToPay) safeTransferETH(msg.sender, msg.value - amountToPay); // return rest
safeTransferETH(s.ICOOwner, amountToPay);
} else { // pay with tokens
safeTransferFrom(paymentToken, msg.sender, s.ICOOwner, amountToPay);
}
s.totalReceived += amountToPay;
s.totalSold += amountToBuy;
// calculate bonus
uint256 bonus;
{
uint256 bonusReserve = p.bonusReserve;
if (bonusReserve != 0) {
if(p.amount * p.bonusActivator / 10000 <= amountToBuy) {
bonus = amountToBuy * p.bonusPercentage / 10000;
if (bonusReserve < bonus) bonus = bonusReserve;
p.bonusReserve -= bonus;
}
}
}
uint256 unlockedAmount = amountToBuy + bonus;
if(s.vestingContract != address(0)) {
// set vesting
uint256 cliffFinish = block.timestamp + p.vestingParams.cliffPeriod;
unlockedAmount = unlockedAmount * p.vestingParams.unlockPercentage / 10000;
uint256 lockedAmount = amountToBuy + bonus - unlockedAmount;
if (lockedAmount != 0) {
safeApprove(p.token, s.vestingContract, lockedAmount);
IVesting(s.vestingContract).allocateTokens(buyer, lockedAmount, cliffFinish, p.vestingParams.vestingPercentage, p.vestingParams.vestingInterval);
}
}
safeTransfer(p.token, buyer, unlockedAmount);
emit BuyToken(buyer, id, amountToPay, amountToBuy, bonus);
}
// allow ICO owner to close ICO and get back unsold tokens
function closeICO(uint256 id) external {
ICOParams storage p = icoParams[id];
ICOState storage s = icoState[id];
require(s.ICOOwner == msg.sender, "Only ICO owner");
require(!s.isClosed, "Already closed");
s.isClosed = true;
uint256 value = p.amount - s.totalSold + p.bonusReserve; // refund leftover tokens
p.amount = s.totalSold;
p.bonusReserve = 0;
safeTransfer(p.token, msg.sender, value);
emit CloseICO(id, msg.sender, p.token, value);
}
// Launchpad owner's functions
function setPauseLaunchpad(bool pause) external onlyOwner {
isPaused = pause;
}
function setVestingImplementation(address vestingImplementation_) external onlyOwner {
vestingImplementation = vestingImplementation_;
}
event Rescue(address _token, uint256 _amount);
function rescueTokens(address _token) onlyOwner external {
uint256 amount;
if (_token == address(0)) {
amount = address(this).balance;
safeTransferETH(msg.sender, amount);
} else {
amount = IERC20(_token).balanceOf(address(this));
safeTransfer(_token, msg.sender, amount);
}
emit Rescue(_token, amount);
}
/**
* @dev A clone instance deployment failed.
*/
error ERC1167FailedCreateClone();
/**
* @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
*
* This function uses the create opcode, which should never revert.
*/
function clone(address implementation) internal returns (address instance) {
/// @solidity memory-safe-assembly
assembly {
// Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes
// of the `implementation` address with the bytecode before the address.
mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
// Packs the remaining 17 bytes of `implementation` with the bytecode after the address.
mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
instance := create(0, 0x09, 0x37)
}
if (instance == address(0)) {
revert ERC1167FailedCreateClone();
}
}
// allow to receive ERC223 tokens
function tokenReceived(address, uint256, bytes memory) external virtual returns(bytes4) {
return this.tokenReceived.selector;
}
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');
}
}
Compiler Settings
{"outputSelection":{"*":{"*":["abi","metadata","devdoc","userdoc","storageLayout","evm.legacyAssembly","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","evm.gasEstimates","evm.assembly"],"":["ast"]}},"optimizer":{"runs":200,"enabled":true},"libraries":{},"evmVersion":"paris"}
Contract ABI
[{"type":"error","name":"ERC1167FailedCreateClone","inputs":[]},{"type":"event","name":"BuyToken","inputs":[{"type":"address","name":"buyer","internalType":"address","indexed":false},{"type":"uint256","name":"ICO_id","internalType":"uint256","indexed":false},{"type":"uint256","name":"amountPaid","internalType":"uint256","indexed":false},{"type":"uint256","name":"amountBought","internalType":"uint256","indexed":false},{"type":"uint256","name":"bonus","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"CloseICO","inputs":[{"type":"uint256","name":"ICO_id","internalType":"uint256","indexed":false},{"type":"address","name":"owner","internalType":"address","indexed":false},{"type":"address","name":"token","internalType":"address","indexed":false},{"type":"uint256","name":"refund","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ICOCreated","inputs":[{"type":"uint256","name":"ICO_id","internalType":"uint256","indexed":false},{"type":"address","name":"token","internalType":"address","indexed":false},{"type":"address","name":"owner","internalType":"address","indexed":false},{"type":"address","name":"vestingContract","internalType":"address","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":"function","stateMutability":"payable","outputs":[],"name":"buyToken","inputs":[{"type":"uint256","name":"id","internalType":"uint256"},{"type":"uint256","name":"amountToBuy","internalType":"uint256"},{"type":"address","name":"buyer","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"closeICO","inputs":[{"type":"uint256","name":"id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"counter","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"createICO","inputs":[{"type":"tuple","name":"params","internalType":"struct Launchpad.ICOParams","components":[{"type":"address","name":"token","internalType":"address"},{"type":"address","name":"paymentToken","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"startPrice","internalType":"uint256"},{"type":"uint256","name":"endPrice","internalType":"uint256"},{"type":"uint256","name":"startDate","internalType":"uint256"},{"type":"uint256","name":"endDate","internalType":"uint256"},{"type":"uint256","name":"bonusReserve","internalType":"uint256"},{"type":"uint256","name":"bonusPercentage","internalType":"uint256"},{"type":"uint256","name":"bonusActivator","internalType":"uint256"},{"type":"tuple","name":"vestingParams","internalType":"struct Launchpad.VestingParams","components":[{"type":"uint256","name":"unlockPercentage","internalType":"uint256"},{"type":"uint256","name":"cliffPeriod","internalType":"uint256"},{"type":"uint256","name":"vestingPercentage","internalType":"uint256"},{"type":"uint256","name":"vestingInterval","internalType":"uint256"}]}]}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"params","internalType":"struct Launchpad.ICOParams","components":[{"type":"address","name":"token","internalType":"address"},{"type":"address","name":"paymentToken","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"startPrice","internalType":"uint256"},{"type":"uint256","name":"endPrice","internalType":"uint256"},{"type":"uint256","name":"startDate","internalType":"uint256"},{"type":"uint256","name":"endDate","internalType":"uint256"},{"type":"uint256","name":"bonusReserve","internalType":"uint256"},{"type":"uint256","name":"bonusPercentage","internalType":"uint256"},{"type":"uint256","name":"bonusActivator","internalType":"uint256"},{"type":"tuple","name":"vestingParams","internalType":"struct Launchpad.VestingParams","components":[{"type":"uint256","name":"unlockPercentage","internalType":"uint256"},{"type":"uint256","name":"cliffPeriod","internalType":"uint256"},{"type":"uint256","name":"vestingPercentage","internalType":"uint256"},{"type":"uint256","name":"vestingInterval","internalType":"uint256"}]}]},{"type":"tuple","name":"state","internalType":"struct Launchpad.ICOState","components":[{"type":"address","name":"ICOOwner","internalType":"address"},{"type":"uint8","name":"icoTokenDecimals","internalType":"uint8"},{"type":"address","name":"vestingContract","internalType":"address"},{"type":"bool","name":"isClosed","internalType":"bool"},{"type":"uint256","name":"totalSold","internalType":"uint256"},{"type":"uint256","name":"totalReceived","internalType":"uint256"}]}],"name":"getICO","inputs":[{"type":"uint256","name":"id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"availableAmount","internalType":"uint256"},{"type":"uint256","name":"value","internalType":"uint256"}],"name":"getValue","inputs":[{"type":"uint256","name":"id","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"token","internalType":"address"},{"type":"address","name":"paymentToken","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"startPrice","internalType":"uint256"},{"type":"uint256","name":"endPrice","internalType":"uint256"},{"type":"uint256","name":"startDate","internalType":"uint256"},{"type":"uint256","name":"endDate","internalType":"uint256"},{"type":"uint256","name":"bonusReserve","internalType":"uint256"},{"type":"uint256","name":"bonusPercentage","internalType":"uint256"},{"type":"uint256","name":"bonusActivator","internalType":"uint256"},{"type":"tuple","name":"vestingParams","internalType":"struct Launchpad.VestingParams","components":[{"type":"uint256","name":"unlockPercentage","internalType":"uint256"},{"type":"uint256","name":"cliffPeriod","internalType":"uint256"},{"type":"uint256","name":"vestingPercentage","internalType":"uint256"},{"type":"uint256","name":"vestingInterval","internalType":"uint256"}]}],"name":"icoParams","inputs":[{"type":"uint256","name":"ICOid","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"ICOOwner","internalType":"address"},{"type":"uint8","name":"icoTokenDecimals","internalType":"uint8"},{"type":"address","name":"vestingContract","internalType":"address"},{"type":"bool","name":"isClosed","internalType":"bool"},{"type":"uint256","name":"totalSold","internalType":"uint256"},{"type":"uint256","name":"totalReceived","internalType":"uint256"}],"name":"icoState","inputs":[{"type":"uint256","name":"ICOid","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialize","inputs":[{"type":"address","name":"vestingImplementation_","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isPaused","inputs":[]},{"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":"function","stateMutability":"nonpayable","outputs":[],"name":"setPauseLaunchpad","inputs":[{"type":"bool","name":"pause","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setVestingImplementation","inputs":[{"type":"address","name":"vestingImplementation_","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bytes4","name":"","internalType":"bytes4"}],"name":"tokenReceived","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"bytes","name":"","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"vestingContract","internalType":"address"}],"name":"vestingContracts","inputs":[{"type":"address","name":"token","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"vestingImplementation","inputs":[]}]
Contract Creation Code
0x608060405234801561001057600080fd5b50600080546001600160a01b0319163390811782556040519091907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a361214a8061005f6000396000f3fe6080604052600436106101085760003560e01c80638882a2f611610095578063b187bd2611610064578063b187bd261461039e578063c4d66de8146103c8578063ce1ee86a146103e8578063f2fde38b14610408578063fc4c07cf1461042857600080fd5b80638882a2f6146103075780638943ec021461032757806389603de0146103605780638da5cb5b1461038057600080fd5b8063423a50b8116100dc578063423a50b8146101c757806355089bac146101e75780635e237b351461028e57806361bc221a146102ae5780636a19e6de146102d257600080fd5b8062ae3bf81461010d57806321466eb51461012f57806331869ebf146101425780633791587414610179575b600080fd5b34801561011957600080fd5b5061012d610128366004611a4e565b6104ec565b005b61012d61013d366004611a69565b61060a565b34801561014e57600080fd5b5061016261015d366004611a9e565b610b0a565b604051610170929190611ab7565b60405180910390f35b34801561018557600080fd5b506101af610194366004611a4e565b6002602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610170565b3480156101d357600080fd5b5061012d6101e2366004611c9a565b610c74565b3480156101f357600080fd5b5061024b610202366004611a9e565b60046020526000908152604090208054600182015460028301546003909301546001600160a01b038084169460ff600160a01b9586900481169592851694929092049091169186565b604080516001600160a01b03978816815260ff969096166020870152939095169284019290925215156060830152608082015260a081019190915260c001610170565b34801561029a57600080fd5b5061012d6102a9366004611d50565b610fc7565b3480156102ba57600080fd5b506102c460055481565b604051908152602001610170565b3480156102de57600080fd5b506102f26102ed366004611d6d565b611013565b60408051928352602083019190915201610170565b34801561031357600080fd5b506001546101af906001600160a01b031681565b34801561033357600080fd5b50610347610342366004611d8f565b61118c565b6040516001600160e01b03199091168152602001610170565b34801561036c57600080fd5b5061012d61037b366004611a9e565b61119c565b34801561038c57600080fd5b506000546001600160a01b03166101af565b3480156103aa57600080fd5b506006546103b89060ff1681565b6040519015158152602001610170565b3480156103d457600080fd5b5061012d6103e3366004611a4e565b611307565b3480156103f457600080fd5b5061012d610403366004611a4e565b6113b0565b34801561041457600080fd5b5061012d610423366004611a4e565b61140b565b34801561043457600080fd5b506104d5610443366004611a9e565b600360208181526000928352604092839020805460018201546002830154948301546004840154600585015460068601546007870154600888015460098901548c51608081018e52600a8b01548152600b8b01549b81019b909b52600c8a01549c8b019c909c52600d9098015460608a01526001600160a01b039687169a95909616989793969295919490939192918b565b6040516101709b9a99989796959493929190611e3e565b336104ff6000546001600160a01b031690565b6001600160a01b03161461052e5760405162461bcd60e51b815260040161052590611ed0565b60405180910390fd5b60006001600160a01b03821661054f57504761054a3382611504565b6105c4565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610593573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b79190611f05565b90506105c48233836115d2565b604080516001600160a01b0384168152602081018390527f542fa6bfee3b4746210fbdd1d83f9e49b65adde3639f8d8f165dd18347938af2910160405180910390a15050565b60008381526003602052604090206005015483904210156106665760405162461bcd60e51b81526020600482015260166024820152751250d3c81a5cc81b9bdd081cdd185c9d1959081e595d60521b6044820152606401610525565b600081815260036020526040902060060154421115806106955750600081815260036020526040902060060154155b6106d35760405162461bcd60e51b815260206004820152600f60248201526e1250d3c81a5cc8199a5b9a5cda1959608a1b6044820152606401610525565b600081815260046020526040902060010154600160a01b900460ff161561072c5760405162461bcd60e51b815260206004820152600d60248201526c1250d3c81a5cc818db1bdcd959609a1b6044820152606401610525565b60065460ff16156107755760405162461bcd60e51b815260206004820152601360248201527213185d5b98da1c1859081a5cc81c185d5cd959606a1b6044820152606401610525565b6001600160a01b0382166107bd5760405162461bcd60e51b815260206004820152600f60248201526e24b731b7b93932b1ba10313abcb2b960891b6044820152606401610525565b60006107c98585611013565b9094509050600084900361080a5760405162461bcd60e51b81526020600482015260086024820152671cdbdb19081bdd5d60c21b6044820152606401610525565b6000858152600360209081526040808320600490925290912060018201546001600160a01b0316806108a957833410156108745760405162461bcd60e51b815260206004820152600b60248201526a131bddc81c185e5b595b9d60aa1b6044820152606401610525565b8334111561088f5761088f3361088a8634611f34565b611504565b81546108a4906001600160a01b031685611504565b6108c2565b81546108c290829033906001600160a01b0316876116ed565b838260030160008282546108d69190611f4d565b92505081905550868260020160008282546108f19190611f4d565b90915550506007830154600090801561097057886127108660090154876002015461091c9190611f60565b6109269190611f77565b116109705761271085600801548a61093e9190611f60565b6109489190611f77565b915081811015610956578091505b8185600701600082825461096a9190611f34565b90915550505b50600061097d828a611f4d565b60018501549091506001600160a01b031615610a9057600b8501546000906109a59042611f4d565b600a870154909150612710906109bb9084611f60565b6109c59190611f77565b91506000826109d4858d611f4d565b6109de9190611f34565b90508015610a8d5786546001870154610a04916001600160a01b0390811691168361181d565b6001860154600c880154600d89015460405163431b1acb60e01b81526001600160a01b038e8116600483015260248201869052604482018790526064820193909352608481019190915291169063431b1acb9060a401600060405180830381600087803b158015610a7457600080fd5b505af1158015610a88573d6000803e3d6000fd5b505050505b50505b8454610aa6906001600160a01b031689836115d2565b604080516001600160a01b038a168152602081018c9052908101879052606081018a9052608081018390527f88ec88080cc26f1cd03f72bfe52eb411992bd2c91c32bcdf596693ed20e9d85d9060a00160405180910390a150505050505050505050565b610b126119a3565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525050600081815260036020818152604080842081516101608101835281546001600160a01b0390811682526001808401548216838701526002808501548487015284880154606080860191909152600480870154608080880191909152600588015460a080890191909152600689015460c0808a019190915260078a015460e08a015260088a01546101008a015260098a01546101208a01528a518084018c52600a8b01548152600b8b0154818e0152600c8b0154818d0152600d909a01548a8601526101408901999099529c8c5290895299879020875196870188528054808616885260ff600160a01b9182900481169a89019a909a52938101549485169787019790975291909204909516151594830194909452928201549481019490945290910154928201929092529091565b610c97816000015133308460e001518560400151610c929190611f4d565b6116ed565b60058054906000610ca783611f99565b909155506000818152600360208181526040808420865181546001600160a01b039182166001600160a01b0319918216178355848901516001840180549184169183169190911790558389015160028401556060808a015196840196909655608089015160048085019190915560a08a0151600585015560c08a0151600685015560e08a015160078501556101008a015160088501556101208a015160098501556101408a01518051600a86015580870151600b86015580860151600c86015590960151600d90930192909255848452948290208054909116331790558551815163313ce56760e01b8152915194169363313ce5679382810193928290030181865afa158015610dbb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ddf9190611fb2565b6000828152600460205260409020805460ff92909216600160a01b0260ff60a01b19909216919091179055610140820151516127101015610e625760405162461bcd60e51b815260206004820152601a60248201527f496e636f727265637420756e6c6f636b50657263656e746167650000000000006044820152606401610525565b6000612710836101400151600001511015610f71575081516001600160a01b039081166000908152600260205260409020541680610f4657600154610eaf906001600160a01b0316611931565b835160405163485cc95560e01b81523360048201526001600160a01b03918216602482015291925082169063485cc95590604401600060405180830381600087803b158015610efd57600080fd5b505af1158015610f11573d6000803e3d6000fd5b505084516001600160a01b03908116600090815260026020526040902080546001600160a01b03191691851691909117905550505b600082815260046020526040902060010180546001600160a01b0319166001600160a01b0383161790555b8251604080518481526001600160a01b03928316602082015233818301529183166060830152517f23c4aa757e39eb798ed23a9649a07ad8c3ba4626211baf9c8bc569090914173e9181900360800190a1505050565b33610fda6000546001600160a01b031690565b6001600160a01b0316146110005760405162461bcd60e51b815260040161052590611ed0565b6006805460ff1916911515919091179055565b6000828152600360209081526040808320600290810154600490935290832001548291906110418183611f34565b93508385101561104f578493505b600086815260036020526040812060040154908190036110bb5760008781526004602052604090205461108d90600160a01b900460ff16600a6120b9565b600088815260036020819052604090912001546110aa9087611f60565b6110b49190611f77565b9350611182565b6000878152600360208190526040822001549084846110da8486611f34565b6110e49190611f60565b6110ee9190611f77565b6110f89083611f4d565b9050846111058886611f4d565b61110f8486611f34565b6111199190611f60565b6111239190611f77565b61112d9083611f4d565b60008a81526004602052604090205490935061115490600160a01b900460ff16600a6120b9565b61115f906002611f60565b6111698483611f4d565b6111739089611f60565b61117d9190611f77565b955050505b5050509250929050565b6344a1f60160e11b5b9392505050565b6000818152600360209081526040808320600490925290912080546001600160a01b031633146111ff5760405162461bcd60e51b815260206004820152600e60248201526d27b7363c9024a1a79037bbb732b960911b6044820152606401610525565b6001810154600160a01b900460ff161561124c5760405162461bcd60e51b815260206004820152600e60248201526d105b1c9958591e4818db1bdcd95960921b6044820152606401610525565b60018101805460ff60a01b1916600160a01b1790556007820154600280830154908401546000929161127d91611f34565b6112879190611f4d565b600280840154908501556000600785015583549091506112b1906001600160a01b031633836115d2565b8254604080518681523360208201526001600160a01b039092168282015260608201839052517fd9200d3b6d4769b5d4fdc7ef18184f6afd5a8ddaf0e48ad27b9af5275e5177699181900360800190a150505050565b6000546001600160a01b03161561134f5760405162461bcd60e51b815260206004820152600c60248201526b105b1c9958591e481a5b9a5d60a21b6044820152606401610525565b600080546001600160a01b0319163390811782556040519091907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b336113c36000546001600160a01b031690565b6001600160a01b0316146113e95760405162461bcd60e51b815260040161052590611ed0565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b3361141e6000546001600160a01b031690565b6001600160a01b0316146114445760405162461bcd60e51b815260040161052590611ed0565b6001600160a01b0381166114a95760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610525565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b604080516000808252602082019092526001600160a01b03841690839060405161152e91906120c8565b60006040518083038185875af1925050503d806000811461156b576040519150601f19603f3d011682016040523d82523d6000602084013e611570565b606091505b50509050806115cd5760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b6064820152608401610525565b505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161162e91906120c8565b6000604051808303816000865af19150503d806000811461166b576040519150601f19603f3d011682016040523d82523d6000602084013e611670565b606091505b509150915081801561169a57508051158061169a57508080602001905181019061169a91906120f7565b6116e65760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610525565b5050505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b179052915160009283929088169161175191906120c8565b6000604051808303816000865af19150503d806000811461178e576040519150601f19603f3d011682016040523d82523d6000602084013e611793565b606091505b50915091508180156117bd5750805115806117bd5750808060200190518101906117bd91906120f7565b6118155760405162461bcd60e51b8152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f46416044820152631253115160e21b6064820152608401610525565b505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b179052915160009283929087169161187991906120c8565b6000604051808303816000865af19150503d80600081146118b6576040519150601f19603f3d011682016040523d82523d6000602084013e6118bb565b606091505b50915091508180156118e55750805115806118e55750808060200190518101906118e591906120f7565b6116e65760405162461bcd60e51b815260206004820152601e60248201527f5472616e7366657248656c7065723a20415050524f56455f4641494c454400006044820152606401610525565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008260601b60e81c176000526e5af43d82803e903d91602b57fd5bf38260781b17602052603760096000f090506001600160a01b03811661199e576040516330be1a3d60e21b815260040160405180910390fd5b919050565b60405180610160016040528060006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001611a326040518060800160405280600081526020016000815260200160008152602001600081525090565b905290565b80356001600160a01b038116811461199e57600080fd5b600060208284031215611a6057600080fd5b61119582611a37565b600080600060608486031215611a7e57600080fd5b8335925060208401359150611a9560408501611a37565b90509250925092565b600060208284031215611ab057600080fd5b5035919050565b82516001600160a01b0316815261028081016020840151611ae360208401826001600160a01b03169052565b5060408401516040830152606084015160608301526080840151608083015260a084015160a083015260c084015160c083015260e084015160e083015261010080850151818401525061012080850151818401525061014080850151611b6c82850182805182526020810151602083015260408101516040830152606081015160608301525050565b505082516001600160a01b039081166101c0840152602084015160ff166101e084015260408401511661020083015260608301511515610220830152608083015161024083015260a0830151610260830152611195565b634e487b7160e01b600052604160045260246000fd5b604051610160810167ffffffffffffffff81118282101715611bfd57611bfd611bc3565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c2c57611c2c611bc3565b604052919050565b600060808284031215611c4657600080fd5b6040516080810181811067ffffffffffffffff82111715611c6957611c69611bc3565b8060405250809150823581526020830135602082015260408301356040820152606083013560608201525092915050565b60006101c08284031215611cad57600080fd5b611cb5611bd9565b611cbe83611a37565b8152611ccc60208401611a37565b602082015260408301356040820152606083013560608201526080830135608082015260a083013560a082015260c083013560c082015260e083013560e0820152610100808401358183015250610120808401358183015250610140611d3485828601611c34565b908201529392505050565b8015158114611d4d57600080fd5b50565b600060208284031215611d6257600080fd5b813561119581611d3f565b60008060408385031215611d8057600080fd5b50508035926020909101359150565b600080600060608486031215611da457600080fd5b611dad84611a37565b92506020808501359250604085013567ffffffffffffffff80821115611dd257600080fd5b818701915087601f830112611de657600080fd5b813581811115611df857611df8611bc3565b611e0a601f8201601f19168501611c03565b91508082528884828501011115611e2057600080fd5b80848401858401376000848284010152508093505050509250925092565b6001600160a01b038c811682528b166020820152604081018a9052606081018990526080810188905260a0810187905260c0810186905260e08101859052610100810184905261012081018390526101c08101611ec0610140830184805182526020810151602083015260408101516040830152606081015160608301525050565b9c9b505050505050505050505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600060208284031215611f1757600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b81810381811115611f4757611f47611f1e565b92915050565b80820180821115611f4757611f47611f1e565b8082028115828204841417611f4757611f47611f1e565b600082611f9457634e487b7160e01b600052601260045260246000fd5b500490565b600060018201611fab57611fab611f1e565b5060010190565b600060208284031215611fc457600080fd5b815160ff8116811461119557600080fd5b600181815b80851115612010578160001904821115611ff657611ff6611f1e565b8085161561200357918102915b93841c9390800290611fda565b509250929050565b60008261202757506001611f47565b8161203457506000611f47565b816001811461204a576002811461205457612070565b6001915050611f47565b60ff84111561206557612065611f1e565b50506001821b611f47565b5060208310610133831016604e8410600b8410161715612093575081810a611f47565b61209d8383611fd5565b80600019048211156120b1576120b1611f1e565b029392505050565b600061119560ff841683612018565b6000825160005b818110156120e957602081860181015185830152016120cf565b506000920191825250919050565b60006020828403121561210957600080fd5b815161119581611d3f56fea2646970667358221220adf527d105120d455e7e14f94267a52da3b82075ee644eb699df9367fb1a565064736f6c63430008130033
Deployed ByteCode
0x6080604052600436106101085760003560e01c80638882a2f611610095578063b187bd2611610064578063b187bd261461039e578063c4d66de8146103c8578063ce1ee86a146103e8578063f2fde38b14610408578063fc4c07cf1461042857600080fd5b80638882a2f6146103075780638943ec021461032757806389603de0146103605780638da5cb5b1461038057600080fd5b8063423a50b8116100dc578063423a50b8146101c757806355089bac146101e75780635e237b351461028e57806361bc221a146102ae5780636a19e6de146102d257600080fd5b8062ae3bf81461010d57806321466eb51461012f57806331869ebf146101425780633791587414610179575b600080fd5b34801561011957600080fd5b5061012d610128366004611a4e565b6104ec565b005b61012d61013d366004611a69565b61060a565b34801561014e57600080fd5b5061016261015d366004611a9e565b610b0a565b604051610170929190611ab7565b60405180910390f35b34801561018557600080fd5b506101af610194366004611a4e565b6002602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610170565b3480156101d357600080fd5b5061012d6101e2366004611c9a565b610c74565b3480156101f357600080fd5b5061024b610202366004611a9e565b60046020526000908152604090208054600182015460028301546003909301546001600160a01b038084169460ff600160a01b9586900481169592851694929092049091169186565b604080516001600160a01b03978816815260ff969096166020870152939095169284019290925215156060830152608082015260a081019190915260c001610170565b34801561029a57600080fd5b5061012d6102a9366004611d50565b610fc7565b3480156102ba57600080fd5b506102c460055481565b604051908152602001610170565b3480156102de57600080fd5b506102f26102ed366004611d6d565b611013565b60408051928352602083019190915201610170565b34801561031357600080fd5b506001546101af906001600160a01b031681565b34801561033357600080fd5b50610347610342366004611d8f565b61118c565b6040516001600160e01b03199091168152602001610170565b34801561036c57600080fd5b5061012d61037b366004611a9e565b61119c565b34801561038c57600080fd5b506000546001600160a01b03166101af565b3480156103aa57600080fd5b506006546103b89060ff1681565b6040519015158152602001610170565b3480156103d457600080fd5b5061012d6103e3366004611a4e565b611307565b3480156103f457600080fd5b5061012d610403366004611a4e565b6113b0565b34801561041457600080fd5b5061012d610423366004611a4e565b61140b565b34801561043457600080fd5b506104d5610443366004611a9e565b600360208181526000928352604092839020805460018201546002830154948301546004840154600585015460068601546007870154600888015460098901548c51608081018e52600a8b01548152600b8b01549b81019b909b52600c8a01549c8b019c909c52600d9098015460608a01526001600160a01b039687169a95909616989793969295919490939192918b565b6040516101709b9a99989796959493929190611e3e565b336104ff6000546001600160a01b031690565b6001600160a01b03161461052e5760405162461bcd60e51b815260040161052590611ed0565b60405180910390fd5b60006001600160a01b03821661054f57504761054a3382611504565b6105c4565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610593573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b79190611f05565b90506105c48233836115d2565b604080516001600160a01b0384168152602081018390527f542fa6bfee3b4746210fbdd1d83f9e49b65adde3639f8d8f165dd18347938af2910160405180910390a15050565b60008381526003602052604090206005015483904210156106665760405162461bcd60e51b81526020600482015260166024820152751250d3c81a5cc81b9bdd081cdd185c9d1959081e595d60521b6044820152606401610525565b600081815260036020526040902060060154421115806106955750600081815260036020526040902060060154155b6106d35760405162461bcd60e51b815260206004820152600f60248201526e1250d3c81a5cc8199a5b9a5cda1959608a1b6044820152606401610525565b600081815260046020526040902060010154600160a01b900460ff161561072c5760405162461bcd60e51b815260206004820152600d60248201526c1250d3c81a5cc818db1bdcd959609a1b6044820152606401610525565b60065460ff16156107755760405162461bcd60e51b815260206004820152601360248201527213185d5b98da1c1859081a5cc81c185d5cd959606a1b6044820152606401610525565b6001600160a01b0382166107bd5760405162461bcd60e51b815260206004820152600f60248201526e24b731b7b93932b1ba10313abcb2b960891b6044820152606401610525565b60006107c98585611013565b9094509050600084900361080a5760405162461bcd60e51b81526020600482015260086024820152671cdbdb19081bdd5d60c21b6044820152606401610525565b6000858152600360209081526040808320600490925290912060018201546001600160a01b0316806108a957833410156108745760405162461bcd60e51b815260206004820152600b60248201526a131bddc81c185e5b595b9d60aa1b6044820152606401610525565b8334111561088f5761088f3361088a8634611f34565b611504565b81546108a4906001600160a01b031685611504565b6108c2565b81546108c290829033906001600160a01b0316876116ed565b838260030160008282546108d69190611f4d565b92505081905550868260020160008282546108f19190611f4d565b90915550506007830154600090801561097057886127108660090154876002015461091c9190611f60565b6109269190611f77565b116109705761271085600801548a61093e9190611f60565b6109489190611f77565b915081811015610956578091505b8185600701600082825461096a9190611f34565b90915550505b50600061097d828a611f4d565b60018501549091506001600160a01b031615610a9057600b8501546000906109a59042611f4d565b600a870154909150612710906109bb9084611f60565b6109c59190611f77565b91506000826109d4858d611f4d565b6109de9190611f34565b90508015610a8d5786546001870154610a04916001600160a01b0390811691168361181d565b6001860154600c880154600d89015460405163431b1acb60e01b81526001600160a01b038e8116600483015260248201869052604482018790526064820193909352608481019190915291169063431b1acb9060a401600060405180830381600087803b158015610a7457600080fd5b505af1158015610a88573d6000803e3d6000fd5b505050505b50505b8454610aa6906001600160a01b031689836115d2565b604080516001600160a01b038a168152602081018c9052908101879052606081018a9052608081018390527f88ec88080cc26f1cd03f72bfe52eb411992bd2c91c32bcdf596693ed20e9d85d9060a00160405180910390a150505050505050505050565b610b126119a3565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525050600081815260036020818152604080842081516101608101835281546001600160a01b0390811682526001808401548216838701526002808501548487015284880154606080860191909152600480870154608080880191909152600588015460a080890191909152600689015460c0808a019190915260078a015460e08a015260088a01546101008a015260098a01546101208a01528a518084018c52600a8b01548152600b8b0154818e0152600c8b0154818d0152600d909a01548a8601526101408901999099529c8c5290895299879020875196870188528054808616885260ff600160a01b9182900481169a89019a909a52938101549485169787019790975291909204909516151594830194909452928201549481019490945290910154928201929092529091565b610c97816000015133308460e001518560400151610c929190611f4d565b6116ed565b60058054906000610ca783611f99565b909155506000818152600360208181526040808420865181546001600160a01b039182166001600160a01b0319918216178355848901516001840180549184169183169190911790558389015160028401556060808a015196840196909655608089015160048085019190915560a08a0151600585015560c08a0151600685015560e08a015160078501556101008a015160088501556101208a015160098501556101408a01518051600a86015580870151600b86015580860151600c86015590960151600d90930192909255848452948290208054909116331790558551815163313ce56760e01b8152915194169363313ce5679382810193928290030181865afa158015610dbb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ddf9190611fb2565b6000828152600460205260409020805460ff92909216600160a01b0260ff60a01b19909216919091179055610140820151516127101015610e625760405162461bcd60e51b815260206004820152601a60248201527f496e636f727265637420756e6c6f636b50657263656e746167650000000000006044820152606401610525565b6000612710836101400151600001511015610f71575081516001600160a01b039081166000908152600260205260409020541680610f4657600154610eaf906001600160a01b0316611931565b835160405163485cc95560e01b81523360048201526001600160a01b03918216602482015291925082169063485cc95590604401600060405180830381600087803b158015610efd57600080fd5b505af1158015610f11573d6000803e3d6000fd5b505084516001600160a01b03908116600090815260026020526040902080546001600160a01b03191691851691909117905550505b600082815260046020526040902060010180546001600160a01b0319166001600160a01b0383161790555b8251604080518481526001600160a01b03928316602082015233818301529183166060830152517f23c4aa757e39eb798ed23a9649a07ad8c3ba4626211baf9c8bc569090914173e9181900360800190a1505050565b33610fda6000546001600160a01b031690565b6001600160a01b0316146110005760405162461bcd60e51b815260040161052590611ed0565b6006805460ff1916911515919091179055565b6000828152600360209081526040808320600290810154600490935290832001548291906110418183611f34565b93508385101561104f578493505b600086815260036020526040812060040154908190036110bb5760008781526004602052604090205461108d90600160a01b900460ff16600a6120b9565b600088815260036020819052604090912001546110aa9087611f60565b6110b49190611f77565b9350611182565b6000878152600360208190526040822001549084846110da8486611f34565b6110e49190611f60565b6110ee9190611f77565b6110f89083611f4d565b9050846111058886611f4d565b61110f8486611f34565b6111199190611f60565b6111239190611f77565b61112d9083611f4d565b60008a81526004602052604090205490935061115490600160a01b900460ff16600a6120b9565b61115f906002611f60565b6111698483611f4d565b6111739089611f60565b61117d9190611f77565b955050505b5050509250929050565b6344a1f60160e11b5b9392505050565b6000818152600360209081526040808320600490925290912080546001600160a01b031633146111ff5760405162461bcd60e51b815260206004820152600e60248201526d27b7363c9024a1a79037bbb732b960911b6044820152606401610525565b6001810154600160a01b900460ff161561124c5760405162461bcd60e51b815260206004820152600e60248201526d105b1c9958591e4818db1bdcd95960921b6044820152606401610525565b60018101805460ff60a01b1916600160a01b1790556007820154600280830154908401546000929161127d91611f34565b6112879190611f4d565b600280840154908501556000600785015583549091506112b1906001600160a01b031633836115d2565b8254604080518681523360208201526001600160a01b039092168282015260608201839052517fd9200d3b6d4769b5d4fdc7ef18184f6afd5a8ddaf0e48ad27b9af5275e5177699181900360800190a150505050565b6000546001600160a01b03161561134f5760405162461bcd60e51b815260206004820152600c60248201526b105b1c9958591e481a5b9a5d60a21b6044820152606401610525565b600080546001600160a01b0319163390811782556040519091907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b336113c36000546001600160a01b031690565b6001600160a01b0316146113e95760405162461bcd60e51b815260040161052590611ed0565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b3361141e6000546001600160a01b031690565b6001600160a01b0316146114445760405162461bcd60e51b815260040161052590611ed0565b6001600160a01b0381166114a95760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610525565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b604080516000808252602082019092526001600160a01b03841690839060405161152e91906120c8565b60006040518083038185875af1925050503d806000811461156b576040519150601f19603f3d011682016040523d82523d6000602084013e611570565b606091505b50509050806115cd5760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b6064820152608401610525565b505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b179052915160009283929087169161162e91906120c8565b6000604051808303816000865af19150503d806000811461166b576040519150601f19603f3d011682016040523d82523d6000602084013e611670565b606091505b509150915081801561169a57508051158061169a57508080602001905181019061169a91906120f7565b6116e65760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610525565b5050505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b179052915160009283929088169161175191906120c8565b6000604051808303816000865af19150503d806000811461178e576040519150601f19603f3d011682016040523d82523d6000602084013e611793565b606091505b50915091508180156117bd5750805115806117bd5750808060200190518101906117bd91906120f7565b6118155760405162461bcd60e51b8152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f46416044820152631253115160e21b6064820152608401610525565b505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b179052915160009283929087169161187991906120c8565b6000604051808303816000865af19150503d80600081146118b6576040519150601f19603f3d011682016040523d82523d6000602084013e6118bb565b606091505b50915091508180156118e55750805115806118e55750808060200190518101906118e591906120f7565b6116e65760405162461bcd60e51b815260206004820152601e60248201527f5472616e7366657248656c7065723a20415050524f56455f4641494c454400006044820152606401610525565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008260601b60e81c176000526e5af43d82803e903d91602b57fd5bf38260781b17602052603760096000f090506001600160a01b03811661199e576040516330be1a3d60e21b815260040160405180910390fd5b919050565b60405180610160016040528060006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001611a326040518060800160405280600081526020016000815260200160008152602001600081525090565b905290565b80356001600160a01b038116811461199e57600080fd5b600060208284031215611a6057600080fd5b61119582611a37565b600080600060608486031215611a7e57600080fd5b8335925060208401359150611a9560408501611a37565b90509250925092565b600060208284031215611ab057600080fd5b5035919050565b82516001600160a01b0316815261028081016020840151611ae360208401826001600160a01b03169052565b5060408401516040830152606084015160608301526080840151608083015260a084015160a083015260c084015160c083015260e084015160e083015261010080850151818401525061012080850151818401525061014080850151611b6c82850182805182526020810151602083015260408101516040830152606081015160608301525050565b505082516001600160a01b039081166101c0840152602084015160ff166101e084015260408401511661020083015260608301511515610220830152608083015161024083015260a0830151610260830152611195565b634e487b7160e01b600052604160045260246000fd5b604051610160810167ffffffffffffffff81118282101715611bfd57611bfd611bc3565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c2c57611c2c611bc3565b604052919050565b600060808284031215611c4657600080fd5b6040516080810181811067ffffffffffffffff82111715611c6957611c69611bc3565b8060405250809150823581526020830135602082015260408301356040820152606083013560608201525092915050565b60006101c08284031215611cad57600080fd5b611cb5611bd9565b611cbe83611a37565b8152611ccc60208401611a37565b602082015260408301356040820152606083013560608201526080830135608082015260a083013560a082015260c083013560c082015260e083013560e0820152610100808401358183015250610120808401358183015250610140611d3485828601611c34565b908201529392505050565b8015158114611d4d57600080fd5b50565b600060208284031215611d6257600080fd5b813561119581611d3f565b60008060408385031215611d8057600080fd5b50508035926020909101359150565b600080600060608486031215611da457600080fd5b611dad84611a37565b92506020808501359250604085013567ffffffffffffffff80821115611dd257600080fd5b818701915087601f830112611de657600080fd5b813581811115611df857611df8611bc3565b611e0a601f8201601f19168501611c03565b91508082528884828501011115611e2057600080fd5b80848401858401376000848284010152508093505050509250925092565b6001600160a01b038c811682528b166020820152604081018a9052606081018990526080810188905260a0810187905260c0810186905260e08101859052610100810184905261012081018390526101c08101611ec0610140830184805182526020810151602083015260408101516040830152606081015160608301525050565b9c9b505050505050505050505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600060208284031215611f1757600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b81810381811115611f4757611f47611f1e565b92915050565b80820180821115611f4757611f47611f1e565b8082028115828204841417611f4757611f47611f1e565b600082611f9457634e487b7160e01b600052601260045260246000fd5b500490565b600060018201611fab57611fab611f1e565b5060010190565b600060208284031215611fc457600080fd5b815160ff8116811461119557600080fd5b600181815b80851115612010578160001904821115611ff657611ff6611f1e565b8085161561200357918102915b93841c9390800290611fda565b509250929050565b60008261202757506001611f47565b8161203457506000611f47565b816001811461204a576002811461205457612070565b6001915050611f47565b60ff84111561206557612065611f1e565b50506001821b611f47565b5060208310610133831016604e8410600b8410161715612093575081810a611f47565b61209d8383611fd5565b80600019048211156120b1576120b1611f1e565b029392505050565b600061119560ff841683612018565b6000825160005b818110156120e957602081860181015185830152016120cf565b506000920191825250919050565b60006020828403121561210957600080fd5b815161119581611d3f56fea2646970667358221220adf527d105120d455e7e14f94267a52da3b82075ee644eb699df9367fb1a565064736f6c63430008130033