Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 2,380 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Grant Keys | 17086759 | 662 days ago | IN | 0 ETH | 0.00570601 | ||||
Grant Keys | 17063093 | 666 days ago | IN | 0 ETH | 0.01045779 | ||||
Grant Keys | 17061177 | 666 days ago | IN | 0 ETH | 0.01780054 | ||||
Grant Keys | 17056759 | 667 days ago | IN | 0 ETH | 0.01446688 | ||||
Purchase Keys | 17055295 | 667 days ago | IN | 0.075 ETH | 0.00076998 | ||||
Set Purchases En... | 17055285 | 667 days ago | IN | 0 ETH | 0.00054326 | ||||
Purchase Keys | 17055254 | 667 days ago | IN | 0.1 ETH | 0.00073877 | ||||
Purchase Keys | 17055251 | 667 days ago | IN | 0.075 ETH | 0.00309971 | ||||
Purchase Keys | 17055251 | 667 days ago | IN | 0.3 ETH | 0.00085522 | ||||
Purchase Keys | 17055250 | 667 days ago | IN | 0.075 ETH | 0.00315925 | ||||
Purchase Keys | 17055250 | 667 days ago | IN | 0.075 ETH | 0.00321806 | ||||
Purchase Keys | 17055250 | 667 days ago | IN | 0.375 ETH | 0.00929664 | ||||
Purchase Keys | 17055249 | 667 days ago | IN | 0.45 ETH | 0.00900137 | ||||
Purchase Keys | 17055248 | 667 days ago | IN | 0.075 ETH | 0.00321657 | ||||
Purchase Keys | 17055246 | 667 days ago | IN | 0.075 ETH | 0.00361169 | ||||
Purchase Keys | 17055242 | 667 days ago | IN | 0.075 ETH | 0.00333327 | ||||
Purchase Keys | 17055239 | 667 days ago | IN | 0 ETH | 0.00891498 | ||||
Purchase Keys | 17055239 | 667 days ago | IN | 0.075 ETH | 0.00344844 | ||||
Purchase Keys | 17055237 | 667 days ago | IN | 0.075 ETH | 0.00326027 | ||||
Purchase Keys | 17055234 | 667 days ago | IN | 0.975 ETH | 0.018238 | ||||
Purchase Keys | 17055232 | 667 days ago | IN | 0.075 ETH | 0.00306099 | ||||
Purchase Keys | 17055232 | 667 days ago | IN | 0.075 ETH | 0.00268809 | ||||
Purchase Keys | 17055228 | 667 days ago | IN | 0.05 ETH | 0.00411695 | ||||
Purchase Keys | 17055224 | 667 days ago | IN | 0.075 ETH | 0.00349412 | ||||
Purchase Keys | 17055224 | 667 days ago | IN | 0.15 ETH | 0.00478993 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
17055251 | 667 days ago | 0.075 ETH | ||||
17055250 | 667 days ago | 0.075 ETH | ||||
17055250 | 667 days ago | 0.075 ETH | ||||
17055250 | 667 days ago | 0.375 ETH | ||||
17055249 | 667 days ago | 0.45 ETH | ||||
17055248 | 667 days ago | 0.075 ETH | ||||
17055246 | 667 days ago | 0.075 ETH | ||||
17055242 | 667 days ago | 0.075 ETH | ||||
17055239 | 667 days ago | 0.075 ETH | ||||
17055237 | 667 days ago | 0.075 ETH | ||||
17055234 | 667 days ago | 0.975 ETH | ||||
17055232 | 667 days ago | 0.075 ETH | ||||
17055232 | 667 days ago | 0.075 ETH | ||||
17055228 | 667 days ago | 0.05 ETH | ||||
17055224 | 667 days ago | 0.075 ETH | ||||
17055224 | 667 days ago | 0.15 ETH | ||||
17055221 | 667 days ago | 0.075 ETH | ||||
17055221 | 667 days ago | 0.075 ETH | ||||
17055218 | 667 days ago | 0.075 ETH | ||||
17055217 | 667 days ago | 0.075 ETH | ||||
17055215 | 667 days ago | 0.075 ETH | ||||
17055215 | 667 days ago | 0.075 ETH | ||||
17055214 | 667 days ago | 0.075 ETH | ||||
17055212 | 667 days ago | 0.075 ETH | ||||
17055210 | 667 days ago | 0.075 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
UniversalKey
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // %% // .@@@@@@@@@ @@@@@@ @@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@ // @@@@@@@@@@@( @@@@@@@ .@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@ // @@@@@@@@@@@@@@ @@@@@@@ @@@@@@@ (@@@@@@ @@@@@@ // @@@@@@@ @@@@@@@ @@@@@@@ @@@@@@@ @@@@@@@@@@@ // @@@@@@@ @@@@@@@ @@@@@@ @@@@@@ @@@@@@@@@@@@@@ // @@@@@@@@@@@@@@@@@@ @@@@@@@ @@@@@@@ #@@@@@@@@@@ // @@@@@@@@@@@@@@@@@@@@ @@@@@@@ @@@@@@@ @@@@@@@ @@@@@@# // @@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@ @@@@@@@ @@@@@@@@@@@@@@@@@ // @@@@@@@ *@@@@@@ @@@@@@@@@@@@@@@@ @@@@@@ .@@@@@@@@@@@@ pragma solidity ^0.8.19; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; import "./interfaces/IDelegationRegistry.sol"; interface IAltsByAdidas is IERC721 { function walletOfOwner( address __owner, uint256 _startingIndex, uint256 _endingIndex ) external view returns (uint256[] memory); } interface IAdidasBluePass is IERC721 { function burnByOperator(uint256[] memory tokenIds) external; } /** * @title UniversalKey * @notice This contract enables ALTS by adidas holders to purchase Universal Keys * @dev This contract should be used with the ALTS by adidas ERC721 contract and optionally the Apecoin ERC20 token. */ contract UniversalKey is Ownable { using SafeERC20 for IERC20; struct Purchase { bool purchased; address owner; } /** * @notice ALTS by adidas ERC721 contract */ IERC721 public erc721; /** * @notice Blue Pass ERC721 contract */ IAdidasBluePass public bluePass; /** * @notice Apecoin ERC20 contract */ IERC20 public apeCoin; /** * @notice Wallet to receive funds */ address payable public receiver; /** * @notice The total limit of keys available for purchase. */ uint256 public totalKeyLimit; /** * @notice The total number of Universal Keys purchased. */ uint256 public totalKeysPurchased; /** * @notice Get the maximum number of ALTS permitted in each team */ uint256[8] public teamLimits; /** * @notice Exchange rate (# of APE per 1 ETH) */ uint256 public ethApeExchangeRate; /** * @notice Snapshot prices */ uint256[4] public snapshotPrices; /** * @notice Status of team selection */ bool public teamSelectionEnabled; /** * @notice Status of Universal Key purchases */ bool public purchasesEnabled; /** * @notice Status of team selection early access */ bool public earlyAccessEnabled; mapping(uint256 => uint8) private tokenTeam; mapping(uint8 => uint256) private teamMemberCounts; mapping(uint256 => Purchase) private tokenPurchases; mapping(address => uint256[]) private userPurchasedTokens; /** * @notice Discounted purchases remaining for relevant snapshot groups */ mapping(address => mapping(uint8 => bool)) public discountUsed; /** * @notice Token IDs with Universal Keys that are permitted for early access team selection */ mapping(uint256 => bool) public earlyAccessTokens; /** * @notice Merkle roots for snapshots */ mapping(uint8 => bytes32) public merkleRoots; IDelegationRegistry public immutable dc; constructor( address _erc721, address _bluePass, address _apeCoin, address payable _receiver, uint256[8] memory _teamLimits, uint256 _totalKeyLimit, uint256[4] memory _snapshotPrices, uint256 _ethApeExchangeRate, address _delegateCash, bytes32 _snapshot1Merkle, bytes32 _snapshot2Merkle, bytes32 _snapshot3Merkle ) { erc721 = IERC721(_erc721); bluePass = IAdidasBluePass(_bluePass); apeCoin = IERC20(_apeCoin); dc = IDelegationRegistry(_delegateCash); receiver = _receiver; totalKeyLimit = _totalKeyLimit; ethApeExchangeRate = _ethApeExchangeRate; snapshotPrices = _snapshotPrices; setMerkleRoot(0, _snapshot1Merkle); setMerkleRoot(1, _snapshot2Merkle); setMerkleRoot(2, _snapshot3Merkle); for (uint8 i = 0; i < 8; i++) { teamLimits[i] = _teamLimits[i]; } } /** * @notice Enables ALTS by adidas holders to burn a Blue Pass for a Universal Key * @dev Purchases one key at zero price for a burned Blue Pass * @param tokenId Blue Pass token ID * @param altTokenId The ALTS by adidas ALT token ID to purchase a key for */ function burnForKey(uint256 tokenId, uint256 altTokenId) public { require( purchasesEnabled || owner() == msg.sender, "Purchases are disabled" ); require( totalKeysPurchased + 1 <= totalKeyLimit, "Total token limit exceeded" ); require( bluePass.ownerOf(tokenId) == msg.sender, "User must own a Blue Pass" ); require( erc721.ownerOf(altTokenId) == msg.sender, "User must own the ALTS token ID" ); require( !tokenPurchases[altTokenId].purchased, "Key already purchased for ALT" ); // Burn the Blue Pass uint256[] memory passToBurn = new uint256[](1); passToBurn[0] = tokenId; bluePass.burnByOperator(passToBurn); // Ensure successful Blue Pass burn before purchase tokenPurchases[altTokenId] = Purchase(true, msg.sender); userPurchasedTokens[msg.sender].push(altTokenId); totalKeysPurchased += 1; uint256[] memory singleTokenId = new uint256[](1); singleTokenId[0] = altTokenId; } /** * @notice Enables ALTS by adidas holders to purchase Universal Keys * @dev Purchases keys for the provided ALTS token IDs and handles payment * @param tokenIds The ALTS by adidas ALTS token IDs to purchase keys for * @param useApe Whether to pay with Apecoin */ function purchaseKeys( uint256[] calldata tokenIds, bool useApe, address _vault, uint8[] calldata snapshotIds, bytes32[][] calldata proofs ) public payable { address requester = msg.sender; require( snapshotIds.length == proofs.length, "Snapshots/proofs length mismatch" ); require( purchasesEnabled || owner() == msg.sender, "Purchases are disabled" ); require( totalKeysPurchased + tokenIds.length <= totalKeyLimit, "Total token limit exceeded" ); if (_vault != address(0)) { bool isDelegateValid = dc.checkDelegateForContract( msg.sender, _vault, address(erc721) ); require(isDelegateValid, "invalid delegate-vault pairing"); requester = _vault; } for (uint256 i = 0; i < tokenIds.length; i++) { require( erc721.ownerOf(tokenIds[i]) == requester, "User must own the token ID" ); require( !tokenPurchases[tokenIds[i]].purchased, "Token ID already purchased" ); } uint256 price = 0; uint256 remainingKeys = tokenIds.length; bool[4] memory inSnapshot; for (uint256 i = 0; i < snapshotIds.length; i++) { inSnapshot[snapshotIds[i]] = isSnapshot( snapshotIds[i], requester, proofs[i] ); } if (inSnapshot[0] && !discountUsed[requester][0]) { price += snapshotPrices[0]; remainingKeys--; discountUsed[requester][0] = true; } if (remainingKeys > 0 && inSnapshot[1] && !discountUsed[requester][1]) { price += snapshotPrices[1]; remainingKeys--; discountUsed[requester][1] = true; } if (remainingKeys > 0) { uint256 nextLowestPrice = inSnapshot[2] ? snapshotPrices[2] : snapshotPrices[3]; price += nextLowestPrice * remainingKeys; } if (useApe) { require(msg.value == 0, "Should not send ETH with APE"); uint256 apePrice = getApePrice(price); SafeERC20.safeTransferFrom(apeCoin, msg.sender, receiver, apePrice); } else { require(msg.value == price, "Insufficient payment"); (bool sent, ) = receiver.call{value: price}(""); require(sent, "Failed to send Ether"); } for (uint256 i = 0; i < tokenIds.length; i++) { tokenPurchases[tokenIds[i]] = Purchase(true, requester); userPurchasedTokens[requester].push(tokenIds[i]); } unchecked { totalKeysPurchased += tokenIds.length; } } /** * @notice Admin function to assign keys to ALTS * @param tokenIds The ALTS token IDs */ function grantKeys(uint256[] calldata tokenIds) public onlyOwner { for (uint256 i = 0; i < tokenIds.length; i++) { uint256 tokenId = tokenIds[i]; address wallet = erc721.ownerOf(tokenId); require( !tokenPurchases[tokenId].purchased, "Token ID already has key" ); tokenPurchases[tokenId] = Purchase(true, wallet); userPurchasedTokens[wallet].push(tokenId); totalKeysPurchased++; } } /** * @notice Admin function to update the wallet address to receive funds from purchases * @dev Only callable by the contract owner * @param newReceiver The new receiver wallet address */ function updateReceiver(address payable newReceiver) public onlyOwner { receiver = newReceiver; } /** * @notice Get owned ALTS by adidas tokens for the given wallet * @param wallet The wallet to check for owned ALTS * @return tokenIds An array of token IDs of owned ALTS */ function getOwnedAlts( address wallet ) public view returns (uint256[] memory tokenIds) { IAltsByAdidas source = IAltsByAdidas(address(erc721)); tokenIds = source.walletOfOwner(wallet, 1, 30000); return tokenIds; } /** * @notice Check if the given ALTS token IDs are purchased and get their respective owner wallet addresses * @param tokenIds The token IDs to check * @return purchased An array of booleans representing the purchase status * @return walletAddresses An array of wallet addresses of the owners */ function isTokenIdPurchased( uint256[] memory tokenIds ) public view returns (bool[] memory purchased, address[] memory walletAddresses) { purchased = new bool[](tokenIds.length); walletAddresses = new address[](tokenIds.length); for (uint256 i = 0; i < tokenIds.length; i++) { uint256 tokenId = tokenIds[i]; purchased[i] = tokenPurchases[tokenId].purchased; if (purchased[i]) { walletAddresses[i] = erc721.ownerOf(tokenId); } } } /** * @notice Get the purchased keys for the given user * @param user The user to check for purchased keys * @return An array of purchased keys (token IDs) */ function getPurchasedKeys( address user ) public view returns (uint256[] memory) { return userPurchasedTokens[user]; } /** * @notice Admin function to update the snapshot prices for all groups * @param prices An array of updated snapshot prices */ function updateSnapshotPrices(uint256[4] memory prices) public onlyOwner { snapshotPrices = prices; } /** * @notice Set the APE to ETH exchange rate * @param rate The multiple of APE per ETH value */ function setEthApeExchangeRate(uint256 rate) public onlyOwner { ethApeExchangeRate = rate; } /** * @notice Get the APE price for the given ETH price * @param ethPrice The ETH price to calculate APE price for * @return The calculated APE price */ function getApePrice(uint256 ethPrice) public view returns (uint256) { return ethPrice * ethApeExchangeRate; } /** * @notice Get the payable amount for the given wallet and ALTS token IDs * @param wallet The wallet to check * @param tokenIds The ALTS token IDs to check * @param useApe Whether to use Ape token for payment * @return price The calculated payable amount */ function getAmountPayable( address wallet, uint8[] calldata snapshotIds, uint256[] calldata tokenIds, bool useApe ) public view returns (uint256) { uint256 price = 0; uint256 remainingKeys = tokenIds.length; bool[4] memory inSnapshot; for (uint256 i = 0; i < snapshotIds.length; i++) { uint8 snapshotId = snapshotIds[i]; inSnapshot[snapshotId] = true; } if (inSnapshot[0] && !discountUsed[wallet][0]) { price += snapshotPrices[0]; remainingKeys--; } if (remainingKeys > 0 && inSnapshot[1] && !discountUsed[wallet][1]) { price += snapshotPrices[1]; remainingKeys--; } if (remainingKeys > 0) { uint256 nextLowestPrice = inSnapshot[2] ? snapshotPrices[2] : snapshotPrices[3]; price += nextLowestPrice * remainingKeys; } if (useApe) { return getApePrice(price); } else { return price; } } /** * @notice Admin function to set the total key limit * @param limit The limit to set for total keys */ function setTotalKeyLimit(uint256 limit) public onlyOwner { totalKeyLimit = limit; } /** * @notice Admin function to update the team limits for all teams * @param limits An array of updated team limits */ function updateTeamLimits(uint256[8] memory limits) public onlyOwner { for (uint8 i = 0; i < 8; i++) { teamLimits[i] = limits[i]; } } /** * @notice Select teams for the given ALTS token IDs for which Universal Keys have been purchased * @param tokenIds The ALTS token IDs to select teams for * @param teams The selected teams for each ALTS token ID */ function selectTeam( uint256[] memory tokenIds, uint8[] memory teams, address _vault ) public { require( tokenIds.length == teams.length, "TokenIds/teams length mismatch" ); // Check if the user has early access for all tokens bool hasEarlyAccess = true; if (earlyAccessEnabled) { for (uint256 i = 0; i < tokenIds.length; i++) { if (!earlyAccessTokens[tokenIds[i]]) { hasEarlyAccess = false; break; } } } require( teamSelectionEnabled || owner() == msg.sender || hasEarlyAccess, "No team selection / early access" ); address requester = msg.sender; if (_vault != address(0)) { bool isDelegateValid = dc.checkDelegateForContract( msg.sender, _vault, address(erc721) ); require(isDelegateValid, "invalid delegate-vault pairing"); requester = _vault; } uint256[8] memory teamSelections; for (uint256 i = 0; i < teams.length; i++) { uint8 team = teams[i]; require(1 <= team && team <= 8, "Invalid team number"); uint256 tokenId = tokenIds[i]; require( erc721.ownerOf(tokenId) == requester, "User must own the token ID" ); require( tokenPurchases[tokenId].purchased && tokenPurchases[tokenId].owner == requester, "No key found for token ID" ); require(tokenTeam[tokenId] == 0, "Token ID already has a team"); /// Check if the team is, or would become, oversubscribed teamSelections[team - 1]++; require( teamMemberCounts[team] + teamSelections[team - 1] <= teamLimits[team - 1], "Not enough spaces in this team" ); tokenTeam[tokenId] = team; } for (uint8 i = 0; i < 8; i++) { teamMemberCounts[i + 1] += teamSelections[i]; } } /** * @notice Admin function to update team selections for ALTS token IDs * @param tokenIds The token IDs to update team selections for * @param teams The updated team selections for each token ID */ function updateTeamSelections( uint256[] memory tokenIds, uint8[] memory teams ) public onlyOwner { require( tokenIds.length == teams.length, "TokenIds/teams length mismatch" ); for (uint256 i = 0; i < tokenIds.length; i++) { uint8 team = teams[i]; uint256 tokenId = tokenIds[i]; tokenTeam[tokenId] = team; teamMemberCounts[team]++; } } /** * @notice Get the team selections for the given ALTS token IDs * @param tokenIds The token IDs to check for teams * @return An array of selected teams (indexed by ALT token ID) */ function getTeam( uint256[] memory tokenIds ) public view returns (uint8[] memory) { uint8[] memory teamsSelected = new uint8[](tokenIds.length); for (uint256 i = 0; i < tokenIds.length; i++) { teamsSelected[i] = tokenTeam[tokenIds[i]]; } return teamsSelected; } /** * @notice Get all ALTS token IDs associated with a specified team * @param team The team number to get the token IDs for * @return An array of token IDs that belong to the specified team */ function getTokenIdsByTeam( uint8 team ) public view returns (uint256[] memory) { require(1 <= team && team <= 8, "Invalid team number"); uint256[] memory tokenIds = new uint256[](teamMemberCounts[team]); uint256 index = 0; for (uint256 tokenId = 1; tokenId <= totalKeyLimit; tokenId++) { if (tokenTeam[tokenId] == team) { tokenIds[index] = tokenId; index++; } } return tokenIds; } /** * @notice Get the total number of ALTS in each team * @return An array containing the number of ALTS in each team */ function getTeamTotals() public view returns (uint256[8] memory) { uint256[8] memory currentTeamMembers; for (uint8 i = 0; i < 8; i++) { currentTeamMembers[i] = teamMemberCounts[i + 1]; } return currentTeamMembers; } /** * @notice Get the total number of keys distributed among all teams * @return The total number of keys in all teams */ function totalKeysInTeams() public view returns (uint256) { uint256 total = 0; for (uint8 i = 1; i <= 8; i++) { total += teamMemberCounts[i]; } return total; } /** * @notice Admin function to set ALTS with early access to select team (golden keys) * @param tokenIds The ALTS token IDs to set */ function setEarlyAccessTokens(uint256[] memory tokenIds) public onlyOwner { for (uint256 i = 0; i < tokenIds.length; i++) { earlyAccessTokens[tokenIds[i]] = true; } } /** * @notice Admin function to enable team selection for early access token holders * @param enabled Bool to enable/disable early access */ function setEarlyAccessEnabled(bool enabled) public onlyOwner { earlyAccessEnabled = enabled; } /** * @notice Admin function to enable or disable the ability to select a team * @param enabled A boolean representing whether team selection should be enabled or disabled */ function setTeamSelectionEnabled(bool enabled) public onlyOwner { teamSelectionEnabled = enabled; } /** * @notice Admin function to enable or disable the ability to make key purchases * @param enabled A boolean for the status of key purchases */ function setPurchasesEnabled(bool enabled) public onlyOwner { purchasesEnabled = enabled; } /** * @notice Admin function to reset discounted purchase availability for multiple wallets * @param users Array of wallet addresses * @param snapshots Snapshot IDs */ function setDiscountedPurchasesRemaining( address[] calldata users, uint8[] calldata snapshots ) public onlyOwner { require( users.length == snapshots.length, "Users/snapshots length mismatch" ); for (uint256 i = 0; i < users.length * snapshots.length; i++) { uint256 userIndex = i / snapshots.length; uint256 snapshotIndex = i % snapshots.length; discountUsed[users[userIndex]][snapshots[snapshotIndex]] = false; } } /** * @notice Admin function to update merkle roots for snapshots * @param snapshotId Snapshot to update root for * @param newRoot The new merkle root */ function setMerkleRoot(uint8 snapshotId, bytes32 newRoot) public onlyOwner { merkleRoots[snapshotId] = newRoot; } /** * @notice Check if a wallet address is valid in the given snapshot * @param wallet Wallet address to check * @param proof Wallet's merkle proof * @param snapshotId Snapshot to check */ function isSnapshot( uint8 snapshotId, address wallet, bytes32[] calldata proof ) public view returns (bool) { bytes32 merkleRoot = merkleRoots[snapshotId]; return MerkleProof.verify( proof, merkleRoot, keccak256(abi.encodePacked(wallet)) ); } /** * @notice Admin function drain any ETH or APE funds stuck in the contract */ function drain(address to) public onlyOwner { // Transfer stuck ETH to the contract owner uint256 balanceETH = address(this).balance; if (balanceETH > 0) { (bool sent, ) = to.call{value: balanceETH}(""); require(sent, "Failed to send Ether"); } // Transfer stuck APE to the contract owner uint256 balanceAPE = apeCoin.balanceOf(address(this)); if (balanceAPE > 0) { apeCoin.safeTransfer(to, balanceAPE); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/draft-IERC20Permit.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)); } } function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @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 (last updated v4.8.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://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 functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol) pragma solidity ^0.8.0; /** * @dev These functions deal with verification of Merkle Tree proofs. * * The tree and the proofs can be generated using our * https://github.com/OpenZeppelin/merkle-tree[JavaScript library]. * You will find a quickstart guide in the readme. * * WARNING: You should avoid using leaf values that are 64 bytes long prior to * hashing, or use a hash function other than keccak256 for hashing leaves. * This is because the concatenation of a sorted pair of internal nodes in * the merkle tree could be reinterpreted as a leaf value. * OpenZeppelin's JavaScript library generates merkle trees that are safe * against this attack out of the box. */ 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 Calldata version of {verify} * * _Available since v4.7._ */ function verifyCalldata( bytes32[] calldata proof, bytes32 root, bytes32 leaf ) internal pure returns (bool) { return processProofCalldata(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle 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++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Calldata version of {processProof} * * _Available since v4.7._ */ function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function multiProofVerify( bytes32[] memory proof, bool[] memory proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProof(proof, proofFlags, leaves) == root; } /** * @dev Calldata version of {multiProofVerify} * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function multiProofVerifyCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProofCalldata(proof, proofFlags, leaves) == root; } /** * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false * respectively. * * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer). * * _Available since v4.7._ */ function processMultiProof( bytes32[] memory proof, bool[] memory proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { return hashes[totalHashes - 1]; } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Calldata version of {processMultiProof}. * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function processMultiProofCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { return hashes[totalHashes - 1]; } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { return a < b ? _efficientHash(a, b) : _efficientHash(b, a); } function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) { /// @solidity memory-safe-assembly assembly { mstore(0x00, a) mstore(0x20, b) value := keccak256(0x00, 0x40) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: CC0-1.0 pragma solidity ^0.8.17; /** * @title An immutable registry contract to be deployed as a standalone primitive * @dev See EIP-5639, new project launches can read previous cold wallet -> hot wallet delegations * from here and integrate those permissions into their flow */ interface IDelegationRegistry { /// @notice Delegation type enum DelegationType { NONE, ALL, CONTRACT, TOKEN } /// @notice Info about a single delegation, used for onchain enumeration struct DelegationInfo { DelegationType type_; address vault; address delegate; address contract_; uint256 tokenId; } /// @notice Info about a single contract-level delegation struct ContractDelegation { address contract_; address delegate; } /// @notice Info about a single token-level delegation struct TokenDelegation { address contract_; uint256 tokenId; address delegate; } /// @notice Emitted when a user delegates their entire wallet event DelegateForAll(address vault, address delegate, bool value); /// @notice Emitted when a user delegates a specific contract event DelegateForContract(address vault, address delegate, address contract_, bool value); /// @notice Emitted when a user delegates a specific token event DelegateForToken(address vault, address delegate, address contract_, uint256 tokenId, bool value); /// @notice Emitted when a user revokes all delegations event RevokeAllDelegates(address vault); /// @notice Emitted when a user revoes all delegations for a given delegate event RevokeDelegate(address vault, address delegate); /** * ----------- WRITE ----------- */ /** * @notice Allow the delegate to act on your behalf for all contracts * @param delegate The hotwallet to act on your behalf * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking */ function delegateForAll(address delegate, bool value) external; /** * @notice Allow the delegate to act on your behalf for a specific contract * @param delegate The hotwallet to act on your behalf * @param contract_ The address for the contract you're delegating * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking */ function delegateForContract(address delegate, address contract_, bool value) external; /** * @notice Allow the delegate to act on your behalf for a specific token * @param delegate The hotwallet to act on your behalf * @param contract_ The address for the contract you're delegating * @param tokenId The token id for the token you're delegating * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking */ function delegateForToken(address delegate, address contract_, uint256 tokenId, bool value) external; /** * @notice Revoke all delegates */ function revokeAllDelegates() external; /** * @notice Revoke a specific delegate for all their permissions * @param delegate The hotwallet to revoke */ function revokeDelegate(address delegate) external; /** * @notice Remove yourself as a delegate for a specific vault * @param vault The vault which delegated to the msg.sender, and should be removed */ function revokeSelf(address vault) external; /** * ----------- READ ----------- */ /** * @notice Returns all active delegations a given delegate is able to claim on behalf of * @param delegate The delegate that you would like to retrieve delegations for * @return info Array of DelegationInfo structs */ function getDelegationsByDelegate(address delegate) external view returns (DelegationInfo[] memory); /** * @notice Returns an array of wallet-level delegates for a given vault * @param vault The cold wallet who issued the delegation * @return addresses Array of wallet-level delegates for a given vault */ function getDelegatesForAll(address vault) external view returns (address[] memory); /** * @notice Returns an array of contract-level delegates for a given vault and contract * @param vault The cold wallet who issued the delegation * @param contract_ The address for the contract you're delegating * @return addresses Array of contract-level delegates for a given vault and contract */ function getDelegatesForContract(address vault, address contract_) external view returns (address[] memory); /** * @notice Returns an array of contract-level delegates for a given vault's token * @param vault The cold wallet who issued the delegation * @param contract_ The address for the contract holding the token * @param tokenId The token id for the token you're delegating * @return addresses Array of contract-level delegates for a given vault's token */ function getDelegatesForToken(address vault, address contract_, uint256 tokenId) external view returns (address[] memory); /** * @notice Returns all contract-level delegations for a given vault * @param vault The cold wallet who issued the delegations * @return delegations Array of ContractDelegation structs */ function getContractLevelDelegations(address vault) external view returns (ContractDelegation[] memory delegations); /** * @notice Returns all token-level delegations for a given vault * @param vault The cold wallet who issued the delegations * @return delegations Array of TokenDelegation structs */ function getTokenLevelDelegations(address vault) external view returns (TokenDelegation[] memory delegations); /** * @notice Returns true if the address is delegated to act on the entire vault * @param delegate The hotwallet to act on your behalf * @param vault The cold wallet who issued the delegation */ function checkDelegateForAll(address delegate, address vault) external view returns (bool); /** * @notice Returns true if the address is delegated to act on your behalf for a token contract or an entire vault * @param delegate The hotwallet to act on your behalf * @param contract_ The address for the contract you're delegating * @param vault The cold wallet who issued the delegation */ function checkDelegateForContract(address delegate, address vault, address contract_) external view returns (bool); /** * @notice Returns true if the address is delegated to act on your behalf for a specific token, the token's contract or an entire vault * @param delegate The hotwallet to act on your behalf * @param contract_ The address for the contract you're delegating * @param tokenId The token id for the token you're delegating * @param vault The cold wallet who issued the delegation */ function checkDelegateForToken(address delegate, address vault, address contract_, uint256 tokenId) external view returns (bool); }
{ "optimizer": { "enabled": true, "runs": 200 }, "viaIR": true, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_erc721","type":"address"},{"internalType":"address","name":"_bluePass","type":"address"},{"internalType":"address","name":"_apeCoin","type":"address"},{"internalType":"address payable","name":"_receiver","type":"address"},{"internalType":"uint256[8]","name":"_teamLimits","type":"uint256[8]"},{"internalType":"uint256","name":"_totalKeyLimit","type":"uint256"},{"internalType":"uint256[4]","name":"_snapshotPrices","type":"uint256[4]"},{"internalType":"uint256","name":"_ethApeExchangeRate","type":"uint256"},{"internalType":"address","name":"_delegateCash","type":"address"},{"internalType":"bytes32","name":"_snapshot1Merkle","type":"bytes32"},{"internalType":"bytes32","name":"_snapshot2Merkle","type":"bytes32"},{"internalType":"bytes32","name":"_snapshot3Merkle","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"apeCoin","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bluePass","outputs":[{"internalType":"contract IAdidasBluePass","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"altTokenId","type":"uint256"}],"name":"burnForKey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"dc","outputs":[{"internalType":"contract IDelegationRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint8","name":"","type":"uint8"}],"name":"discountUsed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"drain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"earlyAccessEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"earlyAccessTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"erc721","outputs":[{"internalType":"contract IERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ethApeExchangeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint8[]","name":"snapshotIds","type":"uint8[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"bool","name":"useApe","type":"bool"}],"name":"getAmountPayable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"ethPrice","type":"uint256"}],"name":"getApePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"getOwnedAlts","outputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getPurchasedKeys","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"getTeam","outputs":[{"internalType":"uint8[]","name":"","type":"uint8[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTeamTotals","outputs":[{"internalType":"uint256[8]","name":"","type":"uint256[8]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"team","type":"uint8"}],"name":"getTokenIdsByTeam","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"grantKeys","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"snapshotId","type":"uint8"},{"internalType":"address","name":"wallet","type":"address"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"isSnapshot","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"isTokenIdPurchased","outputs":[{"internalType":"bool[]","name":"purchased","type":"bool[]"},{"internalType":"address[]","name":"walletAddresses","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"merkleRoots","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"bool","name":"useApe","type":"bool"},{"internalType":"address","name":"_vault","type":"address"},{"internalType":"uint8[]","name":"snapshotIds","type":"uint8[]"},{"internalType":"bytes32[][]","name":"proofs","type":"bytes32[][]"}],"name":"purchaseKeys","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"purchasesEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"receiver","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint8[]","name":"teams","type":"uint8[]"},{"internalType":"address","name":"_vault","type":"address"}],"name":"selectTeam","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"users","type":"address[]"},{"internalType":"uint8[]","name":"snapshots","type":"uint8[]"}],"name":"setDiscountedPurchasesRemaining","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setEarlyAccessEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"setEarlyAccessTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"rate","type":"uint256"}],"name":"setEthApeExchangeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"snapshotId","type":"uint8"},{"internalType":"bytes32","name":"newRoot","type":"bytes32"}],"name":"setMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setPurchasesEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setTeamSelectionEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"setTotalKeyLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"snapshotPrices","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"teamLimits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"teamSelectionEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalKeyLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalKeysInTeams","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalKeysPurchased","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"newReceiver","type":"address"}],"name":"updateReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[4]","name":"prices","type":"uint256[4]"}],"name":"updateSnapshotPrices","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[8]","name":"limits","type":"uint256[8]"}],"name":"updateTeamLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint8[]","name":"teams","type":"uint8[]"}],"name":"updateTeamSelections","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a0346200038f576001600160401b0390620031f13881900390601f8201601f19168301908482118483101762000394578291604052833981016102c0828203126200038f576200005082620003bb565b91602062000060818301620003bb565b916200006f60408201620003bb565b6060820151956001600160a01b03871687036200038f5785609f840112156200038f576040519761010089018981108282111762000394576040526101808401898882116200038f578660808701915b838310620003aa575050505196806101bf860112156200038f5760405191608083019081118382101762000394576040528161022086019182116200038f57866101a08701915b8383106200037e5750505051620001216102408601620003bb565b610260860151946102a061028088015197015198600054953360018060a01b031988161760005560405196339060018060a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3600180546001600160a01b03199081166001600160a01b03938416179091556002805482169383169390931790925560038054831693821693909317909255918116608052600480549092169a169990991789556005978855600f5560005b8881106200036a575050600054336001600160a01b03909116036200033c575060008052601b83526040600020553360018060a01b0360005416036200030b576001600052601b82526040600020553360018060a01b036000541603620002da57601b9060026000525260406000205560005b60088060ff83161015620002b357611fe082841b16850151908210156200029e57816007015560ff80911690811462000289576001016200024d565b601183634e487b7160e01b6000525260246000fd5b603284634e487b7160e01b6000525260246000fd5b604051612e009081620003d182396080518181816104fa01528181610bfc01526115e70152f35b83816064926040519262461bcd60e51b84528301526024820152600080516020620031d18339815191526044820152fd5b60648583806040519262461bcd60e51b84528301526024820152600080516020620031d18339815191526044820152fd5b60649084808962461bcd60e51b84528301526024820152600080516020620031d18339815191526044820152fd5b8151601082015590850190600101620001da565b825181529181019188910162000106565b600080fd5b634e487b7160e01b600052604160045260246000fd5b8251815291810191889101620000bf565b51906001600160a01b03821682036200038f5756fe6080604052600436101561001257600080fd5b6000803560e01c80626ab142146123c057806304219760146123845780631342f8ec146123125780631d89e06314611fd05780631e6ad90314611fa15780631fc01a0b14611ee9578063219eb06114611e835780632200d5fa14611d6c5780632366c10914611d49578063281fe31e14611c745780633029b47314611ad95780633944fc8e14611ab357806341e5fb4014611a815780634ead073f14611a6357806354d77e0e14611a2c5780635cfd2fae1461185057806362879b701461182657806362fd2cc1146116f05780636594dd76146116cd5780636ef6766e14611698578063706ad1f614610fda578063715018a614610f805780637649359314610f065780637ba2196a14610ec157806387233afa14610e5b5780638cea7b6414610db45780638da5cb5b14610d8d5780638ea5474414610d645780639bca19e014610d375780639ecd4d7214610845578063a59b436214610822578063a5c8d172146107f5578063ac7ad9ba146107cc578063bb61848b14610754578063bca6ce641461072b578063c29580e014610640578063c5d472ac14610622578063c8a911401461059f578063cc830a9714610547578063cf5faf3e14610529578063d8a531a6146104e4578063d99f35b7146104be578063e5e0a36a14610412578063ece5313214610307578063f2fde38b146102415763f7260d3e1461021657600080fd5b3461023e578060031936011261023e576004546040516001600160a01b039091168152602090f35b80fd5b503461023e57602036600319011261023e5761025b61240d565b610263612604565b6001600160a01b039081169081156102b357600054826001600160601b0360a01b821617600055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a380f35b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b503461023e5760208060031936011261040e5761032261240d565b9061032b612604565b4783816103ef575b50506003546040516370a0823160e01b81523060048201526001600160a01b03918216918382602481865afa9182156103e45786926103b1575b5081610377578580f35b6103a8946040519463a9059cbb60e01b908601521660248401526044830152604482526103a382612484565b612924565b38808080808580f35b9091508381813d83116103dd575b6103c981836124bb565b810103126103d95751903861036d565b8580fd5b503d6103bf565b6040513d88823e3d90fd5b80808061040794875af16104016128a2565b506128e1565b3883610333565b5080fd5b503461023e5761010036600319011261023e57366023121561023e5760405161043a8161249f565b610104813682116104b9576004905b8282106104a95750505061045b612604565b815b600860ff8216818110156104a5576104759084612c2a565b519082101561049157600782015561048c90612c19565b61045d565b634e487b7160e01b84526032600452602484fd5b8480f35b8135815260209182019101610449565b600080fd5b503461023e578060031936011261023e57602060ff60145460101c166040519015158152f35b503461023e578060031936011261023e576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b503461023e578060031936011261023e576020600654604051908152f35b503461023e57604036600319011261023e5761056161240d565b6024359160ff83168093036104b95760409160018060a01b0316815260196020522090600052602052602060ff604060002054166040519015158152f35b503461023e5760208060031936011261040e576001600160a01b036105c261240d565b1682526018815260408220916040518092808554928381520194835280832092905b82821061060b57610607856105fb818903826124bb565b604051918291826125c9565b0390f35b8354865294850194600193840193909101906105e4565b503461023e578060031936011261023e576020600f54604051908152f35b503461023e5760208060031936011261040e576004356001600160401b038111610727576106729036906004016124f3565b90815190610698610682836124dc565b9261069060405194856124bb565b8084526124dc565b8282019390601f1901368537845b81518110156106e157806106bd6106dc9284612752565b5187526015845260ff6040882054166106d68287612752565b526127f8565b6106a6565b505091909260405193838594850191818652518092526040850193925b82811061070d57505050500390f35b835160ff16855286955093810193928101926001016106fe565b8280fd5b503461023e578060031936011261023e576001546040516001600160a01b039091168152602090f35b503461023e5760208060031936011261040e576004356001600160401b038111610727576107869036906004016124f3565b9061078f612604565b825b82518110156107c857806107a86107c39285612752565b518552601a835260408520805460ff191660011790556127f8565b610791565b8380f35b503461023e578060031936011261023e576003546040516001600160a01b039091168152602090f35b503461023e57602036600319011261023e57600435600481101561040e5760209060100154604051908152f35b503461023e57602036600319011261023e5761083c612604565b60043560055580f35b503461023e57606036600319011261023e576001600160401b039060043582811161040e576108789036906004016124f3565b602492833590811161072757610892903690600401612561565b9061089b612423565b926108a98251845114612c3b565b6001936014549060ff91828160101c16610cd8575b918093949596919216908115610cc4575b8115610cbc575b5015610c785733906001600160a01b0390818116610bbf575b50604051926108fd8461249f565b610100368537845b8751811015610b715781610919828a612752565b5116806001111580610b66575b61092f90612c87565b6109398289612752565b5184600154168b604051918280926331a9108f60e11b825285600483015260209485935afa908115610b5b57879161097f918c91610b2e575b5089831692168214612817565b828a526017825260408a205490878783169283610b1f575b50505015610adc578189526015918282528560408b205416610a9857856109bd85612cc9565b166109db6109d46109ce838d612c2a565b516127f8565b918b612c2a565b52838a5260168252610a0660408b20546109ff886109f888612cc9565b168c612c2a565b51906126a1565b610a0f85612cc9565b6008811015610a85576007015410610a415789525260408720805460ff19169091179055610a3c906127f8565b610905565b60405162461bcd60e51b815260048101839052601e818f01527f4e6f7420656e6f7567682073706163657320696e2074686973207465616d00006044820152606490fd5b634e487b7160e01b8c5260326004528e8cfd5b60405162461bcd60e51b815260048101839052601b818f01527f546f6b656e20494420616c7265616479206861732061207465616d00000000006044820152606490fd5b60649060198d6040519262461bcd60e51b845260048401528201527f4e6f206b657920666f756e6420666f7220746f6b656e204944000000000000006044820152fd5b60081c16149050388781610997565b610b4e9150843d8611610b54575b610b4681836124bb565b810190612710565b38610972565b503d610b3c565b6040513d8c823e3d90fd5b506008811115610926565b50915050825b8181169060088210156104a557610b91610bba9285612c2a565b5183610b9c83612cdc565b1686526016602052610bb3604087209182546126a1565b9055612c19565b610b77565b60015460405163090c9a2d60e41b81526001600160a01b0394851660048201528285166024820152908316909316604484015290916020816064817f000000000000000000000000000000000000000000000000000000000000000087165afa908115610c6d5790610c38918691610c3f575b506127ac565b90386108ef565b610c60915060203d8111610c66575b610c5881836124bb565b810190612794565b38610c32565b503d610c4e565b6040513d87823e3d90fd5b60405162461bcd60e51b8152602060048201819052818801527f4e6f207465616d2073656c656374696f6e202f206561726c79206163636573736044820152606490fd5b9050386108d6565b84546001600160a01b0316331491506108cf565b835b8551811015610d2957610ced8187612752565b518552601a6020528360408620541615610d0f57610d0a906127f8565b610cda565b50909183819495969750915b9050959493929190956108be565b509180939495969192610d1b565b503461023e57602036600319011261023e57600435600881101561040e5760209060070154604051908152f35b503461023e578060031936011261023e576002546040516001600160a01b039091168152602090f35b503461023e578060031936011261023e57546040516001600160a01b039091168152602090f35b503461023e578060031936011261023e5760405190610dd28261249f565b6101008092369037604051610de68161249f565b82368237815b60ff808216906008821015610e2c57908291610e0a610e2794612cdc565b1685526016602052610e2160408620549185612c2a565b52612c19565b610dec565b505060405192919050825b60088310610e4457505050f35b600190825181526020809101920192019190610e37565b503461023e578060031936011261023e576001908181815b610e83575b602083604051908152f35b909160ff841660088111610eba57610eb191610eab91845260166020526040842054906126a1565b93612c19565b92919081610e73565b5091610e78565b503461023e57602036600319011261023e576004356001600160a01b0381169081900361040e57610ef0612604565b6001600160601b0360a01b600454161760045580f35b503461023e57608036600319011261023e57366023121561023e57604051610f2d81612484565b6084813682116104b9576004905b828210610f7057505050610f4d612604565b815b60048110610f5b578280f35b60019060208351930192816010015501610f4f565b8135815260209182019101610f3b565b503461023e578060031936011261023e57610f99612604565b600080546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b5060a036600319011261023e576004356001600160401b03811161040e57611006903690600401612439565b906024351515602435036104b95761101c612423565b906064356001600160401b0381116116945761103c903690600401612439565b6084356001600160401b0381116116905761105b903690600401612439565b90339582840361164c5760ff60145460081c168015611639575b61107e9061265c565b61109761108d896006546126a1565b60055410156126c4565b6001600160a01b0381166115aa575b506001546001600160a01b0316885b8881106114c157505087938793604051936110cf85612484565b60803686378a5b82811061141957505050505080511515806113ee575b6113ad575b811515806113a0575b80611374575b61132a575b816112fb575b505060243515611296573461125157600f546111269161288f565b6003546004546040516323b872dd60e01b60208201523360248201526001600160a01b03918216604482015260648082019490945292835260a083019291166001600160401b0383118284101761123b5761118392604052612924565b835b838110611199575050506006540160065580f35b6112369060186040516111ab81612469565b600181526001600160a01b03861660208083018281529092906111cf868b8a612807565b358b52601784526111f360408c2092511515839060ff801983541691151516179055565b518154610100600160a81b03191660089190911b610100600160a81b0316179055885252604086206112319061122a838887612807565b3590612766565b6127f8565b611185565b634e487b7160e01b600052604160045260246000fd5b60405162461bcd60e51b815260206004820152601c60248201527f53686f756c64206e6f742073656e6420455448207769746820415045000000006044820152606490fd5b8034036112bf57848080806112ba9460018060a01b03600454165af16104016128a2565b611183565b60405162461bcd60e51b8152602060048201526014602482015273125b9cdd59999a58da595b9d081c185e5b595b9d60621b6044820152606490fd5b6040015161131b929161131591156113225760125461288f565b906126a1565b388061110b565b60135461288f565b909161133c61134291601154906126a1565b92612882565b6001600160a01b03851687526019602090815260408089206001808b5292528820805460ff1916909117905590611105565b506001600160a01b038516875260196020908152604080892060018a5290915287205460ff1615611100565b50602081015115156110fa565b915050601054906113bd85612882565b6001600160a01b03851687526019602090815260408089208980529091528720805460ff19166001179055906110f1565b506001600160a01b038516875260196020908152604080892089805290915287205460ff16156110ec565b61142c611427828587612807565b612863565b90828110156114ad578060051b860135601e19873603018112156114a9578601918235926001600160401b0384116114a557602001928060051b360384136114a5576114a0938d61147c93612cee565b61149660ff61148f61142785898b612807565b1689612871565b90151590526127f8565b6110d6565b8e80fd5b8d80fd5b634e487b7160e01b8d52603260045260248dfd5b6114cc818a89612807565b6040516331a9108f60e11b815290356004820152602081602481865afa801561159f5761150e918c91611580575b506001600160a01b038a8116911614612817565b611519818a89612807565b358a52601760205260ff60408b20541661153b57611536906127f8565b6110b5565b60405162461bcd60e51b815260206004820152601a60248201527f546f6b656e20494420616c7265616479207075726368617365640000000000006044820152606490fd5b611599915060203d602011610b5457610b4681836124bb565b386114fa565b6040513d8d823e3d90fd5b60015460405163090c9a2d60e41b81526001600160a01b0398891660048201528883166024820152971660448801529095602081806064810103817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa801561162e57611627918a91610c3f57506127ac565b94386110a6565b6040513d8b823e3d90fd5b5088546001600160a01b03168714611075565b606460405162461bcd60e51b815260206004820152602060248201527f536e617073686f74732f70726f6f6673206c656e677468206d69736d617463686044820152fd5b8680fd5b8480fd5b503461023e57602036600319011261023e576116b26123fe565b6116ba612604565b60ff801960145416911515161760145580f35b503461023e57602036600319011261023e576116e7612604565b600435600f5580f35b503461023e57604036600319011261023e576001600160401b0360043581811161072757611722903690600401612439565b60249283359081116116945761173c903690600401612439565b929091611747612604565b8381036117e257855b61175a858361288f565b8110156117de5784156117cb576117748582048385612807565b356001600160a01b03811691908290036117c7576117c2918852602060198152604089209060ff6117ab6114278a86068b8b612807565b1660005252604060002060ff1981541690556127f8565b611750565b8780fd5b634e487b7160e01b875260126004528587fd5b8680f35b60405162461bcd60e51b815260206004820152601f818701527f55736572732f736e617073686f7473206c656e677468206d69736d61746368006044820152606490fd5b503461023e57602036600319011261023e576020611848600f5460043561288f565b604051908152f35b503461023e5760208060031936011261040e576004356001600160401b038111610727576118829036906004016124f3565b9081516118a7611891826124dc565b9161189f60405193846124bb565b8083526124dc565b81830193601f199182013686378051916118d96118c3846124dc565b936118d160405195866124bb565b8085526124dc565b8386019101368237865b82518110156119a8576118f68184612752565b51908189526017875260ff60408a2054166119118288612752565b90151590526119208187612752565b51611935575b61193091506127f8565b6118e3565b6001546040516331a9108f60e11b815260048101939093526001600160a01b039088908490602490829085165afa908115610b5b57611930938b92611989575b506119808388612752565b91169052611926565b6119a1919250893d8b11610b5457610b4681836124bb565b9038611975565b8385838a8a8a60405195869560408701906040885251809152606087019390855b818110611a1357505050858303868301525180835291810193925b8281106119f357505050500390f35b83516001600160a01b0316855286955093810193928101926001016119e4565b82511515865289985094840194918401916001016119c9565b503461023e57604036600319011261023e5760ff611a48612551565b611a50612604565b168152601b602052602435604082205580f35b503461023e578060031936011261023e576020600554604051908152f35b503461023e57602036600319011261023e57604060209160ff611aa2612551565b168152601b83522054604051908152f35b503461023e578060031936011261023e57602060ff60145460081c166040519015158152f35b503461023e5760208060031936011261040e576004356001600160401b03811161072757611b0b903690600401612439565b611b13612604565b835b818110611b20578480f35b611b2b818385612807565b600180546040516331a9108f60e11b815292356004840181905292602492916001600160a01b0390899083908690829085165afa918215610b5b578a92611c55575b50848a52601793848a5260ff60408c205416611c12575091611bfa9391611c0d96959360405192611b9d84612469565b83528a8301911692838252848c528a52611bca60408c2092511515839060ff801983541691151516179055565b518154610100600160a81b03191660089190911b610100600160a81b031617905588526018875260408820612766565b6006611c0681546127f8565b90556127f8565b611b15565b8960186064926040519262461bcd60e51b845260048401528201527f546f6b656e20494420616c726561647920686173206b657900000000000000006044820152fd5b611c6d919250893d8b11610b5457610b4681836124bb565b9038611b6d565b503461023e5760208060031936011261040e5760ff9182611c93612551565b16806001111580611d3e575b611ca890612c87565b80825260168352604082205493611cbe856124dc565b94611ccc60405196876124bb565b808652611cdb601f19916124dc565b01368587013782600194600554955b86811115611d0057604051806106078a826125c9565b80835260158252848460408520541614611d23575b611d1e906127f8565b611cea565b94611d3681876106d6611d1e948c612752565b959050611d15565b506008811115611c9f565b503461023e578060031936011261023e57602060ff601454166040519015158152f35b503461023e576020908160031936011261023e57611d8861240d565b908060018060a01b03606481600154169460405195869384926327a8d7ab60e01b84521660048301526001602483015261753060448301525afa918215611e76578192611dde575b6040518061060785826125c9565b9091503d8083833e611df081836124bb565b8101908381830312610727578051906001600160401b038211611e72570181601f8201121561072757805190611e25826124dc565b93611e3360405195866124bb565b828552858086019360051b83010193841161023e57508401905b828210611e635750505061060791503880611dd0565b81518152908401908401611e4d565b8380fd5b50604051903d90823e3d90fd5b503461023e57606036600319011261023e57611e9d612551565b602435916001600160a01b03831683036104b957604435906001600160401b03821161023e576020611edf8585611ed73660048801612439565b929091612cee565b6040519015158152f35b503461023e57604036600319011261023e576001600160401b0360043581811161072757611f1b9036906004016124f3565b9060243590811161072757611f34903690600401612561565b90611f3d612604565b611f4a8151835114612c3b565b825b81518110156107c85780601660ff611f67611f9c9487612752565b5116611f738386612752565b51875260209060158252604088208160ff1982541617905587525260408520611c0681546127f8565b611f4c565b503461023e57602036600319011261023e5760ff60406020926004358152601a84522054166040519015158152f35b503461023e57604036600319011261023e576004359060249182359060ff60145460081c1680156122ff575b6120059061265c565b600654906001918281018091116121ab576120249060055410156126c4565b6002546040516331a9108f60e11b808252600482018490526020936001600160a01b0393841693909285818b81885afa90811561162e5789916122e2575b50813391160361229e578481875416928a6040518095819382528b60048301525afa918215612293578892612274575b5033911603612230578486526017835260ff6040872054166121ec57604051906120bb82612469565b8482528336818401376120cd8261272f565b52813b156103d9576120f88692839260405194858094819363a552d0bf60e01b8352600483016125c9565b03925af18015610c6d576121be575b5060405161211481612469565b828152818101338152848652601783526121416040872092511515839060ff801983541691151516179055565b518154610100600160a81b03191660089190911b610100600160a81b03161790553384526018815260408420612178908490612766565b6006548281018091116121ab57906121a792916006556040519161219b83612469565b8252368183013761272f565b5280f35b634e487b7160e01b855260116004528585fd5b6001600160401b0381959295116121d9576040529238612107565b634e487b7160e01b825260416004528582fd5b60405162461bcd60e51b815260048101849052601d818901527f4b657920616c72656164792070757263686173656420666f7220414c540000006044820152606490fd5b60405162461bcd60e51b815260048101849052601f818901527f55736572206d757374206f776e2074686520414c545320746f6b656e204944006044820152606490fd5b61228c919250853d8711610b5457610b4681836124bb565b9038612092565b6040513d8a823e3d90fd5b60405162461bcd60e51b8152600481018690526019818b01527f55736572206d757374206f776e206120426c75652050617373000000000000006044820152606490fd5b6122f99150863d8811610b5457610b4681836124bb565b38612062565b5082546001600160a01b03163314611ffc565b503461023e57608036600319011261023e5761232c61240d565b6001600160401b03602435818111611e725761234c903690600401612439565b9160443590811161169457612365903690600401612439565b93905060643594851515860361023e5760206118488787878787612ad2565b503461023e57602036600319011261023e5761239e6123fe565b6123a6612604565b61ff0060145491151560081b169061ff0019161760145580f35b503461023e57602036600319011261023e576123da6123fe565b6123e2612604565b62ff000060145491151560101b169062ff000019161760145580f35b6004359081151582036104b957565b600435906001600160a01b03821682036104b957565b604435906001600160a01b03821682036104b957565b9181601f840112156104b9578235916001600160401b0383116104b9576020808501948460051b0101116104b957565b604081019081106001600160401b0382111761123b57604052565b608081019081106001600160401b0382111761123b57604052565b61010081019081106001600160401b0382111761123b57604052565b90601f801991011681019081106001600160401b0382111761123b57604052565b6001600160401b03811161123b5760051b60200190565b81601f820112156104b95780359161250a836124dc565b9261251860405194856124bb565b808452602092838086019260051b8201019283116104b9578301905b828210612542575050505090565b81358152908301908301612534565b6004359060ff821682036104b957565b81601f820112156104b957803591612578836124dc565b9261258660405194856124bb565b808452602092838086019260051b8201019283116104b9578301905b8282106125b0575050505090565b813560ff811681036104b95781529083019083016125a2565b6020908160408183019282815285518094520193019160005b8281106125f0575050505090565b8351855293810193928101926001016125e2565b6000546001600160a01b0316330361261857565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b1561266357565b60405162461bcd60e51b8152602060048201526016602482015275141d5c98da185cd95cc8185c9948191a5cd8589b195960521b6044820152606490fd5b919082018092116126ae57565b634e487b7160e01b600052601160045260246000fd5b156126cb57565b60405162461bcd60e51b815260206004820152601a60248201527f546f74616c20746f6b656e206c696d69742065786365656465640000000000006044820152606490fd5b908160209103126104b957516001600160a01b03811681036104b95790565b80511561273c5760200190565b634e487b7160e01b600052603260045260246000fd5b805182101561273c5760209160051b010190565b8054906801000000000000000082101561123b576001820180825582101561273c5760005260206000200155565b908160209103126104b9575180151581036104b95790565b156127b357565b60405162461bcd60e51b815260206004820152601e60248201527f696e76616c69642064656c65676174652d7661756c742070616972696e6700006044820152606490fd5b60001981146126ae5760010190565b919081101561273c5760051b0190565b1561281e57565b60405162461bcd60e51b815260206004820152601a60248201527f55736572206d757374206f776e2074686520746f6b656e2049440000000000006044820152606490fd5b3560ff811681036104b95790565b90600481101561273c5760051b0190565b80156126ae576000190190565b818102929181159184041417156126ae57565b3d156128dc573d906001600160401b03821161123b57604051916128d0601f8201601f1916602001846124bb565b82523d6000602084013e565b606090565b156128e857565b60405162461bcd60e51b81526020600482015260146024820152732330b4b632b2103a379039b2b7321022ba3432b960611b6044820152606490fd5b604051612982916001600160a01b031661293d82612469565b6000806020958685527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656487860152868151910182855af161297c6128a2565b916129fe565b8051908161298f57505050565b828061299f938301019101612794565b156129a75750565b6084906040519062461bcd60e51b82526004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152fd5b91929015612a605750815115612a12575090565b3b15612a1b5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b825190915015612a735750805190602001fd5b6040519062461bcd60e51b82528160208060048301528251908160248401526000935b828510612ab9575050604492506000838284010152601f80199101168101030190fd5b8481018201518686016044015293810193859350612a96565b93929160009483604093845193612ae885612484565b6080368637885b818110612bfb575050508251151580612bd2575b612bbb575b508315159081612bad575b81612b80575b50612b62575b82612b3e575b505050600014612b3b57600f54612b3b9161288f565b90565b01519192612b5992909161131591156113225760125461288f565b90388080612b25565b9193612b74612b7a91601154906126a1565b94612882565b91612b1f565b905060018060a01b0316600052601960205281600020600160005260205260ff8260002054161538612b19565b602083015115159150612b13565b95509250612bcb60105495612882565b9238612b08565b506001600160a01b03821687526019602090815284882088805290528387205460ff1615612b03565b8060016106d660ff61148f611427612c1496888a612807565b612aef565b60ff1660ff81146126ae5760010190565b90600881101561273c5760051b0190565b15612c4257565b60405162461bcd60e51b815260206004820152601e60248201527f546f6b656e4964732f7465616d73206c656e677468206d69736d6174636800006044820152606490fd5b15612c8e57565b60405162461bcd60e51b815260206004820152601360248201527224b73b30b634b2103a32b0b690373ab6b132b960691b6044820152606490fd5b60ff6000199116019060ff82116126ae57565b60ff60019116019060ff82116126ae57565b90929360ff6000921682526020601b815260409384842054958551838101916001600160601b03199060601b16825260148152612d2a81612469565b51902090612d37886124dc565b97612d448751998a6124bb565b8089528389019060051b820191368311611690578490915b838310612dba57505050509183925b8751841015612daf57612d7e8489612752565b519081811015612d9f5785528252612d998585205b936127f8565b92612d6b565b9085528252612d99858520612d93565b945095505050501490565b8235815291810191859101612d5c56fea26469706673582212205af845cbb2c3a83818f8ab0e7df985b10aa064b56a1b2768ec9b571798357ab264736f6c634300081300334f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572000000000000000000000000749f5ddf5ab4c1f26f74560a78300563c34b417d000000000000000000000000c778e11492cf9d44c9ffc074648a34897e4664cb0000000000000000000000004d224452801aced8b2f0aebe155379bb5d59438100000000000000000000000054da2032be4661c741e07d0e7d3c422e5389f45f00000000000000000000000000000000000000000000000000000000000014820000000000000000000000000000000000000000000000000000000000001356000000000000000000000000000000000000000000000000000000000000135600000000000000000000000000000000000000000000000000000000000012c000000000000000000000000000000000000000000000000000000000000011940000000000000000000000000000000000000000000000000000000000000ea6000000000000000000000000000000000000000000000000000000000000038400000000000000000000000000000000000000000000000000000000000003840000000000000000000000000000000000000000000000000000000000000dac000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1a2bc2ec50000000000000000000000000000000000000000000000000000010a741a46278000000000000000000000000000000000000000000000000000016345785d8a000000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000076a84fef008cdabe6409d2fe638b9d2eda87ee18d77f08408dfc3e765c5fed74a0dc1a5fcff27c8853973aa109c9b524f38376edfa68c63f00cb7f9e435e98656502ee5515b90620bcfec9b8bf2ea8a4d7c922905464c1d81c8c84c403e2848ccc000210651f1b5ec53faa8c2bf6
Deployed Bytecode
0x6080604052600436101561001257600080fd5b6000803560e01c80626ab142146123c057806304219760146123845780631342f8ec146123125780631d89e06314611fd05780631e6ad90314611fa15780631fc01a0b14611ee9578063219eb06114611e835780632200d5fa14611d6c5780632366c10914611d49578063281fe31e14611c745780633029b47314611ad95780633944fc8e14611ab357806341e5fb4014611a815780634ead073f14611a6357806354d77e0e14611a2c5780635cfd2fae1461185057806362879b701461182657806362fd2cc1146116f05780636594dd76146116cd5780636ef6766e14611698578063706ad1f614610fda578063715018a614610f805780637649359314610f065780637ba2196a14610ec157806387233afa14610e5b5780638cea7b6414610db45780638da5cb5b14610d8d5780638ea5474414610d645780639bca19e014610d375780639ecd4d7214610845578063a59b436214610822578063a5c8d172146107f5578063ac7ad9ba146107cc578063bb61848b14610754578063bca6ce641461072b578063c29580e014610640578063c5d472ac14610622578063c8a911401461059f578063cc830a9714610547578063cf5faf3e14610529578063d8a531a6146104e4578063d99f35b7146104be578063e5e0a36a14610412578063ece5313214610307578063f2fde38b146102415763f7260d3e1461021657600080fd5b3461023e578060031936011261023e576004546040516001600160a01b039091168152602090f35b80fd5b503461023e57602036600319011261023e5761025b61240d565b610263612604565b6001600160a01b039081169081156102b357600054826001600160601b0360a01b821617600055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a380f35b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b503461023e5760208060031936011261040e5761032261240d565b9061032b612604565b4783816103ef575b50506003546040516370a0823160e01b81523060048201526001600160a01b03918216918382602481865afa9182156103e45786926103b1575b5081610377578580f35b6103a8946040519463a9059cbb60e01b908601521660248401526044830152604482526103a382612484565b612924565b38808080808580f35b9091508381813d83116103dd575b6103c981836124bb565b810103126103d95751903861036d565b8580fd5b503d6103bf565b6040513d88823e3d90fd5b80808061040794875af16104016128a2565b506128e1565b3883610333565b5080fd5b503461023e5761010036600319011261023e57366023121561023e5760405161043a8161249f565b610104813682116104b9576004905b8282106104a95750505061045b612604565b815b600860ff8216818110156104a5576104759084612c2a565b519082101561049157600782015561048c90612c19565b61045d565b634e487b7160e01b84526032600452602484fd5b8480f35b8135815260209182019101610449565b600080fd5b503461023e578060031936011261023e57602060ff60145460101c166040519015158152f35b503461023e578060031936011261023e576040517f00000000000000000000000000000000000076a84fef008cdabe6409d2fe638b6001600160a01b03168152602090f35b503461023e578060031936011261023e576020600654604051908152f35b503461023e57604036600319011261023e5761056161240d565b6024359160ff83168093036104b95760409160018060a01b0316815260196020522090600052602052602060ff604060002054166040519015158152f35b503461023e5760208060031936011261040e576001600160a01b036105c261240d565b1682526018815260408220916040518092808554928381520194835280832092905b82821061060b57610607856105fb818903826124bb565b604051918291826125c9565b0390f35b8354865294850194600193840193909101906105e4565b503461023e578060031936011261023e576020600f54604051908152f35b503461023e5760208060031936011261040e576004356001600160401b038111610727576106729036906004016124f3565b90815190610698610682836124dc565b9261069060405194856124bb565b8084526124dc565b8282019390601f1901368537845b81518110156106e157806106bd6106dc9284612752565b5187526015845260ff6040882054166106d68287612752565b526127f8565b6106a6565b505091909260405193838594850191818652518092526040850193925b82811061070d57505050500390f35b835160ff16855286955093810193928101926001016106fe565b8280fd5b503461023e578060031936011261023e576001546040516001600160a01b039091168152602090f35b503461023e5760208060031936011261040e576004356001600160401b038111610727576107869036906004016124f3565b9061078f612604565b825b82518110156107c857806107a86107c39285612752565b518552601a835260408520805460ff191660011790556127f8565b610791565b8380f35b503461023e578060031936011261023e576003546040516001600160a01b039091168152602090f35b503461023e57602036600319011261023e57600435600481101561040e5760209060100154604051908152f35b503461023e57602036600319011261023e5761083c612604565b60043560055580f35b503461023e57606036600319011261023e576001600160401b039060043582811161040e576108789036906004016124f3565b602492833590811161072757610892903690600401612561565b9061089b612423565b926108a98251845114612c3b565b6001936014549060ff91828160101c16610cd8575b918093949596919216908115610cc4575b8115610cbc575b5015610c785733906001600160a01b0390818116610bbf575b50604051926108fd8461249f565b610100368537845b8751811015610b715781610919828a612752565b5116806001111580610b66575b61092f90612c87565b6109398289612752565b5184600154168b604051918280926331a9108f60e11b825285600483015260209485935afa908115610b5b57879161097f918c91610b2e575b5089831692168214612817565b828a526017825260408a205490878783169283610b1f575b50505015610adc578189526015918282528560408b205416610a9857856109bd85612cc9565b166109db6109d46109ce838d612c2a565b516127f8565b918b612c2a565b52838a5260168252610a0660408b20546109ff886109f888612cc9565b168c612c2a565b51906126a1565b610a0f85612cc9565b6008811015610a85576007015410610a415789525260408720805460ff19169091179055610a3c906127f8565b610905565b60405162461bcd60e51b815260048101839052601e818f01527f4e6f7420656e6f7567682073706163657320696e2074686973207465616d00006044820152606490fd5b634e487b7160e01b8c5260326004528e8cfd5b60405162461bcd60e51b815260048101839052601b818f01527f546f6b656e20494420616c7265616479206861732061207465616d00000000006044820152606490fd5b60649060198d6040519262461bcd60e51b845260048401528201527f4e6f206b657920666f756e6420666f7220746f6b656e204944000000000000006044820152fd5b60081c16149050388781610997565b610b4e9150843d8611610b54575b610b4681836124bb565b810190612710565b38610972565b503d610b3c565b6040513d8c823e3d90fd5b506008811115610926565b50915050825b8181169060088210156104a557610b91610bba9285612c2a565b5183610b9c83612cdc565b1686526016602052610bb3604087209182546126a1565b9055612c19565b610b77565b60015460405163090c9a2d60e41b81526001600160a01b0394851660048201528285166024820152908316909316604484015290916020816064817f00000000000000000000000000000000000076a84fef008cdabe6409d2fe638b87165afa908115610c6d5790610c38918691610c3f575b506127ac565b90386108ef565b610c60915060203d8111610c66575b610c5881836124bb565b810190612794565b38610c32565b503d610c4e565b6040513d87823e3d90fd5b60405162461bcd60e51b8152602060048201819052818801527f4e6f207465616d2073656c656374696f6e202f206561726c79206163636573736044820152606490fd5b9050386108d6565b84546001600160a01b0316331491506108cf565b835b8551811015610d2957610ced8187612752565b518552601a6020528360408620541615610d0f57610d0a906127f8565b610cda565b50909183819495969750915b9050959493929190956108be565b509180939495969192610d1b565b503461023e57602036600319011261023e57600435600881101561040e5760209060070154604051908152f35b503461023e578060031936011261023e576002546040516001600160a01b039091168152602090f35b503461023e578060031936011261023e57546040516001600160a01b039091168152602090f35b503461023e578060031936011261023e5760405190610dd28261249f565b6101008092369037604051610de68161249f565b82368237815b60ff808216906008821015610e2c57908291610e0a610e2794612cdc565b1685526016602052610e2160408620549185612c2a565b52612c19565b610dec565b505060405192919050825b60088310610e4457505050f35b600190825181526020809101920192019190610e37565b503461023e578060031936011261023e576001908181815b610e83575b602083604051908152f35b909160ff841660088111610eba57610eb191610eab91845260166020526040842054906126a1565b93612c19565b92919081610e73565b5091610e78565b503461023e57602036600319011261023e576004356001600160a01b0381169081900361040e57610ef0612604565b6001600160601b0360a01b600454161760045580f35b503461023e57608036600319011261023e57366023121561023e57604051610f2d81612484565b6084813682116104b9576004905b828210610f7057505050610f4d612604565b815b60048110610f5b578280f35b60019060208351930192816010015501610f4f565b8135815260209182019101610f3b565b503461023e578060031936011261023e57610f99612604565b600080546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b5060a036600319011261023e576004356001600160401b03811161040e57611006903690600401612439565b906024351515602435036104b95761101c612423565b906064356001600160401b0381116116945761103c903690600401612439565b6084356001600160401b0381116116905761105b903690600401612439565b90339582840361164c5760ff60145460081c168015611639575b61107e9061265c565b61109761108d896006546126a1565b60055410156126c4565b6001600160a01b0381166115aa575b506001546001600160a01b0316885b8881106114c157505087938793604051936110cf85612484565b60803686378a5b82811061141957505050505080511515806113ee575b6113ad575b811515806113a0575b80611374575b61132a575b816112fb575b505060243515611296573461125157600f546111269161288f565b6003546004546040516323b872dd60e01b60208201523360248201526001600160a01b03918216604482015260648082019490945292835260a083019291166001600160401b0383118284101761123b5761118392604052612924565b835b838110611199575050506006540160065580f35b6112369060186040516111ab81612469565b600181526001600160a01b03861660208083018281529092906111cf868b8a612807565b358b52601784526111f360408c2092511515839060ff801983541691151516179055565b518154610100600160a81b03191660089190911b610100600160a81b0316179055885252604086206112319061122a838887612807565b3590612766565b6127f8565b611185565b634e487b7160e01b600052604160045260246000fd5b60405162461bcd60e51b815260206004820152601c60248201527f53686f756c64206e6f742073656e6420455448207769746820415045000000006044820152606490fd5b8034036112bf57848080806112ba9460018060a01b03600454165af16104016128a2565b611183565b60405162461bcd60e51b8152602060048201526014602482015273125b9cdd59999a58da595b9d081c185e5b595b9d60621b6044820152606490fd5b6040015161131b929161131591156113225760125461288f565b906126a1565b388061110b565b60135461288f565b909161133c61134291601154906126a1565b92612882565b6001600160a01b03851687526019602090815260408089206001808b5292528820805460ff1916909117905590611105565b506001600160a01b038516875260196020908152604080892060018a5290915287205460ff1615611100565b50602081015115156110fa565b915050601054906113bd85612882565b6001600160a01b03851687526019602090815260408089208980529091528720805460ff19166001179055906110f1565b506001600160a01b038516875260196020908152604080892089805290915287205460ff16156110ec565b61142c611427828587612807565b612863565b90828110156114ad578060051b860135601e19873603018112156114a9578601918235926001600160401b0384116114a557602001928060051b360384136114a5576114a0938d61147c93612cee565b61149660ff61148f61142785898b612807565b1689612871565b90151590526127f8565b6110d6565b8e80fd5b8d80fd5b634e487b7160e01b8d52603260045260248dfd5b6114cc818a89612807565b6040516331a9108f60e11b815290356004820152602081602481865afa801561159f5761150e918c91611580575b506001600160a01b038a8116911614612817565b611519818a89612807565b358a52601760205260ff60408b20541661153b57611536906127f8565b6110b5565b60405162461bcd60e51b815260206004820152601a60248201527f546f6b656e20494420616c7265616479207075726368617365640000000000006044820152606490fd5b611599915060203d602011610b5457610b4681836124bb565b386114fa565b6040513d8d823e3d90fd5b60015460405163090c9a2d60e41b81526001600160a01b0398891660048201528883166024820152971660448801529095602081806064810103817f00000000000000000000000000000000000076a84fef008cdabe6409d2fe638b6001600160a01b03165afa801561162e57611627918a91610c3f57506127ac565b94386110a6565b6040513d8b823e3d90fd5b5088546001600160a01b03168714611075565b606460405162461bcd60e51b815260206004820152602060248201527f536e617073686f74732f70726f6f6673206c656e677468206d69736d617463686044820152fd5b8680fd5b8480fd5b503461023e57602036600319011261023e576116b26123fe565b6116ba612604565b60ff801960145416911515161760145580f35b503461023e57602036600319011261023e576116e7612604565b600435600f5580f35b503461023e57604036600319011261023e576001600160401b0360043581811161072757611722903690600401612439565b60249283359081116116945761173c903690600401612439565b929091611747612604565b8381036117e257855b61175a858361288f565b8110156117de5784156117cb576117748582048385612807565b356001600160a01b03811691908290036117c7576117c2918852602060198152604089209060ff6117ab6114278a86068b8b612807565b1660005252604060002060ff1981541690556127f8565b611750565b8780fd5b634e487b7160e01b875260126004528587fd5b8680f35b60405162461bcd60e51b815260206004820152601f818701527f55736572732f736e617073686f7473206c656e677468206d69736d61746368006044820152606490fd5b503461023e57602036600319011261023e576020611848600f5460043561288f565b604051908152f35b503461023e5760208060031936011261040e576004356001600160401b038111610727576118829036906004016124f3565b9081516118a7611891826124dc565b9161189f60405193846124bb565b8083526124dc565b81830193601f199182013686378051916118d96118c3846124dc565b936118d160405195866124bb565b8085526124dc565b8386019101368237865b82518110156119a8576118f68184612752565b51908189526017875260ff60408a2054166119118288612752565b90151590526119208187612752565b51611935575b61193091506127f8565b6118e3565b6001546040516331a9108f60e11b815260048101939093526001600160a01b039088908490602490829085165afa908115610b5b57611930938b92611989575b506119808388612752565b91169052611926565b6119a1919250893d8b11610b5457610b4681836124bb565b9038611975565b8385838a8a8a60405195869560408701906040885251809152606087019390855b818110611a1357505050858303868301525180835291810193925b8281106119f357505050500390f35b83516001600160a01b0316855286955093810193928101926001016119e4565b82511515865289985094840194918401916001016119c9565b503461023e57604036600319011261023e5760ff611a48612551565b611a50612604565b168152601b602052602435604082205580f35b503461023e578060031936011261023e576020600554604051908152f35b503461023e57602036600319011261023e57604060209160ff611aa2612551565b168152601b83522054604051908152f35b503461023e578060031936011261023e57602060ff60145460081c166040519015158152f35b503461023e5760208060031936011261040e576004356001600160401b03811161072757611b0b903690600401612439565b611b13612604565b835b818110611b20578480f35b611b2b818385612807565b600180546040516331a9108f60e11b815292356004840181905292602492916001600160a01b0390899083908690829085165afa918215610b5b578a92611c55575b50848a52601793848a5260ff60408c205416611c12575091611bfa9391611c0d96959360405192611b9d84612469565b83528a8301911692838252848c528a52611bca60408c2092511515839060ff801983541691151516179055565b518154610100600160a81b03191660089190911b610100600160a81b031617905588526018875260408820612766565b6006611c0681546127f8565b90556127f8565b611b15565b8960186064926040519262461bcd60e51b845260048401528201527f546f6b656e20494420616c726561647920686173206b657900000000000000006044820152fd5b611c6d919250893d8b11610b5457610b4681836124bb565b9038611b6d565b503461023e5760208060031936011261040e5760ff9182611c93612551565b16806001111580611d3e575b611ca890612c87565b80825260168352604082205493611cbe856124dc565b94611ccc60405196876124bb565b808652611cdb601f19916124dc565b01368587013782600194600554955b86811115611d0057604051806106078a826125c9565b80835260158252848460408520541614611d23575b611d1e906127f8565b611cea565b94611d3681876106d6611d1e948c612752565b959050611d15565b506008811115611c9f565b503461023e578060031936011261023e57602060ff601454166040519015158152f35b503461023e576020908160031936011261023e57611d8861240d565b908060018060a01b03606481600154169460405195869384926327a8d7ab60e01b84521660048301526001602483015261753060448301525afa918215611e76578192611dde575b6040518061060785826125c9565b9091503d8083833e611df081836124bb565b8101908381830312610727578051906001600160401b038211611e72570181601f8201121561072757805190611e25826124dc565b93611e3360405195866124bb565b828552858086019360051b83010193841161023e57508401905b828210611e635750505061060791503880611dd0565b81518152908401908401611e4d565b8380fd5b50604051903d90823e3d90fd5b503461023e57606036600319011261023e57611e9d612551565b602435916001600160a01b03831683036104b957604435906001600160401b03821161023e576020611edf8585611ed73660048801612439565b929091612cee565b6040519015158152f35b503461023e57604036600319011261023e576001600160401b0360043581811161072757611f1b9036906004016124f3565b9060243590811161072757611f34903690600401612561565b90611f3d612604565b611f4a8151835114612c3b565b825b81518110156107c85780601660ff611f67611f9c9487612752565b5116611f738386612752565b51875260209060158252604088208160ff1982541617905587525260408520611c0681546127f8565b611f4c565b503461023e57602036600319011261023e5760ff60406020926004358152601a84522054166040519015158152f35b503461023e57604036600319011261023e576004359060249182359060ff60145460081c1680156122ff575b6120059061265c565b600654906001918281018091116121ab576120249060055410156126c4565b6002546040516331a9108f60e11b808252600482018490526020936001600160a01b0393841693909285818b81885afa90811561162e5789916122e2575b50813391160361229e578481875416928a6040518095819382528b60048301525afa918215612293578892612274575b5033911603612230578486526017835260ff6040872054166121ec57604051906120bb82612469565b8482528336818401376120cd8261272f565b52813b156103d9576120f88692839260405194858094819363a552d0bf60e01b8352600483016125c9565b03925af18015610c6d576121be575b5060405161211481612469565b828152818101338152848652601783526121416040872092511515839060ff801983541691151516179055565b518154610100600160a81b03191660089190911b610100600160a81b03161790553384526018815260408420612178908490612766565b6006548281018091116121ab57906121a792916006556040519161219b83612469565b8252368183013761272f565b5280f35b634e487b7160e01b855260116004528585fd5b6001600160401b0381959295116121d9576040529238612107565b634e487b7160e01b825260416004528582fd5b60405162461bcd60e51b815260048101849052601d818901527f4b657920616c72656164792070757263686173656420666f7220414c540000006044820152606490fd5b60405162461bcd60e51b815260048101849052601f818901527f55736572206d757374206f776e2074686520414c545320746f6b656e204944006044820152606490fd5b61228c919250853d8711610b5457610b4681836124bb565b9038612092565b6040513d8a823e3d90fd5b60405162461bcd60e51b8152600481018690526019818b01527f55736572206d757374206f776e206120426c75652050617373000000000000006044820152606490fd5b6122f99150863d8811610b5457610b4681836124bb565b38612062565b5082546001600160a01b03163314611ffc565b503461023e57608036600319011261023e5761232c61240d565b6001600160401b03602435818111611e725761234c903690600401612439565b9160443590811161169457612365903690600401612439565b93905060643594851515860361023e5760206118488787878787612ad2565b503461023e57602036600319011261023e5761239e6123fe565b6123a6612604565b61ff0060145491151560081b169061ff0019161760145580f35b503461023e57602036600319011261023e576123da6123fe565b6123e2612604565b62ff000060145491151560101b169062ff000019161760145580f35b6004359081151582036104b957565b600435906001600160a01b03821682036104b957565b604435906001600160a01b03821682036104b957565b9181601f840112156104b9578235916001600160401b0383116104b9576020808501948460051b0101116104b957565b604081019081106001600160401b0382111761123b57604052565b608081019081106001600160401b0382111761123b57604052565b61010081019081106001600160401b0382111761123b57604052565b90601f801991011681019081106001600160401b0382111761123b57604052565b6001600160401b03811161123b5760051b60200190565b81601f820112156104b95780359161250a836124dc565b9261251860405194856124bb565b808452602092838086019260051b8201019283116104b9578301905b828210612542575050505090565b81358152908301908301612534565b6004359060ff821682036104b957565b81601f820112156104b957803591612578836124dc565b9261258660405194856124bb565b808452602092838086019260051b8201019283116104b9578301905b8282106125b0575050505090565b813560ff811681036104b95781529083019083016125a2565b6020908160408183019282815285518094520193019160005b8281106125f0575050505090565b8351855293810193928101926001016125e2565b6000546001600160a01b0316330361261857565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b1561266357565b60405162461bcd60e51b8152602060048201526016602482015275141d5c98da185cd95cc8185c9948191a5cd8589b195960521b6044820152606490fd5b919082018092116126ae57565b634e487b7160e01b600052601160045260246000fd5b156126cb57565b60405162461bcd60e51b815260206004820152601a60248201527f546f74616c20746f6b656e206c696d69742065786365656465640000000000006044820152606490fd5b908160209103126104b957516001600160a01b03811681036104b95790565b80511561273c5760200190565b634e487b7160e01b600052603260045260246000fd5b805182101561273c5760209160051b010190565b8054906801000000000000000082101561123b576001820180825582101561273c5760005260206000200155565b908160209103126104b9575180151581036104b95790565b156127b357565b60405162461bcd60e51b815260206004820152601e60248201527f696e76616c69642064656c65676174652d7661756c742070616972696e6700006044820152606490fd5b60001981146126ae5760010190565b919081101561273c5760051b0190565b1561281e57565b60405162461bcd60e51b815260206004820152601a60248201527f55736572206d757374206f776e2074686520746f6b656e2049440000000000006044820152606490fd5b3560ff811681036104b95790565b90600481101561273c5760051b0190565b80156126ae576000190190565b818102929181159184041417156126ae57565b3d156128dc573d906001600160401b03821161123b57604051916128d0601f8201601f1916602001846124bb565b82523d6000602084013e565b606090565b156128e857565b60405162461bcd60e51b81526020600482015260146024820152732330b4b632b2103a379039b2b7321022ba3432b960611b6044820152606490fd5b604051612982916001600160a01b031661293d82612469565b6000806020958685527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656487860152868151910182855af161297c6128a2565b916129fe565b8051908161298f57505050565b828061299f938301019101612794565b156129a75750565b6084906040519062461bcd60e51b82526004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152fd5b91929015612a605750815115612a12575090565b3b15612a1b5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b825190915015612a735750805190602001fd5b6040519062461bcd60e51b82528160208060048301528251908160248401526000935b828510612ab9575050604492506000838284010152601f80199101168101030190fd5b8481018201518686016044015293810193859350612a96565b93929160009483604093845193612ae885612484565b6080368637885b818110612bfb575050508251151580612bd2575b612bbb575b508315159081612bad575b81612b80575b50612b62575b82612b3e575b505050600014612b3b57600f54612b3b9161288f565b90565b01519192612b5992909161131591156113225760125461288f565b90388080612b25565b9193612b74612b7a91601154906126a1565b94612882565b91612b1f565b905060018060a01b0316600052601960205281600020600160005260205260ff8260002054161538612b19565b602083015115159150612b13565b95509250612bcb60105495612882565b9238612b08565b506001600160a01b03821687526019602090815284882088805290528387205460ff1615612b03565b8060016106d660ff61148f611427612c1496888a612807565b612aef565b60ff1660ff81146126ae5760010190565b90600881101561273c5760051b0190565b15612c4257565b60405162461bcd60e51b815260206004820152601e60248201527f546f6b656e4964732f7465616d73206c656e677468206d69736d6174636800006044820152606490fd5b15612c8e57565b60405162461bcd60e51b815260206004820152601360248201527224b73b30b634b2103a32b0b690373ab6b132b960691b6044820152606490fd5b60ff6000199116019060ff82116126ae57565b60ff60019116019060ff82116126ae57565b90929360ff6000921682526020601b815260409384842054958551838101916001600160601b03199060601b16825260148152612d2a81612469565b51902090612d37886124dc565b97612d448751998a6124bb565b8089528389019060051b820191368311611690578490915b838310612dba57505050509183925b8751841015612daf57612d7e8489612752565b519081811015612d9f5785528252612d998585205b936127f8565b92612d6b565b9085528252612d99858520612d93565b945095505050501490565b8235815291810191859101612d5c56fea26469706673582212205af845cbb2c3a83818f8ab0e7df985b10aa064b56a1b2768ec9b571798357ab264736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000749f5ddf5ab4c1f26f74560a78300563c34b417d000000000000000000000000c778e11492cf9d44c9ffc074648a34897e4664cb0000000000000000000000004d224452801aced8b2f0aebe155379bb5d59438100000000000000000000000054da2032be4661c741e07d0e7d3c422e5389f45f00000000000000000000000000000000000000000000000000000000000014820000000000000000000000000000000000000000000000000000000000001356000000000000000000000000000000000000000000000000000000000000135600000000000000000000000000000000000000000000000000000000000012c000000000000000000000000000000000000000000000000000000000000011940000000000000000000000000000000000000000000000000000000000000ea6000000000000000000000000000000000000000000000000000000000000038400000000000000000000000000000000000000000000000000000000000003840000000000000000000000000000000000000000000000000000000000000dac000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1a2bc2ec50000000000000000000000000000000000000000000000000000010a741a46278000000000000000000000000000000000000000000000000000016345785d8a000000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000076a84fef008cdabe6409d2fe638b9d2eda87ee18d77f08408dfc3e765c5fed74a0dc1a5fcff27c8853973aa109c9b524f38376edfa68c63f00cb7f9e435e98656502ee5515b90620bcfec9b8bf2ea8a4d7c922905464c1d81c8c84c403e2848ccc000210651f1b5ec53faa8c2bf6
-----Decoded View---------------
Arg [0] : _erc721 (address): 0x749f5Ddf5Ab4c1F26f74560A78300563C34B417d
Arg [1] : _bluePass (address): 0xc778e11492cf9D44c9fFc074648a34897E4664cb
Arg [2] : _apeCoin (address): 0x4d224452801ACEd8B2F0aebE155379bb5D594381
Arg [3] : _receiver (address): 0x54DA2032be4661c741e07D0E7d3c422e5389f45F
Arg [4] : _teamLimits (uint256[8]): 5250,4950,4950,4800,4500,3750,900,900
Arg [5] : _totalKeyLimit (uint256): 3500
Arg [6] : _snapshotPrices (uint256[4]): 0,50000000000000000,75000000000000000,100000000000000000
Arg [7] : _ethApeExchangeRate (uint256): 480
Arg [8] : _delegateCash (address): 0x00000000000076A84feF008CDAbe6409d2FE638B
Arg [9] : _snapshot1Merkle (bytes32): 0x9d2eda87ee18d77f08408dfc3e765c5fed74a0dc1a5fcff27c8853973aa109c9
Arg [10] : _snapshot2Merkle (bytes32): 0xb524f38376edfa68c63f00cb7f9e435e98656502ee5515b90620bcfec9b8bf2e
Arg [11] : _snapshot3Merkle (bytes32): 0xa8a4d7c922905464c1d81c8c84c403e2848ccc000210651f1b5ec53faa8c2bf6
-----Encoded View---------------
22 Constructor Arguments found :
Arg [0] : 000000000000000000000000749f5ddf5ab4c1f26f74560a78300563c34b417d
Arg [1] : 000000000000000000000000c778e11492cf9d44c9ffc074648a34897e4664cb
Arg [2] : 0000000000000000000000004d224452801aced8b2f0aebe155379bb5d594381
Arg [3] : 00000000000000000000000054da2032be4661c741e07d0e7d3c422e5389f45f
Arg [4] : 0000000000000000000000000000000000000000000000000000000000001482
Arg [5] : 0000000000000000000000000000000000000000000000000000000000001356
Arg [6] : 0000000000000000000000000000000000000000000000000000000000001356
Arg [7] : 00000000000000000000000000000000000000000000000000000000000012c0
Arg [8] : 0000000000000000000000000000000000000000000000000000000000001194
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000ea6
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000384
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000384
Arg [12] : 0000000000000000000000000000000000000000000000000000000000000dac
Arg [13] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [14] : 00000000000000000000000000000000000000000000000000b1a2bc2ec50000
Arg [15] : 000000000000000000000000000000000000000000000000010a741a46278000
Arg [16] : 000000000000000000000000000000000000000000000000016345785d8a0000
Arg [17] : 00000000000000000000000000000000000000000000000000000000000001e0
Arg [18] : 00000000000000000000000000000000000076a84fef008cdabe6409d2fe638b
Arg [19] : 9d2eda87ee18d77f08408dfc3e765c5fed74a0dc1a5fcff27c8853973aa109c9
Arg [20] : b524f38376edfa68c63f00cb7f9e435e98656502ee5515b90620bcfec9b8bf2e
Arg [21] : a8a4d7c922905464c1d81c8c84c403e2848ccc000210651f1b5ec53faa8c2bf6
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.