Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 7 from a total of 7 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Deploy Wave | 18375357 | 332 days ago | IN | 0 ETH | 0.01707486 | ||||
Deploy Wave | 18370935 | 332 days ago | IN | 0 ETH | 0.03696548 | ||||
Deploy Wave | 18367994 | 333 days ago | IN | 0 ETH | 0.01564707 | ||||
Deploy Wave | 18340661 | 336 days ago | IN | 0 ETH | 0.01818205 | ||||
Deploy Wave | 18220200 | 353 days ago | IN | 0 ETH | 0.04443263 | ||||
Change Raffle Ma... | 18083366 | 372 days ago | IN | 0 ETH | 0.00030596 | ||||
0x60806040 | 18083352 | 372 days ago | IN | 0 ETH | 0.05580204 |
Latest 5 internal transactions
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
18375357 | 332 days ago | Contract Creation | 0 ETH | |||
18370935 | 332 days ago | Contract Creation | 0 ETH | |||
18367994 | 333 days ago | Contract Creation | 0 ETH | |||
18340661 | 336 days ago | Contract Creation | 0 ETH | |||
18220200 | 353 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
WaveFactory
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.21; pragma abicoder v2; import {Ownable} from "../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; import {WaveContract} from "./WaveContract.sol"; import {IWaveFactory} from "./interfaces/IWaveFactory.sol"; import {IERC20} from "../lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; contract WaveFactory is Ownable, IWaveFactory { address[] public waves; address public keeper; address public trustedForwarder; address public verifier; address public raffleManager; mapping(address => bool) public isRaffleWave; error TooManyRewards(); event WaveCreated(address indexed wave, address indexed owner); constructor(address _keeper, address _trustedForwarder, address _verifier, address _raffleManager) Ownable() { keeper = _keeper; trustedForwarder = _trustedForwarder; verifier = _verifier; raffleManager = _raffleManager; } /// @dev changes the keeper associated with the factory /// @param _keeper address of the new keeper function changeKeeper(address _keeper) public onlyOwner { keeper = _keeper; } /// @dev changes the trusted forwarder for EIP-2771 meta transactions /// @param _trustedForwarder address of the new trusted forwarder function changeTrustedForwarder(address _trustedForwarder) public onlyOwner { trustedForwarder = _trustedForwarder; } /// @dev changes the verifier for EIP-712 signatures /// @param _verifier address of the new verifier function changeVerifier(address _verifier) public onlyOwner { verifier = _verifier; } /// @dev changes the raffle manager for the factory /// @param _raffleManager address of the new raffle manager function changeRaffleManager(address _raffleManager) public onlyOwner { raffleManager = _raffleManager; } /// @notice deploys a new campaign /// @param _name name of the campaign /// @param _symbol symbol of the campaign /// @param _baseURI base URI of the ERC-721 metadata /// @param _startTimestamp start timestamp of the campaign /// @param _endTimestamp end timestamp of the campaign /// @param _isSoulbound whether the wave badges will be soulbound /// @param _claimRewards array of claim rewards /// @param _raffleRewards array of raffle rewards function deployWave( string memory _name, string memory _symbol, string memory _baseURI, uint256 _startTimestamp, uint256 _endTimestamp, bool _isSoulbound, IWaveFactory.TokenRewards[] memory _claimRewards, IWaveFactory.TokenRewards[] memory _raffleRewards ) public override { if (_claimRewards.length >= 2 ** 8 || _raffleRewards.length >= 2 ** 8) { revert TooManyRewards(); } WaveContract wave = new WaveContract( _name, _symbol, _baseURI, _startTimestamp, _endTimestamp, _isSoulbound, trustedForwarder, _claimRewards, _raffleRewards ); waves.push(address(wave)); wave.transferOwnership(msg.sender); if (_raffleRewards.length > 0) { isRaffleWave[address(wave)] = true; } _initiateRewards(_claimRewards, address(wave)); _initiateRewards(_raffleRewards, address(wave)); emit WaveCreated(address(wave), msg.sender); } /// @notice funds the campaign with the specified token rewards /// @param _tokenRewards array of token rewards /// @param wave address of the campaign function _initiateRewards(IWaveFactory.TokenRewards[] memory _tokenRewards, address wave) internal { uint8 len = uint8(_tokenRewards.length); for (uint8 i = 0; i < len; ++i) { IERC20(_tokenRewards[i].token).transferFrom( msg.sender, wave, _tokenRewards[i].amountPerUser * _tokenRewards[i].rewardsLeft ); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.21; pragma abicoder v2; import {Strings} from "../lib/openzeppelin-contracts/contracts/utils/Strings.sol"; import {Ownable} from "../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; import {ERC2771Context, Context} from "../lib/openzeppelin-contracts/contracts/metatx/ERC2771Context.sol"; import {IWaveFactory} from "./interfaces/IWaveFactory.sol"; import {IWaveContract} from "./interfaces/IWaveContract.sol"; import {IRaffleManager} from "./interfaces/IRaffleManager.sol"; import {ERC721} from "lib/openzeppelin-contracts/contracts/token/ERC721/ERC721.sol"; import {IERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {SignatureVerifier} from "./helpers/SignatureVerifier.sol"; contract WaveContract is ERC2771Context, Ownable, ERC721, SignatureVerifier, IWaveContract { IWaveFactory public factory; uint256 public lastId; uint256 public startTimestamp; uint256 public endTimestamp; string _metadataBaseURI; bool public customMetadata; bool public isSoulbound; mapping(address => bool) _claimed; mapping(bytes32 => bool) public tokenIdRewardIdxHashToHasWon; IWaveFactory.TokenRewards[] public claimRewards; IWaveFactory.TokenRewards[] public raffleRewards; uint8 public immutable claimRewardsLength; uint8 public immutable raffleRewardsLength; bool public raffleCompleted; error OnlyRaffleManager(); error OnlyAuthorized(); error InvalidTimings(); error CampaignNotActive(); error CampaignNotEnded(); error RewardAlreadyClaimed(); error PermitDeadlineExpired(); error NotTransferrable(); event Claimed(address indexed user, uint256 indexed tokenId); event FCFSAwarded(address indexed user, address indexed token, uint256 amount); event RaffleWon(address indexed user, address indexed token, uint256 amount); event RaffleStarted(address indexed user); event RaffleCompleted(); event CampaignForceEnded(); event ClaimRewardsFundsWithdrawn(); event RaffleRewardsFundsWithdrawn(); modifier onlyAuthorized() { if (_msgSender() != factory.keeper() && _msgSender() != owner()) revert OnlyAuthorized(); _; } modifier onlyRaffleManager() { if (_msgSender() != factory.raffleManager()) revert OnlyRaffleManager(); _; } modifier onlyActive() { if (block.timestamp < startTimestamp || block.timestamp > endTimestamp) { revert CampaignNotActive(); } _; } modifier onlyEnded() { if (block.timestamp < endTimestamp) revert CampaignNotEnded(); _; } constructor( string memory _name, string memory _symbol, string memory _uri, uint256 _startTimestamp, uint256 _endTimestamp, bool _isSoulbound, address _trustedForwarder, IWaveFactory.TokenRewards[] memory _claimRewards, IWaveFactory.TokenRewards[] memory _raffleRewards ) ERC2771Context(_trustedForwarder) Ownable() ERC721(_name, _symbol) SignatureVerifier(_name) { if (_startTimestamp > _endTimestamp || _endTimestamp < block.timestamp) { revert InvalidTimings(); } factory = IWaveFactory(_msgSender()); _metadataBaseURI = _uri; startTimestamp = _startTimestamp; endTimestamp = _endTimestamp; isSoulbound = _isSoulbound; claimRewardsLength = uint8(_claimRewards.length); for (uint8 i = 0; i < claimRewardsLength; ++i) { claimRewards.push(_claimRewards[i]); } raffleRewardsLength = uint8(_raffleRewards.length); for (uint8 i = 0; i < raffleRewardsLength; ++i) { raffleRewards.push(_raffleRewards[i]); } } /// @notice Allows the governance and the owner of the contract to set metadata base URI for all tokens /// @param _uri The base URI to set /// @param _customMetadata Whether the metadata is encoded with rewardId or tokenId function changeBaseURI(string memory _uri, bool _customMetadata) public onlyAuthorized { _metadataBaseURI = _uri; customMetadata = _customMetadata; } /// @notice Allows the owner to set the campaign start timestamp function setStartTimestamp(uint256 _startTimestamp) public onlyOwner { require(block.timestamp < _startTimestamp && _startTimestamp < endTimestamp, "Invalid start timestamp"); startTimestamp = _startTimestamp; } /// @notice Allows the governance to set the campaign end timestamp function setEndTimestamp(uint256 _endTimestamp) public onlyOwner { require(raffleRewardsLength == 0, "Can't change end timestamp for raffles"); require(_endTimestamp > block.timestamp && _endTimestamp > startTimestamp, "Invalid end timestamp"); endTimestamp = _endTimestamp; } /// @notice Allows the owner to end the campaign early function endCampaign() public onlyActive onlyOwner { endTimestamp = block.timestamp; emit CampaignForceEnded(); } /// @notice Allows anyone to make the claim rewards funds /// return to the owner after the campaign is ended function withdrawClaimRewardsFunds() public onlyEnded { for (uint8 i = 0; i < claimRewardsLength; ++i) { _returnTokenToOwner(IERC20(claimRewards[i].token)); } emit ClaimRewardsFundsWithdrawn(); } /// @notice Execute the mint with permit by verifying the off-chain verifier signature /// @dev Also works with gasless EIP-2612 forwarders /// @param deadline The deadline for the permit /// @param v The v component of the signature /// @param r The r component of the signature /// @param s The s component of the signature function claim(uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual onlyActive { if (_claimed[_msgSender()]) { revert RewardAlreadyClaimed(); } if (block.timestamp > deadline) revert PermitDeadlineExpired(); _verifySignature(_msgSender(), deadline, v, r, s, factory.verifier()); _mintBadge(_msgSender()); _emitERC20Rewards(_msgSender()); } /// @notice sends a request for random numbers to the raffle manager /// @dev this function can be called multiple times because Airnode /// might fail for whatever reason function startRaffle() public onlyEnded { require(!raffleCompleted, "Raffle already done"); emit RaffleStarted(_msgSender()); address raffleManager = factory.raffleManager(); IRaffleManager(raffleManager).makeRequestUint256Array(raffleRewardsLength); } /// @notice fulfills the raffle by assigning random numbers to each reward /// and emitting the tokens. Then, returns the remaining funds for raffle rewards /// to the owner /// @param randomNumbers the random numbers to use for the raffle /// @dev the set of winning token ids per reward is generated by a single /// random number provided by the raffle manager function fulfillRaffle(uint256[] memory randomNumbers) public onlyEnded onlyRaffleManager { require(!raffleCompleted, "Raffle already done"); for (uint8 i = 0; i < raffleRewardsLength; i++) { uint256 randomNumber = randomNumbers[i]; address tokenAddress = raffleRewards[i].token; uint256 amountPerUser = raffleRewards[i].amountPerUser; IERC20 token = IERC20(tokenAddress); uint256 counter = 0; uint256 rewardsLeft = raffleRewards[i].rewardsLeft; if (lastId <= rewardsLeft) { for (uint256 tokenId = 1; tokenId <= lastId; tokenId++) { address winner = ownerOf(tokenId); token.transfer(winner, amountPerUser); emit RaffleWon(winner, tokenAddress, amountPerUser); } } else { for (uint256 assigned = 0; assigned < rewardsLeft; assigned++) { uint256 tokenId; do { tokenId = uint256(keccak256(abi.encodePacked(randomNumber, counter, block.timestamp))) % lastId + 1; counter++; } while (tokenIdRewardIdxHashToHasWon[keccak256(abi.encodePacked(tokenId, i))]); tokenIdRewardIdxHashToHasWon[keccak256(abi.encodePacked(tokenId, i))] = true; address winner = ownerOf(tokenId); token.transfer(winner, amountPerUser); emit RaffleWon(winner, tokenAddress, amountPerUser); } } } raffleCompleted = true; emit RaffleCompleted(); _withdrawRaffleRewardsFunds(); } /// @notice returns the URI for a given token ID /// @param tokenId The token ID to get the URI for /// @return string The URI for the given token ID function tokenURI(uint256 tokenId) public view override returns (string memory) { _requireMinted(tokenId); return customMetadata ? string(abi.encodePacked(_metadataBaseURI, "/", Strings.toString(tokenId), ".json")) : string(abi.encodePacked(_metadataBaseURI, "/metadata.json")); } /// @dev override the transfer function to allow transfers only if not soulbound /// @param from The address to transfer from /// @param to The address to transfer to /// @param tokenId The token ID to transfer function _transfer(address from, address to, uint256 tokenId) internal override { if (isSoulbound) revert NotTransferrable(); super._transfer(from, to, tokenId); } /// @dev internal function to mint a reward for a user /// @param user The user to mint the reward for function _mintBadge(address user) internal { _safeMint(user, ++lastId); _claimed[user] = true; emit Claimed(user, lastId); } ///@dev use ERC2771Context to get msg data ///@return bytes calldata function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) { return ERC2771Context._msgData(); } ///@dev use ERC2771Context to get msg sender ///@return address sender function _msgSender() internal view override(ERC2771Context, Context) returns (address) { return ERC2771Context._msgSender(); } /// @dev internal function to emit the first FCFS ERC20 reward available /// @param claimer The address to emit the rewards to function _emitERC20Rewards(address claimer) internal { for (uint8 i = 0; i < claimRewardsLength; i++) { IERC20 token = IERC20(claimRewards[i].token); uint256 amountPerUser = claimRewards[i].amountPerUser; bool enoughBalance = amountPerUser <= token.balanceOf(address(this)); if (claimRewards[i].rewardsLeft != 0 && enoughBalance) { token.transfer(claimer, amountPerUser); emit FCFSAwarded(claimer, claimRewards[i].token, amountPerUser); claimRewards[i].rewardsLeft--; break; } } } /// @dev internal function to call when withdrawing funds after campaign is ended /// @param token the token address of which balance has to be returned to the owner function _returnTokenToOwner(IERC20 token) internal { uint256 balance = token.balanceOf(address(this)); if (balance != 0) { token.transfer(owner(), balance); } } /// @dev internal function to call after the raffle is completed, to return /// the remaining funds to the owner function _withdrawRaffleRewardsFunds() internal { for (uint8 i = 0; i < raffleRewardsLength; ++i) { _returnTokenToOwner(IERC20(raffleRewards[i].token)); } emit RaffleRewardsFundsWithdrawn(); } }
// SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.21; pragma abicoder v2; interface IWaveFactory { struct TokenRewards { uint256 rewardsLeft; uint256 amountPerUser; address token; } function deployWave( string memory _name, string memory _symbol, string memory _baseURI, uint256 _startTimestamp, uint256 _endTimestamp, bool _isSoulbound, TokenRewards[] memory _claimRewards, TokenRewards[] memory _raffleRewards ) external; function keeper() external view returns (address); function verifier() external view returns (address); function raffleManager() external view returns (address); function isRaffleWave(address) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; import "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (metatx/ERC2771Context.sol) pragma solidity ^0.8.9; import "../utils/Context.sol"; /** * @dev Context variant with ERC2771 support. */ abstract contract ERC2771Context is Context { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address private immutable _trustedForwarder; /// @custom:oz-upgrades-unsafe-allow constructor constructor(address trustedForwarder) { _trustedForwarder = trustedForwarder; } function isTrustedForwarder(address forwarder) public view virtual returns (bool) { return forwarder == _trustedForwarder; } function _msgSender() internal view virtual override returns (address sender) { if (isTrustedForwarder(msg.sender)) { // The assembly code is more direct than the Solidity version using `abi.decode`. /// @solidity memory-safe-assembly assembly { sender := shr(96, calldataload(sub(calldatasize(), 20))) } } else { return super._msgSender(); } } function _msgData() internal view virtual override returns (bytes calldata) { if (isTrustedForwarder(msg.sender)) { return msg.data[:msg.data.length - 20]; } else { return super._msgData(); } } }
// SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.21; pragma abicoder v2; interface IWaveContract { struct TokenReward { uint256 count; uint256 amount; address token; bool isRaffle; } /// @notice Allows the governance to set metadata base URI for all tokens /// @param _uri The base URI to set /// @param _customMetadata Whether the metadata is encoded with tokenId function changeBaseURI(string memory _uri, bool _customMetadata) external; /// @notice Allows the owner to set the campaign start timestamp function setStartTimestamp(uint256 _startTimestamp) external; /// @notice Allows the governance to set the campaign end timestamp function setEndTimestamp(uint256 _endTimestamp) external; /// @notice Allows the owner to end the campaign early function endCampaign() external; /// @notice Allows anyone to make the claim rewards funds /// return to the owner after the campaign is ended function withdrawClaimRewardsFunds() external; /// @notice Execute the mint with permit by verifying the off-chain verifier signature /// @param deadline The deadline for the permit /// @param v The v component of the signature /// @param r The r component of the signature /// @param s The s component of the signature function claim(uint256 deadline, uint8 v, bytes32 r, bytes32 s) external; /// @notice sends a request for random numbers to the raffle manager function startRaffle() external; /// @notice fulfills the raffle by assigning random numbers to each reward /// and emitting the tokens. Then, returns the remaining funds for raffle rewards /// to the owner /// @param randomNumbers the random numbers to use for the raffle /// @dev the set of winning token ids per reward is generated by a single /// random number provided by the raffle manager function fulfillRaffle(uint256[] memory randomNumbers) external; }
//SPDX-License-Identifier: MIT pragma solidity 0.8.21; interface IRaffleManager { /// @notice Sets parameters used in requesting QRNG services /// @param _airnode Airnode address /// @param _endpointIdUint256Array Endpoint ID used to request a `uint256[]` /// @param _sponsor address used to sponsor this requester /// @param _sponsorWallet Sponsor wallet address function setRequestParameters(address _airnode, bytes32 _endpointIdUint256Array, address _sponsor, address _sponsorWallet) external; /// @notice Requests a `uint256[]` /// @param size Size of the requested array function makeRequestUint256Array(uint256 size) external returns (bytes32 requestId); /// @notice Called by the Airnode through the AirnodeRrp contract to /// fulfill the request /// @param requestId Request ID /// @param data ABI-encoded response function fulfillUint256Array(bytes32 requestId, bytes calldata data) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.0; import "./IERC721.sol"; import "./IERC721Receiver.sol"; import "./extensions/IERC721Metadata.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/Strings.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { using Address for address; using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: address zero is not a valid owner"); return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _ownerOf(tokenId); require(owner != address(0), "ERC721: invalid token ID"); return owner; } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { _requireMinted(tokenId); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( _msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not token owner or approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { _requireMinted(tokenId); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom(address from, address to, uint256 tokenId) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _safeTransfer(from, to, tokenId, data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist */ function _ownerOf(uint256 tokenId) internal view virtual returns (address) { return _owners[tokenId]; } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _ownerOf(tokenId) != address(0); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { address owner = ERC721.ownerOf(tokenId); return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual { _mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId, 1); // Check that tokenId was not minted by `_beforeTokenTransfer` hook require(!_exists(tokenId), "ERC721: token already minted"); unchecked { // Will not overflow unless all 2**256 token ids are minted to the same owner. // Given that tokens are minted one by one, it is impossible in practice that // this ever happens. Might change if we allow batch minting. // The ERC fails to describe this case. _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId, 1); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * This is an internal function that does not check if the sender is authorized to operate on the token. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId, 1); // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook owner = ERC721.ownerOf(tokenId); // Clear approvals delete _tokenApprovals[tokenId]; unchecked { // Cannot overflow, as that would require more tokens to be burned/transferred // out than the owner initially received through minting and transferring in. _balances[owner] -= 1; } delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId, 1); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer(address from, address to, uint256 tokenId) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId, 1); // Check that tokenId was not transferred by `_beforeTokenTransfer` hook require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); // Clear approvals from the previous owner delete _tokenApprovals[tokenId]; unchecked { // `_balances[from]` cannot overflow for the same reason as described in `_burn`: // `from`'s balance is the number of token held, which is at least one before the current // transfer. // `_balances[to]` could overflow in the conditions described in `_mint`. That would require // all 2**256 token ids to be minted, which in practice is impossible. _balances[from] -= 1; _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId, 1); } /** * @dev Approve `to` to operate on `tokenId` * * Emits an {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, tokenId); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll(address owner, address operator, bool approved) internal virtual { require(owner != operator, "ERC721: approve to caller"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Reverts if the `tokenId` has not been minted yet. */ function _requireMinted(uint256 tokenId) internal view virtual { require(_exists(tokenId), "ERC721: invalid token ID"); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory data ) private returns (bool) { if (to.isContract()) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver implementer"); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`. * - When `from` is zero, the tokens will be minted for `to`. * - When `to` is zero, ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {} /** * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`. * - When `from` is zero, the tokens were minted for `to`. * - When `to` is zero, ``from``'s tokens were burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {} /** * @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override. * * WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant * being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such * that `ownerOf(tokenId)` is `a`. */ // solhint-disable-next-line func-name-mixedcase function __unsafe_increaseBalance(address account, uint256 amount) internal { _balances[account] += amount; } }
// SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.21; pragma abicoder v2; import {IERC721} from "../../lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol"; contract SignatureVerifier { struct Permit { address spender; uint256 deadline; } bytes32 public immutable DOMAIN_SEPARATOR; bytes32 public immutable PERMIT_TYPEHASH; error InvalidSignature(); constructor(string memory _name) { DOMAIN_SEPARATOR = _computeDomainSeparator(bytes(_name)); PERMIT_TYPEHASH = keccak256("Permit(address spender,uint256 deadline)"); } function _verifySignature(address sender, uint256 deadline, uint8 v, bytes32 r, bytes32 s, address verifier) internal view { bytes32 typedDataHash = getTypedDataHash(Permit(sender, deadline)); address recoveredAddress = ecrecover(_prefixed(typedDataHash), v, r, s); if (recoveredAddress == address(0) || recoveredAddress != verifier) revert InvalidSignature(); } /// @dev computes the hash of the fully encoded EIP-712 message for the domain, /// which can be used to recover the signer /// @param _permit The permit struct /// @return bytes32 The hash of the fully encoded EIP-712 message for the domain function getTypedDataHash(Permit memory _permit) public view returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR, _getStructHash(_permit))); } /// @dev returns the domain separator for the contract /// @param _name The name of the contract /// @return bytes32 The domain separator for the contract function _computeDomainSeparator(bytes memory _name) internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(_name), keccak256("1"), block.chainid, address(this) ) ); } /// @dev computes the hash of a permit struct /// @param _permit The permit struct /// @return bytes32 The hash of the permit struct function _getStructHash(Permit memory _permit) internal view returns (bytes32) { return keccak256(abi.encode(PERMIT_TYPEHASH, _permit.spender, _permit.deadline)); } /// @dev Builds a prefixed hash to mimic the behavior of eth_sign. /// @param hash The hash to prefix /// @return bytes32 The prefixed hash function _prefixed(bytes32 hash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 tokenId) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
{ "remappings": [ "@openzeppelin/=lib/openzeppelin-contracts/", "airnode/=lib/airnode/", "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "lib/forge-std:ds-test/=lib/forge-std/lib/ds-test/src/", "lib/openzeppelin-contracts:ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/", "lib/openzeppelin-contracts:erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "lib/openzeppelin-contracts:forge-std/=lib/openzeppelin-contracts/lib/forge-std/src/", "lib/openzeppelin-contracts:openzeppelin/=lib/openzeppelin-contracts/contracts/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_keeper","type":"address"},{"internalType":"address","name":"_trustedForwarder","type":"address"},{"internalType":"address","name":"_verifier","type":"address"},{"internalType":"address","name":"_raffleManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"TooManyRewards","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wave","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"WaveCreated","type":"event"},{"inputs":[{"internalType":"address","name":"_keeper","type":"address"}],"name":"changeKeeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_raffleManager","type":"address"}],"name":"changeRaffleManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_trustedForwarder","type":"address"}],"name":"changeTrustedForwarder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_verifier","type":"address"}],"name":"changeVerifier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"string","name":"_baseURI","type":"string"},{"internalType":"uint256","name":"_startTimestamp","type":"uint256"},{"internalType":"uint256","name":"_endTimestamp","type":"uint256"},{"internalType":"bool","name":"_isSoulbound","type":"bool"},{"components":[{"internalType":"uint256","name":"rewardsLeft","type":"uint256"},{"internalType":"uint256","name":"amountPerUser","type":"uint256"},{"internalType":"address","name":"token","type":"address"}],"internalType":"struct IWaveFactory.TokenRewards[]","name":"_claimRewards","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"rewardsLeft","type":"uint256"},{"internalType":"uint256","name":"amountPerUser","type":"uint256"},{"internalType":"address","name":"token","type":"address"}],"internalType":"struct IWaveFactory.TokenRewards[]","name":"_raffleRewards","type":"tuple[]"}],"name":"deployWave","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isRaffleWave","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keeper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"raffleManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"trustedForwarder","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"verifier","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"waves","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b506040516200469238038062004692833981016040819052610031916100f9565b61003a3361008d565b600280546001600160a01b039586166001600160a01b031991821617909155600380549486169482169490941790935560048054928516928416929092179091556005805491909316911617905561014d565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146100f457600080fd5b919050565b6000806000806080858703121561010f57600080fd5b610118856100dd565b9350610126602086016100dd565b9250610134604086016100dd565b9150610142606086016100dd565b905092959194509250565b614535806200015d6000396000f3fe60806040523480156200001157600080fd5b5060043610620000fd5760003560e01c8063aced16611162000097578063cf04fb94116200006e578063cf04fb941462000209578063d3f8a33a1462000220578063f2fde38b1462000237578063f51341e4146200024e57600080fd5b8063aced166114620001a7578063b553469914620001bb578063c781267a14620001f257600080fd5b8063715018a611620000d8578063715018a614620001635780637da0a877146200016d5780638da5cb5b1462000181578063aa6527d9146200019357600080fd5b806308c7a8dd146200010257806309779838146200011b5780632b7ac3f31462000132575b600080fd5b6200011962000113366004620007a1565b62000265565b005b620001196200012c366004620007a1565b62000291565b60045462000146906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b62000119620002bd565b60035462000146906001600160a01b031681565b6000546001600160a01b031662000146565b60055462000146906001600160a01b031681565b60025462000146906001600160a01b031681565b620001e1620001cc366004620007a1565b60066020526000908152604090205460ff1681565b60405190151581526020016200015a565b6200014662000203366004620007c6565b620002d5565b620001196200021a366004620007a1565b62000300565b6200011962000231366004620007a1565b6200032c565b6200011962000248366004620007a1565b62000358565b620001196200025f366004620009ac565b620003db565b6200026f62000599565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6200029b62000599565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b620002c762000599565b620002d36000620005f5565b565b60018181548110620002e657600080fd5b6000918252602090912001546001600160a01b0316905081565b6200030a62000599565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6200033662000599565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b6200036262000599565b6001600160a01b038116620003cd5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b620003d881620005f5565b50565b6101008251101580620003f15750610100815110155b15620004105760405163428680e160e11b815260040160405180910390fd5b6000888888888888600360009054906101000a90046001600160a01b031689896040516200043e9062000776565b620004529998979695949392919062000b58565b604051809103906000f0801580156200046f573d6000803e3d6000fd5b506001805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b0319166001600160a01b03831690811790915560405163f2fde38b60e01b81523360048201529192509063f2fde38b90602401600060405180830381600087803b158015620004f857600080fd5b505af11580156200050d573d6000803e3d6000fd5b5050505060008251111562000540576001600160a01b0381166000908152600660205260409020805460ff191660011790555b6200054c838262000645565b62000558828262000645565b60405133906001600160a01b038316907fb49597eb6ae32b938af897f271f3c6f6448014880f91ccee242476f2db9af06c90600090a3505050505050505050565b6000546001600160a01b03163314620002d35760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620003c4565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b815160005b8160ff168160ff1610156200077057838160ff168151811062000671576200067162000bfc565b6020026020010151604001516001600160a01b03166323b872dd3385878560ff1681518110620006a557620006a562000bfc565b602002602001015160000151888660ff1681518110620006c957620006c962000bfc565b602002602001015160200151620006e1919062000c28565b6040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064016020604051808303816000875af115801562000736573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200075c919062000c48565b50620007688162000c68565b90506200064a565b50505050565b6138758062000c8b83390190565b80356001600160a01b03811681146200079c57600080fd5b919050565b600060208284031215620007b457600080fd5b620007bf8262000784565b9392505050565b600060208284031215620007d957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff811182821017156200081c576200081c620007e0565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156200084e576200084e620007e0565b604052919050565b600082601f8301126200086857600080fd5b813567ffffffffffffffff811115620008855762000885620007e0565b6200089a601f8201601f191660200162000822565b818152846020838601011115620008b057600080fd5b816020850160208301376000918101602001919091529392505050565b8015158114620003d857600080fd5b80356200079c81620008cd565b600082601f830112620008fb57600080fd5b8135602067ffffffffffffffff8211156200091a576200091a620007e0565b6200092a818360051b0162000822565b828152606092830285018201928282019190878511156200094a57600080fd5b8387015b858110156200099f5781818a031215620009685760008081fd5b62000972620007f6565b81358152858201358682015260406200098d81840162000784565b9082015284529284019281016200094e565b5090979650505050505050565b600080600080600080600080610100898b031215620009ca57600080fd5b883567ffffffffffffffff80821115620009e357600080fd5b620009f18c838d0162000856565b995060208b013591508082111562000a0857600080fd5b62000a168c838d0162000856565b985060408b013591508082111562000a2d57600080fd5b62000a3b8c838d0162000856565b975060608b0135965060808b0135955062000a5960a08c01620008dc565b945060c08b013591508082111562000a7057600080fd5b62000a7e8c838d01620008e9565b935060e08b013591508082111562000a9557600080fd5b5062000aa48b828c01620008e9565b9150509295985092959890939650565b6000815180845260005b8181101562000adc5760208185018101518683018201520162000abe565b506000602082860101526020601f19601f83011685010191505092915050565b600081518084526020808501945080840160005b8381101562000b4d5781518051885283810151848901526040908101516001600160a01b0316908801526060909601959082019060010162000b10565b509495945050505050565b600061012080835262000b6e8184018d62000ab4565b9050828103602084015262000b84818c62000ab4565b9050828103604084015262000b9a818b62000ab4565b606084018a90526080840189905287151560a08501526001600160a01b03871660c085015283810360e0850152905062000bd5818662000afc565b905082810361010084015262000bec818562000afc565b9c9b505050505050505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b808202811582820484141762000c425762000c4262000c12565b92915050565b60006020828403121562000c5b57600080fd5b8151620007bf81620008cd565b600060ff821660ff810362000c815762000c8162000c12565b6001019291505056fe6101206040523480156200001257600080fd5b506040516200387538038062003875833981016040819052620000359162000593565b6001600160a01b038316608052888089620000596200005362000292565b620002a3565b60016200006783826200073c565b5060026200007682826200073c565b5050506200008a81620002f360201b60201c565b60a052507f05d55ef4a8a7ca3d0b75d9ecd47170a2bf895536707a031d23b6bb013c73f73f60c05284861180620000c057504285105b15620000df5760405163c6e369f960e01b815260040160405180910390fd5b620000e962000292565b600780546001600160a01b0319166001600160a01b0392909216919091179055600b6200011788826200073c565b506009869055600a859055600c805461ff00191661010086151502179055815160ff1660e05260005b60e05160ff168160ff161015620001da57600f838260ff16815181106200016b576200016b62000808565b60209081029190910181015182546001808201855560009485529383902082516003909202019081559181015192820192909255604090910151600290910180546001600160a01b0319166001600160a01b03909216919091179055620001d2816200081e565b905062000140565b50805160ff166101005260005b6101005160ff168160ff16101562000282576010828260ff168151811062000213576200021362000808565b60209081029190910181015182546001808201855560009485529383902082516003909202019081559181015192820192909255604090910151600290910180546001600160a01b0319166001600160a01b039092169190911790556200027a816200081e565b9050620001e7565b505050505050505050506200084c565b60006200029e6200037a565b905090565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8051602091820120604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81850152808201929092527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528151808403909101815260c09092019052805191012090565b6080516000906001600160a01b031633036200039d575060131936013560601c90565b503390565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b0381118282101715620003dd57620003dd620003a2565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200040e576200040e620003a2565b604052919050565b600082601f8301126200042857600080fd5b81516001600160401b03811115620004445762000444620003a2565b60206200045a601f8301601f19168201620003e3565b82815285828487010111156200046f57600080fd5b60005b838110156200048f57858101830151828201840152820162000472565b506000928101909101919091529392505050565b80518015158114620004b457600080fd5b919050565b80516001600160a01b0381168114620004b457600080fd5b600082601f830112620004e357600080fd5b815160206001600160401b03821115620005015762000501620003a2565b62000511818360051b01620003e3565b828152606092830285018201928282019190878511156200053157600080fd5b8387015b85811015620005865781818a0312156200054f5760008081fd5b62000559620003b8565b815181528582015186820152604062000574818401620004b9565b90820152845292840192810162000535565b5090979650505050505050565b60008060008060008060008060006101208a8c031215620005b357600080fd5b89516001600160401b0380821115620005cb57600080fd5b620005d98d838e0162000416565b9a5060208c0151915080821115620005f057600080fd5b620005fe8d838e0162000416565b995060408c01519150808211156200061557600080fd5b620006238d838e0162000416565b985060608c0151975060808c015196506200064160a08d01620004a3565b95506200065160c08d01620004b9565b945060e08c01519150808211156200066857600080fd5b620006768d838e01620004d1565b93506101008c01519150808211156200068e57600080fd5b506200069d8c828d01620004d1565b9150509295985092959850929598565b600181811c90821680620006c257607f821691505b602082108103620006e357634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200073757600081815260208120601f850160051c81016020861015620007125750805b601f850160051c820191505b8181101562000733578281556001016200071e565b5050505b505050565b81516001600160401b03811115620007585762000758620003a2565b6200077081620007698454620006ad565b84620006e9565b602080601f831160018114620007a857600084156200078f5750858301515b600019600386901b1c1916600185901b17855562000733565b600085815260208120601f198616915b82811015620007d957888601518255948401946001909101908401620007b8565b5085821015620007f85787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052603260045260246000fd5b600060ff821660ff81036200084357634e487b7160e01b600052601160045260246000fd5b60010192915050565b60805160a05160c05160e05161010051612fa5620008d0600039600081816104a301528181610b2701528181610dc00152818161137b0152611db10152600081816103e101528181610be2015261198801526000818161036a0152611f0f01526000818161039f015261145401526000818161043801526120e90152612fa56000f3fe608060405234801561001057600080fd5b50600436106102485760003560e01c806371aac7f91161013b578063b88d4fde116100b8578063d5c688d61161007c578063d5c688d614610595578063e6fd48bc146105a2578063e985e9c5146105ab578063f2fde38b146105e7578063f7eca6d0146105fa57600080fd5b8063b88d4fde14610540578063c1292cc314610553578063c44bef751461055c578063c45a01551461056f578063c87b56dd1461058257600080fd5b806395d89b41116100ff57806395d89b41146104fc57806398428dbf146105045780639917840814610511578063a22cb46514610524578063a85adeab1461053757600080fd5b806371aac7f9146104965780637c97853a1461049e5780637df6a6c8146104c55780638da5cb5b146104d8578063902413d0146104e957600080fd5b806330adf81f116101c957806356d9d14b1161018d57806356d9d14b14610415578063572b6c05146104285780636352211e1461046857806370a082311461047b578063715018a61461048e57600080fd5b806330adf81f146103655780633644e5151461039a5780633bbbda65146103c157806342842e0e146103c957806346e51f9a146103dc57600080fd5b80631278e00a116102105780631278e00a1461030157806323b872dd14610314578063242284f114610327578063263c2e341461032f5780633010a8b71461034257600080fd5b806301ffc9a71461024d57806306fdde0314610275578063081812fc1461028a578063095ea7b3146102b55780630962ef79146102ca575b600080fd5b61026061025b366004612696565b61060c565b60405190151581526020015b60405180910390f35b61027d61065e565b60405161026c919061270a565b61029d61029836600461271d565b6106f0565b6040516001600160a01b03909116815260200161026c565b6102c86102c336600461274b565b610717565b005b6102dd6102d836600461271d565b610843565b6040805193845260208401929092526001600160a01b03169082015260600161026c565b6102c861030f366004612777565b61087f565b6102c86103223660046127ba565b6109c7565b6102c86109ff565b6102dd61033d36600461271d565b610baa565b61026061035036600461271d565b600e6020526000908152604090205460ff1681565b61038c7f000000000000000000000000000000000000000000000000000000000000000081565b60405190815260200161026c565b61038c7f000000000000000000000000000000000000000000000000000000000000000081565b6102c8610bba565b6102c86103d73660046127ba565b610c85565b6104037f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff909116815260200161026c565b6102c8610423366004612842565b610ca0565b6102606104363660046128e8565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b61029d61047636600461271d565b61120f565b61038c6104893660046128e8565b61126f565b6102c86112f5565b6102c8611309565b6104037f000000000000000000000000000000000000000000000000000000000000000081565b6102c86104d336600461271d565b61136f565b6000546001600160a01b031661029d565b61038c6104f7366004612905565b611450565b61027d6114b8565b600c546102609060ff1681565b6102c861051f3660046129c3565b6114c7565b6102c8610532366004612a29565b6115c0565b61038c600a5481565b6102c861054e366004612a57565b6115d2565b61038c60085481565b6102c861056a36600461271d565b61160b565b60075461029d906001600160a01b031681565b61027d61059036600461271d565b611674565b6011546102609060ff1681565b61038c60095481565b6102606105b9366004612ad7565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205460ff1690565b6102c86105f53660046128e8565b6116e0565b600c5461026090610100900460ff1681565b60006001600160e01b031982166380ac58cd60e01b148061063d57506001600160e01b03198216635b5e139f60e01b145b8061065857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606001805461066d90612b05565b80601f016020809104026020016040519081016040528092919081815260200182805461069990612b05565b80156106e65780601f106106bb576101008083540402835291602001916106e6565b820191906000526020600020905b8154815290600101906020018083116106c957829003601f168201915b5050505050905090565b60006106fb82611756565b506000908152600560205260409020546001600160a01b031690565b60006107228261120f565b9050806001600160a01b0316836001600160a01b0316036107945760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b806001600160a01b03166107a66117b5565b6001600160a01b031614806107c257506107c2816105b96117b5565b6108345760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000606482015260840161078b565b61083e83836117c4565b505050565b600f818154811061085357600080fd5b60009182526020909120600390910201805460018201546002909201549092506001600160a01b031683565b6009544210806108905750600a5442115b156108ae5760405163219a945b60e11b815260040160405180910390fd5b600d60006108ba6117b5565b6001600160a01b0316815260208101919091526040016000205460ff16156108f557604051632cfe303760e21b815260040160405180910390fd5b83421115610916576040516305787bdf60e01b815260040160405180910390fd5b6109a16109216117b5565b85858585600760009054906101000a90046001600160a01b03166001600160a01b0316632b7ac3f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610978573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099c9190612b3f565b611832565b6109b16109ac6117b5565b611914565b6109c16109bc6117b5565b611983565b50505050565b6109d86109d26117b5565b82611bf4565b6109f45760405162461bcd60e51b815260040161078b90612b5c565b61083e838383611c73565b600a54421015610a225760405163cc76115360e01b815260040160405180910390fd5b60115460ff1615610a6b5760405162461bcd60e51b8152602060048201526013602482015272526166666c6520616c726561647920646f6e6560681b604482015260640161078b565b610a736117b5565b6001600160a01b03167fe5ed10a2abb6a808edb6fbb7ae5cd09aad196ddaa1bd4e9295688a4d508460c860405160405180910390a26007546040805163aa6527d960e01b815290516000926001600160a01b03169163aa6527d99160048083019260209291908290030181865afa158015610af2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b169190612b3f565b6040516315be9e9160e11b815260ff7f00000000000000000000000000000000000000000000000000000000000000001660048201529091506001600160a01b03821690632b7d3d22906024016020604051808303816000875af1158015610b82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ba69190612ba9565b5050565b6010818154811061085357600080fd5b600a54421015610bdd5760405163cc76115360e01b815260040160405180910390fd5b60005b7f000000000000000000000000000000000000000000000000000000000000000060ff168160ff161015610c5957610c49600f8260ff1681548110610c2757610c27612bc2565b60009182526020909120600260039092020101546001600160a01b0316611ca7565b610c5281612bee565b9050610be0565b506040517f7f55430b29ae5a8c80e07c8bcba9b96d9a4904baff6645f7b6f1941ac53c736590600090a1565b61083e838383604051806020016040528060008152506115d2565b600a54421015610cc35760405163cc76115360e01b815260040160405180910390fd5b600760009054906101000a90046001600160a01b03166001600160a01b031663aa6527d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3a9190612b3f565b6001600160a01b0316610d4b6117b5565b6001600160a01b031614610d725760405163712a092360e01b815260040160405180910390fd5b60115460ff1615610dbb5760405162461bcd60e51b8152602060048201526013602482015272526166666c6520616c726561647920646f6e6560681b604482015260640161078b565b60005b7f000000000000000000000000000000000000000000000000000000000000000060ff168160ff1610156111cd576000828260ff1681518110610e0357610e03612bc2565b60200260200101519050600060108360ff1681548110610e2557610e25612bc2565b60009182526020822060026003909202010154601080546001600160a01b0390921693509060ff8616908110610e5d57610e5d612bc2565b9060005260206000209060030201600101549050600082905060008060108760ff1681548110610e8f57610e8f612bc2565b90600052602060002090600302016000015490508060085411610fa15760015b6008548111610f9b576000610ec38261120f565b60405163a9059cbb60e01b81526001600160a01b038083166004830152602482018990529192509086169063a9059cbb906044016020604051808303816000875af1158015610f16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3a9190612c0d565b50866001600160a01b0316816001600160a01b03167f80b887c8189ccc457f4b3077692f6d6d11abc05537566d3273df1747af53495488604051610f8091815260200190565b60405180910390a35080610f9381612c2a565b915050610eaf565b506111b4565b60005b818110156111b25760005b60085460408051602081018b90529081018690524260608201526080016040516020818303038152906040528051906020012060001c610fef9190612c43565b610ffa906001612c65565b90508361100681612c2a565b945050600e6000828b60405160200161103692919091825260f81b6001600160f81b031916602082015260210190565b60408051601f198184030181529181528151602092830120835290820192909252016000205460ff16610faf576001600e6000838c60405160200161109292919091825260f81b6001600160f81b031916602082015260210190565b60405160208183030381529060405280519060200120815260200190815260200160002060006101000a81548160ff02191690831515021790555060006110d88261120f565b60405163a9059cbb60e01b81526001600160a01b038083166004830152602482018a90529192509087169063a9059cbb906044016020604051808303816000875af115801561112b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114f9190612c0d565b50876001600160a01b0316816001600160a01b03167f80b887c8189ccc457f4b3077692f6d6d11abc05537566d3273df1747af5349548960405161119591815260200190565b60405180910390a3505080806111aa90612c2a565b915050610fa4565b505b50505050505080806111c590612bee565b915050610dbe565b506011805460ff191660011790556040517f27570828a3b3d654a69144a8ca6c7e066e01acd2e5c41405c83fa9f03011831290600090a161120c611dac565b50565b6000818152600360205260408120546001600160a01b0316806106585760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604482015260640161078b565b60006001600160a01b0382166112d95760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b606482015260840161078b565b506001600160a01b031660009081526004602052604090205490565b6112fd611e32565b6113076000611eab565b565b60095442108061131a5750600a5442115b156113385760405163219a945b60e11b815260040160405180910390fd5b611340611e32565b42600a556040517f434b671a95fb0071b0127874981939c3cd42e8f1f7d602b761482102d4a5507290600090a1565b611377611e32565b60ff7f000000000000000000000000000000000000000000000000000000000000000016156113f75760405162461bcd60e51b815260206004820152602660248201527f43616e2774206368616e676520656e642074696d657374616d7020666f7220726044820152656166666c657360d01b606482015260840161078b565b4281118015611407575060095481115b61144b5760405162461bcd60e51b81526020600482015260156024820152740496e76616c696420656e642074696d657374616d7605c1b604482015260640161078b565b600a55565b60007f000000000000000000000000000000000000000000000000000000000000000061147c83611efb565b60405161190160f01b6020820152602281019290925260428201526062015b604051602081830303815290604052805190602001209050919050565b60606002805461066d90612b05565b600760009054906101000a90046001600160a01b03166001600160a01b031663aced16616040518163ffffffff1660e01b8152600401602060405180830381865afa15801561151a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153e9190612b3f565b6001600160a01b031661154f6117b5565b6001600160a01b03161415801561158157506000546001600160a01b03166115756117b5565b6001600160a01b031614155b1561159f57604051637d7b71b560e01b815260040160405180910390fd5b600b6115ab8382612cc6565b50600c805460ff191691151591909117905550565b610ba66115cb6117b5565b8383611f51565b6115e36115dd6117b5565b83611bf4565b6115ff5760405162461bcd60e51b815260040161078b90612b5c565b6109c18484848461201f565b611613611e32565b80421080156116235750600a5481105b61166f5760405162461bcd60e51b815260206004820152601760248201527f496e76616c69642073746172742074696d657374616d70000000000000000000604482015260640161078b565b600955565b606061167f82611756565b600c5460ff166116af57600b60405160200161169b9190612df9565b604051602081830303815290604052610658565b600b6116ba83612052565b6040516020016116cb929190612e23565b60405160208183030381529060405292915050565b6116e8611e32565b6001600160a01b03811661174d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161078b565b61120c81611eab565b6000818152600360205260409020546001600160a01b031661120c5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604482015260640161078b565b60006117bf6120e5565b905090565b600081815260056020526040902080546001600160a01b0319166001600160a01b03841690811790915581906117f98261120f565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061185a6040518060400160405280896001600160a01b0316815260200188815250611450565b90506000600161186983612129565b6040805160008152602081018083529290925260ff891690820152606081018790526080810186905260a0016020604051602081039080840390855afa1580156118b7573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615806118ec5750826001600160a01b0316816001600160a01b031614155b1561190a57604051638baa579f60e01b815260040160405180910390fd5b5050505050505050565b6119318160086000815461192790612c2a565b9182905550612164565b6001600160a01b0381166000818152600d6020526040808220805460ff1916600117905560085490519092917fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a91a350565b60005b7f000000000000000000000000000000000000000000000000000000000000000060ff168160ff161015610ba6576000600f8260ff16815481106119cc576119cc612bc2565b60009182526020822060026003909202010154600f80546001600160a01b0390921693509060ff8516908110611a0457611a04612bc2565b600091825260208220600160039092020101546040516370a0823160e01b81523060048201529092506001600160a01b038416906370a0823190602401602060405180830381865afa158015611a5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a829190612ba9565b8211159050600f8460ff1681548110611a9d57611a9d612bc2565b906000526020600020906003020160000154600014158015611abc5750805b15611bde5760405163a9059cbb60e01b81526001600160a01b0386811660048301526024820184905284169063a9059cbb906044016020604051808303816000875af1158015611b10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b349190612c0d565b50600f8460ff1681548110611b4b57611b4b612bc2565b6000918252602091829020600390910201600201546040518481526001600160a01b0391821692918816917f2b5a46847b5904937aa26c09373883ac411399d3404814f716b47721af04ff4f910160405180910390a3600f8460ff1681548110611bb757611bb7612bc2565b600091825260208220600390910201805491611bd283612e67565b91905055505050505050565b5050508080611bec90612bee565b915050611986565b600080611c008361120f565b9050806001600160a01b0316846001600160a01b03161480611c4757506001600160a01b0380821660009081526006602090815260408083209388168352929052205460ff165b80611c6b5750836001600160a01b0316611c60846106f0565b6001600160a01b0316145b949350505050565b600c54610100900460ff1615611c9c576040516354ee515160e01b815260040160405180910390fd5b61083e83838361217e565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015611cee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d129190612ba9565b90508015610ba657816001600160a01b031663a9059cbb611d3b6000546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303816000875af1158015611d88573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061083e9190612c0d565b60005b7f000000000000000000000000000000000000000000000000000000000000000060ff168160ff161015611e0657611df660108260ff1681548110610c2757610c27612bc2565b611dff81612bee565b9050611daf565b506040517ff54a6d4a21d85c024952c8d95373adfbb78b39d0cdcc90236722b6343c525c5a90600090a1565b611e3a6117b5565b6001600160a01b0316611e556000546001600160a01b031690565b6001600160a01b0316146113075760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161078b565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b805160208083015160405160009361149b937f0000000000000000000000000000000000000000000000000000000000000000939192019283526001600160a01b03919091166020830152604082015260600190565b816001600160a01b0316836001600160a01b031603611fb25760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015260640161078b565b6001600160a01b03838116600081815260066020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b61202a848484611c73565b612036848484846122e2565b6109c15760405162461bcd60e51b815260040161078b90612e7e565b6060600061205f836123ea565b600101905060008167ffffffffffffffff81111561207f5761207f6127fb565b6040519080825280601f01601f1916602001820160405280156120a9576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a85049450846120b357509392505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303612124575060131936013560601c90565b503390565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c0161149b565b610ba68282604051806020016040528060008152506124c2565b826001600160a01b03166121918261120f565b6001600160a01b0316146121b75760405162461bcd60e51b815260040161078b90612ed0565b6001600160a01b0382166122195760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b606482015260840161078b565b826001600160a01b031661222c8261120f565b6001600160a01b0316146122525760405162461bcd60e51b815260040161078b90612ed0565b600081815260056020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260048552838620805460001901905590871680865283862080546001019055868652600390945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b60006001600160a01b0384163b156123df57836001600160a01b031663150b7a0261230b6117b5565b8786866040518563ffffffff1660e01b815260040161232d9493929190612f15565b6020604051808303816000875af1925050508015612368575060408051601f3d908101601f1916820190925261236591810190612f52565b60015b6123c5573d808015612396576040519150601f19603f3d011682016040523d82523d6000602084013e61239b565b606091505b5080516000036123bd5760405162461bcd60e51b815260040161078b90612e7e565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611c6b565b506001949350505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106124295772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310612455576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061247357662386f26fc10000830492506010015b6305f5e100831061248b576305f5e100830492506008015b612710831061249f57612710830492506004015b606483106124b1576064830492506002015b600a83106106585760010192915050565b6124cc83836124f5565b6124d960008484846122e2565b61083e5760405162461bcd60e51b815260040161078b90612e7e565b6001600160a01b03821661254b5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161078b565b6000818152600360205260409020546001600160a01b0316156125b05760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161078b565b6000818152600360205260409020546001600160a01b0316156126155760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161078b565b6001600160a01b038216600081815260046020908152604080832080546001019055848352600390915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6001600160e01b03198116811461120c57600080fd5b6000602082840312156126a857600080fd5b81356126b381612680565b9392505050565b60005b838110156126d55781810151838201526020016126bd565b50506000910152565b600081518084526126f68160208601602086016126ba565b601f01601f19169290920160200192915050565b6020815260006126b360208301846126de565b60006020828403121561272f57600080fd5b5035919050565b6001600160a01b038116811461120c57600080fd5b6000806040838503121561275e57600080fd5b823561276981612736565b946020939093013593505050565b6000806000806080858703121561278d57600080fd5b84359350602085013560ff811681146127a557600080fd5b93969395505050506040820135916060013590565b6000806000606084860312156127cf57600080fd5b83356127da81612736565b925060208401356127ea81612736565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561283a5761283a6127fb565b604052919050565b6000602080838503121561285557600080fd5b823567ffffffffffffffff8082111561286d57600080fd5b818501915085601f83011261288157600080fd5b813581811115612893576128936127fb565b8060051b91506128a4848301612811565b81815291830184019184810190888411156128be57600080fd5b938501935b838510156128dc578435825293850193908501906128c3565b98975050505050505050565b6000602082840312156128fa57600080fd5b81356126b381612736565b60006040828403121561291757600080fd5b6040516040810181811067ffffffffffffffff8211171561293a5761293a6127fb565b604052823561294881612736565b81526020928301359281019290925250919050565b600067ffffffffffffffff831115612977576129776127fb565b61298a601f8401601f1916602001612811565b905082815283838301111561299e57600080fd5b828260208301376000602084830101529392505050565b801515811461120c57600080fd5b600080604083850312156129d657600080fd5b823567ffffffffffffffff8111156129ed57600080fd5b8301601f810185136129fe57600080fd5b612a0d8582356020840161295d565b9250506020830135612a1e816129b5565b809150509250929050565b60008060408385031215612a3c57600080fd5b8235612a4781612736565b91506020830135612a1e816129b5565b60008060008060808587031215612a6d57600080fd5b8435612a7881612736565b93506020850135612a8881612736565b925060408501359150606085013567ffffffffffffffff811115612aab57600080fd5b8501601f81018713612abc57600080fd5b612acb8782356020840161295d565b91505092959194509250565b60008060408385031215612aea57600080fd5b8235612af581612736565b91506020830135612a1e81612736565b600181811c90821680612b1957607f821691505b602082108103612b3957634e487b7160e01b600052602260045260246000fd5b50919050565b600060208284031215612b5157600080fd5b81516126b381612736565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b600060208284031215612bbb57600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060ff821660ff8103612c0457612c04612bd8565b60010192915050565b600060208284031215612c1f57600080fd5b81516126b3816129b5565b600060018201612c3c57612c3c612bd8565b5060010190565b600082612c6057634e487b7160e01b600052601260045260246000fd5b500690565b8082018082111561065857610658612bd8565b601f82111561083e57600081815260208120601f850160051c81016020861015612c9f5750805b601f850160051c820191505b81811015612cbe57828155600101612cab565b505050505050565b815167ffffffffffffffff811115612ce057612ce06127fb565b612cf481612cee8454612b05565b84612c78565b602080601f831160018114612d295760008415612d115750858301515b600019600386901b1c1916600185901b178555612cbe565b600085815260208120601f198616915b82811015612d5857888601518255948401946001909101908401612d39565b5085821015612d765787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008154612d9381612b05565b60018281168015612dab5760018114612dc057612def565b60ff1984168752821515830287019450612def565b8560005260208060002060005b85811015612de65781548a820152908401908201612dcd565b50505082870194505b5050505092915050565b6000612e058284612d86565b6d17b6b2ba30b230ba30973539b7b760911b8152600e019392505050565b6000612e2f8285612d86565b602f60f81b81528351612e498160018401602088016126ba565b64173539b7b760d91b60019290910191820152600601949350505050565b600081612e7657612e76612bd8565b506000190190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612f48908301846126de565b9695505050505050565b600060208284031215612f6457600080fd5b81516126b38161268056fea26469706673582212206b9ba6c88e39c8076fec85732794044f57536c74e3d4863b0fdf6ccecb31db0e64736f6c63430008150033a26469706673582212209036c166991b7ec8ec84b16ee58f5554cb963a27541d9545437c87ccd4965c2f64736f6c63430008150033000000000000000000000000607291c9b3b03d8c2dc1f5f7f8db2b6a06c91183000000000000000000000000dead00000000000000000000000000000000dead00000000000000000000000075d14f0ae59003c0806b625b402a40340ffde63400000000000000000000000075d14f0ae59003c0806b625b402a40340ffde634
Deployed Bytecode
0x60806040523480156200001157600080fd5b5060043610620000fd5760003560e01c8063aced16611162000097578063cf04fb94116200006e578063cf04fb941462000209578063d3f8a33a1462000220578063f2fde38b1462000237578063f51341e4146200024e57600080fd5b8063aced166114620001a7578063b553469914620001bb578063c781267a14620001f257600080fd5b8063715018a611620000d8578063715018a614620001635780637da0a877146200016d5780638da5cb5b1462000181578063aa6527d9146200019357600080fd5b806308c7a8dd146200010257806309779838146200011b5780632b7ac3f31462000132575b600080fd5b6200011962000113366004620007a1565b62000265565b005b620001196200012c366004620007a1565b62000291565b60045462000146906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b62000119620002bd565b60035462000146906001600160a01b031681565b6000546001600160a01b031662000146565b60055462000146906001600160a01b031681565b60025462000146906001600160a01b031681565b620001e1620001cc366004620007a1565b60066020526000908152604090205460ff1681565b60405190151581526020016200015a565b6200014662000203366004620007c6565b620002d5565b620001196200021a366004620007a1565b62000300565b6200011962000231366004620007a1565b6200032c565b6200011962000248366004620007a1565b62000358565b620001196200025f366004620009ac565b620003db565b6200026f62000599565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6200029b62000599565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b620002c762000599565b620002d36000620005f5565b565b60018181548110620002e657600080fd5b6000918252602090912001546001600160a01b0316905081565b6200030a62000599565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6200033662000599565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b6200036262000599565b6001600160a01b038116620003cd5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b620003d881620005f5565b50565b6101008251101580620003f15750610100815110155b15620004105760405163428680e160e11b815260040160405180910390fd5b6000888888888888600360009054906101000a90046001600160a01b031689896040516200043e9062000776565b620004529998979695949392919062000b58565b604051809103906000f0801580156200046f573d6000803e3d6000fd5b506001805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b0319166001600160a01b03831690811790915560405163f2fde38b60e01b81523360048201529192509063f2fde38b90602401600060405180830381600087803b158015620004f857600080fd5b505af11580156200050d573d6000803e3d6000fd5b5050505060008251111562000540576001600160a01b0381166000908152600660205260409020805460ff191660011790555b6200054c838262000645565b62000558828262000645565b60405133906001600160a01b038316907fb49597eb6ae32b938af897f271f3c6f6448014880f91ccee242476f2db9af06c90600090a3505050505050505050565b6000546001600160a01b03163314620002d35760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620003c4565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b815160005b8160ff168160ff1610156200077057838160ff168151811062000671576200067162000bfc565b6020026020010151604001516001600160a01b03166323b872dd3385878560ff1681518110620006a557620006a562000bfc565b602002602001015160000151888660ff1681518110620006c957620006c962000bfc565b602002602001015160200151620006e1919062000c28565b6040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064016020604051808303816000875af115801562000736573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200075c919062000c48565b50620007688162000c68565b90506200064a565b50505050565b6138758062000c8b83390190565b80356001600160a01b03811681146200079c57600080fd5b919050565b600060208284031215620007b457600080fd5b620007bf8262000784565b9392505050565b600060208284031215620007d957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff811182821017156200081c576200081c620007e0565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156200084e576200084e620007e0565b604052919050565b600082601f8301126200086857600080fd5b813567ffffffffffffffff811115620008855762000885620007e0565b6200089a601f8201601f191660200162000822565b818152846020838601011115620008b057600080fd5b816020850160208301376000918101602001919091529392505050565b8015158114620003d857600080fd5b80356200079c81620008cd565b600082601f830112620008fb57600080fd5b8135602067ffffffffffffffff8211156200091a576200091a620007e0565b6200092a818360051b0162000822565b828152606092830285018201928282019190878511156200094a57600080fd5b8387015b858110156200099f5781818a031215620009685760008081fd5b62000972620007f6565b81358152858201358682015260406200098d81840162000784565b9082015284529284019281016200094e565b5090979650505050505050565b600080600080600080600080610100898b031215620009ca57600080fd5b883567ffffffffffffffff80821115620009e357600080fd5b620009f18c838d0162000856565b995060208b013591508082111562000a0857600080fd5b62000a168c838d0162000856565b985060408b013591508082111562000a2d57600080fd5b62000a3b8c838d0162000856565b975060608b0135965060808b0135955062000a5960a08c01620008dc565b945060c08b013591508082111562000a7057600080fd5b62000a7e8c838d01620008e9565b935060e08b013591508082111562000a9557600080fd5b5062000aa48b828c01620008e9565b9150509295985092959890939650565b6000815180845260005b8181101562000adc5760208185018101518683018201520162000abe565b506000602082860101526020601f19601f83011685010191505092915050565b600081518084526020808501945080840160005b8381101562000b4d5781518051885283810151848901526040908101516001600160a01b0316908801526060909601959082019060010162000b10565b509495945050505050565b600061012080835262000b6e8184018d62000ab4565b9050828103602084015262000b84818c62000ab4565b9050828103604084015262000b9a818b62000ab4565b606084018a90526080840189905287151560a08501526001600160a01b03871660c085015283810360e0850152905062000bd5818662000afc565b905082810361010084015262000bec818562000afc565b9c9b505050505050505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b808202811582820484141762000c425762000c4262000c12565b92915050565b60006020828403121562000c5b57600080fd5b8151620007bf81620008cd565b600060ff821660ff810362000c815762000c8162000c12565b6001019291505056fe6101206040523480156200001257600080fd5b506040516200387538038062003875833981016040819052620000359162000593565b6001600160a01b038316608052888089620000596200005362000292565b620002a3565b60016200006783826200073c565b5060026200007682826200073c565b5050506200008a81620002f360201b60201c565b60a052507f05d55ef4a8a7ca3d0b75d9ecd47170a2bf895536707a031d23b6bb013c73f73f60c05284861180620000c057504285105b15620000df5760405163c6e369f960e01b815260040160405180910390fd5b620000e962000292565b600780546001600160a01b0319166001600160a01b0392909216919091179055600b6200011788826200073c565b506009869055600a859055600c805461ff00191661010086151502179055815160ff1660e05260005b60e05160ff168160ff161015620001da57600f838260ff16815181106200016b576200016b62000808565b60209081029190910181015182546001808201855560009485529383902082516003909202019081559181015192820192909255604090910151600290910180546001600160a01b0319166001600160a01b03909216919091179055620001d2816200081e565b905062000140565b50805160ff166101005260005b6101005160ff168160ff16101562000282576010828260ff168151811062000213576200021362000808565b60209081029190910181015182546001808201855560009485529383902082516003909202019081559181015192820192909255604090910151600290910180546001600160a01b0319166001600160a01b039092169190911790556200027a816200081e565b9050620001e7565b505050505050505050506200084c565b60006200029e6200037a565b905090565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8051602091820120604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81850152808201929092527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528151808403909101815260c09092019052805191012090565b6080516000906001600160a01b031633036200039d575060131936013560601c90565b503390565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b0381118282101715620003dd57620003dd620003a2565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200040e576200040e620003a2565b604052919050565b600082601f8301126200042857600080fd5b81516001600160401b03811115620004445762000444620003a2565b60206200045a601f8301601f19168201620003e3565b82815285828487010111156200046f57600080fd5b60005b838110156200048f57858101830151828201840152820162000472565b506000928101909101919091529392505050565b80518015158114620004b457600080fd5b919050565b80516001600160a01b0381168114620004b457600080fd5b600082601f830112620004e357600080fd5b815160206001600160401b03821115620005015762000501620003a2565b62000511818360051b01620003e3565b828152606092830285018201928282019190878511156200053157600080fd5b8387015b85811015620005865781818a0312156200054f5760008081fd5b62000559620003b8565b815181528582015186820152604062000574818401620004b9565b90820152845292840192810162000535565b5090979650505050505050565b60008060008060008060008060006101208a8c031215620005b357600080fd5b89516001600160401b0380821115620005cb57600080fd5b620005d98d838e0162000416565b9a5060208c0151915080821115620005f057600080fd5b620005fe8d838e0162000416565b995060408c01519150808211156200061557600080fd5b620006238d838e0162000416565b985060608c0151975060808c015196506200064160a08d01620004a3565b95506200065160c08d01620004b9565b945060e08c01519150808211156200066857600080fd5b620006768d838e01620004d1565b93506101008c01519150808211156200068e57600080fd5b506200069d8c828d01620004d1565b9150509295985092959850929598565b600181811c90821680620006c257607f821691505b602082108103620006e357634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200073757600081815260208120601f850160051c81016020861015620007125750805b601f850160051c820191505b8181101562000733578281556001016200071e565b5050505b505050565b81516001600160401b03811115620007585762000758620003a2565b6200077081620007698454620006ad565b84620006e9565b602080601f831160018114620007a857600084156200078f5750858301515b600019600386901b1c1916600185901b17855562000733565b600085815260208120601f198616915b82811015620007d957888601518255948401946001909101908401620007b8565b5085821015620007f85787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052603260045260246000fd5b600060ff821660ff81036200084357634e487b7160e01b600052601160045260246000fd5b60010192915050565b60805160a05160c05160e05161010051612fa5620008d0600039600081816104a301528181610b2701528181610dc00152818161137b0152611db10152600081816103e101528181610be2015261198801526000818161036a0152611f0f01526000818161039f015261145401526000818161043801526120e90152612fa56000f3fe608060405234801561001057600080fd5b50600436106102485760003560e01c806371aac7f91161013b578063b88d4fde116100b8578063d5c688d61161007c578063d5c688d614610595578063e6fd48bc146105a2578063e985e9c5146105ab578063f2fde38b146105e7578063f7eca6d0146105fa57600080fd5b8063b88d4fde14610540578063c1292cc314610553578063c44bef751461055c578063c45a01551461056f578063c87b56dd1461058257600080fd5b806395d89b41116100ff57806395d89b41146104fc57806398428dbf146105045780639917840814610511578063a22cb46514610524578063a85adeab1461053757600080fd5b806371aac7f9146104965780637c97853a1461049e5780637df6a6c8146104c55780638da5cb5b146104d8578063902413d0146104e957600080fd5b806330adf81f116101c957806356d9d14b1161018d57806356d9d14b14610415578063572b6c05146104285780636352211e1461046857806370a082311461047b578063715018a61461048e57600080fd5b806330adf81f146103655780633644e5151461039a5780633bbbda65146103c157806342842e0e146103c957806346e51f9a146103dc57600080fd5b80631278e00a116102105780631278e00a1461030157806323b872dd14610314578063242284f114610327578063263c2e341461032f5780633010a8b71461034257600080fd5b806301ffc9a71461024d57806306fdde0314610275578063081812fc1461028a578063095ea7b3146102b55780630962ef79146102ca575b600080fd5b61026061025b366004612696565b61060c565b60405190151581526020015b60405180910390f35b61027d61065e565b60405161026c919061270a565b61029d61029836600461271d565b6106f0565b6040516001600160a01b03909116815260200161026c565b6102c86102c336600461274b565b610717565b005b6102dd6102d836600461271d565b610843565b6040805193845260208401929092526001600160a01b03169082015260600161026c565b6102c861030f366004612777565b61087f565b6102c86103223660046127ba565b6109c7565b6102c86109ff565b6102dd61033d36600461271d565b610baa565b61026061035036600461271d565b600e6020526000908152604090205460ff1681565b61038c7f000000000000000000000000000000000000000000000000000000000000000081565b60405190815260200161026c565b61038c7f000000000000000000000000000000000000000000000000000000000000000081565b6102c8610bba565b6102c86103d73660046127ba565b610c85565b6104037f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff909116815260200161026c565b6102c8610423366004612842565b610ca0565b6102606104363660046128e8565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b61029d61047636600461271d565b61120f565b61038c6104893660046128e8565b61126f565b6102c86112f5565b6102c8611309565b6104037f000000000000000000000000000000000000000000000000000000000000000081565b6102c86104d336600461271d565b61136f565b6000546001600160a01b031661029d565b61038c6104f7366004612905565b611450565b61027d6114b8565b600c546102609060ff1681565b6102c861051f3660046129c3565b6114c7565b6102c8610532366004612a29565b6115c0565b61038c600a5481565b6102c861054e366004612a57565b6115d2565b61038c60085481565b6102c861056a36600461271d565b61160b565b60075461029d906001600160a01b031681565b61027d61059036600461271d565b611674565b6011546102609060ff1681565b61038c60095481565b6102606105b9366004612ad7565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205460ff1690565b6102c86105f53660046128e8565b6116e0565b600c5461026090610100900460ff1681565b60006001600160e01b031982166380ac58cd60e01b148061063d57506001600160e01b03198216635b5e139f60e01b145b8061065857506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606001805461066d90612b05565b80601f016020809104026020016040519081016040528092919081815260200182805461069990612b05565b80156106e65780601f106106bb576101008083540402835291602001916106e6565b820191906000526020600020905b8154815290600101906020018083116106c957829003601f168201915b5050505050905090565b60006106fb82611756565b506000908152600560205260409020546001600160a01b031690565b60006107228261120f565b9050806001600160a01b0316836001600160a01b0316036107945760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b806001600160a01b03166107a66117b5565b6001600160a01b031614806107c257506107c2816105b96117b5565b6108345760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000606482015260840161078b565b61083e83836117c4565b505050565b600f818154811061085357600080fd5b60009182526020909120600390910201805460018201546002909201549092506001600160a01b031683565b6009544210806108905750600a5442115b156108ae5760405163219a945b60e11b815260040160405180910390fd5b600d60006108ba6117b5565b6001600160a01b0316815260208101919091526040016000205460ff16156108f557604051632cfe303760e21b815260040160405180910390fd5b83421115610916576040516305787bdf60e01b815260040160405180910390fd5b6109a16109216117b5565b85858585600760009054906101000a90046001600160a01b03166001600160a01b0316632b7ac3f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610978573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099c9190612b3f565b611832565b6109b16109ac6117b5565b611914565b6109c16109bc6117b5565b611983565b50505050565b6109d86109d26117b5565b82611bf4565b6109f45760405162461bcd60e51b815260040161078b90612b5c565b61083e838383611c73565b600a54421015610a225760405163cc76115360e01b815260040160405180910390fd5b60115460ff1615610a6b5760405162461bcd60e51b8152602060048201526013602482015272526166666c6520616c726561647920646f6e6560681b604482015260640161078b565b610a736117b5565b6001600160a01b03167fe5ed10a2abb6a808edb6fbb7ae5cd09aad196ddaa1bd4e9295688a4d508460c860405160405180910390a26007546040805163aa6527d960e01b815290516000926001600160a01b03169163aa6527d99160048083019260209291908290030181865afa158015610af2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b169190612b3f565b6040516315be9e9160e11b815260ff7f00000000000000000000000000000000000000000000000000000000000000001660048201529091506001600160a01b03821690632b7d3d22906024016020604051808303816000875af1158015610b82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ba69190612ba9565b5050565b6010818154811061085357600080fd5b600a54421015610bdd5760405163cc76115360e01b815260040160405180910390fd5b60005b7f000000000000000000000000000000000000000000000000000000000000000060ff168160ff161015610c5957610c49600f8260ff1681548110610c2757610c27612bc2565b60009182526020909120600260039092020101546001600160a01b0316611ca7565b610c5281612bee565b9050610be0565b506040517f7f55430b29ae5a8c80e07c8bcba9b96d9a4904baff6645f7b6f1941ac53c736590600090a1565b61083e838383604051806020016040528060008152506115d2565b600a54421015610cc35760405163cc76115360e01b815260040160405180910390fd5b600760009054906101000a90046001600160a01b03166001600160a01b031663aa6527d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3a9190612b3f565b6001600160a01b0316610d4b6117b5565b6001600160a01b031614610d725760405163712a092360e01b815260040160405180910390fd5b60115460ff1615610dbb5760405162461bcd60e51b8152602060048201526013602482015272526166666c6520616c726561647920646f6e6560681b604482015260640161078b565b60005b7f000000000000000000000000000000000000000000000000000000000000000060ff168160ff1610156111cd576000828260ff1681518110610e0357610e03612bc2565b60200260200101519050600060108360ff1681548110610e2557610e25612bc2565b60009182526020822060026003909202010154601080546001600160a01b0390921693509060ff8616908110610e5d57610e5d612bc2565b9060005260206000209060030201600101549050600082905060008060108760ff1681548110610e8f57610e8f612bc2565b90600052602060002090600302016000015490508060085411610fa15760015b6008548111610f9b576000610ec38261120f565b60405163a9059cbb60e01b81526001600160a01b038083166004830152602482018990529192509086169063a9059cbb906044016020604051808303816000875af1158015610f16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3a9190612c0d565b50866001600160a01b0316816001600160a01b03167f80b887c8189ccc457f4b3077692f6d6d11abc05537566d3273df1747af53495488604051610f8091815260200190565b60405180910390a35080610f9381612c2a565b915050610eaf565b506111b4565b60005b818110156111b25760005b60085460408051602081018b90529081018690524260608201526080016040516020818303038152906040528051906020012060001c610fef9190612c43565b610ffa906001612c65565b90508361100681612c2a565b945050600e6000828b60405160200161103692919091825260f81b6001600160f81b031916602082015260210190565b60408051601f198184030181529181528151602092830120835290820192909252016000205460ff16610faf576001600e6000838c60405160200161109292919091825260f81b6001600160f81b031916602082015260210190565b60405160208183030381529060405280519060200120815260200190815260200160002060006101000a81548160ff02191690831515021790555060006110d88261120f565b60405163a9059cbb60e01b81526001600160a01b038083166004830152602482018a90529192509087169063a9059cbb906044016020604051808303816000875af115801561112b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114f9190612c0d565b50876001600160a01b0316816001600160a01b03167f80b887c8189ccc457f4b3077692f6d6d11abc05537566d3273df1747af5349548960405161119591815260200190565b60405180910390a3505080806111aa90612c2a565b915050610fa4565b505b50505050505080806111c590612bee565b915050610dbe565b506011805460ff191660011790556040517f27570828a3b3d654a69144a8ca6c7e066e01acd2e5c41405c83fa9f03011831290600090a161120c611dac565b50565b6000818152600360205260408120546001600160a01b0316806106585760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604482015260640161078b565b60006001600160a01b0382166112d95760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b606482015260840161078b565b506001600160a01b031660009081526004602052604090205490565b6112fd611e32565b6113076000611eab565b565b60095442108061131a5750600a5442115b156113385760405163219a945b60e11b815260040160405180910390fd5b611340611e32565b42600a556040517f434b671a95fb0071b0127874981939c3cd42e8f1f7d602b761482102d4a5507290600090a1565b611377611e32565b60ff7f000000000000000000000000000000000000000000000000000000000000000016156113f75760405162461bcd60e51b815260206004820152602660248201527f43616e2774206368616e676520656e642074696d657374616d7020666f7220726044820152656166666c657360d01b606482015260840161078b565b4281118015611407575060095481115b61144b5760405162461bcd60e51b81526020600482015260156024820152740496e76616c696420656e642074696d657374616d7605c1b604482015260640161078b565b600a55565b60007f000000000000000000000000000000000000000000000000000000000000000061147c83611efb565b60405161190160f01b6020820152602281019290925260428201526062015b604051602081830303815290604052805190602001209050919050565b60606002805461066d90612b05565b600760009054906101000a90046001600160a01b03166001600160a01b031663aced16616040518163ffffffff1660e01b8152600401602060405180830381865afa15801561151a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153e9190612b3f565b6001600160a01b031661154f6117b5565b6001600160a01b03161415801561158157506000546001600160a01b03166115756117b5565b6001600160a01b031614155b1561159f57604051637d7b71b560e01b815260040160405180910390fd5b600b6115ab8382612cc6565b50600c805460ff191691151591909117905550565b610ba66115cb6117b5565b8383611f51565b6115e36115dd6117b5565b83611bf4565b6115ff5760405162461bcd60e51b815260040161078b90612b5c565b6109c18484848461201f565b611613611e32565b80421080156116235750600a5481105b61166f5760405162461bcd60e51b815260206004820152601760248201527f496e76616c69642073746172742074696d657374616d70000000000000000000604482015260640161078b565b600955565b606061167f82611756565b600c5460ff166116af57600b60405160200161169b9190612df9565b604051602081830303815290604052610658565b600b6116ba83612052565b6040516020016116cb929190612e23565b60405160208183030381529060405292915050565b6116e8611e32565b6001600160a01b03811661174d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161078b565b61120c81611eab565b6000818152600360205260409020546001600160a01b031661120c5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604482015260640161078b565b60006117bf6120e5565b905090565b600081815260056020526040902080546001600160a01b0319166001600160a01b03841690811790915581906117f98261120f565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061185a6040518060400160405280896001600160a01b0316815260200188815250611450565b90506000600161186983612129565b6040805160008152602081018083529290925260ff891690820152606081018790526080810186905260a0016020604051602081039080840390855afa1580156118b7573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615806118ec5750826001600160a01b0316816001600160a01b031614155b1561190a57604051638baa579f60e01b815260040160405180910390fd5b5050505050505050565b6119318160086000815461192790612c2a565b9182905550612164565b6001600160a01b0381166000818152600d6020526040808220805460ff1916600117905560085490519092917fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a91a350565b60005b7f000000000000000000000000000000000000000000000000000000000000000060ff168160ff161015610ba6576000600f8260ff16815481106119cc576119cc612bc2565b60009182526020822060026003909202010154600f80546001600160a01b0390921693509060ff8516908110611a0457611a04612bc2565b600091825260208220600160039092020101546040516370a0823160e01b81523060048201529092506001600160a01b038416906370a0823190602401602060405180830381865afa158015611a5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a829190612ba9565b8211159050600f8460ff1681548110611a9d57611a9d612bc2565b906000526020600020906003020160000154600014158015611abc5750805b15611bde5760405163a9059cbb60e01b81526001600160a01b0386811660048301526024820184905284169063a9059cbb906044016020604051808303816000875af1158015611b10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b349190612c0d565b50600f8460ff1681548110611b4b57611b4b612bc2565b6000918252602091829020600390910201600201546040518481526001600160a01b0391821692918816917f2b5a46847b5904937aa26c09373883ac411399d3404814f716b47721af04ff4f910160405180910390a3600f8460ff1681548110611bb757611bb7612bc2565b600091825260208220600390910201805491611bd283612e67565b91905055505050505050565b5050508080611bec90612bee565b915050611986565b600080611c008361120f565b9050806001600160a01b0316846001600160a01b03161480611c4757506001600160a01b0380821660009081526006602090815260408083209388168352929052205460ff165b80611c6b5750836001600160a01b0316611c60846106f0565b6001600160a01b0316145b949350505050565b600c54610100900460ff1615611c9c576040516354ee515160e01b815260040160405180910390fd5b61083e83838361217e565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015611cee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d129190612ba9565b90508015610ba657816001600160a01b031663a9059cbb611d3b6000546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303816000875af1158015611d88573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061083e9190612c0d565b60005b7f000000000000000000000000000000000000000000000000000000000000000060ff168160ff161015611e0657611df660108260ff1681548110610c2757610c27612bc2565b611dff81612bee565b9050611daf565b506040517ff54a6d4a21d85c024952c8d95373adfbb78b39d0cdcc90236722b6343c525c5a90600090a1565b611e3a6117b5565b6001600160a01b0316611e556000546001600160a01b031690565b6001600160a01b0316146113075760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161078b565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b805160208083015160405160009361149b937f0000000000000000000000000000000000000000000000000000000000000000939192019283526001600160a01b03919091166020830152604082015260600190565b816001600160a01b0316836001600160a01b031603611fb25760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015260640161078b565b6001600160a01b03838116600081815260066020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b61202a848484611c73565b612036848484846122e2565b6109c15760405162461bcd60e51b815260040161078b90612e7e565b6060600061205f836123ea565b600101905060008167ffffffffffffffff81111561207f5761207f6127fb565b6040519080825280601f01601f1916602001820160405280156120a9576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a85049450846120b357509392505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303612124575060131936013560601c90565b503390565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c0161149b565b610ba68282604051806020016040528060008152506124c2565b826001600160a01b03166121918261120f565b6001600160a01b0316146121b75760405162461bcd60e51b815260040161078b90612ed0565b6001600160a01b0382166122195760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b606482015260840161078b565b826001600160a01b031661222c8261120f565b6001600160a01b0316146122525760405162461bcd60e51b815260040161078b90612ed0565b600081815260056020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260048552838620805460001901905590871680865283862080546001019055868652600390945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b60006001600160a01b0384163b156123df57836001600160a01b031663150b7a0261230b6117b5565b8786866040518563ffffffff1660e01b815260040161232d9493929190612f15565b6020604051808303816000875af1925050508015612368575060408051601f3d908101601f1916820190925261236591810190612f52565b60015b6123c5573d808015612396576040519150601f19603f3d011682016040523d82523d6000602084013e61239b565b606091505b5080516000036123bd5760405162461bcd60e51b815260040161078b90612e7e565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611c6b565b506001949350505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106124295772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310612455576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061247357662386f26fc10000830492506010015b6305f5e100831061248b576305f5e100830492506008015b612710831061249f57612710830492506004015b606483106124b1576064830492506002015b600a83106106585760010192915050565b6124cc83836124f5565b6124d960008484846122e2565b61083e5760405162461bcd60e51b815260040161078b90612e7e565b6001600160a01b03821661254b5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161078b565b6000818152600360205260409020546001600160a01b0316156125b05760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161078b565b6000818152600360205260409020546001600160a01b0316156126155760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161078b565b6001600160a01b038216600081815260046020908152604080832080546001019055848352600390915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6001600160e01b03198116811461120c57600080fd5b6000602082840312156126a857600080fd5b81356126b381612680565b9392505050565b60005b838110156126d55781810151838201526020016126bd565b50506000910152565b600081518084526126f68160208601602086016126ba565b601f01601f19169290920160200192915050565b6020815260006126b360208301846126de565b60006020828403121561272f57600080fd5b5035919050565b6001600160a01b038116811461120c57600080fd5b6000806040838503121561275e57600080fd5b823561276981612736565b946020939093013593505050565b6000806000806080858703121561278d57600080fd5b84359350602085013560ff811681146127a557600080fd5b93969395505050506040820135916060013590565b6000806000606084860312156127cf57600080fd5b83356127da81612736565b925060208401356127ea81612736565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561283a5761283a6127fb565b604052919050565b6000602080838503121561285557600080fd5b823567ffffffffffffffff8082111561286d57600080fd5b818501915085601f83011261288157600080fd5b813581811115612893576128936127fb565b8060051b91506128a4848301612811565b81815291830184019184810190888411156128be57600080fd5b938501935b838510156128dc578435825293850193908501906128c3565b98975050505050505050565b6000602082840312156128fa57600080fd5b81356126b381612736565b60006040828403121561291757600080fd5b6040516040810181811067ffffffffffffffff8211171561293a5761293a6127fb565b604052823561294881612736565b81526020928301359281019290925250919050565b600067ffffffffffffffff831115612977576129776127fb565b61298a601f8401601f1916602001612811565b905082815283838301111561299e57600080fd5b828260208301376000602084830101529392505050565b801515811461120c57600080fd5b600080604083850312156129d657600080fd5b823567ffffffffffffffff8111156129ed57600080fd5b8301601f810185136129fe57600080fd5b612a0d8582356020840161295d565b9250506020830135612a1e816129b5565b809150509250929050565b60008060408385031215612a3c57600080fd5b8235612a4781612736565b91506020830135612a1e816129b5565b60008060008060808587031215612a6d57600080fd5b8435612a7881612736565b93506020850135612a8881612736565b925060408501359150606085013567ffffffffffffffff811115612aab57600080fd5b8501601f81018713612abc57600080fd5b612acb8782356020840161295d565b91505092959194509250565b60008060408385031215612aea57600080fd5b8235612af581612736565b91506020830135612a1e81612736565b600181811c90821680612b1957607f821691505b602082108103612b3957634e487b7160e01b600052602260045260246000fd5b50919050565b600060208284031215612b5157600080fd5b81516126b381612736565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b600060208284031215612bbb57600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060ff821660ff8103612c0457612c04612bd8565b60010192915050565b600060208284031215612c1f57600080fd5b81516126b3816129b5565b600060018201612c3c57612c3c612bd8565b5060010190565b600082612c6057634e487b7160e01b600052601260045260246000fd5b500690565b8082018082111561065857610658612bd8565b601f82111561083e57600081815260208120601f850160051c81016020861015612c9f5750805b601f850160051c820191505b81811015612cbe57828155600101612cab565b505050505050565b815167ffffffffffffffff811115612ce057612ce06127fb565b612cf481612cee8454612b05565b84612c78565b602080601f831160018114612d295760008415612d115750858301515b600019600386901b1c1916600185901b178555612cbe565b600085815260208120601f198616915b82811015612d5857888601518255948401946001909101908401612d39565b5085821015612d765787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008154612d9381612b05565b60018281168015612dab5760018114612dc057612def565b60ff1984168752821515830287019450612def565b8560005260208060002060005b85811015612de65781548a820152908401908201612dcd565b50505082870194505b5050505092915050565b6000612e058284612d86565b6d17b6b2ba30b230ba30973539b7b760911b8152600e019392505050565b6000612e2f8285612d86565b602f60f81b81528351612e498160018401602088016126ba565b64173539b7b760d91b60019290910191820152600601949350505050565b600081612e7657612e76612bd8565b506000190190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612f48908301846126de565b9695505050505050565b600060208284031215612f6457600080fd5b81516126b38161268056fea26469706673582212206b9ba6c88e39c8076fec85732794044f57536c74e3d4863b0fdf6ccecb31db0e64736f6c63430008150033a26469706673582212209036c166991b7ec8ec84b16ee58f5554cb963a27541d9545437c87ccd4965c2f64736f6c63430008150033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000607291c9b3b03d8c2dc1f5f7f8db2b6a06c91183000000000000000000000000dead00000000000000000000000000000000dead00000000000000000000000075d14f0ae59003c0806b625b402a40340ffde63400000000000000000000000075d14f0ae59003c0806b625b402a40340ffde634
-----Decoded View---------------
Arg [0] : _keeper (address): 0x607291C9B3b03D8C2DC1F5f7F8db2B6A06C91183
Arg [1] : _trustedForwarder (address): 0xdeAD00000000000000000000000000000000dEAd
Arg [2] : _verifier (address): 0x75d14F0Ae59003C0806B625B402a40340Ffde634
Arg [3] : _raffleManager (address): 0x75d14F0Ae59003C0806B625B402a40340Ffde634
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000607291c9b3b03d8c2dc1f5f7f8db2b6a06c91183
Arg [1] : 000000000000000000000000dead00000000000000000000000000000000dead
Arg [2] : 00000000000000000000000075d14f0ae59003c0806b625b402a40340ffde634
Arg [3] : 00000000000000000000000075d14f0ae59003c0806b625b402a40340ffde634
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 25 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.