Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 125 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Claim Airdrop | 14507096 | 966 days ago | IN | 0 ETH | 0.0015693 | ||||
Claim Airdrop | 14507093 | 966 days ago | IN | 0 ETH | 0.00154112 | ||||
Pause | 14497981 | 967 days ago | IN | 0 ETH | 0.00443017 | ||||
Purchase Tokens | 14495318 | 968 days ago | IN | 0 ETH | 0.00865411 | ||||
Withdraw All Tok... | 14495128 | 968 days ago | IN | 0 ETH | 0.01107099 | ||||
Purchase Tokens | 14494468 | 968 days ago | IN | 0 ETH | 0.01356398 | ||||
Purchase Tokens | 14492293 | 968 days ago | IN | 0 ETH | 0.00513034 | ||||
Purchase Tokens | 14491428 | 968 days ago | IN | 0 ETH | 0.00554618 | ||||
Claim Airdrop | 14491103 | 968 days ago | IN | 0 ETH | 0.0028393 | ||||
Purchase Tokens | 14484274 | 969 days ago | IN | 0 ETH | 0.00441529 | ||||
Purchase Tokens | 14479681 | 970 days ago | IN | 0 ETH | 0.00447705 | ||||
Purchase Tokens | 14479655 | 970 days ago | IN | 0 ETH | 0.00383523 | ||||
Purchase Tokens | 14479302 | 970 days ago | IN | 0 ETH | 0.00459822 | ||||
Purchase Tokens | 14476813 | 970 days ago | IN | 0 ETH | 0.00896974 | ||||
Purchase Tokens | 14476782 | 970 days ago | IN | 0 ETH | 0.00422366 | ||||
Purchase Tokens | 14476782 | 970 days ago | IN | 0 ETH | 0.00981024 | ||||
Purchase Tokens | 14476581 | 970 days ago | IN | 0 ETH | 0.01392066 | ||||
Set Rate | 14476394 | 971 days ago | IN | 0 ETH | 0.00344429 | ||||
Purchase Tokens | 14474243 | 971 days ago | IN | 0 ETH | 0.00344006 | ||||
Purchase Tokens | 14460306 | 973 days ago | IN | 0 ETH | 0.00553796 | ||||
Purchase Tokens | 14460033 | 973 days ago | IN | 0 ETH | 0.00393221 | ||||
Set Rate | 14458969 | 973 days ago | IN | 0 ETH | 0.00220615 | ||||
Purchase Tokens | 14445393 | 975 days ago | IN | 0 ETH | 0.00619183 | ||||
Purchase Tokens | 14445351 | 975 days ago | IN | 0 ETH | 0.00934166 | ||||
Purchase Tokens | 14440253 | 976 days ago | IN | 0 ETH | 0.00503614 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
MembershipContract
Compiler Version
v0.8.7+commit.e28d00a7
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/utils/math/SafeMath.sol"; import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; import "@openzeppelin/contracts/security/Pausable.sol"; import "@chainlink/contracts/src/v0.8/ChainlinkClient.sol"; /// @notice Contract for facilitating a whitelisted airdrop and token sale contract MembershipContract is Pausable, ChainlinkClient { using Chainlink for Chainlink.Request; using SafeMath for uint256; using SafeERC20 for IERC20; /*/////////////////////////////////////////////////////////////// IMMUTABLE STORAGE //////////////////////////////////////////////////////////////*/ bytes32 public immutable merkleRoot; /*/////////////////////////////////////////////////////////////// MUTABLE STORAGE //////////////////////////////////////////////////////////////*/ address public owner; address public usdcTokenContract; address public gcrTokenContract; address public linkTokenContract; IERC20 public usdcToken; IERC20 public gcrToken; IERC20 public linkToken; uint256 public rate; // rate of exchange between GCR and USDC uint256 public airdropAmount; // airdrop amount that qualified members can claim // various tiers uint256 public proTier; uint256 public midTier; uint256 public baseTier; // chainlink oracle params address private oracle; bytes32 private jobId; uint256 private oracleFee; string public priceFeedURI; string public priceFeedPath; // need parameters around validity window of sale (start + end times). also should be able to be adjusted by owner // mapping for eligible airdrop recipients mapping (address => bool) private _hasClaimedAirdrop; // mapping for those who are entitled to purchasing tokens at a discount mapping (address => uint256) private _purchasedAmount; /*/////////////////////////////////////////////////////////////// ERRORS //////////////////////////////////////////////////////////////*/ /// @notice Thrown if address has already claimed error AlreadyClaimed(); /// @notice Thrown if address/amount are not part of Merkle tree error NotInMerkle(); /*/////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event ClaimAirdrop(address indexed claimant, uint256 amount); event Purchase(address indexed claimaint, uint256 amount); event SetOwner(address indexed prevOwner, address indexed newOwner); event SetRate(address indexed owner, uint256 oldRate, uint256 newRate); event WithdrawAll(address indexed owner); event WithdrawToken(address indexed owner, address indexed token); /*/////////////////////////////////////////////////////////////// MODIFIERS //////////////////////////////////////////////////////////////*/ modifier onlyOwner() { require(owner == msg.sender, "Function is only callable by the owner"); _; } /*/////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ // @dev assume we initialize this contract with arrays with addresses <> balances matched up at the same index, // though this may be costly constructor( bytes32 _merkleRoot, address _usdcTokenContract, address _gcrTokenContract, address _linkTokenContract, address _oracle, string memory _jobId, uint256 _oracleFee, string memory _priceFeedURI, string memory _priceFeedPath ) { owner = msg.sender; merkleRoot = _merkleRoot; usdcTokenContract = _usdcTokenContract; usdcToken = IERC20(_usdcTokenContract); gcrTokenContract = _gcrTokenContract; gcrToken = IERC20(_gcrTokenContract); linkTokenContract = _linkTokenContract; linkToken = IERC20(_linkTokenContract); rate = 350; // # USDC required for 1 GCR in base units airdropAmount = 1600000; // 160 GCR proTier = 20000000; // 2000 GCR midTier = 7000000; // 700 GCR baseTier = 1000000; // 100 GCR // Oracle setup oracle = _oracle; jobId = stringToBytes32(_jobId); oracleFee = _oracleFee; priceFeedURI = _priceFeedURI; priceFeedPath = _priceFeedPath; setChainlinkToken(_linkTokenContract); } /*/////////////////////////////////////////////////////////////// AIRDROP + PURCHASE FUNCTIONALITY //////////////////////////////////////////////////////////////*/ // @dev Claim airdrop, only for those with > 2000 balance. // Note: only claimable to msg.sender so that people can't claim airdrops on behalf of others // examples of how to do such crowdsales: https://docs.openzeppelin.com/contracts/2.x/crowdsales // @return success (bool) function claimAirdrop(uint256 snapshotAmount, bytes32[] memory proof) public whenNotPaused returns (bool success){ require(!checkAirdropClaimed(msg.sender), "Airdrop already claimed"); require(_purchasedAmount[msg.sender] == 0, "You've begun purchasing tokens"); // this should not be possible, per logic require(verifyMerkleProof(msg.sender, snapshotAmount, proof), "Ineligible"); _hasClaimedAirdrop[msg.sender] = true; gcrToken.safeTransfer(msg.sender, airdropAmount); // this should guard against the case where balance is insufficient emit ClaimAirdrop(msg.sender, airdropAmount); success = true; } // @dev Purchase GCR tokens in exchange for USDC // purchasing tokens will require the user to approve the token (USDC) for spending with this dapp // @param amount (uint256): desired amount of GCR, in base units // example: you want to buy 1600 GCR at 3.50 USDC each. you transfer 1600 * 3.50 USDC, get back 1600 GCR. function purchaseTokens(uint256 purchaseAmount, uint256 snapshotAmount, bytes32[] memory proof) public whenNotPaused returns (bool success) { require(!checkAirdropClaimed(msg.sender), "Airdrop claimed. Ineligible for purchase"); require(verifyMerkleProof(msg.sender, snapshotAmount, proof), "Ineligible"); require(snapshotAmount >= baseTier, "Insufficient tokens to participate in purchase"); // 100 whole unit requirement require(snapshotAmount <= proTier, "Ineligible to participate in purchase. See airdrop instead"); // 2000 whole unit maximum uint256 allocation; uint256 usdcCost; if (snapshotAmount >= 3500000) { // < 2000 due to the above require case, >= 350 tokens // entitled to 2000 - amount allocation = remainingAllocation(msg.sender, snapshotAmount, proof); require(purchaseAmount <= allocation, "Attempting to buy more than allocation"); usdcCost = purchaseAmount * rate; conductTrade(msg.sender, usdcCost, purchaseAmount); } else if (snapshotAmount >= baseTier) { // < 300, >= 100 tokens // entitled to 700 - amount allocation = remainingAllocation(msg.sender, snapshotAmount, proof); require(purchaseAmount <= allocation, "Attempting to buy more than allocation"); usdcCost = purchaseAmount * rate; conductTrade(msg.sender, usdcCost, purchaseAmount); } else { // < 100 tokens // we shouldn't reach this case given we have that require statement above; ineligible to participate } emit Purchase(msg.sender, purchaseAmount); success = true; } // @dev Helper function that facilitates purchases + movement of funds // Note: purchasing tokens will require the user to approve the token (USDC) for spending with this dapp // @param buyer (address): address that will be spending USDC in exchange for GCR // @param GCRAmount (uint256): desired amount of GCR, in base units // @param USDCAmount (uint256): USDC being spent, in base units // @return success (bool) function conductTrade(address buyer, uint256 USDCAmount, uint256 GCRAmount) internal returns (bool success) { checkUSDCAllowance(buyer, USDCAmount); // send USDC tokens from buyer to contract usdcToken.safeTransferFrom(buyer, address(this), USDCAmount); // send tokens from contract to buyer; maybe we can specify a separate recipient gcrToken.safeTransfer(buyer, GCRAmount); // update state _purchasedAmount[buyer] += GCRAmount; success = true; } /*/////////////////////////////////////////////////////////////// ADMIN FUNCTIONS (note owner == admin) //////////////////////////////////////////////////////////////*/ // @dev Update the owner of the contract (admin only) // @param newOwner (address) function setOwner(address newOwner) onlyOwner external { // prevent accidentally making this contract inaccessible require(newOwner != address(0)); // prevent unnecessary change require(newOwner != owner); emit SetOwner(owner, newOwner); owner = newOwner; } // @dev Update the exchange rate between USDC <> GCR (admin only). // Note that this is in the form of USDC per GCR in base units function setRate(uint256 usdcPerToken) onlyOwner external { require(usdcPerToken > 0, "Rejecting a 0 rate"); emit SetRate(owner, rate, usdcPerToken); rate = usdcPerToken; } // @dev Withdraw allows admin to return all funds (USDC, GCR, ETH) to admin address // @return success (bool) function withdrawAllTokens() onlyOwner public returns (bool success) { if (usdcToken.balanceOf(address(this)) > 0) { usdcToken.safeTransfer(owner, usdcToken.balanceOf(address(this))); } if (gcrToken.balanceOf(address(this)) > 0) { gcrToken.safeTransfer(owner, gcrToken.balanceOf(address(this))); } if (linkToken.balanceOf(address(this)) > 0) { linkToken.safeTransfer(owner, linkToken.balanceOf(address(this))); } if (address(this).balance > 0) { payable(owner).transfer(address(this).balance); } emit WithdrawAll(owner); success = true; } // @dev Withdraw specific token contract to admin address // @return success (bool) function withdrawToken(address tokenAddress) onlyOwner public returns (bool success) { IERC20 token = IERC20(tokenAddress); if (token.balanceOf(address(this)) > 0) { token.safeTransfer(owner, token.balanceOf(address(this))); } emit WithdrawToken(owner, tokenAddress); success = true; } function pause() onlyOwner public { _pause(); } function unpause() onlyOwner public { _unpause(); } /*/////////////////////////////////////////////////////////////// EXTERNAL GETTERS //////////////////////////////////////////////////////////////*/ // @dev Check if participant has claimed airdrop // @param participant (address) // @return bool function checkAirdropClaimed(address participant) public view returns (bool) { return _hasClaimedAirdrop[participant]; } // // @dev Check if participant is eligible to claim airdrop // @param participant (address) // @return bool function checkAirdropEligibility(address participant, uint256 amount, bytes32[] memory proof) public view returns (bool) { require(verifyMerkleProof(participant, amount, proof), "Ineligible"); return amount >= proTier; } // @dev Check if participant is eligible for discounted token sale // @param participant (address) // @return bool function checkPurchaseEligibility(address participant, uint256 amount, bytes32[] memory proof) public view returns (bool) { return initialAllocation(participant, amount, proof) > 0; } // @dev Public function that returns the total initial purchase allocation for participant. // Allocation is dependent upon initial snapshot values, which are determined at deployment time. // @param participant (address) // @return allocation (uint256) function initialAllocation(address participant, uint256 amount, bytes32[] memory proof) public view returns (uint256 allocation) { require(verifyMerkleProof(participant, amount, proof), "Ineligible"); if (amount > proTier) { // > 2000 // no allocation; eligible for airdrop instead allocation = 0; } else if (amount >= 3500000) { // <= 2000, >= 350 tokens // entitled to 2000 - amount allocation = proTier - amount; } else if (amount >= baseTier) { // < 300, >= 100 tokens // entitled to 700 - amount allocation = midTier - amount; } else { // < 100 tokens allocation = 0; // we can also return -1 if that better indicates that the address wasn't eligible in the first place (insufficienrt funds) } } // @dev Public function that returns the purchased allocation for participant. // @param participant (address) // @return allocation (uint256) function purchasedAllocation(address participant) public view returns (uint256 purchasedAmount) { purchasedAmount = _purchasedAmount[participant]; } // @dev Public function that returns the remaining allocation for participant. // Remaining allocation is dependent upon initial snapshot values, user tier, and amount already claimed. // @param participant (address) // @return allocation (uint256) function remainingAllocation(address participant, uint256 amount, bytes32[] memory proof) public view returns (uint256 allocation) { require(verifyMerkleProof(participant, amount, proof), "Ineligible"); uint256 purchasedAmount = _purchasedAmount[participant]; uint256 initial = initialAllocation(participant, amount, proof); allocation = initial - purchasedAmount; // should never be negative } /*/////////////////////////////////////////////////////////////// HELPERS //////////////////////////////////////////////////////////////*/ // @dev Helper function that ensures USDC spend allowance by this contract is sufficient // @param _participant (address): spender // @param _amount (uint256): amount to be spent // @return allowed (bool) function checkUSDCAllowance(address _participant, uint256 _amount) internal view returns (bool allowed) { uint256 allowance = usdcToken.allowance(_participant, address(this)); require(allowance >= _amount, "Insufficient token allowance"); allowed = true; } function verifyMerkleProof(address _address, uint256 _amount, bytes32[] memory _proof) internal view returns (bool valid) { // Verify merkle proof, or revert if not in tree bytes32 leaf = keccak256(abi.encodePacked(_address, _amount)); bool isValidLeaf = MerkleProof.verify(_proof, merkleRoot, leaf); if (!isValidLeaf) revert NotInMerkle(); valid = true; } function stringToBytes32(string memory source) public pure returns (bytes32 result) { bytes memory tempEmptyStringTest = bytes(source); if (tempEmptyStringTest.length == 0) { return 0x0; } assembly { result := mload(add(source, 32)) } } function stringEquals(string memory a, string memory b) internal pure returns (bool) { return keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b)); } /*/////////////////////////////////////////////////////////////// ORACLE //////////////////////////////////////////////////////////////*/ function updateChainlinkTokenContract(address _newChainlinkTokenContract) onlyOwner public { require(linkTokenContract != _newChainlinkTokenContract, "Using the same token"); linkTokenContract = _newChainlinkTokenContract; } function updateChainlinkOracle(address _newOracle) onlyOwner public { require(oracle != _newOracle, "Using the same oracle"); oracle = _newOracle; } function updateOracleFee(uint256 _newOracleFee) onlyOwner public { require(oracleFee != _newOracleFee, "Using the same oracleFee"); oracleFee = _newOracleFee; } function updateChainlinkJobId(bytes32 _newJobId) onlyOwner public { require(jobId != _newJobId, "Using the same jobId"); jobId = _newJobId; } function updatePriceFeedURI(string memory _newPriceFeedURI) onlyOwner public { require(!stringEquals(priceFeedURI, _newPriceFeedURI), "Using the same priceFeedURI"); priceFeedURI = _newPriceFeedURI; } function updatePriceFeedPath(string memory _newPriceFeedPath) onlyOwner public { require(!stringEquals(priceFeedPath, _newPriceFeedPath), "Using the same priceFeedPath"); priceFeedPath = _newPriceFeedPath; } // @dev Helper function that allows the USDC / SAMP rate to be updated // Must be able to handle errors/faulty API responses // @return requestId (bytes32) function requestPriceData() public returns (bytes32 requestId) { Chainlink.Request memory request = buildChainlinkRequest(jobId, address(this), this.fulfill.selector); // GET request for token price on Ethereum request.add("get", priceFeedURI); // Set the path to find the desired data in the API response, where the response format is: // { // "0x6307b25a665efc992ec1c1bc403c38f3ddd7c661": { // "usd": x.xx // } // } request.add("path", priceFeedPath); // Multiply the result by 100 to get to an amount in cents // Note that this also aligns with the units for general USDC / GCR token exchange int timesAmount = 100; request.addInt("times", timesAmount); // Sends the request return sendChainlinkRequestTo(oracle, request, oracleFee); } /** * Receive the response in the form of uint256 */ function fulfill(bytes32 _requestId, uint256 _rate) public recordChainlinkFulfillment(_requestId) { if (_rate >= 400) { rate = _rate * 9 / 10; } else { rate = 350; } } /*/////////////////////////////////////////////////////////////// FALLBACK //////////////////////////////////////////////////////////////*/ fallback() external payable {} receive() external payable {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/cryptography/MerkleProof.sol) pragma solidity ^0.8.0; /** * @dev These functions deal with verification of Merkle Trees proofs. * * The proofs can be generated using the JavaScript library * https://github.com/miguelmota/merkletreejs[merkletreejs]. * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled. * * See `test/utils/cryptography/MerkleProof.test.js` for some examples. */ library MerkleProof { /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify( bytes32[] memory proof, bytes32 root, bytes32 leaf ) internal pure returns (bool) { return processProof(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merklee tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leafs & pre-images are assumed to be sorted. * * _Available since v4.4._ */ function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { bytes32 proofElement = proof[i]; if (computedHash <= proofElement) { // Hash(current computed hash + current element of the proof) computedHash = keccak256(abi.encodePacked(computedHash, proofElement)); } else { // Hash(current element of the proof + current computed hash) computedHash = keccak256(abi.encodePacked(proofElement, computedHash)); } } return computedHash; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./Chainlink.sol"; import "./interfaces/ENSInterface.sol"; import "./interfaces/LinkTokenInterface.sol"; import "./interfaces/ChainlinkRequestInterface.sol"; import "./interfaces/OperatorInterface.sol"; import "./interfaces/PointerInterface.sol"; import {ENSResolver as ENSResolver_Chainlink} from "./vendor/ENSResolver.sol"; /** * @title The ChainlinkClient contract * @notice Contract writers can inherit this contract in order to create requests for the * Chainlink network */ abstract contract ChainlinkClient { using Chainlink for Chainlink.Request; uint256 internal constant LINK_DIVISIBILITY = 10**18; uint256 private constant AMOUNT_OVERRIDE = 0; address private constant SENDER_OVERRIDE = address(0); uint256 private constant ORACLE_ARGS_VERSION = 1; uint256 private constant OPERATOR_ARGS_VERSION = 2; bytes32 private constant ENS_TOKEN_SUBNAME = keccak256("link"); bytes32 private constant ENS_ORACLE_SUBNAME = keccak256("oracle"); address private constant LINK_TOKEN_POINTER = 0xC89bD4E1632D3A43CB03AAAd5262cbe4038Bc571; ENSInterface private s_ens; bytes32 private s_ensNode; LinkTokenInterface private s_link; OperatorInterface private s_oracle; uint256 private s_requestCount = 1; mapping(bytes32 => address) private s_pendingRequests; event ChainlinkRequested(bytes32 indexed id); event ChainlinkFulfilled(bytes32 indexed id); event ChainlinkCancelled(bytes32 indexed id); /** * @notice Creates a request that can hold additional parameters * @param specId The Job Specification ID that the request will be created for * @param callbackAddr address to operate the callback on * @param callbackFunctionSignature function signature to use for the callback * @return A Chainlink Request struct in memory */ function buildChainlinkRequest( bytes32 specId, address callbackAddr, bytes4 callbackFunctionSignature ) internal pure returns (Chainlink.Request memory) { Chainlink.Request memory req; return req.initialize(specId, callbackAddr, callbackFunctionSignature); } /** * @notice Creates a request that can hold additional parameters * @param specId The Job Specification ID that the request will be created for * @param callbackFunctionSignature function signature to use for the callback * @return A Chainlink Request struct in memory */ function buildOperatorRequest(bytes32 specId, bytes4 callbackFunctionSignature) internal view returns (Chainlink.Request memory) { Chainlink.Request memory req; return req.initialize(specId, address(this), callbackFunctionSignature); } /** * @notice Creates a Chainlink request to the stored oracle address * @dev Calls `chainlinkRequestTo` with the stored oracle address * @param req The initialized Chainlink Request * @param payment The amount of LINK to send for the request * @return requestId The request ID */ function sendChainlinkRequest(Chainlink.Request memory req, uint256 payment) internal returns (bytes32) { return sendChainlinkRequestTo(address(s_oracle), req, payment); } /** * @notice Creates a Chainlink request to the specified oracle address * @dev Generates and stores a request ID, increments the local nonce, and uses `transferAndCall` to * send LINK which creates a request on the target oracle contract. * Emits ChainlinkRequested event. * @param oracleAddress The address of the oracle for the request * @param req The initialized Chainlink Request * @param payment The amount of LINK to send for the request * @return requestId The request ID */ function sendChainlinkRequestTo( address oracleAddress, Chainlink.Request memory req, uint256 payment ) internal returns (bytes32 requestId) { uint256 nonce = s_requestCount; s_requestCount = nonce + 1; bytes memory encodedRequest = abi.encodeWithSelector( ChainlinkRequestInterface.oracleRequest.selector, SENDER_OVERRIDE, // Sender value - overridden by onTokenTransfer by the requesting contract's address AMOUNT_OVERRIDE, // Amount value - overridden by onTokenTransfer by the actual amount of LINK sent req.id, address(this), req.callbackFunctionId, nonce, ORACLE_ARGS_VERSION, req.buf.buf ); return _rawRequest(oracleAddress, nonce, payment, encodedRequest); } /** * @notice Creates a Chainlink request to the stored oracle address * @dev This function supports multi-word response * @dev Calls `sendOperatorRequestTo` with the stored oracle address * @param req The initialized Chainlink Request * @param payment The amount of LINK to send for the request * @return requestId The request ID */ function sendOperatorRequest(Chainlink.Request memory req, uint256 payment) internal returns (bytes32) { return sendOperatorRequestTo(address(s_oracle), req, payment); } /** * @notice Creates a Chainlink request to the specified oracle address * @dev This function supports multi-word response * @dev Generates and stores a request ID, increments the local nonce, and uses `transferAndCall` to * send LINK which creates a request on the target oracle contract. * Emits ChainlinkRequested event. * @param oracleAddress The address of the oracle for the request * @param req The initialized Chainlink Request * @param payment The amount of LINK to send for the request * @return requestId The request ID */ function sendOperatorRequestTo( address oracleAddress, Chainlink.Request memory req, uint256 payment ) internal returns (bytes32 requestId) { uint256 nonce = s_requestCount; s_requestCount = nonce + 1; bytes memory encodedRequest = abi.encodeWithSelector( OperatorInterface.operatorRequest.selector, SENDER_OVERRIDE, // Sender value - overridden by onTokenTransfer by the requesting contract's address AMOUNT_OVERRIDE, // Amount value - overridden by onTokenTransfer by the actual amount of LINK sent req.id, req.callbackFunctionId, nonce, OPERATOR_ARGS_VERSION, req.buf.buf ); return _rawRequest(oracleAddress, nonce, payment, encodedRequest); } /** * @notice Make a request to an oracle * @param oracleAddress The address of the oracle for the request * @param nonce used to generate the request ID * @param payment The amount of LINK to send for the request * @param encodedRequest data encoded for request type specific format * @return requestId The request ID */ function _rawRequest( address oracleAddress, uint256 nonce, uint256 payment, bytes memory encodedRequest ) private returns (bytes32 requestId) { requestId = keccak256(abi.encodePacked(this, nonce)); s_pendingRequests[requestId] = oracleAddress; emit ChainlinkRequested(requestId); require(s_link.transferAndCall(oracleAddress, payment, encodedRequest), "unable to transferAndCall to oracle"); } /** * @notice Allows a request to be cancelled if it has not been fulfilled * @dev Requires keeping track of the expiration value emitted from the oracle contract. * Deletes the request from the `pendingRequests` mapping. * Emits ChainlinkCancelled event. * @param requestId The request ID * @param payment The amount of LINK sent for the request * @param callbackFunc The callback function specified for the request * @param expiration The time of the expiration for the request */ function cancelChainlinkRequest( bytes32 requestId, uint256 payment, bytes4 callbackFunc, uint256 expiration ) internal { OperatorInterface requested = OperatorInterface(s_pendingRequests[requestId]); delete s_pendingRequests[requestId]; emit ChainlinkCancelled(requestId); requested.cancelOracleRequest(requestId, payment, callbackFunc, expiration); } /** * @notice the next request count to be used in generating a nonce * @dev starts at 1 in order to ensure consistent gas cost * @return returns the next request count to be used in a nonce */ function getNextRequestCount() internal view returns (uint256) { return s_requestCount; } /** * @notice Sets the stored oracle address * @param oracleAddress The address of the oracle contract */ function setChainlinkOracle(address oracleAddress) internal { s_oracle = OperatorInterface(oracleAddress); } /** * @notice Sets the LINK token address * @param linkAddress The address of the LINK token contract */ function setChainlinkToken(address linkAddress) internal { s_link = LinkTokenInterface(linkAddress); } /** * @notice Sets the Chainlink token address for the public * network as given by the Pointer contract */ function setPublicChainlinkToken() internal { setChainlinkToken(PointerInterface(LINK_TOKEN_POINTER).getAddress()); } /** * @notice Retrieves the stored address of the LINK token * @return The address of the LINK token */ function chainlinkTokenAddress() internal view returns (address) { return address(s_link); } /** * @notice Retrieves the stored address of the oracle contract * @return The address of the oracle contract */ function chainlinkOracleAddress() internal view returns (address) { return address(s_oracle); } /** * @notice Allows for a request which was created on another contract to be fulfilled * on this contract * @param oracleAddress The address of the oracle contract that will fulfill the request * @param requestId The request ID used for the response */ function addChainlinkExternalRequest(address oracleAddress, bytes32 requestId) internal notPendingRequest(requestId) { s_pendingRequests[requestId] = oracleAddress; } /** * @notice Sets the stored oracle and LINK token contracts with the addresses resolved by ENS * @dev Accounts for subnodes having different resolvers * @param ensAddress The address of the ENS contract * @param node The ENS node hash */ function useChainlinkWithENS(address ensAddress, bytes32 node) internal { s_ens = ENSInterface(ensAddress); s_ensNode = node; bytes32 linkSubnode = keccak256(abi.encodePacked(s_ensNode, ENS_TOKEN_SUBNAME)); ENSResolver_Chainlink resolver = ENSResolver_Chainlink(s_ens.resolver(linkSubnode)); setChainlinkToken(resolver.addr(linkSubnode)); updateChainlinkOracleWithENS(); } /** * @notice Sets the stored oracle contract with the address resolved by ENS * @dev This may be called on its own as long as `useChainlinkWithENS` has been called previously */ function updateChainlinkOracleWithENS() internal { bytes32 oracleSubnode = keccak256(abi.encodePacked(s_ensNode, ENS_ORACLE_SUBNAME)); ENSResolver_Chainlink resolver = ENSResolver_Chainlink(s_ens.resolver(oracleSubnode)); setChainlinkOracle(resolver.addr(oracleSubnode)); } /** * @notice Ensures that the fulfillment is valid for this contract * @dev Use if the contract developer prefers methods instead of modifiers for validation * @param requestId The request ID for fulfillment */ function validateChainlinkCallback(bytes32 requestId) internal recordChainlinkFulfillment(requestId) // solhint-disable-next-line no-empty-blocks { } /** * @dev Reverts if the sender is not the oracle of the request. * Emits ChainlinkFulfilled event. * @param requestId The request ID for fulfillment */ modifier recordChainlinkFulfillment(bytes32 requestId) { require(msg.sender == s_pendingRequests[requestId], "Source must be the oracle of the request"); delete s_pendingRequests[requestId]; emit ChainlinkFulfilled(requestId); _; } /** * @dev Reverts if the request is already pending * @param requestId The request ID for fulfillment */ modifier notPendingRequest(bytes32 requestId) { require(s_pendingRequests[requestId] == address(0), "Request is already pending"); _; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Address.sol) pragma solidity ^0.8.0; /** * @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 * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 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://diligence.consensys.net/posts/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.5.11/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 functionCall(target, data, "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"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(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) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(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) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason 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 { // 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 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/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 pragma solidity ^0.8.0; import {CBORChainlink} from "./vendor/CBORChainlink.sol"; import {BufferChainlink} from "./vendor/BufferChainlink.sol"; /** * @title Library for common Chainlink functions * @dev Uses imported CBOR library for encoding to buffer */ library Chainlink { uint256 internal constant defaultBufferSize = 256; // solhint-disable-line const-name-snakecase using CBORChainlink for BufferChainlink.buffer; struct Request { bytes32 id; address callbackAddress; bytes4 callbackFunctionId; uint256 nonce; BufferChainlink.buffer buf; } /** * @notice Initializes a Chainlink request * @dev Sets the ID, callback address, and callback function signature on the request * @param self The uninitialized request * @param jobId The Job Specification ID * @param callbackAddr The callback address * @param callbackFunc The callback function signature * @return The initialized request */ function initialize( Request memory self, bytes32 jobId, address callbackAddr, bytes4 callbackFunc ) internal pure returns (Chainlink.Request memory) { BufferChainlink.init(self.buf, defaultBufferSize); self.id = jobId; self.callbackAddress = callbackAddr; self.callbackFunctionId = callbackFunc; return self; } /** * @notice Sets the data for the buffer without encoding CBOR on-chain * @dev CBOR can be closed with curly-brackets {} or they can be left off * @param self The initialized request * @param data The CBOR data */ function setBuffer(Request memory self, bytes memory data) internal pure { BufferChainlink.init(self.buf, data.length); BufferChainlink.append(self.buf, data); } /** * @notice Adds a string value to the request with a given key name * @param self The initialized request * @param key The name of the key * @param value The string value to add */ function add( Request memory self, string memory key, string memory value ) internal pure { self.buf.encodeString(key); self.buf.encodeString(value); } /** * @notice Adds a bytes value to the request with a given key name * @param self The initialized request * @param key The name of the key * @param value The bytes value to add */ function addBytes( Request memory self, string memory key, bytes memory value ) internal pure { self.buf.encodeString(key); self.buf.encodeBytes(value); } /** * @notice Adds a int256 value to the request with a given key name * @param self The initialized request * @param key The name of the key * @param value The int256 value to add */ function addInt( Request memory self, string memory key, int256 value ) internal pure { self.buf.encodeString(key); self.buf.encodeInt(value); } /** * @notice Adds a uint256 value to the request with a given key name * @param self The initialized request * @param key The name of the key * @param value The uint256 value to add */ function addUint( Request memory self, string memory key, uint256 value ) internal pure { self.buf.encodeString(key); self.buf.encodeUInt(value); } /** * @notice Adds an array of strings to the request with a given key name * @param self The initialized request * @param key The name of the key * @param values The array of string values to add */ function addStringArray( Request memory self, string memory key, string[] memory values ) internal pure { self.buf.encodeString(key); self.buf.startArray(); for (uint256 i = 0; i < values.length; i++) { self.buf.encodeString(values[i]); } self.buf.endSequence(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ENSInterface { // Logged when the owner of a node assigns a new owner to a subnode. event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner); // Logged when the owner of a node transfers ownership to a new account. event Transfer(bytes32 indexed node, address owner); // Logged when the resolver for a node changes. event NewResolver(bytes32 indexed node, address resolver); // Logged when the TTL of a node changes event NewTTL(bytes32 indexed node, uint64 ttl); function setSubnodeOwner( bytes32 node, bytes32 label, address owner ) external; function setResolver(bytes32 node, address resolver) external; function setOwner(bytes32 node, address owner) external; function setTTL(bytes32 node, uint64 ttl) external; function owner(bytes32 node) external view returns (address); function resolver(bytes32 node) external view returns (address); function ttl(bytes32 node) external view returns (uint64); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface LinkTokenInterface { function allowance(address owner, address spender) external view returns (uint256 remaining); function approve(address spender, uint256 value) external returns (bool success); function balanceOf(address owner) external view returns (uint256 balance); function decimals() external view returns (uint8 decimalPlaces); function decreaseApproval(address spender, uint256 addedValue) external returns (bool success); function increaseApproval(address spender, uint256 subtractedValue) external; function name() external view returns (string memory tokenName); function symbol() external view returns (string memory tokenSymbol); function totalSupply() external view returns (uint256 totalTokensIssued); function transfer(address to, uint256 value) external returns (bool success); function transferAndCall( address to, uint256 value, bytes calldata data ) external returns (bool success); function transferFrom( address from, address to, uint256 value ) external returns (bool success); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ChainlinkRequestInterface { function oracleRequest( address sender, uint256 requestPrice, bytes32 serviceAgreementID, address callbackAddress, bytes4 callbackFunctionId, uint256 nonce, uint256 dataVersion, bytes calldata data ) external; function cancelOracleRequest( bytes32 requestId, uint256 payment, bytes4 callbackFunctionId, uint256 expiration ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./OracleInterface.sol"; import "./ChainlinkRequestInterface.sol"; interface OperatorInterface is OracleInterface, ChainlinkRequestInterface { function operatorRequest( address sender, uint256 payment, bytes32 specId, bytes4 callbackFunctionId, uint256 nonce, uint256 dataVersion, bytes calldata data ) external; function fulfillOracleRequest2( bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes calldata data ) external returns (bool); function ownerTransferAndCall( address to, uint256 value, bytes calldata data ) external returns (bool success); function distributeFunds(address payable[] calldata receivers, uint256[] calldata amounts) external payable; function getAuthorizedSenders() external returns (address[] memory); function setAuthorizedSenders(address[] calldata senders) external; function getForwarder() external returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface PointerInterface { function getAddress() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; abstract contract ENSResolver { function addr(bytes32 node) public view virtual returns (address); }
// SPDX-License-Identifier: MIT pragma solidity >=0.4.19; import {BufferChainlink} from "./BufferChainlink.sol"; library CBORChainlink { using BufferChainlink for BufferChainlink.buffer; uint8 private constant MAJOR_TYPE_INT = 0; uint8 private constant MAJOR_TYPE_NEGATIVE_INT = 1; uint8 private constant MAJOR_TYPE_BYTES = 2; uint8 private constant MAJOR_TYPE_STRING = 3; uint8 private constant MAJOR_TYPE_ARRAY = 4; uint8 private constant MAJOR_TYPE_MAP = 5; uint8 private constant MAJOR_TYPE_TAG = 6; uint8 private constant MAJOR_TYPE_CONTENT_FREE = 7; uint8 private constant TAG_TYPE_BIGNUM = 2; uint8 private constant TAG_TYPE_NEGATIVE_BIGNUM = 3; function encodeFixedNumeric(BufferChainlink.buffer memory buf, uint8 major, uint64 value) private pure { if(value <= 23) { buf.appendUint8(uint8((major << 5) | value)); } else if (value <= 0xFF) { buf.appendUint8(uint8((major << 5) | 24)); buf.appendInt(value, 1); } else if (value <= 0xFFFF) { buf.appendUint8(uint8((major << 5) | 25)); buf.appendInt(value, 2); } else if (value <= 0xFFFFFFFF) { buf.appendUint8(uint8((major << 5) | 26)); buf.appendInt(value, 4); } else { buf.appendUint8(uint8((major << 5) | 27)); buf.appendInt(value, 8); } } function encodeIndefiniteLengthType(BufferChainlink.buffer memory buf, uint8 major) private pure { buf.appendUint8(uint8((major << 5) | 31)); } function encodeUInt(BufferChainlink.buffer memory buf, uint value) internal pure { if(value > 0xFFFFFFFFFFFFFFFF) { encodeBigNum(buf, value); } else { encodeFixedNumeric(buf, MAJOR_TYPE_INT, uint64(value)); } } function encodeInt(BufferChainlink.buffer memory buf, int value) internal pure { if(value < -0x10000000000000000) { encodeSignedBigNum(buf, value); } else if(value > 0xFFFFFFFFFFFFFFFF) { encodeBigNum(buf, uint(value)); } else if(value >= 0) { encodeFixedNumeric(buf, MAJOR_TYPE_INT, uint64(uint256(value))); } else { encodeFixedNumeric(buf, MAJOR_TYPE_NEGATIVE_INT, uint64(uint256(-1 - value))); } } function encodeBytes(BufferChainlink.buffer memory buf, bytes memory value) internal pure { encodeFixedNumeric(buf, MAJOR_TYPE_BYTES, uint64(value.length)); buf.append(value); } function encodeBigNum(BufferChainlink.buffer memory buf, uint value) internal pure { buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_BIGNUM)); encodeBytes(buf, abi.encode(value)); } function encodeSignedBigNum(BufferChainlink.buffer memory buf, int input) internal pure { buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_NEGATIVE_BIGNUM)); encodeBytes(buf, abi.encode(uint256(-1 - input))); } function encodeString(BufferChainlink.buffer memory buf, string memory value) internal pure { encodeFixedNumeric(buf, MAJOR_TYPE_STRING, uint64(bytes(value).length)); buf.append(bytes(value)); } function startArray(BufferChainlink.buffer memory buf) internal pure { encodeIndefiniteLengthType(buf, MAJOR_TYPE_ARRAY); } function startMap(BufferChainlink.buffer memory buf) internal pure { encodeIndefiniteLengthType(buf, MAJOR_TYPE_MAP); } function endSequence(BufferChainlink.buffer memory buf) internal pure { encodeIndefiniteLengthType(buf, MAJOR_TYPE_CONTENT_FREE); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev A library for working with mutable byte buffers in Solidity. * * Byte buffers are mutable and expandable, and provide a variety of primitives * for writing to them. At any time you can fetch a bytes object containing the * current contents of the buffer. The bytes object should not be stored between * operations, as it may change due to resizing of the buffer. */ library BufferChainlink { /** * @dev Represents a mutable buffer. Buffers have a current value (buf) and * a capacity. The capacity may be longer than the current value, in * which case it can be extended without the need to allocate more memory. */ struct buffer { bytes buf; uint256 capacity; } /** * @dev Initializes a buffer with an initial capacity. * @param buf The buffer to initialize. * @param capacity The number of bytes of space to allocate the buffer. * @return The buffer, for chaining. */ function init(buffer memory buf, uint256 capacity) internal pure returns (buffer memory) { if (capacity % 32 != 0) { capacity += 32 - (capacity % 32); } // Allocate space for the buffer data buf.capacity = capacity; assembly { let ptr := mload(0x40) mstore(buf, ptr) mstore(ptr, 0) mstore(0x40, add(32, add(ptr, capacity))) } return buf; } /** * @dev Initializes a new buffer from an existing bytes object. * Changes to the buffer may mutate the original value. * @param b The bytes object to initialize the buffer with. * @return A new buffer. */ function fromBytes(bytes memory b) internal pure returns (buffer memory) { buffer memory buf; buf.buf = b; buf.capacity = b.length; return buf; } function resize(buffer memory buf, uint256 capacity) private pure { bytes memory oldbuf = buf.buf; init(buf, capacity); append(buf, oldbuf); } function max(uint256 a, uint256 b) private pure returns (uint256) { if (a > b) { return a; } return b; } /** * @dev Sets buffer length to 0. * @param buf The buffer to truncate. * @return The original buffer, for chaining.. */ function truncate(buffer memory buf) internal pure returns (buffer memory) { assembly { let bufptr := mload(buf) mstore(bufptr, 0) } return buf; } /** * @dev Writes a byte string to a buffer. Resizes if doing so would exceed * the capacity of the buffer. * @param buf The buffer to append to. * @param off The start offset to write to. * @param data The data to append. * @param len The number of bytes to copy. * @return The original buffer, for chaining. */ function write( buffer memory buf, uint256 off, bytes memory data, uint256 len ) internal pure returns (buffer memory) { require(len <= data.length); if (off + len > buf.capacity) { resize(buf, max(buf.capacity, len + off) * 2); } uint256 dest; uint256 src; assembly { // Memory address of the buffer data let bufptr := mload(buf) // Length of existing buffer data let buflen := mload(bufptr) // Start address = buffer address + offset + sizeof(buffer length) dest := add(add(bufptr, 32), off) // Update buffer length if we're extending it if gt(add(len, off), buflen) { mstore(bufptr, add(len, off)) } src := add(data, 32) } // Copy word-length chunks while possible for (; len >= 32; len -= 32) { assembly { mstore(dest, mload(src)) } dest += 32; src += 32; } // Copy remaining bytes unchecked { uint256 mask = (256**(32 - len)) - 1; assembly { let srcpart := and(mload(src), not(mask)) let destpart := and(mload(dest), mask) mstore(dest, or(destpart, srcpart)) } } return buf; } /** * @dev Appends a byte string to a buffer. Resizes if doing so would exceed * the capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @param len The number of bytes to copy. * @return The original buffer, for chaining. */ function append( buffer memory buf, bytes memory data, uint256 len ) internal pure returns (buffer memory) { return write(buf, buf.buf.length, data, len); } /** * @dev Appends a byte string to a buffer. Resizes if doing so would exceed * the capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @return The original buffer, for chaining. */ function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) { return write(buf, buf.buf.length, data, data.length); } /** * @dev Writes a byte to the buffer. Resizes if doing so would exceed the * capacity of the buffer. * @param buf The buffer to append to. * @param off The offset to write the byte at. * @param data The data to append. * @return The original buffer, for chaining. */ function writeUint8( buffer memory buf, uint256 off, uint8 data ) internal pure returns (buffer memory) { if (off >= buf.capacity) { resize(buf, buf.capacity * 2); } assembly { // Memory address of the buffer data let bufptr := mload(buf) // Length of existing buffer data let buflen := mload(bufptr) // Address = buffer address + sizeof(buffer length) + off let dest := add(add(bufptr, off), 32) mstore8(dest, data) // Update buffer length if we extended it if eq(off, buflen) { mstore(bufptr, add(buflen, 1)) } } return buf; } /** * @dev Appends a byte to the buffer. Resizes if doing so would exceed the * capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @return The original buffer, for chaining. */ function appendUint8(buffer memory buf, uint8 data) internal pure returns (buffer memory) { return writeUint8(buf, buf.buf.length, data); } /** * @dev Writes up to 32 bytes to the buffer. Resizes if doing so would * exceed the capacity of the buffer. * @param buf The buffer to append to. * @param off The offset to write at. * @param data The data to append. * @param len The number of bytes to write (left-aligned). * @return The original buffer, for chaining. */ function write( buffer memory buf, uint256 off, bytes32 data, uint256 len ) private pure returns (buffer memory) { if (len + off > buf.capacity) { resize(buf, (len + off) * 2); } unchecked { uint256 mask = (256**len) - 1; // Right-align data data = data >> (8 * (32 - len)); assembly { // Memory address of the buffer data let bufptr := mload(buf) // Address = buffer address + sizeof(buffer length) + off + len let dest := add(add(bufptr, off), len) mstore(dest, or(and(mload(dest), not(mask)), data)) // Update buffer length if we extended it if gt(add(off, len), mload(bufptr)) { mstore(bufptr, add(off, len)) } } } return buf; } /** * @dev Writes a bytes20 to the buffer. Resizes if doing so would exceed the * capacity of the buffer. * @param buf The buffer to append to. * @param off The offset to write at. * @param data The data to append. * @return The original buffer, for chaining. */ function writeBytes20( buffer memory buf, uint256 off, bytes20 data ) internal pure returns (buffer memory) { return write(buf, off, bytes32(data), 20); } /** * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed * the capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @return The original buffer, for chhaining. */ function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) { return write(buf, buf.buf.length, bytes32(data), 20); } /** * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed * the capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @return The original buffer, for chaining. */ function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) { return write(buf, buf.buf.length, data, 32); } /** * @dev Writes an integer to the buffer. Resizes if doing so would exceed * the capacity of the buffer. * @param buf The buffer to append to. * @param off The offset to write at. * @param data The data to append. * @param len The number of bytes to write (right-aligned). * @return The original buffer, for chaining. */ function writeInt( buffer memory buf, uint256 off, uint256 data, uint256 len ) private pure returns (buffer memory) { if (len + off > buf.capacity) { resize(buf, (len + off) * 2); } uint256 mask = (256**len) - 1; assembly { // Memory address of the buffer data let bufptr := mload(buf) // Address = buffer address + off + sizeof(buffer length) + len let dest := add(add(bufptr, off), len) mstore(dest, or(and(mload(dest), not(mask)), data)) // Update buffer length if we extended it if gt(add(off, len), mload(bufptr)) { mstore(bufptr, add(off, len)) } } return buf; } /** * @dev Appends a byte to the end of the buffer. Resizes if doing so would * exceed the capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @return The original buffer. */ function appendInt( buffer memory buf, uint256 data, uint256 len ) internal pure returns (buffer memory) { return writeInt(buf, buf.buf.length, data, len); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface OracleInterface { function fulfillOracleRequest( bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes32 data ) external returns (bool); function isAuthorizedSender(address node) external view returns (bool); function withdraw(address recipient, uint256 amount) external; function withdrawable() external view returns (uint256); }
{ "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"},{"internalType":"address","name":"_usdcTokenContract","type":"address"},{"internalType":"address","name":"_gcrTokenContract","type":"address"},{"internalType":"address","name":"_linkTokenContract","type":"address"},{"internalType":"address","name":"_oracle","type":"address"},{"internalType":"string","name":"_jobId","type":"string"},{"internalType":"uint256","name":"_oracleFee","type":"uint256"},{"internalType":"string","name":"_priceFeedURI","type":"string"},{"internalType":"string","name":"_priceFeedPath","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyClaimed","type":"error"},{"inputs":[],"name":"NotInMerkle","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"ChainlinkCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"ChainlinkFulfilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"ChainlinkRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"claimant","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ClaimAirdrop","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"claimaint","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Purchase","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"prevOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"SetOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRate","type":"uint256"}],"name":"SetRate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"WithdrawAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"WithdrawToken","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"airdropAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"participant","type":"address"}],"name":"checkAirdropClaimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"participant","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"checkAirdropEligibility","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"participant","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"checkPurchaseEligibility","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"snapshotAmount","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"claimAirdrop","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_requestId","type":"bytes32"},{"internalType":"uint256","name":"_rate","type":"uint256"}],"name":"fulfill","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"gcrToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gcrTokenContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"participant","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"initialAllocation","outputs":[{"internalType":"uint256","name":"allocation","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"linkToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"linkTokenContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"midTier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeedPath","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeedURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proTier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"purchaseAmount","type":"uint256"},{"internalType":"uint256","name":"snapshotAmount","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"purchaseTokens","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"participant","type":"address"}],"name":"purchasedAllocation","outputs":[{"internalType":"uint256","name":"purchasedAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"participant","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"remainingAllocation","outputs":[{"internalType":"uint256","name":"allocation","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"requestPriceData","outputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"usdcPerToken","type":"uint256"}],"name":"setRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"source","type":"string"}],"name":"stringToBytes32","outputs":[{"internalType":"bytes32","name":"result","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_newJobId","type":"bytes32"}],"name":"updateChainlinkJobId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOracle","type":"address"}],"name":"updateChainlinkOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newChainlinkTokenContract","type":"address"}],"name":"updateChainlinkTokenContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newOracleFee","type":"uint256"}],"name":"updateOracleFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newPriceFeedPath","type":"string"}],"name":"updatePriceFeedPath","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newPriceFeedURI","type":"string"}],"name":"updatePriceFeedURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"usdcToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"usdcTokenContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawAllTokens","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"withdrawToken","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60a060405260016004553480156200001657600080fd5b50604051620063983803806200639883398181016040528101906200003c9190620004eb565b60008060006101000a81548160ff02191690831515021790555033600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550886080818152505087600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555085600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555085600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061015e600d8190555062186a00600e819055506301312d00600f81905550626acfc0601081905550620f424060118190555084601260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620002a9846200030860201b60201c565b601381905550826014819055508160159080519060200190620002ce92919062000378565b508060169080519060200190620002e792919062000378565b50620002f9866200033460201b60201c565b50505050505050505062000841565b60008082905060008151141562000326576000801b9150506200032f565b60208301519150505b919050565b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b828054620003869062000704565b90600052602060002090601f016020900481019282620003aa5760008555620003f6565b82601f10620003c557805160ff1916838001178555620003f6565b82800160010185558215620003f6579182015b82811115620003f5578251825591602001919060010190620003d8565b5b50905062000405919062000409565b5090565b5b80821115620004245760008160009055506001016200040a565b5090565b60006200043f620004398462000650565b62000627565b9050828152602081018484840111156200045e576200045d620007d3565b5b6200046b848285620006ce565b509392505050565b6000815190506200048481620007f3565b92915050565b6000815190506200049b816200080d565b92915050565b600082601f830112620004b957620004b8620007ce565b5b8151620004cb84826020860162000428565b91505092915050565b600081519050620004e58162000827565b92915050565b60008060008060008060008060006101208a8c031215620005115762000510620007dd565b5b6000620005218c828d016200048a565b9950506020620005348c828d0162000473565b9850506040620005478c828d0162000473565b97505060606200055a8c828d0162000473565b96505060806200056d8c828d0162000473565b95505060a08a015167ffffffffffffffff811115620005915762000590620007d8565b5b6200059f8c828d01620004a1565b94505060c0620005b28c828d01620004d4565b93505060e08a015167ffffffffffffffff811115620005d657620005d5620007d8565b5b620005e48c828d01620004a1565b9250506101008a015167ffffffffffffffff811115620006095762000608620007d8565b5b620006178c828d01620004a1565b9150509295985092959850929598565b60006200063362000646565b90506200064182826200073a565b919050565b6000604051905090565b600067ffffffffffffffff8211156200066e576200066d6200079f565b5b6200067982620007e2565b9050602081019050919050565b60006200069382620006a4565b9050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b83811015620006ee578082015181840152602081019050620006d1565b83811115620006fe576000848401525b50505050565b600060028204905060018216806200071d57607f821691505b6020821081141562000734576200073362000770565b5b50919050565b6200074582620007e2565b810181811067ffffffffffffffff821117156200076757620007666200079f565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b620007fe8162000686565b81146200080a57600080fd5b50565b62000818816200069a565b81146200082457600080fd5b50565b6200083281620006c4565b81146200083e57600080fd5b50565b608051615b3462000864600039600081816117d60152612c820152615b346000f3fe6080604052600436106102345760003560e01c80635c975abb1161012e578063adc764bf116100ab578063db848d491161006f578063db848d491461086f578063ecbe74aa1461089a578063f95e0053146108c5578063fc2ea8a5146108ee578063ff6e2988146109195761023b565b8063adc764bf1461078a578063b7ce5010146107b5578063cfb51928146107de578063d4bd49931461081b578063d7322862146108445761023b565b80638532ac4e116100f25780638532ac4e1461067d57806389476069146106ba5780638da5cb5b146106f7578063a71ede6c14610722578063acceba771461075f5761023b565b80635c975abb1461059857806377eb8126146105c35780637bd49056146106005780637e9dce76146106295780638456cb59146106665761023b565b80632bbfe897116101bc5780633efbd330116101805780633efbd330146104c75780633f4ba83a146105045780634357855e1461051b5780634eca519f1461054457806357970e931461056d5761023b565b80632bbfe897146103e05780632bcbc18f1461040b5780632c4e722e146104485780632eb4a7ab1461047357806334fcf4371461049e5761023b565b806311eac8551161020357806311eac8551461030d578063125dc8311461033857806313af403514610361578063202806a41461038a578063280da6fa146103b55761023b565b8063013eef4f1461023d57806307c1e2f01461027a5780630bcae1ac146102a55780631193d7e3146102e25761023b565b3661023b57005b005b34801561024957600080fd5b50610264600480360381019061025f919061415a565b610944565b6040516102719190614e19565b60405180910390f35b34801561028657600080fd5b5061028f61098d565b60405161029c9190614b17565b60405180910390f35b3480156102b157600080fd5b506102cc60048036038101906102c79190614333565b610a1b565b6040516102d99190614ac6565b60405180910390f35b3480156102ee57600080fd5b506102f7610c7b565b6040516103049190614afc565b60405180910390f35b34801561031957600080fd5b50610322610ca1565b60405161032f9190614afc565b60405180910390f35b34801561034457600080fd5b5061035f600480360381019061035a9190614290565b610cc7565b005b34801561036d57600080fd5b506103886004803603810190610383919061415a565b610e45565b005b34801561039657600080fd5b5061039f61102a565b6040516103ac9190614b17565b60405180910390f35b3480156103c157600080fd5b506103ca6110b8565b6040516103d79190614ac6565b60405180910390f35b3480156103ec57600080fd5b506103f5611790565b604051610402919061495f565b60405180910390f35b34801561041757600080fd5b50610432600480360381019061042d9190614187565b6117b6565b60405161043f9190614ac6565b60405180910390f35b34801561045457600080fd5b5061045d6117ce565b60405161046a9190614e19565b60405180910390f35b34801561047f57600080fd5b506104886117d4565b6040516104959190614ae1565b60405180910390f35b3480156104aa57600080fd5b506104c560048036038101906104c091906142d9565b6117f8565b005b3480156104d357600080fd5b506104ee60048036038101906104e99190614187565b611949565b6040516104fb9190614e19565b60405180910390f35b34801561051057600080fd5b506105196119ff565b005b34801561052757600080fd5b50610542600480360381019061053d9190614250565b611a99565b005b34801561055057600080fd5b5061056b60048036038101906105669190614223565b611bda565b005b34801561057957600080fd5b50610582611cb9565b60405161058f9190614afc565b60405180910390f35b3480156105a457600080fd5b506105ad611cdf565b6040516105ba9190614ac6565b60405180910390f35b3480156105cf57600080fd5b506105ea60048036038101906105e5919061415a565b611cf5565b6040516105f79190614ac6565b60405180910390f35b34801561060c57600080fd5b50610627600480360381019061062291906142d9565b611d4b565b005b34801561063557600080fd5b50610650600480360381019061064b9190614187565b611e2a565b60405161065d9190614e19565b60405180910390f35b34801561067257600080fd5b5061067b611ed4565b005b34801561068957600080fd5b506106a4600480360381019061069f919061438f565b611f6e565b6040516106b19190614ac6565b60405180910390f35b3480156106c657600080fd5b506106e160048036038101906106dc919061415a565b61222a565b6040516106ee9190614ac6565b60405180910390f35b34801561070357600080fd5b5061070c6124ae565b604051610719919061495f565b60405180910390f35b34801561072e57600080fd5b5061074960048036038101906107449190614187565b6124d4565b6040516107569190614ac6565b60405180910390f35b34801561076b57600080fd5b5061077461252f565b604051610781919061495f565b60405180910390f35b34801561079657600080fd5b5061079f612555565b6040516107ac9190614e19565b60405180910390f35b3480156107c157600080fd5b506107dc60048036038101906107d7919061415a565b61255b565b005b3480156107ea57600080fd5b5061080560048036038101906108009190614290565b6126c0565b6040516108129190614ae1565b60405180910390f35b34801561082757600080fd5b50610842600480360381019061083d919061415a565b6126ea565b005b34801561085057600080fd5b5061085961284f565b6040516108669190614ae1565b60405180910390f35b34801561087b57600080fd5b50610884612a96565b604051610891919061495f565b60405180910390f35b3480156108a657600080fd5b506108af612abc565b6040516108bc9190614e19565b60405180910390f35b3480156108d157600080fd5b506108ec60048036038101906108e79190614290565b612ac2565b005b3480156108fa57600080fd5b50610903612c40565b6040516109109190614e19565b60405180910390f35b34801561092557600080fd5b5061092e612c46565b60405161093b9190614e19565b60405180910390f35b6000601860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6016805461099a90615359565b80601f01602080910402602001604051908101604052809291908181526020018280546109c690615359565b8015610a135780601f106109e857610100808354040283529160200191610a13565b820191906000526020600020905b8154815290600101906020018083116109f657829003601f168201915b505050505081565b6000610a25611cdf565b15610a65576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5c90614cd9565b60405180910390fd5b610a6e33611cf5565b15610aae576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa590614d19565b60405180910390fd5b6000601860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414610b30576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b2790614d59565b60405180910390fd5b610b3b338484612c4c565b610b7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b7190614cb9565b60405180910390fd5b6001601760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550610c2133600e54600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612ced9092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167fcebbbce55cb558a80c89a83b5e23dca5186979853be88c28e9e01232c7fdc98b600e54604051610c699190614e19565b60405180910390a26001905092915050565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b3373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610d57576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d4e90614db9565b60405180910390fd5b610deb60158054610d6790615359565b80601f0160208091040260200160405190810160405280929190818152602001828054610d9390615359565b8015610de05780601f10610db557610100808354040283529160200191610de0565b820191906000526020600020905b815481529060010190602001808311610dc357829003601f168201915b505050505082612d73565b15610e2b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2290614d79565b60405180910390fd5b8060159080519060200190610e41929190613eb9565b5050565b3373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610ed5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ecc90614db9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610f0f57600080fd5b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610f6a57600080fd5b8073ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fcbf985117192c8f614a58aaf97226bb80a754772f5f6edf06f87c675f2e6c66360405160405180910390a380600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6015805461103790615359565b80601f016020809104026020016040519081016040528092919081815260200182805461106390615359565b80156110b05780601f10611085576101008083540402835291602001916110b0565b820191906000526020600020905b81548152906001019060200180831161109357829003601f168201915b505050505081565b60003373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461114a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161114190614db9565b60405180910390fd5b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016111a7919061495f565b60206040518083038186803b1580156111bf57600080fd5b505afa1580156111d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f79190614306565b111561131757611316600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161127e919061495f565b60206040518083038186803b15801561129657600080fd5b505afa1580156112aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ce9190614306565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612ced9092919063ffffffff16565b5b6000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401611374919061495f565b60206040518083038186803b15801561138c57600080fd5b505afa1580156113a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c49190614306565b11156114e4576114e3600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161144b919061495f565b60206040518083038186803b15801561146357600080fd5b505afa158015611477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149b9190614306565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612ced9092919063ffffffff16565b5b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401611541919061495f565b60206040518083038186803b15801561155957600080fd5b505afa15801561156d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115919190614306565b11156116b1576116b0600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401611618919061495f565b60206040518083038186803b15801561163057600080fd5b505afa158015611644573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116689190614306565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612ced9092919063ffffffff16565b5b600047111561172457600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f19350505050158015611722573d6000803e3d6000fd5b505b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f2b3ede1cd1dfcbe081c86c4381460612351a278070aef7f89dad40e805fda5ab60405160405180910390a26001905090565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806117c4858585611e2a565b1190509392505050565b600d5481565b7f000000000000000000000000000000000000000000000000000000000000000081565b3373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611888576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161187f90614db9565b60405180910390fd5b600081116118cb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118c290614bf9565b60405180910390fd5b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f9002403f1fb7daf8ef984c2925644987f2198485d18e7818fe275bf93244314e600d5483604051611937929190614e34565b60405180910390a280600d8190555050565b6000611956848484612c4c565b611995576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161198c90614cb9565b60405180910390fd5b6000601860008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060006119e6868686611e2a565b905081816119f49190615213565b925050509392505050565b3373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611a8f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a8690614db9565b60405180910390fd5b611a97612dcc565b565b816005600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b3290614d99565b60405180910390fd5b6005600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055807f7cc135e0cebb02c3480ae5d74d377283180a2601f8f644edf7987b009316c63a60405160405180910390a26101908210611bcb57600a600983611bb69190615125565b611bc09190614f83565b600d81905550611bd5565b61015e600d819055505b505050565b3373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611c6a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c6190614db9565b60405180910390fd5b806013541415611caf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ca690614b79565b60405180910390fd5b8060138190555050565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060009054906101000a900460ff16905090565b6000601760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b3373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611ddb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dd290614db9565b60405180910390fd5b806014541415611e20576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e1790614c39565b60405180910390fd5b8060148190555050565b6000611e37848484612c4c565b611e76576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e6d90614cb9565b60405180910390fd5b600f54831115611e895760009050611ecd565b623567e08310611ea85782600f54611ea19190615213565b9050611ecc565b6011548310611ec65782601054611ebf9190615213565b9050611ecb565b600090505b5b5b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611f64576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f5b90614db9565b60405180910390fd5b611f6c612e6d565b565b6000611f78611cdf565b15611fb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611faf90614cd9565b60405180910390fd5b611fc133611cf5565b15612001576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ff890614b99565b60405180910390fd5b61200c338484612c4c565b61204b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161204290614cb9565b60405180910390fd5b601154831015612090576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161208790614bb9565b60405180910390fd5b600f548311156120d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120cc90614c79565b60405180910390fd5b600080623567e08510612153576120ed338686611949565b915081861115612132576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161212990614cf9565b60405180910390fd5b600d54866121409190615125565b905061214d338288612f0f565b506121cf565b60115485106121cd57612167338686611949565b9150818611156121ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121a390614cf9565b60405180910390fd5b600d54866121ba9190615125565b90506121c7338288612f0f565b506121ce565b5b5b3373ffffffffffffffffffffffffffffffffffffffff167f2499a5330ab0979cc612135e7883ebc3cd5c9f7a8508f042540c34723348f632876040516122159190614e19565b60405180910390a26001925050509392505050565b60003373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146122bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122b390614db9565b60405180910390fd5b600082905060008173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016122fc919061495f565b60206040518083038186803b15801561231457600080fd5b505afa158015612328573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061234c9190614306565b111561242857612427600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016123b1919061495f565b60206040518083038186803b1580156123c957600080fd5b505afa1580156123dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124019190614306565b8373ffffffffffffffffffffffffffffffffffffffff16612ced9092919063ffffffff16565b5b8273ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fce9ecd720079c00c86716fadb783ea8b0577f02c0f55b98d8a4a86ecdcb7918b60405160405180910390a36001915050919050565b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006124e1848484612c4c565b612520576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161251790614cb9565b60405180910390fd5b600f5483101590509392505050565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60115481565b3373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146125eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125e290614db9565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561267c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161267390614c99565b60405180910390fd5b80600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000808290506000815114156126dc576000801b9150506126e5565b60208301519150505b919050565b3373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461277a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161277190614db9565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561280b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161280290614df9565b60405180910390fd5b80601260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008061286660135430634357855e60e01b613019565b905061293c6040518060400160405280600381526020017f6765740000000000000000000000000000000000000000000000000000000000815250601580546128ae90615359565b80601f01602080910402602001604051908101604052809291908181526020018280546128da90615359565b80156129275780601f106128fc57610100808354040283529160200191612927565b820191906000526020600020905b81548152906001019060200180831161290a57829003601f168201915b50505050508361304a9092919063ffffffff16565b612a106040518060400160405280600481526020017f70617468000000000000000000000000000000000000000000000000000000008152506016805461298290615359565b80601f01602080910402602001604051908101604052809291908181526020018280546129ae90615359565b80156129fb5780601f106129d0576101008083540402835291602001916129fb565b820191906000526020600020905b8154815290600101906020018083116129de57829003601f168201915b50505050508361304a9092919063ffffffff16565b600060649050612a606040518060400160405280600581526020017f74696d6573000000000000000000000000000000000000000000000000000000815250828461307d9092919063ffffffff16565b612a8f601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836014546130b0565b9250505090565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600f5481565b3373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612b52576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b4990614db9565b60405180910390fd5b612be660168054612b6290615359565b80601f0160208091040260200160405190810160405280929190818152602001828054612b8e90615359565b8015612bdb5780601f10612bb057610100808354040283529160200191612bdb565b820191906000526020600020905b815481529060010190602001808311612bbe57829003601f168201915b505050505082612d73565b15612c26576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c1d90614c19565b60405180910390fd5b8060169080519060200190612c3c929190613eb9565b5050565b600e5481565b60105481565b6000808484604051602001612c629291906148ad565b6040516020818303038152906040528051906020012090506000612ca7847f00000000000000000000000000000000000000000000000000000000000000008461317c565b905080612ce0576040517f8a585be200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001925050509392505050565b612d6e8363a9059cbb60e01b8484604051602401612d0c9291906149da565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613193565b505050565b600081604051602001612d869190614948565b6040516020818303038152906040528051906020012083604051602001612dad9190614948565b6040516020818303038152906040528051906020012014905092915050565b612dd4611cdf565b612e13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e0a90614b39565b60405180910390fd5b60008060006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612e5661325a565b604051612e63919061495f565b60405180910390a1565b612e75611cdf565b15612eb5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612eac90614cd9565b60405180910390fd5b60016000806101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612ef861325a565b604051612f05919061495f565b60405180910390a1565b6000612f1b8484613262565b50612f6b843085600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16613362909392919063ffffffff16565b612fb88483600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612ced9092919063ffffffff16565b81601860008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546130079190614f2d565b92505081905550600190509392505050565b613021613f3f565b613029613f3f565b613040858585846133eb909392919063ffffffff16565b9150509392505050565b61306182846080015161349b90919063ffffffff16565b61307881846080015161349b90919063ffffffff16565b505050565b61309482846080015161349b90919063ffffffff16565b6130ab8184608001516134c090919063ffffffff16565b505050565b60008060045490506001816130c59190614f2d565b6004819055506000634042994660e01b60008087600001513089604001518760018c6080015160000151604051602401613106989796959493929190614a03565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506131718683868461356d565b925050509392505050565b6000826131898584613711565b1490509392505050565b60006131f5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166137c49092919063ffffffff16565b9050600081511115613255578080602001905181019061321591906141f6565b613254576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161324b90614dd9565b60405180910390fd5b5b505050565b600033905090565b600080600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e85306040518363ffffffff1660e01b81526004016132c292919061497a565b60206040518083038186803b1580156132da57600080fd5b505afa1580156132ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133129190614306565b905082811015613357576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161334e90614b59565b60405180910390fd5b600191505092915050565b6133e5846323b872dd60e01b858585604051602401613383939291906149a3565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613193565b50505050565b6133f3613f3f565b61340385608001516101006137dc565b508385600001818152505082856020019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508185604001907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681525050849050949350505050565b6134a88260038351613846565b6134bb81836139cb90919063ffffffff16565b505050565b7fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008112156134f7576134f282826139ed565b613569565b67ffffffffffffffff811315613516576135118282613a64565b613568565b6000811261352f5761352a82600083613846565b613567565b613566826001837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff613561919061517f565b613846565b5b5b5b5050565b6000308460405160200161358292919061491c565b604051602081830303815290604052805190602001209050846005600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550807fb5e6e01e79f91267dc17b4e6314d5d4d03593d2ceee0fbb452b750bd70ea5af960405160405180910390a2600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634000aea08685856040518463ffffffff1660e01b815260040161367893929190614a88565b602060405180830381600087803b15801561369257600080fd5b505af11580156136a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136ca91906141f6565b613709576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161370090614bd9565b60405180910390fd5b949350505050565b60008082905060005b84518110156137b9576000858281518110613738576137376154fb565b5b6020026020010151905080831161377957828160405160200161375c9291906148d9565b6040516020818303038152906040528051906020012092506137a5565b808360405160200161378c9291906148d9565b6040516020818303038152906040528051906020012092505b5080806137b1906153bc565b91505061371a565b508091505092915050565b60606137d38484600085613ab0565b90509392505050565b6137e4613fac565b60006020836137f3919061543d565b1461381f57602082613805919061543d565b60206138119190615213565b8261381c9190614f2d565b91505b81836020018181525050604051808452600081528281016020016040525082905092915050565b60178167ffffffffffffffff161161387d576138778160058460ff16901b60ff161784613bc490919063ffffffff16565b506139c6565b60ff8167ffffffffffffffff16116138d3576138ac601860058460ff16901b1784613bc490919063ffffffff16565b506138cd8167ffffffffffffffff16600185613be49092919063ffffffff16565b506139c5565b61ffff8167ffffffffffffffff161161392a57613903601960058460ff16901b1784613bc490919063ffffffff16565b506139248167ffffffffffffffff16600285613be49092919063ffffffff16565b506139c4565b63ffffffff8167ffffffffffffffff16116139835761395c601a60058460ff16901b1784613bc490919063ffffffff16565b5061397d8167ffffffffffffffff16600485613be49092919063ffffffff16565b506139c3565b6139a0601b60058460ff16901b1784613bc490919063ffffffff16565b506139c18167ffffffffffffffff16600885613be49092919063ffffffff16565b505b5b5b5b505050565b6139d3613fac565b6139e583846000015151848551613c06565b905092915050565b613a0b60036005600660ff16901b1783613bc490919063ffffffff16565b50613a6082827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff613a3c919061517f565b604051602001613a4c9190614e19565b604051602081830303815290604052613cf5565b5050565b613a8260026005600660ff16901b1783613bc490919063ffffffff16565b50613aac8282604051602001613a989190614e19565b604051602081830303815290604052613cf5565b5050565b606082471015613af5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613aec90614c59565b60405180910390fd5b613afe85613d1a565b613b3d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613b3490614d39565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051613b669190614905565b60006040518083038185875af1925050503d8060008114613ba3576040519150601f19603f3d011682016040523d82523d6000602084013e613ba8565b606091505b5091509150613bb8828286613d2d565b92505050949350505050565b613bcc613fac565b613bdc8384600001515184613d94565b905092915050565b613bec613fac565b613bfd848560000151518585613deb565b90509392505050565b613c0e613fac565b8251821115613c1c57600080fd5b84602001518285613c2d9190614f2d565b1115613c6257613c61856002613c5288602001518887613c4d9190614f2d565b613e79565b613c5c9190615125565b613e95565b5b600080865180518760208301019350808887011115613c815787860182525b60208701925050505b60208410613cc85780518252602082613ca39190614f2d565b9150602081613cb29190614f2d565b9050602084613cc19190615213565b9350613c8a565b60006001856020036101000a03905080198251168184511681811785525050508692505050949350505050565b613d028260028351613846565b613d1581836139cb90919063ffffffff16565b505050565b600080823b905060008111915050919050565b60608315613d3d57829050613d8d565b600083511115613d505782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613d849190614b17565b60405180910390fd5b9392505050565b613d9c613fac565b83602001518310613dc257613dc18460028660200151613dbc9190615125565b613e95565b5b8351805160208583010184815381861415613dde576001820183525b5050508390509392505050565b613df3613fac565b84602001518483613e049190614f2d565b1115613e2c57613e2b8560028685613e1c9190614f2d565b613e269190615125565b613e95565b5b6000600183610100613e3e9190615007565b613e489190615213565b90508551838682010185831982511617815281518588011115613e6b5784870182525b505085915050949350505050565b600081831115613e8b57829050613e8f565b8190505b92915050565b600082600001519050613ea883836137dc565b50613eb383826139cb565b50505050565b828054613ec590615359565b90600052602060002090601f016020900481019282613ee75760008555613f2e565b82601f10613f0057805160ff1916838001178555613f2e565b82800160010185558215613f2e579182015b82811115613f2d578251825591602001919060010190613f12565b5b509050613f3b9190613fc6565b5090565b6040518060a0016040528060008019168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200160008152602001613fa6613fac565b81525090565b604051806040016040528060608152602001600081525090565b5b80821115613fdf576000816000905550600101613fc7565b5090565b6000613ff6613ff184614e82565b614e5d565b905080838252602082019050828560208602820111156140195761401861555e565b5b60005b85811015614049578161402f88826140ed565b84526020840193506020830192505060018101905061401c565b5050509392505050565b600061406661406184614eae565b614e5d565b90508281526020810184848401111561408257614081615563565b5b61408d848285615317565b509392505050565b6000813590506140a481615aa2565b92915050565b600082601f8301126140bf576140be615559565b5b81356140cf848260208601613fe3565b91505092915050565b6000815190506140e781615ab9565b92915050565b6000813590506140fc81615ad0565b92915050565b600082601f83011261411757614116615559565b5b8135614127848260208601614053565b91505092915050565b60008135905061413f81615ae7565b92915050565b60008151905061415481615ae7565b92915050565b6000602082840312156141705761416f61556d565b5b600061417e84828501614095565b91505092915050565b6000806000606084860312156141a05761419f61556d565b5b60006141ae86828701614095565b93505060206141bf86828701614130565b925050604084013567ffffffffffffffff8111156141e0576141df615568565b5b6141ec868287016140aa565b9150509250925092565b60006020828403121561420c5761420b61556d565b5b600061421a848285016140d8565b91505092915050565b6000602082840312156142395761423861556d565b5b6000614247848285016140ed565b91505092915050565b600080604083850312156142675761426661556d565b5b6000614275858286016140ed565b925050602061428685828601614130565b9150509250929050565b6000602082840312156142a6576142a561556d565b5b600082013567ffffffffffffffff8111156142c4576142c3615568565b5b6142d084828501614102565b91505092915050565b6000602082840312156142ef576142ee61556d565b5b60006142fd84828501614130565b91505092915050565b60006020828403121561431c5761431b61556d565b5b600061432a84828501614145565b91505092915050565b6000806040838503121561434a5761434961556d565b5b600061435885828601614130565b925050602083013567ffffffffffffffff81111561437957614378615568565b5b614385858286016140aa565b9150509250929050565b6000806000606084860312156143a8576143a761556d565b5b60006143b686828701614130565b93505060206143c786828701614130565b925050604084013567ffffffffffffffff8111156143e8576143e7615568565b5b6143f4868287016140aa565b9150509250925092565b61440781615247565b82525050565b61441e61441982615247565b615405565b82525050565b61442d81615259565b82525050565b61443c81615265565b82525050565b61445361444e82615265565b615417565b82525050565b6144628161526f565b82525050565b600061447382614edf565b61447d8185614ef5565b935061448d818560208601615326565b61449681615572565b840191505092915050565b60006144ac82614edf565b6144b68185614f06565b93506144c6818560208601615326565b80840191505092915050565b6144e36144de826152cf565b615405565b82525050565b6144f2816152e1565b82525050565b600061450382614eea565b61450d8185614f11565b935061451d818560208601615326565b61452681615572565b840191505092915050565b600061453c82614eea565b6145468185614f22565b9350614556818560208601615326565b80840191505092915050565b600061456f601483614f11565b915061457a8261559d565b602082019050919050565b6000614592601c83614f11565b915061459d826155c6565b602082019050919050565b60006145b5601483614f11565b91506145c0826155ef565b602082019050919050565b60006145d8602883614f11565b91506145e382615618565b604082019050919050565b60006145fb602e83614f11565b915061460682615667565b604082019050919050565b600061461e602383614f11565b9150614629826156b6565b604082019050919050565b6000614641601283614f11565b915061464c82615705565b602082019050919050565b6000614664601c83614f11565b915061466f8261572e565b602082019050919050565b6000614687601883614f11565b915061469282615757565b602082019050919050565b60006146aa602683614f11565b91506146b582615780565b604082019050919050565b60006146cd603a83614f11565b91506146d8826157cf565b604082019050919050565b60006146f0601483614f11565b91506146fb8261581e565b602082019050919050565b6000614713600a83614f11565b915061471e82615847565b602082019050919050565b6000614736601083614f11565b915061474182615870565b602082019050919050565b6000614759602683614f11565b915061476482615899565b604082019050919050565b600061477c601783614f11565b9150614787826158e8565b602082019050919050565b600061479f601d83614f11565b91506147aa82615911565b602082019050919050565b60006147c2601e83614f11565b91506147cd8261593a565b602082019050919050565b60006147e5601b83614f11565b91506147f082615963565b602082019050919050565b6000614808602883614f11565b91506148138261598c565b604082019050919050565b600061482b602683614f11565b9150614836826159db565b604082019050919050565b600061484e602a83614f11565b915061485982615a2a565b604082019050919050565b6000614871601583614f11565b915061487c82615a79565b602082019050919050565b614890816152c5565b82525050565b6148a76148a2826152c5565b615433565b82525050565b60006148b9828561440d565b6014820191506148c98284614896565b6020820191508190509392505050565b60006148e58285614442565b6020820191506148f58284614442565b6020820191508190509392505050565b600061491182846144a1565b915081905092915050565b600061492882856144d2565b6014820191506149388284614896565b6020820191508190509392505050565b60006149548284614531565b915081905092915050565b600060208201905061497460008301846143fe565b92915050565b600060408201905061498f60008301856143fe565b61499c60208301846143fe565b9392505050565b60006060820190506149b860008301866143fe565b6149c560208301856143fe565b6149d26040830184614887565b949350505050565b60006040820190506149ef60008301856143fe565b6149fc6020830184614887565b9392505050565b600061010082019050614a19600083018b6143fe565b614a26602083018a614887565b614a336040830189614433565b614a4060608301886143fe565b614a4d6080830187614459565b614a5a60a0830186614887565b614a6760c0830185614887565b81810360e0830152614a798184614468565b90509998505050505050505050565b6000606082019050614a9d60008301866143fe565b614aaa6020830185614887565b8181036040830152614abc8184614468565b9050949350505050565b6000602082019050614adb6000830184614424565b92915050565b6000602082019050614af66000830184614433565b92915050565b6000602082019050614b1160008301846144e9565b92915050565b60006020820190508181036000830152614b3181846144f8565b905092915050565b60006020820190508181036000830152614b5281614562565b9050919050565b60006020820190508181036000830152614b7281614585565b9050919050565b60006020820190508181036000830152614b92816145a8565b9050919050565b60006020820190508181036000830152614bb2816145cb565b9050919050565b60006020820190508181036000830152614bd2816145ee565b9050919050565b60006020820190508181036000830152614bf281614611565b9050919050565b60006020820190508181036000830152614c1281614634565b9050919050565b60006020820190508181036000830152614c3281614657565b9050919050565b60006020820190508181036000830152614c528161467a565b9050919050565b60006020820190508181036000830152614c728161469d565b9050919050565b60006020820190508181036000830152614c92816146c0565b9050919050565b60006020820190508181036000830152614cb2816146e3565b9050919050565b60006020820190508181036000830152614cd281614706565b9050919050565b60006020820190508181036000830152614cf281614729565b9050919050565b60006020820190508181036000830152614d128161474c565b9050919050565b60006020820190508181036000830152614d328161476f565b9050919050565b60006020820190508181036000830152614d5281614792565b9050919050565b60006020820190508181036000830152614d72816147b5565b9050919050565b60006020820190508181036000830152614d92816147d8565b9050919050565b60006020820190508181036000830152614db2816147fb565b9050919050565b60006020820190508181036000830152614dd28161481e565b9050919050565b60006020820190508181036000830152614df281614841565b9050919050565b60006020820190508181036000830152614e1281614864565b9050919050565b6000602082019050614e2e6000830184614887565b92915050565b6000604082019050614e496000830185614887565b614e566020830184614887565b9392505050565b6000614e67614e78565b9050614e73828261538b565b919050565b6000604051905090565b600067ffffffffffffffff821115614e9d57614e9c61552a565b5b602082029050602081019050919050565b600067ffffffffffffffff821115614ec957614ec861552a565b5b614ed282615572565b9050602081019050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b6000614f38826152c5565b9150614f43836152c5565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115614f7857614f7761546e565b5b828201905092915050565b6000614f8e826152c5565b9150614f99836152c5565b925082614fa957614fa861549d565b5b828204905092915050565b6000808291508390505b6001851115614ffe57808604811115614fda57614fd961546e565b5b6001851615614fe95780820291505b8081029050614ff785615590565b9450614fbe565b94509492505050565b6000615012826152c5565b915061501d836152c5565b925061504a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484615052565b905092915050565b600082615062576001905061511e565b81615070576000905061511e565b81600181146150865760028114615090576150bf565b600191505061511e565b60ff8411156150a2576150a161546e565b5b8360020a9150848211156150b9576150b861546e565b5b5061511e565b5060208310610133831016604e8410600b84101617156150f45782820a9050838111156150ef576150ee61546e565b5b61511e565b6151018484846001614fb4565b925090508184048111156151185761511761546e565b5b81810290505b9392505050565b6000615130826152c5565b915061513b836152c5565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156151745761517361546e565b5b828202905092915050565b600061518a8261529b565b91506151958361529b565b9250827f8000000000000000000000000000000000000000000000000000000000000000018212600084121516156151d0576151cf61546e565b5b827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0182136000841216156152085761520761546e565b5b828203905092915050565b600061521e826152c5565b9150615229836152c5565b92508282101561523c5761523b61546e565b5b828203905092915050565b6000615252826152a5565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006152da826152f3565b9050919050565b60006152ec826152f3565b9050919050565b60006152fe82615305565b9050919050565b6000615310826152a5565b9050919050565b82818337600083830152505050565b60005b83811015615344578082015181840152602081019050615329565b83811115615353576000848401525b50505050565b6000600282049050600182168061537157607f821691505b60208210811415615385576153846154cc565b5b50919050565b61539482615572565b810181811067ffffffffffffffff821117156153b3576153b261552a565b5b80604052505050565b60006153c7826152c5565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156153fa576153f961546e565b5b600182019050919050565b600061541082615421565b9050919050565b6000819050919050565b600061542c82615583565b9050919050565b6000819050919050565b6000615448826152c5565b9150615453836152c5565b9250826154635761546261549d565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b60008160601b9050919050565b60008160011c9050919050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b7f496e73756666696369656e7420746f6b656e20616c6c6f77616e636500000000600082015250565b7f5573696e67207468652073616d65206a6f624964000000000000000000000000600082015250565b7f41697264726f7020636c61696d65642e20496e656c696769626c6520666f722060008201527f7075726368617365000000000000000000000000000000000000000000000000602082015250565b7f496e73756666696369656e7420746f6b656e7320746f2070617274696369706160008201527f746520696e207075726368617365000000000000000000000000000000000000602082015250565b7f756e61626c6520746f207472616e73666572416e6443616c6c20746f206f726160008201527f636c650000000000000000000000000000000000000000000000000000000000602082015250565b7f52656a656374696e672061203020726174650000000000000000000000000000600082015250565b7f5573696e67207468652073616d65207072696365466565645061746800000000600082015250565b7f5573696e67207468652073616d65206f7261636c654665650000000000000000600082015250565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b7f496e656c696769626c6520746f20706172746963697061746520696e2070757260008201527f63686173652e205365652061697264726f7020696e7374656164000000000000602082015250565b7f5573696e67207468652073616d6520746f6b656e000000000000000000000000600082015250565b7f496e656c696769626c6500000000000000000000000000000000000000000000600082015250565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b7f417474656d7074696e6720746f20627579206d6f7265207468616e20616c6c6f60008201527f636174696f6e0000000000000000000000000000000000000000000000000000602082015250565b7f41697264726f7020616c726561647920636c61696d6564000000000000000000600082015250565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b7f596f7527766520626567756e2070757263686173696e6720746f6b656e730000600082015250565b7f5573696e67207468652073616d65207072696365466565645552490000000000600082015250565b7f536f75726365206d75737420626520746865206f7261636c65206f662074686560008201527f2072657175657374000000000000000000000000000000000000000000000000602082015250565b7f46756e6374696f6e206973206f6e6c792063616c6c61626c652062792074686560008201527f206f776e65720000000000000000000000000000000000000000000000000000602082015250565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b7f5573696e67207468652073616d65206f7261636c650000000000000000000000600082015250565b615aab81615247565b8114615ab657600080fd5b50565b615ac281615259565b8114615acd57600080fd5b50565b615ad981615265565b8114615ae457600080fd5b50565b615af0816152c5565b8114615afb57600080fd5b5056fea2646970667358221220b0b0167dfca59898396b1ec9601014df9281c4bc22ad756ff1a351d4080e5af564736f6c6343000807003322d0b44d4d1527c9e1a337a08cb4ded4677be3891eb99b9a3db476f5ba492044000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000006307b25a665efc992ec1c1bc403c38f3ddd7c661000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca000000000000000000000000b92ec7d213a28e21b426d79ede3c9bbcf6917c090000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000016345785d8a00000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000203162396639623162613230333439323961323131333163346437643762313831000000000000000000000000000000000000000000000000000000000000008c68747470733a2f2f6170692e636f696e6765636b6f2e636f6d2f6170692f76332f73696d706c652f746f6b656e5f70726963652f657468657265756d3f636f6e74726163745f6164647265737365733d3078363330376232356136363565666339393265633163316263343033633338663364646437633636312676735f63757272656e636965733d5553440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002e3078363330376232356136363565666339393265633163316263343033633338663364646437633636312e757364000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106102345760003560e01c80635c975abb1161012e578063adc764bf116100ab578063db848d491161006f578063db848d491461086f578063ecbe74aa1461089a578063f95e0053146108c5578063fc2ea8a5146108ee578063ff6e2988146109195761023b565b8063adc764bf1461078a578063b7ce5010146107b5578063cfb51928146107de578063d4bd49931461081b578063d7322862146108445761023b565b80638532ac4e116100f25780638532ac4e1461067d57806389476069146106ba5780638da5cb5b146106f7578063a71ede6c14610722578063acceba771461075f5761023b565b80635c975abb1461059857806377eb8126146105c35780637bd49056146106005780637e9dce76146106295780638456cb59146106665761023b565b80632bbfe897116101bc5780633efbd330116101805780633efbd330146104c75780633f4ba83a146105045780634357855e1461051b5780634eca519f1461054457806357970e931461056d5761023b565b80632bbfe897146103e05780632bcbc18f1461040b5780632c4e722e146104485780632eb4a7ab1461047357806334fcf4371461049e5761023b565b806311eac8551161020357806311eac8551461030d578063125dc8311461033857806313af403514610361578063202806a41461038a578063280da6fa146103b55761023b565b8063013eef4f1461023d57806307c1e2f01461027a5780630bcae1ac146102a55780631193d7e3146102e25761023b565b3661023b57005b005b34801561024957600080fd5b50610264600480360381019061025f919061415a565b610944565b6040516102719190614e19565b60405180910390f35b34801561028657600080fd5b5061028f61098d565b60405161029c9190614b17565b60405180910390f35b3480156102b157600080fd5b506102cc60048036038101906102c79190614333565b610a1b565b6040516102d99190614ac6565b60405180910390f35b3480156102ee57600080fd5b506102f7610c7b565b6040516103049190614afc565b60405180910390f35b34801561031957600080fd5b50610322610ca1565b60405161032f9190614afc565b60405180910390f35b34801561034457600080fd5b5061035f600480360381019061035a9190614290565b610cc7565b005b34801561036d57600080fd5b506103886004803603810190610383919061415a565b610e45565b005b34801561039657600080fd5b5061039f61102a565b6040516103ac9190614b17565b60405180910390f35b3480156103c157600080fd5b506103ca6110b8565b6040516103d79190614ac6565b60405180910390f35b3480156103ec57600080fd5b506103f5611790565b604051610402919061495f565b60405180910390f35b34801561041757600080fd5b50610432600480360381019061042d9190614187565b6117b6565b60405161043f9190614ac6565b60405180910390f35b34801561045457600080fd5b5061045d6117ce565b60405161046a9190614e19565b60405180910390f35b34801561047f57600080fd5b506104886117d4565b6040516104959190614ae1565b60405180910390f35b3480156104aa57600080fd5b506104c560048036038101906104c091906142d9565b6117f8565b005b3480156104d357600080fd5b506104ee60048036038101906104e99190614187565b611949565b6040516104fb9190614e19565b60405180910390f35b34801561051057600080fd5b506105196119ff565b005b34801561052757600080fd5b50610542600480360381019061053d9190614250565b611a99565b005b34801561055057600080fd5b5061056b60048036038101906105669190614223565b611bda565b005b34801561057957600080fd5b50610582611cb9565b60405161058f9190614afc565b60405180910390f35b3480156105a457600080fd5b506105ad611cdf565b6040516105ba9190614ac6565b60405180910390f35b3480156105cf57600080fd5b506105ea60048036038101906105e5919061415a565b611cf5565b6040516105f79190614ac6565b60405180910390f35b34801561060c57600080fd5b50610627600480360381019061062291906142d9565b611d4b565b005b34801561063557600080fd5b50610650600480360381019061064b9190614187565b611e2a565b60405161065d9190614e19565b60405180910390f35b34801561067257600080fd5b5061067b611ed4565b005b34801561068957600080fd5b506106a4600480360381019061069f919061438f565b611f6e565b6040516106b19190614ac6565b60405180910390f35b3480156106c657600080fd5b506106e160048036038101906106dc919061415a565b61222a565b6040516106ee9190614ac6565b60405180910390f35b34801561070357600080fd5b5061070c6124ae565b604051610719919061495f565b60405180910390f35b34801561072e57600080fd5b5061074960048036038101906107449190614187565b6124d4565b6040516107569190614ac6565b60405180910390f35b34801561076b57600080fd5b5061077461252f565b604051610781919061495f565b60405180910390f35b34801561079657600080fd5b5061079f612555565b6040516107ac9190614e19565b60405180910390f35b3480156107c157600080fd5b506107dc60048036038101906107d7919061415a565b61255b565b005b3480156107ea57600080fd5b5061080560048036038101906108009190614290565b6126c0565b6040516108129190614ae1565b60405180910390f35b34801561082757600080fd5b50610842600480360381019061083d919061415a565b6126ea565b005b34801561085057600080fd5b5061085961284f565b6040516108669190614ae1565b60405180910390f35b34801561087b57600080fd5b50610884612a96565b604051610891919061495f565b60405180910390f35b3480156108a657600080fd5b506108af612abc565b6040516108bc9190614e19565b60405180910390f35b3480156108d157600080fd5b506108ec60048036038101906108e79190614290565b612ac2565b005b3480156108fa57600080fd5b50610903612c40565b6040516109109190614e19565b60405180910390f35b34801561092557600080fd5b5061092e612c46565b60405161093b9190614e19565b60405180910390f35b6000601860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6016805461099a90615359565b80601f01602080910402602001604051908101604052809291908181526020018280546109c690615359565b8015610a135780601f106109e857610100808354040283529160200191610a13565b820191906000526020600020905b8154815290600101906020018083116109f657829003601f168201915b505050505081565b6000610a25611cdf565b15610a65576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5c90614cd9565b60405180910390fd5b610a6e33611cf5565b15610aae576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa590614d19565b60405180910390fd5b6000601860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414610b30576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b2790614d59565b60405180910390fd5b610b3b338484612c4c565b610b7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b7190614cb9565b60405180910390fd5b6001601760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550610c2133600e54600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612ced9092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167fcebbbce55cb558a80c89a83b5e23dca5186979853be88c28e9e01232c7fdc98b600e54604051610c699190614e19565b60405180910390a26001905092915050565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b3373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610d57576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d4e90614db9565b60405180910390fd5b610deb60158054610d6790615359565b80601f0160208091040260200160405190810160405280929190818152602001828054610d9390615359565b8015610de05780601f10610db557610100808354040283529160200191610de0565b820191906000526020600020905b815481529060010190602001808311610dc357829003601f168201915b505050505082612d73565b15610e2b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2290614d79565b60405180910390fd5b8060159080519060200190610e41929190613eb9565b5050565b3373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610ed5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ecc90614db9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610f0f57600080fd5b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610f6a57600080fd5b8073ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fcbf985117192c8f614a58aaf97226bb80a754772f5f6edf06f87c675f2e6c66360405160405180910390a380600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6015805461103790615359565b80601f016020809104026020016040519081016040528092919081815260200182805461106390615359565b80156110b05780601f10611085576101008083540402835291602001916110b0565b820191906000526020600020905b81548152906001019060200180831161109357829003601f168201915b505050505081565b60003373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461114a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161114190614db9565b60405180910390fd5b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016111a7919061495f565b60206040518083038186803b1580156111bf57600080fd5b505afa1580156111d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f79190614306565b111561131757611316600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161127e919061495f565b60206040518083038186803b15801561129657600080fd5b505afa1580156112aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ce9190614306565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612ced9092919063ffffffff16565b5b6000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401611374919061495f565b60206040518083038186803b15801561138c57600080fd5b505afa1580156113a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c49190614306565b11156114e4576114e3600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161144b919061495f565b60206040518083038186803b15801561146357600080fd5b505afa158015611477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149b9190614306565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612ced9092919063ffffffff16565b5b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401611541919061495f565b60206040518083038186803b15801561155957600080fd5b505afa15801561156d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115919190614306565b11156116b1576116b0600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401611618919061495f565b60206040518083038186803b15801561163057600080fd5b505afa158015611644573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116689190614306565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612ced9092919063ffffffff16565b5b600047111561172457600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f19350505050158015611722573d6000803e3d6000fd5b505b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f2b3ede1cd1dfcbe081c86c4381460612351a278070aef7f89dad40e805fda5ab60405160405180910390a26001905090565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806117c4858585611e2a565b1190509392505050565b600d5481565b7f22d0b44d4d1527c9e1a337a08cb4ded4677be3891eb99b9a3db476f5ba49204481565b3373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611888576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161187f90614db9565b60405180910390fd5b600081116118cb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118c290614bf9565b60405180910390fd5b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f9002403f1fb7daf8ef984c2925644987f2198485d18e7818fe275bf93244314e600d5483604051611937929190614e34565b60405180910390a280600d8190555050565b6000611956848484612c4c565b611995576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161198c90614cb9565b60405180910390fd5b6000601860008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060006119e6868686611e2a565b905081816119f49190615213565b925050509392505050565b3373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611a8f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a8690614db9565b60405180910390fd5b611a97612dcc565b565b816005600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b3290614d99565b60405180910390fd5b6005600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055807f7cc135e0cebb02c3480ae5d74d377283180a2601f8f644edf7987b009316c63a60405160405180910390a26101908210611bcb57600a600983611bb69190615125565b611bc09190614f83565b600d81905550611bd5565b61015e600d819055505b505050565b3373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611c6a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c6190614db9565b60405180910390fd5b806013541415611caf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ca690614b79565b60405180910390fd5b8060138190555050565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060009054906101000a900460ff16905090565b6000601760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b3373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611ddb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dd290614db9565b60405180910390fd5b806014541415611e20576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e1790614c39565b60405180910390fd5b8060148190555050565b6000611e37848484612c4c565b611e76576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e6d90614cb9565b60405180910390fd5b600f54831115611e895760009050611ecd565b623567e08310611ea85782600f54611ea19190615213565b9050611ecc565b6011548310611ec65782601054611ebf9190615213565b9050611ecb565b600090505b5b5b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611f64576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f5b90614db9565b60405180910390fd5b611f6c612e6d565b565b6000611f78611cdf565b15611fb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611faf90614cd9565b60405180910390fd5b611fc133611cf5565b15612001576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ff890614b99565b60405180910390fd5b61200c338484612c4c565b61204b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161204290614cb9565b60405180910390fd5b601154831015612090576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161208790614bb9565b60405180910390fd5b600f548311156120d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120cc90614c79565b60405180910390fd5b600080623567e08510612153576120ed338686611949565b915081861115612132576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161212990614cf9565b60405180910390fd5b600d54866121409190615125565b905061214d338288612f0f565b506121cf565b60115485106121cd57612167338686611949565b9150818611156121ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121a390614cf9565b60405180910390fd5b600d54866121ba9190615125565b90506121c7338288612f0f565b506121ce565b5b5b3373ffffffffffffffffffffffffffffffffffffffff167f2499a5330ab0979cc612135e7883ebc3cd5c9f7a8508f042540c34723348f632876040516122159190614e19565b60405180910390a26001925050509392505050565b60003373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146122bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122b390614db9565b60405180910390fd5b600082905060008173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016122fc919061495f565b60206040518083038186803b15801561231457600080fd5b505afa158015612328573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061234c9190614306565b111561242857612427600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016123b1919061495f565b60206040518083038186803b1580156123c957600080fd5b505afa1580156123dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124019190614306565b8373ffffffffffffffffffffffffffffffffffffffff16612ced9092919063ffffffff16565b5b8273ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fce9ecd720079c00c86716fadb783ea8b0577f02c0f55b98d8a4a86ecdcb7918b60405160405180910390a36001915050919050565b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006124e1848484612c4c565b612520576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161251790614cb9565b60405180910390fd5b600f5483101590509392505050565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60115481565b3373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146125eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125e290614db9565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561267c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161267390614c99565b60405180910390fd5b80600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000808290506000815114156126dc576000801b9150506126e5565b60208301519150505b919050565b3373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461277a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161277190614db9565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561280b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161280290614df9565b60405180910390fd5b80601260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008061286660135430634357855e60e01b613019565b905061293c6040518060400160405280600381526020017f6765740000000000000000000000000000000000000000000000000000000000815250601580546128ae90615359565b80601f01602080910402602001604051908101604052809291908181526020018280546128da90615359565b80156129275780601f106128fc57610100808354040283529160200191612927565b820191906000526020600020905b81548152906001019060200180831161290a57829003601f168201915b50505050508361304a9092919063ffffffff16565b612a106040518060400160405280600481526020017f70617468000000000000000000000000000000000000000000000000000000008152506016805461298290615359565b80601f01602080910402602001604051908101604052809291908181526020018280546129ae90615359565b80156129fb5780601f106129d0576101008083540402835291602001916129fb565b820191906000526020600020905b8154815290600101906020018083116129de57829003601f168201915b50505050508361304a9092919063ffffffff16565b600060649050612a606040518060400160405280600581526020017f74696d6573000000000000000000000000000000000000000000000000000000815250828461307d9092919063ffffffff16565b612a8f601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836014546130b0565b9250505090565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600f5481565b3373ffffffffffffffffffffffffffffffffffffffff16600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612b52576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b4990614db9565b60405180910390fd5b612be660168054612b6290615359565b80601f0160208091040260200160405190810160405280929190818152602001828054612b8e90615359565b8015612bdb5780601f10612bb057610100808354040283529160200191612bdb565b820191906000526020600020905b815481529060010190602001808311612bbe57829003601f168201915b505050505082612d73565b15612c26576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c1d90614c19565b60405180910390fd5b8060169080519060200190612c3c929190613eb9565b5050565b600e5481565b60105481565b6000808484604051602001612c629291906148ad565b6040516020818303038152906040528051906020012090506000612ca7847f22d0b44d4d1527c9e1a337a08cb4ded4677be3891eb99b9a3db476f5ba4920448461317c565b905080612ce0576040517f8a585be200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001925050509392505050565b612d6e8363a9059cbb60e01b8484604051602401612d0c9291906149da565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613193565b505050565b600081604051602001612d869190614948565b6040516020818303038152906040528051906020012083604051602001612dad9190614948565b6040516020818303038152906040528051906020012014905092915050565b612dd4611cdf565b612e13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e0a90614b39565b60405180910390fd5b60008060006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612e5661325a565b604051612e63919061495f565b60405180910390a1565b612e75611cdf565b15612eb5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612eac90614cd9565b60405180910390fd5b60016000806101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612ef861325a565b604051612f05919061495f565b60405180910390a1565b6000612f1b8484613262565b50612f6b843085600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16613362909392919063ffffffff16565b612fb88483600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612ced9092919063ffffffff16565b81601860008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546130079190614f2d565b92505081905550600190509392505050565b613021613f3f565b613029613f3f565b613040858585846133eb909392919063ffffffff16565b9150509392505050565b61306182846080015161349b90919063ffffffff16565b61307881846080015161349b90919063ffffffff16565b505050565b61309482846080015161349b90919063ffffffff16565b6130ab8184608001516134c090919063ffffffff16565b505050565b60008060045490506001816130c59190614f2d565b6004819055506000634042994660e01b60008087600001513089604001518760018c6080015160000151604051602401613106989796959493929190614a03565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506131718683868461356d565b925050509392505050565b6000826131898584613711565b1490509392505050565b60006131f5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166137c49092919063ffffffff16565b9050600081511115613255578080602001905181019061321591906141f6565b613254576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161324b90614dd9565b60405180910390fd5b5b505050565b600033905090565b600080600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e85306040518363ffffffff1660e01b81526004016132c292919061497a565b60206040518083038186803b1580156132da57600080fd5b505afa1580156132ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133129190614306565b905082811015613357576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161334e90614b59565b60405180910390fd5b600191505092915050565b6133e5846323b872dd60e01b858585604051602401613383939291906149a3565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613193565b50505050565b6133f3613f3f565b61340385608001516101006137dc565b508385600001818152505082856020019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508185604001907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681525050849050949350505050565b6134a88260038351613846565b6134bb81836139cb90919063ffffffff16565b505050565b7fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008112156134f7576134f282826139ed565b613569565b67ffffffffffffffff811315613516576135118282613a64565b613568565b6000811261352f5761352a82600083613846565b613567565b613566826001837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff613561919061517f565b613846565b5b5b5b5050565b6000308460405160200161358292919061491c565b604051602081830303815290604052805190602001209050846005600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550807fb5e6e01e79f91267dc17b4e6314d5d4d03593d2ceee0fbb452b750bd70ea5af960405160405180910390a2600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634000aea08685856040518463ffffffff1660e01b815260040161367893929190614a88565b602060405180830381600087803b15801561369257600080fd5b505af11580156136a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136ca91906141f6565b613709576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161370090614bd9565b60405180910390fd5b949350505050565b60008082905060005b84518110156137b9576000858281518110613738576137376154fb565b5b6020026020010151905080831161377957828160405160200161375c9291906148d9565b6040516020818303038152906040528051906020012092506137a5565b808360405160200161378c9291906148d9565b6040516020818303038152906040528051906020012092505b5080806137b1906153bc565b91505061371a565b508091505092915050565b60606137d38484600085613ab0565b90509392505050565b6137e4613fac565b60006020836137f3919061543d565b1461381f57602082613805919061543d565b60206138119190615213565b8261381c9190614f2d565b91505b81836020018181525050604051808452600081528281016020016040525082905092915050565b60178167ffffffffffffffff161161387d576138778160058460ff16901b60ff161784613bc490919063ffffffff16565b506139c6565b60ff8167ffffffffffffffff16116138d3576138ac601860058460ff16901b1784613bc490919063ffffffff16565b506138cd8167ffffffffffffffff16600185613be49092919063ffffffff16565b506139c5565b61ffff8167ffffffffffffffff161161392a57613903601960058460ff16901b1784613bc490919063ffffffff16565b506139248167ffffffffffffffff16600285613be49092919063ffffffff16565b506139c4565b63ffffffff8167ffffffffffffffff16116139835761395c601a60058460ff16901b1784613bc490919063ffffffff16565b5061397d8167ffffffffffffffff16600485613be49092919063ffffffff16565b506139c3565b6139a0601b60058460ff16901b1784613bc490919063ffffffff16565b506139c18167ffffffffffffffff16600885613be49092919063ffffffff16565b505b5b5b5b505050565b6139d3613fac565b6139e583846000015151848551613c06565b905092915050565b613a0b60036005600660ff16901b1783613bc490919063ffffffff16565b50613a6082827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff613a3c919061517f565b604051602001613a4c9190614e19565b604051602081830303815290604052613cf5565b5050565b613a8260026005600660ff16901b1783613bc490919063ffffffff16565b50613aac8282604051602001613a989190614e19565b604051602081830303815290604052613cf5565b5050565b606082471015613af5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613aec90614c59565b60405180910390fd5b613afe85613d1a565b613b3d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613b3490614d39565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051613b669190614905565b60006040518083038185875af1925050503d8060008114613ba3576040519150601f19603f3d011682016040523d82523d6000602084013e613ba8565b606091505b5091509150613bb8828286613d2d565b92505050949350505050565b613bcc613fac565b613bdc8384600001515184613d94565b905092915050565b613bec613fac565b613bfd848560000151518585613deb565b90509392505050565b613c0e613fac565b8251821115613c1c57600080fd5b84602001518285613c2d9190614f2d565b1115613c6257613c61856002613c5288602001518887613c4d9190614f2d565b613e79565b613c5c9190615125565b613e95565b5b600080865180518760208301019350808887011115613c815787860182525b60208701925050505b60208410613cc85780518252602082613ca39190614f2d565b9150602081613cb29190614f2d565b9050602084613cc19190615213565b9350613c8a565b60006001856020036101000a03905080198251168184511681811785525050508692505050949350505050565b613d028260028351613846565b613d1581836139cb90919063ffffffff16565b505050565b600080823b905060008111915050919050565b60608315613d3d57829050613d8d565b600083511115613d505782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613d849190614b17565b60405180910390fd5b9392505050565b613d9c613fac565b83602001518310613dc257613dc18460028660200151613dbc9190615125565b613e95565b5b8351805160208583010184815381861415613dde576001820183525b5050508390509392505050565b613df3613fac565b84602001518483613e049190614f2d565b1115613e2c57613e2b8560028685613e1c9190614f2d565b613e269190615125565b613e95565b5b6000600183610100613e3e9190615007565b613e489190615213565b90508551838682010185831982511617815281518588011115613e6b5784870182525b505085915050949350505050565b600081831115613e8b57829050613e8f565b8190505b92915050565b600082600001519050613ea883836137dc565b50613eb383826139cb565b50505050565b828054613ec590615359565b90600052602060002090601f016020900481019282613ee75760008555613f2e565b82601f10613f0057805160ff1916838001178555613f2e565b82800160010185558215613f2e579182015b82811115613f2d578251825591602001919060010190613f12565b5b509050613f3b9190613fc6565b5090565b6040518060a0016040528060008019168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200160008152602001613fa6613fac565b81525090565b604051806040016040528060608152602001600081525090565b5b80821115613fdf576000816000905550600101613fc7565b5090565b6000613ff6613ff184614e82565b614e5d565b905080838252602082019050828560208602820111156140195761401861555e565b5b60005b85811015614049578161402f88826140ed565b84526020840193506020830192505060018101905061401c565b5050509392505050565b600061406661406184614eae565b614e5d565b90508281526020810184848401111561408257614081615563565b5b61408d848285615317565b509392505050565b6000813590506140a481615aa2565b92915050565b600082601f8301126140bf576140be615559565b5b81356140cf848260208601613fe3565b91505092915050565b6000815190506140e781615ab9565b92915050565b6000813590506140fc81615ad0565b92915050565b600082601f83011261411757614116615559565b5b8135614127848260208601614053565b91505092915050565b60008135905061413f81615ae7565b92915050565b60008151905061415481615ae7565b92915050565b6000602082840312156141705761416f61556d565b5b600061417e84828501614095565b91505092915050565b6000806000606084860312156141a05761419f61556d565b5b60006141ae86828701614095565b93505060206141bf86828701614130565b925050604084013567ffffffffffffffff8111156141e0576141df615568565b5b6141ec868287016140aa565b9150509250925092565b60006020828403121561420c5761420b61556d565b5b600061421a848285016140d8565b91505092915050565b6000602082840312156142395761423861556d565b5b6000614247848285016140ed565b91505092915050565b600080604083850312156142675761426661556d565b5b6000614275858286016140ed565b925050602061428685828601614130565b9150509250929050565b6000602082840312156142a6576142a561556d565b5b600082013567ffffffffffffffff8111156142c4576142c3615568565b5b6142d084828501614102565b91505092915050565b6000602082840312156142ef576142ee61556d565b5b60006142fd84828501614130565b91505092915050565b60006020828403121561431c5761431b61556d565b5b600061432a84828501614145565b91505092915050565b6000806040838503121561434a5761434961556d565b5b600061435885828601614130565b925050602083013567ffffffffffffffff81111561437957614378615568565b5b614385858286016140aa565b9150509250929050565b6000806000606084860312156143a8576143a761556d565b5b60006143b686828701614130565b93505060206143c786828701614130565b925050604084013567ffffffffffffffff8111156143e8576143e7615568565b5b6143f4868287016140aa565b9150509250925092565b61440781615247565b82525050565b61441e61441982615247565b615405565b82525050565b61442d81615259565b82525050565b61443c81615265565b82525050565b61445361444e82615265565b615417565b82525050565b6144628161526f565b82525050565b600061447382614edf565b61447d8185614ef5565b935061448d818560208601615326565b61449681615572565b840191505092915050565b60006144ac82614edf565b6144b68185614f06565b93506144c6818560208601615326565b80840191505092915050565b6144e36144de826152cf565b615405565b82525050565b6144f2816152e1565b82525050565b600061450382614eea565b61450d8185614f11565b935061451d818560208601615326565b61452681615572565b840191505092915050565b600061453c82614eea565b6145468185614f22565b9350614556818560208601615326565b80840191505092915050565b600061456f601483614f11565b915061457a8261559d565b602082019050919050565b6000614592601c83614f11565b915061459d826155c6565b602082019050919050565b60006145b5601483614f11565b91506145c0826155ef565b602082019050919050565b60006145d8602883614f11565b91506145e382615618565b604082019050919050565b60006145fb602e83614f11565b915061460682615667565b604082019050919050565b600061461e602383614f11565b9150614629826156b6565b604082019050919050565b6000614641601283614f11565b915061464c82615705565b602082019050919050565b6000614664601c83614f11565b915061466f8261572e565b602082019050919050565b6000614687601883614f11565b915061469282615757565b602082019050919050565b60006146aa602683614f11565b91506146b582615780565b604082019050919050565b60006146cd603a83614f11565b91506146d8826157cf565b604082019050919050565b60006146f0601483614f11565b91506146fb8261581e565b602082019050919050565b6000614713600a83614f11565b915061471e82615847565b602082019050919050565b6000614736601083614f11565b915061474182615870565b602082019050919050565b6000614759602683614f11565b915061476482615899565b604082019050919050565b600061477c601783614f11565b9150614787826158e8565b602082019050919050565b600061479f601d83614f11565b91506147aa82615911565b602082019050919050565b60006147c2601e83614f11565b91506147cd8261593a565b602082019050919050565b60006147e5601b83614f11565b91506147f082615963565b602082019050919050565b6000614808602883614f11565b91506148138261598c565b604082019050919050565b600061482b602683614f11565b9150614836826159db565b604082019050919050565b600061484e602a83614f11565b915061485982615a2a565b604082019050919050565b6000614871601583614f11565b915061487c82615a79565b602082019050919050565b614890816152c5565b82525050565b6148a76148a2826152c5565b615433565b82525050565b60006148b9828561440d565b6014820191506148c98284614896565b6020820191508190509392505050565b60006148e58285614442565b6020820191506148f58284614442565b6020820191508190509392505050565b600061491182846144a1565b915081905092915050565b600061492882856144d2565b6014820191506149388284614896565b6020820191508190509392505050565b60006149548284614531565b915081905092915050565b600060208201905061497460008301846143fe565b92915050565b600060408201905061498f60008301856143fe565b61499c60208301846143fe565b9392505050565b60006060820190506149b860008301866143fe565b6149c560208301856143fe565b6149d26040830184614887565b949350505050565b60006040820190506149ef60008301856143fe565b6149fc6020830184614887565b9392505050565b600061010082019050614a19600083018b6143fe565b614a26602083018a614887565b614a336040830189614433565b614a4060608301886143fe565b614a4d6080830187614459565b614a5a60a0830186614887565b614a6760c0830185614887565b81810360e0830152614a798184614468565b90509998505050505050505050565b6000606082019050614a9d60008301866143fe565b614aaa6020830185614887565b8181036040830152614abc8184614468565b9050949350505050565b6000602082019050614adb6000830184614424565b92915050565b6000602082019050614af66000830184614433565b92915050565b6000602082019050614b1160008301846144e9565b92915050565b60006020820190508181036000830152614b3181846144f8565b905092915050565b60006020820190508181036000830152614b5281614562565b9050919050565b60006020820190508181036000830152614b7281614585565b9050919050565b60006020820190508181036000830152614b92816145a8565b9050919050565b60006020820190508181036000830152614bb2816145cb565b9050919050565b60006020820190508181036000830152614bd2816145ee565b9050919050565b60006020820190508181036000830152614bf281614611565b9050919050565b60006020820190508181036000830152614c1281614634565b9050919050565b60006020820190508181036000830152614c3281614657565b9050919050565b60006020820190508181036000830152614c528161467a565b9050919050565b60006020820190508181036000830152614c728161469d565b9050919050565b60006020820190508181036000830152614c92816146c0565b9050919050565b60006020820190508181036000830152614cb2816146e3565b9050919050565b60006020820190508181036000830152614cd281614706565b9050919050565b60006020820190508181036000830152614cf281614729565b9050919050565b60006020820190508181036000830152614d128161474c565b9050919050565b60006020820190508181036000830152614d328161476f565b9050919050565b60006020820190508181036000830152614d5281614792565b9050919050565b60006020820190508181036000830152614d72816147b5565b9050919050565b60006020820190508181036000830152614d92816147d8565b9050919050565b60006020820190508181036000830152614db2816147fb565b9050919050565b60006020820190508181036000830152614dd28161481e565b9050919050565b60006020820190508181036000830152614df281614841565b9050919050565b60006020820190508181036000830152614e1281614864565b9050919050565b6000602082019050614e2e6000830184614887565b92915050565b6000604082019050614e496000830185614887565b614e566020830184614887565b9392505050565b6000614e67614e78565b9050614e73828261538b565b919050565b6000604051905090565b600067ffffffffffffffff821115614e9d57614e9c61552a565b5b602082029050602081019050919050565b600067ffffffffffffffff821115614ec957614ec861552a565b5b614ed282615572565b9050602081019050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b6000614f38826152c5565b9150614f43836152c5565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115614f7857614f7761546e565b5b828201905092915050565b6000614f8e826152c5565b9150614f99836152c5565b925082614fa957614fa861549d565b5b828204905092915050565b6000808291508390505b6001851115614ffe57808604811115614fda57614fd961546e565b5b6001851615614fe95780820291505b8081029050614ff785615590565b9450614fbe565b94509492505050565b6000615012826152c5565b915061501d836152c5565b925061504a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484615052565b905092915050565b600082615062576001905061511e565b81615070576000905061511e565b81600181146150865760028114615090576150bf565b600191505061511e565b60ff8411156150a2576150a161546e565b5b8360020a9150848211156150b9576150b861546e565b5b5061511e565b5060208310610133831016604e8410600b84101617156150f45782820a9050838111156150ef576150ee61546e565b5b61511e565b6151018484846001614fb4565b925090508184048111156151185761511761546e565b5b81810290505b9392505050565b6000615130826152c5565b915061513b836152c5565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156151745761517361546e565b5b828202905092915050565b600061518a8261529b565b91506151958361529b565b9250827f8000000000000000000000000000000000000000000000000000000000000000018212600084121516156151d0576151cf61546e565b5b827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0182136000841216156152085761520761546e565b5b828203905092915050565b600061521e826152c5565b9150615229836152c5565b92508282101561523c5761523b61546e565b5b828203905092915050565b6000615252826152a5565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006152da826152f3565b9050919050565b60006152ec826152f3565b9050919050565b60006152fe82615305565b9050919050565b6000615310826152a5565b9050919050565b82818337600083830152505050565b60005b83811015615344578082015181840152602081019050615329565b83811115615353576000848401525b50505050565b6000600282049050600182168061537157607f821691505b60208210811415615385576153846154cc565b5b50919050565b61539482615572565b810181811067ffffffffffffffff821117156153b3576153b261552a565b5b80604052505050565b60006153c7826152c5565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156153fa576153f961546e565b5b600182019050919050565b600061541082615421565b9050919050565b6000819050919050565b600061542c82615583565b9050919050565b6000819050919050565b6000615448826152c5565b9150615453836152c5565b9250826154635761546261549d565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b60008160601b9050919050565b60008160011c9050919050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b7f496e73756666696369656e7420746f6b656e20616c6c6f77616e636500000000600082015250565b7f5573696e67207468652073616d65206a6f624964000000000000000000000000600082015250565b7f41697264726f7020636c61696d65642e20496e656c696769626c6520666f722060008201527f7075726368617365000000000000000000000000000000000000000000000000602082015250565b7f496e73756666696369656e7420746f6b656e7320746f2070617274696369706160008201527f746520696e207075726368617365000000000000000000000000000000000000602082015250565b7f756e61626c6520746f207472616e73666572416e6443616c6c20746f206f726160008201527f636c650000000000000000000000000000000000000000000000000000000000602082015250565b7f52656a656374696e672061203020726174650000000000000000000000000000600082015250565b7f5573696e67207468652073616d65207072696365466565645061746800000000600082015250565b7f5573696e67207468652073616d65206f7261636c654665650000000000000000600082015250565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b7f496e656c696769626c6520746f20706172746963697061746520696e2070757260008201527f63686173652e205365652061697264726f7020696e7374656164000000000000602082015250565b7f5573696e67207468652073616d6520746f6b656e000000000000000000000000600082015250565b7f496e656c696769626c6500000000000000000000000000000000000000000000600082015250565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b7f417474656d7074696e6720746f20627579206d6f7265207468616e20616c6c6f60008201527f636174696f6e0000000000000000000000000000000000000000000000000000602082015250565b7f41697264726f7020616c726561647920636c61696d6564000000000000000000600082015250565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b7f596f7527766520626567756e2070757263686173696e6720746f6b656e730000600082015250565b7f5573696e67207468652073616d65207072696365466565645552490000000000600082015250565b7f536f75726365206d75737420626520746865206f7261636c65206f662074686560008201527f2072657175657374000000000000000000000000000000000000000000000000602082015250565b7f46756e6374696f6e206973206f6e6c792063616c6c61626c652062792074686560008201527f206f776e65720000000000000000000000000000000000000000000000000000602082015250565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b7f5573696e67207468652073616d65206f7261636c650000000000000000000000600082015250565b615aab81615247565b8114615ab657600080fd5b50565b615ac281615259565b8114615acd57600080fd5b50565b615ad981615265565b8114615ae457600080fd5b50565b615af0816152c5565b8114615afb57600080fd5b5056fea2646970667358221220b0b0167dfca59898396b1ec9601014df9281c4bc22ad756ff1a351d4080e5af564736f6c63430008070033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
22d0b44d4d1527c9e1a337a08cb4ded4677be3891eb99b9a3db476f5ba492044000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000006307b25a665efc992ec1c1bc403c38f3ddd7c661000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca000000000000000000000000b92ec7d213a28e21b426d79ede3c9bbcf6917c090000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000016345785d8a00000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000203162396639623162613230333439323961323131333163346437643762313831000000000000000000000000000000000000000000000000000000000000008c68747470733a2f2f6170692e636f696e6765636b6f2e636f6d2f6170692f76332f73696d706c652f746f6b656e5f70726963652f657468657265756d3f636f6e74726163745f6164647265737365733d3078363330376232356136363565666339393265633163316263343033633338663364646437633636312676735f63757272656e636965733d5553440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002e3078363330376232356136363565666339393265633163316263343033633338663364646437633636312e757364000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _merkleRoot (bytes32): 0x22d0b44d4d1527c9e1a337a08cb4ded4677be3891eb99b9a3db476f5ba492044
Arg [1] : _usdcTokenContract (address): 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
Arg [2] : _gcrTokenContract (address): 0x6307B25A665Efc992EC1C1bC403c38F3dDd7c661
Arg [3] : _linkTokenContract (address): 0x514910771AF9Ca656af840dff83E8264EcF986CA
Arg [4] : _oracle (address): 0xB92ec7D213a28e21b426D79EDe3c9BBcf6917c09
Arg [5] : _jobId (string): 1b9f9b1ba2034929a21131c4d7d7b181
Arg [6] : _oracleFee (uint256): 100000000000000000
Arg [7] : _priceFeedURI (string): https://api.coingecko.com/api/v3/simple/token_price/ethereum?contract_addresses=0x6307b25a665efc992ec1c1bc403c38f3ddd7c661&vs_currencies=USD
Arg [8] : _priceFeedPath (string): 0x6307b25a665efc992ec1c1bc403c38f3ddd7c661.usd
-----Encoded View---------------
20 Constructor Arguments found :
Arg [0] : 22d0b44d4d1527c9e1a337a08cb4ded4677be3891eb99b9a3db476f5ba492044
Arg [1] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [2] : 0000000000000000000000006307b25a665efc992ec1c1bc403c38f3ddd7c661
Arg [3] : 000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca
Arg [4] : 000000000000000000000000b92ec7d213a28e21b426d79ede3c9bbcf6917c09
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000120
Arg [6] : 000000000000000000000000000000000000000000000000016345785d8a0000
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000220
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [10] : 3162396639623162613230333439323961323131333163346437643762313831
Arg [11] : 000000000000000000000000000000000000000000000000000000000000008c
Arg [12] : 68747470733a2f2f6170692e636f696e6765636b6f2e636f6d2f6170692f7633
Arg [13] : 2f73696d706c652f746f6b656e5f70726963652f657468657265756d3f636f6e
Arg [14] : 74726163745f6164647265737365733d30783633303762323561363635656663
Arg [15] : 39393265633163316263343033633338663364646437633636312676735f6375
Arg [16] : 7272656e636965733d5553440000000000000000000000000000000000000000
Arg [17] : 000000000000000000000000000000000000000000000000000000000000002e
Arg [18] : 3078363330376232356136363565666339393265633163316263343033633338
Arg [19] : 663364646437633636312e757364000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ 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.