Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
0x60a06040 | 16058372 | 582 days ago | IN | Create: BattleZone | 0 ETH | 0.04619767 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
BattleZone
Compiler Version
v0.8.16+commit.07a7930e
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.16; import {ECDSA} from "@solady/utils/ECDSA.sol"; import {OwnableUpgradeable} from "@oz-upgradeable/access/OwnableUpgradeable.sol"; import {IERC721} from "@oz/token/ERC721/IERC721.sol"; import {IERC20} from "@oz/token/ERC20/IERC20.sol"; import {Initializable} from "@oz-upgradeable/proxy/utils/Initializable.sol"; import {UUPSUpgradeable} from "@oz-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import {IBattleZone} from "./interfaces/IBattleZone.sol"; import {IERC721Receiver} from "@oz/token/ERC721/IERC721Receiver.sol"; contract BattleZone is IBattleZone, Initializable, OwnableUpgradeable, UUPSUpgradeable { using ECDSA for bytes32; uint256 public constant SECONDS_IN_DAY = 1 days; uint256 public constant ACCELERATED_YIELD_DAYS = 2 days; uint256 public constant ACCELERATED_YIELD_MULTIPLIER = 2; uint256 public constant MAX_TOOL_BOXES_STAKED = 3; /// @notice Staker information struct Staker { uint256 currentYield; uint256 accumulatedAmount; uint256 lastCheckpoint; uint256[] stakedBots; uint256[] stakedBattery; } /// @notice Beep Boop Box NFT IERC721 public beepBoopBotNft; /// @notice Battery NFT IERC721 public batteryNft; /// @notice Toolbox NFT IERC721 public toolboxNft; /// @notice Accelerated yield time uint256 public acceleratedYield; /// @notice For rarity based rewards address public signerAddress; /// @notice Launch staking with the bonus bool public stakingLaunched; /// @notice Pause all deposits bool public depositPaused; mapping(address => uint256) public baseYieldRate; mapping(address => mapping(uint256 => uint256)) private _rarityBasedYield; mapping(address => Staker) private _stakers; mapping(address => mapping(uint256 => address)) private _ownerOfToken; /// @notice The toolboxes associated to a bot mapping(uint256 => uint256[]) beepBoopBotToolboxes; // unused /// @notice The beep boop asigned to the toolbox mapping(uint256 => uint256) private _beepBoopBotOfToolboxId; // unused /// @notice Temporary gating of withdrawals mapping(address => bool) private withdrawGated; /// @notice Staked exo suits IERC721 public exoSuitNft; mapping(uint256 => uint256) beepBoopBotExoSuit; mapping(uint256 => uint256) private _beepBoopBotOfExoSuit; /// @notice Stake batteries mapping(address => uint256[]) userToolboxes; /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } function initialize(address _beepBoopBot, address _signer) external initializer { beepBoopBotNft = IERC721(_beepBoopBot); baseYieldRate[_beepBoopBot] = 1500e18; signerAddress = _signer; __Ownable_init(); __UUPSUpgradeable_init(); } function deposit( address contractAddress, uint256[] memory tokenIds, uint256[] memory tokenRarities, bytes calldata signature ) public validContract(contractAddress) { require(!depositPaused, "Deposit paused"); require(stakingLaunched, "Staking is not launched yet"); require(contractAddress != address(toolboxNft), "Use deposit toolbox"); require(contractAddress != address(exoSuitNft), "Use deposit exosuit"); // validate the source of truth of the rarity if (tokenRarities.length > 0) { require(tokenIds.length == tokenRarities.length, "Array mismatch"); require( _validateSignature( signature, contractAddress, tokenIds, tokenRarities ), "Bad signature" ); } Staker storage user = _stakers[msg.sender]; uint256 newYield = user.currentYield; // refactor toolbox yield if (contractAddress == address(beepBoopBotNft)) { uint256 beforeYield = _calculateToolboxYield( userToolboxes[msg.sender].length, user.stakedBots.length ); uint256 afterYield = _calculateToolboxYield( userToolboxes[msg.sender].length, user.stakedBots.length + tokenIds.length ); newYield += afterYield - beforeYield; } else if (contractAddress == address(batteryNft)) { require( user.stakedBattery.length + tokenIds.length <= 20, "Maximum of 20 batteries can be staked" ); } for (uint256 i; i < tokenIds.length; ++i) { uint256 tokenId = tokenIds[i]; IERC721(contractAddress).safeTransferFrom( msg.sender, address(this), tokenId ); // set rarity if it exists if (tokenRarities.length > 0) { uint256 tokenRarity = tokenRarities[i]; if (tokenRarity != 0) { _rarityBasedYield[contractAddress][tokenId] = tokenRarity; } } _ownerOfToken[contractAddress][tokenId] = msg.sender; newYield += getTokenYield(contractAddress, tokenId); if (contractAddress == address(beepBoopBotNft)) { user.stakedBots.push(tokenId); } else if (contractAddress == address(batteryNft)) { user.stakedBattery.push(tokenId); } } accumulate(msg.sender); user.currentYield = newYield; emit Deposit(msg.sender, contractAddress, tokenIds.length); } function withdraw(address contractAddress, uint256[] memory tokenIds) public validContract(contractAddress) { require(contractAddress != address(toolboxNft), "Use withdraw toolbox"); require(contractAddress != address(exoSuitNft), "Use withdraw exosuit"); require(!withdrawGated[msg.sender], "Unable to withdraw"); Staker storage user = _stakers[msg.sender]; uint256 newYield = user.currentYield; // refactor toolbox yield if (contractAddress == address(beepBoopBotNft)) { uint256 beforeYield = _calculateToolboxYield( userToolboxes[msg.sender].length, user.stakedBots.length ); uint256 afterYield = _calculateToolboxYield( userToolboxes[msg.sender].length, user.stakedBots.length - tokenIds.length ); newYield -= beforeYield - afterYield; } for (uint256 i; i < tokenIds.length; i++) { require( IERC721(contractAddress).ownerOf(tokenIds[i]) == address(this), "Not the owner" ); _ownerOfToken[contractAddress][tokenIds[i]] = address(0); if (user.currentYield != 0) { uint256 tokenYield = getTokenYield( contractAddress, tokenIds[i] ); newYield -= tokenYield; } if (contractAddress == address(beepBoopBotNft)) { require( beepBoopBotExoSuit[tokenIds[i]] == 0, "Must Unstake Exo Suit" ); user.stakedBots = _shiftElementToEnd( user.stakedBots, tokenIds[i] ); user.stakedBots.pop(); } else if (contractAddress == address(batteryNft)) { user.stakedBattery = _shiftElementToEnd( user.stakedBattery, tokenIds[i] ); user.stakedBattery.pop(); } IERC721(contractAddress).safeTransferFrom( address(this), msg.sender, tokenIds[i] ); } accumulate(msg.sender); user.currentYield = newYield; emit Withdraw(msg.sender, contractAddress, tokenIds.length); } /** * @notice Deposit */ function depositToolboxes(uint256[] memory toolboxTokenIds) public { require(!depositPaused, "Deposit paused"); require(stakingLaunched, "Staking is not launched yet"); address toolboxNft_ = address(toolboxNft); require(toolboxNft_ != address(0), "!disabled"); Staker storage user = _stakers[msg.sender]; uint256 netIncrease; // get number of bots uint256 numBots = user.stakedBots.length; require(numBots > 0, "Must have a bot staked"); uint256 numToolboxes = userToolboxes[msg.sender].length; for (uint256 i; i < toolboxTokenIds.length; i++) { uint256 toolboxTokenId = toolboxTokenIds[i]; IERC721(toolboxNft_).safeTransferFrom( msg.sender, address(this), toolboxTokenId ); userToolboxes[msg.sender].push(toolboxTokenId); _ownerOfToken[toolboxNft_][toolboxTokenId] = msg.sender; } uint256 beforeYield = _calculateToolboxYield(numToolboxes, numBots); uint256 afterYield = _calculateToolboxYield( numToolboxes + toolboxTokenIds.length, numBots ); netIncrease = afterYield - beforeYield; accumulate(msg.sender); user.currentYield += netIncrease; emit Deposit(msg.sender, toolboxNft_, toolboxTokenIds.length); } function _calculateToolboxYield(uint256 numToolboxes, uint256 numBots) private view returns (uint256 total) { uint256 botsPerToolbox = (numToolboxes / MAX_TOOL_BOXES_STAKED); return (numBots < botsPerToolbox ? numBots : botsPerToolbox) * baseYieldRate[address(toolboxNft)]; } function withdrawToolboxes(uint256[] memory toolboxTokenIds) public { address toolboxNft_ = address(toolboxNft); require(toolboxNft_ != address(0), "!disabled"); Staker storage user = _stakers[msg.sender]; uint256 newYield = user.currentYield; uint256 numToolboxes = userToolboxes[msg.sender].length; uint256 beforeYield = _calculateToolboxYield( numToolboxes, user.stakedBots.length ); for (uint256 i; i < toolboxTokenIds.length; i++) { uint256 toolboxTokenId = toolboxTokenIds[i]; require( ownerOf(address(toolboxNft_), toolboxTokenId) == msg.sender, "Not the owner" ); _ownerOfToken[toolboxNft_][toolboxTokenId] = address(0); // remove toolbox from beep bop userToolboxes[msg.sender] = _shiftElementToEnd( userToolboxes[msg.sender], toolboxTokenId ); userToolboxes[msg.sender].pop(); // return it back IERC721(toolboxNft_).safeTransferFrom( address(this), msg.sender, toolboxTokenId ); } if (user.currentYield != 0) { uint256 afterYield = _calculateToolboxYield( numToolboxes - toolboxTokenIds.length, user.stakedBots.length ); newYield -= beforeYield - afterYield; } accumulate(msg.sender); user.currentYield = newYield; emit Withdraw(msg.sender, toolboxNft_, toolboxTokenIds.length); } /** * @notice Deposit */ function depositExoSuit(uint256 beepBoopTokenId, uint256 beepBoopExoSuitId) public { require(!depositPaused, "Deposit paused"); require(stakingLaunched, "Staking is not launched yet"); require( ownerOf(address(beepBoopBotNft), beepBoopTokenId) == msg.sender, "Beep boop not staked" ); address exoSuitNft_ = address(exoSuitNft); require(exoSuitNft_ != address(0), "!disabled"); Staker storage user = _stakers[msg.sender]; uint256 netIncrease; IERC721(exoSuitNft_).safeTransferFrom( msg.sender, address(this), beepBoopExoSuitId ); require( beepBoopBotExoSuit[beepBoopTokenId] == 0, "Bot already has an exo suit" ); beepBoopBotExoSuit[beepBoopTokenId] = beepBoopExoSuitId; netIncrease += getTokenYield(exoSuitNft_, beepBoopExoSuitId); _ownerOfToken[exoSuitNft_][beepBoopExoSuitId] = msg.sender; _beepBoopBotOfExoSuit[beepBoopExoSuitId] = beepBoopTokenId; accumulate(msg.sender); user.currentYield += netIncrease; emit Deposit(msg.sender, exoSuitNft_, 1); } function withdrawExoSuit(uint256 exoSuitTokenId) public { address exoSuitNft_ = address(exoSuitNft); require(exoSuitNft_ != address(0), "!disabled"); Staker storage user = _stakers[msg.sender]; uint256 newYield = user.currentYield; uint256 exoSuitBeepBoopId = _beepBoopBotOfExoSuit[exoSuitTokenId]; require( IERC721(exoSuitNft_).ownerOf(exoSuitTokenId) == address(this), "Exo suit not staked" ); require( ownerOf(address(beepBoopBotNft), exoSuitBeepBoopId) == msg.sender, "Not the bot owner" ); _ownerOfToken[exoSuitNft_][exoSuitTokenId] = address(0); // reduce yield if (user.currentYield != 0) { uint256 tokenYield = getTokenYield(exoSuitNft_, exoSuitTokenId); newYield -= tokenYield; } // remove suit from beep bop delete beepBoopBotExoSuit[exoSuitBeepBoopId]; // return it back IERC721(exoSuitNft_).safeTransferFrom( address(this), msg.sender, exoSuitTokenId ); accumulate(msg.sender); user.currentYield = newYield; emit Withdraw(msg.sender, exoSuitNft_, 1); } modifier validContract(address contract_) { require( (contract_ != address(0) && contract_ == address(beepBoopBotNft)) || contract_ == address(toolboxNft) || contract_ == address(batteryNft) || contract_ == address(exoSuitNft), "Unknown contract" ); _; } function getAccumulatedAmount(address staker) external view returns (uint256) { if (withdrawGated[staker] == true) { return 0; } return _stakers[staker].accumulatedAmount + getCurrentReward(staker); } function getTokenYield(address contractAddress, uint256 tokenId) public view returns (uint256) { uint256 tokenYield = _rarityBasedYield[contractAddress][tokenId]; if (tokenYield == 0) { tokenYield = baseYieldRate[contractAddress]; } return tokenYield; } function getStakerYield(address staker) public view returns (uint256) { return _stakers[staker].currentYield; } function getStakerTokens(address staker) public view returns ( uint256[] memory, uint256[] memory, uint256[] memory, uint256[] memory ) { uint256[] memory stakedBots = _stakers[staker].stakedBots; uint256[] memory stakedExoSuits = new uint256[](stakedBots.length); for (uint256 i; i < stakedBots.length; ++i) { stakedExoSuits[i] = beepBoopBotExoSuit[stakedBots[i]]; } return ( stakedBots, _stakers[staker].stakedBattery, userToolboxes[staker], stakedExoSuits ); } function isRaritiesSet(address contractAddress, uint256[] memory tokenIds) public view returns (bool[] memory) { unchecked { bool[] memory rarities = new bool[](tokenIds.length); for (uint256 t; t < tokenIds.length; ++t) { rarities[t] = _rarityBasedYield[contractAddress][tokenIds[t]] > 0; } return rarities; } } function _shiftElementToEnd(uint256[] memory list, uint256 tokenId) internal pure returns (uint256[] memory) { uint256 tokenIndex = 0; uint256 lastTokenIndex = list.length - 1; uint256 length = list.length; for (uint256 i = 0; i < length; i++) { if (list[i] == tokenId) { tokenIndex = i + 1; break; } } require(tokenIndex != 0, "msg.sender is not the owner"); tokenIndex -= 1; if (tokenIndex != lastTokenIndex) { list[tokenIndex] = list[lastTokenIndex]; list[lastTokenIndex] = tokenId; } return list; } function _validateSignature( bytes calldata signature, address contractAddress, uint256[] memory tokenIds, uint256[] memory tokenRarities ) internal view returns (bool) { bytes32 dataHash = keccak256( abi.encodePacked(contractAddress, tokenIds, tokenRarities) ); address receivedAddress = dataHash.toEthSignedMessageHash().recover( signature ); return (receivedAddress != address(0) && receivedAddress == signerAddress); } function getCurrentReward(address staker) public view returns (uint256) { Staker memory user = _stakers[staker]; if (user.lastCheckpoint == 0) { return 0; } if ( user.lastCheckpoint < acceleratedYield && block.timestamp < acceleratedYield ) { return (((block.timestamp - user.lastCheckpoint) * user.currentYield) / SECONDS_IN_DAY) * ACCELERATED_YIELD_MULTIPLIER; } if ( user.lastCheckpoint < acceleratedYield && block.timestamp > acceleratedYield ) { uint256 currentReward; currentReward += (((acceleratedYield - user.lastCheckpoint) * user.currentYield) / SECONDS_IN_DAY) * ACCELERATED_YIELD_MULTIPLIER; currentReward += ((block.timestamp - acceleratedYield) * user.currentYield) / SECONDS_IN_DAY; return currentReward; } return ((block.timestamp - user.lastCheckpoint) * user.currentYield) / SECONDS_IN_DAY; } /** * @dev Used prior to mutating rewards, to save what has been accumulated so far */ function accumulate(address staker) internal { _stakers[staker].accumulatedAmount += getCurrentReward(staker); _stakers[staker].lastCheckpoint = block.timestamp; } /** * @dev Returns token owner address (returns address(0) if token is not inside the gateway) */ function ownerOf(address contractAddress, uint256 tokenId) public view returns (address) { return _ownerOfToken[contractAddress][tokenId]; } function setBatteryNft(address _battery, uint256 baseReward) public onlyOwner { batteryNft = IERC721(_battery); baseYieldRate[_battery] = baseReward; } function setExoSuitNft(address _battery, uint256 baseReward) public onlyOwner { exoSuitNft = IERC721(_battery); baseYieldRate[_battery] = baseReward; } function setToolboxNft(address toolboxNft_, uint256 baseReward) public onlyOwner { toolboxNft = IERC721(toolboxNft_); baseYieldRate[toolboxNft_] = baseReward; } /** * @dev Function allows admin withdraw ERC721 in case of emergency. */ function emergencyWithdraw(address tokenAddress, uint256[] memory tokenIds) public onlyOwner { require(tokenIds.length <= 50, "50 is max per tx"); depositPaused = true; for (uint256 i; i < tokenIds.length; i++) { address receiver = _ownerOfToken[tokenAddress][tokenIds[i]]; if ( receiver != address(0) && IERC721(tokenAddress).ownerOf(tokenIds[i]) == address(this) ) { IERC721(tokenAddress).transferFrom( address(this), receiver, tokenIds[i] ); emit WithdrawStuckERC721(receiver, tokenAddress, tokenIds[i]); } } } function withdrawGatedAsAdmin( address gatedAddress, address contractAddress, address destAddress ) public validContract(contractAddress) onlyOwner { require(withdrawGated[gatedAddress], "Gated addresses only"); uint256[] memory tokenIds; ( uint256[] memory bots, uint256[] memory batteries, uint256[] memory toolboxes, uint256[] memory exosuits ) = getStakerTokens(gatedAddress); // reset the token balance if (contractAddress == address(beepBoopBotNft)) { tokenIds = bots; delete _stakers[gatedAddress].stakedBots; } else if (contractAddress == address(batteryNft)) { tokenIds = batteries; delete _stakers[gatedAddress].stakedBattery; } else if (contractAddress == address(toolboxNft)) { tokenIds = toolboxes; delete userToolboxes[gatedAddress]; } else if (contractAddress == address(exoSuitNft)) { tokenIds = exosuits; } // transfer out nft for (uint256 i; i < tokenIds.length; i++) { uint256 tokenId = tokenIds[i]; if (tokenId == 0) { continue; } _ownerOfToken[contractAddress][tokenId] = address(0); if (contractAddress == address(exoSuitNft)) { uint256 exoSuitBeepBoopId = _beepBoopBotOfExoSuit[tokenId]; if (exoSuitBeepBoopId != 0) { delete beepBoopBotExoSuit[exoSuitBeepBoopId]; } } IERC721(contractAddress).safeTransferFrom( address(this), destAddress, tokenId ); } } /** * @dev Function allows to pause deposits if needed. Withdraw remains active. */ function toggleDeposits() public onlyOwner { depositPaused = !depositPaused; } /** * @dev Function allows to pause deposits if needed. Withdraw remains active. */ function updateSignerAddress(address _signer) public onlyOwner { signerAddress = _signer; } function launchStaking() public onlyOwner { require(!stakingLaunched, "Staking has been launched already"); stakingLaunched = true; acceleratedYield = block.timestamp + ACCELERATED_YIELD_DAYS; } function setWithdrawalGate(address[] memory addresses, bool toggle) public onlyOwner { for (uint256 i; i < addresses.length; ++i) { address address_ = addresses[i]; withdrawGated[address_] = toggle; } } function updateBaseYield(address _contract, uint256 _yield) public onlyOwner { baseYieldRate[_contract] = _yield; } /** * @notice Do not use this function unless you know what you are doing */ function updateUserYield( address[] memory addresses, uint256[] memory yields ) public onlyOwner { require(addresses.length == yields.length); for (uint256 i; i < addresses.length; ++i) { address user = addresses[i]; accumulate(user); _stakers[user].currentYield = yields[i]; } } function onERC721Received( address, address, uint256, bytes calldata ) external pure returns (bytes4) { return IERC721Receiver.onERC721Received.selector; } function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} function getImplementation() external view returns (address) { return _getImplementation(); } }
// 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.7.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (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: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _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); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.0; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822ProxiableUpgradeable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeaconUpgradeable.sol"; import "../../interfaces/draft-IERC1822Upgradeable.sol"; import "../../utils/AddressUpgradeable.sol"; import "../../utils/StorageSlotUpgradeable.sol"; import "../utils/Initializable.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ * * @custom:oz-upgrades-unsafe-allow delegatecall */ abstract contract ERC1967UpgradeUpgradeable is Initializable { function __ERC1967Upgrade_init() internal onlyInitializing { } function __ERC1967Upgrade_init_unchained() internal onlyInitializing { } // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall( address newImplementation, bytes memory data, bool forceCall ) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { _functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS( address newImplementation, bytes memory data, bool forceCall ) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Emitted when the beacon is upgraded. */ event BeaconUpgraded(address indexed beacon); /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall( address newBeacon, bytes memory data, bool forceCall ) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { _functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data); } } /** * @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) private returns (bytes memory) { require(AddressUpgradeable.isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return AddressUpgradeable.verifyCallResult(success, returndata, "Address: low-level delegate call failed"); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeaconUpgradeable { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized < type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Internal function that returns the initialized version. Returns `_initialized` */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Internal function that returns the initialized version. Returns `_initializing` */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.0; import "../../interfaces/draft-IERC1822Upgradeable.sol"; import "../ERC1967/ERC1967UpgradeUpgradeable.sol"; import "./Initializable.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. * * _Available since v4.1._ */ abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable { function __UUPSUpgradeable_init() internal onlyInitializing { } function __UUPSUpgradeable_init_unchained() internal onlyInitializing { } /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment address private immutable __self = address(this); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { require(address(this) != __self, "Function must be called through delegatecall"); require(_getImplementation() == __self, "Function must be called through active proxy"); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall"); _; } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual override notDelegated returns (bytes32) { return _IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. */ function upgradeTo(address newImplementation) external virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, new bytes(0), false); } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. */ function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data, true); } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeTo} and {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal override onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @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://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.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 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; import "../proxy/utils/Initializable.sol"; /** * @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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol) pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ``` * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._ */ library StorageSlotUpgradeable { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Gas optimized ECDSA wrapper. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol) library ECDSA { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The number which `s` must not exceed in order for /// the signature to be non-malleable. bytes32 private constant _MALLEABILITY_THRESHOLD = 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* RECOVERY OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Recovers the signer's address from a message digest `hash`, /// and the `signature`. /// /// This function does NOT accept EIP-2098 short form signatures. /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098 /// short form signatures instead. /// /// WARNING! /// The `result` will be the zero address upon recovery failure. /// As such, it is extremely important to ensure that the address which /// the `result` is compared against is never zero. function recover(bytes32 hash, bytes calldata signature) internal view returns (address result) { assembly { if eq(signature.length, 65) { // Copy the free memory pointer so that we can restore it later. let m := mload(0x40) // Directly copy `r` and `s` from the calldata. calldatacopy(0x40, signature.offset, 0x40) // If `s` in lower half order, such that the signature is not malleable. if iszero(gt(mload(0x60), _MALLEABILITY_THRESHOLD)) { mstore(0x00, hash) // Compute `v` and store it in the scratch space. mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) pop( staticcall( gas(), // Amount of gas left for the transaction. 0x01, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x40, // Start of output. 0x20 // Size of output. ) ) // Restore the zero slot. mstore(0x60, 0) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(sub(0x60, returndatasize())) } // Restore the free memory pointer. mstore(0x40, m) } } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the EIP-2098 short form signature defined by `r` and `vs`. /// /// This function only accepts EIP-2098 short form signatures. /// See: https://eips.ethereum.org/EIPS/eip-2098 /// /// To be honest, I do not recommend using EIP-2098 signatures /// for simplicity, performance, and security reasons. Most if not /// all clients support traditional non EIP-2098 signatures by default. /// As such, this method is intentionally not fully inlined. /// It is merely included for completeness. /// /// WARNING! /// The `result` will be the zero address upon recovery failure. /// As such, it is extremely important to ensure that the address which /// the `result` is compared against is never zero. function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal view returns (address result) { uint8 v; bytes32 s; assembly { s := shr(1, shl(1, vs)) v := add(shr(255, vs), 27) } result = recover(hash, v, r, s); } /// @dev Recovers the signer's address from a message digest `hash`, /// and the signature defined by `v`, `r`, `s`. /// /// WARNING! /// The `result` will be the zero address upon recovery failure. /// As such, it is extremely important to ensure that the address which /// the `result` is compared against is never zero. function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal view returns (address result) { assembly { // Copy the free memory pointer so that we can restore it later. let m := mload(0x40) // If `s` in lower half order, such that the signature is not malleable. if iszero(gt(s, _MALLEABILITY_THRESHOLD)) { mstore(0x00, hash) mstore(0x20, v) mstore(0x40, r) mstore(0x60, s) pop( staticcall( gas(), // Amount of gas left for the transaction. 0x01, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x40, // Start of output. 0x20 // Size of output. ) ) // Restore the zero slot. mstore(0x60, 0) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(sub(0x60, returndatasize())) } // Restore the free memory pointer. mstore(0x40, m) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HASHING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns an Ethereum Signed Message, created from a `hash`. /// This produces a hash corresponding to the one signed with the /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign) /// JSON-RPC method as part of EIP-191. function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) { assembly { // Store into scratch space for keccak256. mstore(0x20, hash) mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 0x40 - 0x04 = 0x3c result := keccak256(0x04, 0x3c) } } /// @dev Returns an Ethereum Signed Message, created from `s`. /// This produces a hash corresponding to the one signed with the /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign) /// JSON-RPC method as part of EIP-191. function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) { assembly { // We need at most 128 bytes for Ethereum signed message header. // The max length of the ASCII reprenstation of a uint256 is 78 bytes. // The length of "\x19Ethereum Signed Message:\n" is 26 bytes (i.e. 0x1a). // The next multiple of 32 above 78 + 26 is 128 (i.e. 0x80). // Instead of allocating, we temporarily copy the 128 bytes before the // start of `s` data to some variables. let m3 := mload(sub(s, 0x60)) let m2 := mload(sub(s, 0x40)) let m1 := mload(sub(s, 0x20)) // The length of `s` is in bytes. let sLength := mload(s) let ptr := add(s, 0x20) // `end` marks the end of the memory which we will compute the keccak256 of. let end := add(ptr, sLength) // Convert the length of the bytes to ASCII decimal representation // and store it into the memory. // prettier-ignore for { let temp := sLength } 1 {} { ptr := sub(ptr, 1) mstore8(ptr, add(48, mod(temp, 10))) temp := div(temp, 10) // prettier-ignore if iszero(temp) { break } } // Copy the header over to the memory. mstore(sub(ptr, 0x20), "\x00\x00\x00\x00\x00\x00\x19Ethereum Signed Message:\n") // Compute the keccak256 of the memory. result := keccak256(sub(ptr, 0x1a), sub(end, sub(ptr, 0x1a))) // Restore the previous memory. mstore(s, sLength) mstore(sub(s, 0x20), m1) mstore(sub(s, 0x40), m2) mstore(sub(s, 0x60), m3) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; interface IBattleZone { event Deposit( address indexed staker, address contractAddress, uint256 tokensAmount ); event Withdraw( address indexed staker, address contractAddress, uint256 tokensAmount ); event AutoDeposit( address indexed contractAddress, uint256 tokenId, address indexed owner ); event WithdrawStuckERC721( address indexed receiver, address indexed tokenAddress, uint256 indexed tokenId ); function deposit( address contractAddress, uint256[] memory tokenIds, uint256[] memory tokenRarities, bytes calldata signature ) external; function withdraw(address contractAddress, uint256[] memory tokenIds) external; function depositToolboxes(uint256[] memory toolboxTokenIds) external; function withdrawToolboxes(uint256[] memory toolboxTokenIds) external; function getAccumulatedAmount(address staker) external view returns (uint256); function getStakerTokens(address staker) external view returns ( uint256[] memory, uint256[] memory, uint256[] memory, uint256[] memory ); }
{ "remappings": [ "@erc721a/=lib/erc721a/contracts/", "@oz-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@oz/=lib/openzeppelin-contracts/contracts/", "@prb/test/=lib/prb-test/src/", "@solady/=lib/solady/src/", "@std/=lib/forge-std/src/", "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/operator-filter-registry/lib/openzeppelin-contracts/lib/erc4626-tests/", "erc721a/=lib/erc721a/contracts/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/", "operator-filter-registry/=lib/operator-filter-registry/src/", "prb-test/=lib/prb-test/src/", "solady/=lib/solady/src/", "solmate/=lib/solady/lib/solmate/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"AutoDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokensAmount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokensAmount","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"WithdrawStuckERC721","type":"event"},{"inputs":[],"name":"ACCELERATED_YIELD_DAYS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ACCELERATED_YIELD_MULTIPLIER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TOOL_BOXES_STAKED","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECONDS_IN_DAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceleratedYield","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"baseYieldRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"batteryNft","outputs":[{"internalType":"contract IERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"beepBoopBotNft","outputs":[{"internalType":"contract IERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"tokenRarities","type":"uint256[]"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"beepBoopTokenId","type":"uint256"},{"internalType":"uint256","name":"beepBoopExoSuitId","type":"uint256"}],"name":"depositExoSuit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"toolboxTokenIds","type":"uint256[]"}],"name":"depositToolboxes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"exoSuitNft","outputs":[{"internalType":"contract IERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"getAccumulatedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"getCurrentReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"getStakerTokens","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"getStakerYield","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getTokenYield","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_beepBoopBot","type":"address"},{"internalType":"address","name":"_signer","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"isRaritiesSet","outputs":[{"internalType":"bool[]","name":"","type":"bool[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"launchStaking","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_battery","type":"address"},{"internalType":"uint256","name":"baseReward","type":"uint256"}],"name":"setBatteryNft","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_battery","type":"address"},{"internalType":"uint256","name":"baseReward","type":"uint256"}],"name":"setExoSuitNft","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"toolboxNft_","type":"address"},{"internalType":"uint256","name":"baseReward","type":"uint256"}],"name":"setToolboxNft","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"bool","name":"toggle","type":"bool"}],"name":"setWithdrawalGate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingLaunched","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toggleDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toolboxNft","outputs":[{"internalType":"contract IERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_contract","type":"address"},{"internalType":"uint256","name":"_yield","type":"uint256"}],"name":"updateBaseYield","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_signer","type":"address"}],"name":"updateSignerAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"yields","type":"uint256[]"}],"name":"updateUserYield","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"exoSuitTokenId","type":"uint256"}],"name":"withdrawExoSuit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"gatedAddress","type":"address"},{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"address","name":"destAddress","type":"address"}],"name":"withdrawGatedAsAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"toolboxTokenIds","type":"uint256[]"}],"name":"withdrawToolboxes","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a0604052306080523480156200001557600080fd5b506200002062000026565b620000e8565b600054610100900460ff1615620000935760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff9081161015620000e6576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b60805161430e6200012060003960008181610d9f01528181610ddf015281816111f20152818161123201526112ae015261430e6000f3fe60806040526004361061027d5760003560e01c80637af617751161014f578063b5cc14b0116100c1578063df0ef69d1161007a578063df0ef69d146107ab578063dfeaa74c146107cb578063e1af5698146107eb578063f2fde38b1461080c578063f610f50a1461082c578063fa224c3f1461084157600080fd5b8063b5cc14b014610701578063bf7da66814610721578063c1c1ef9814610741578063c66a717414610756578063c68e516114610776578063d907813c1461079657600080fd5b80638ac94275116101135780638ac94275146106595780638da5cb5b146106795780638fa2a9f014610697578063a30a2474146106b7578063aaf10f42146106cc578063b396f34b146106e157600080fd5b80637af61775146105b957806381d7a7a9146105d95780638293744b146105f957806382dd013f14610619578063876a23ff1461063957600080fd5b80634d307e3f116101f357806361499ab9116101ac57806361499ab91461051657806361a52a36146105365780636d462ea31461054d5780636dea22e01461056d578063715018a61461058d5780637486560d146105a257600080fd5b80634d307e3f146104615780634f1ef28614610481578063524f76e91461049457806352d1902d146104b45780635b7633d0146104c95780635e22e16f146104e957600080fd5b80631f29d2dc116102455780631f29d2dc146103635780632161a2b61461039b57806336332028146103cb5780633659cfe6146103eb578063485cc9551461040b5780634bee21d41461042b57600080fd5b806302befd241461028257806304129667146102b857806309828c9f146102e657806312259252146102fc578063150b7a021461031e575b600080fd5b34801561028e57600080fd5b5060cd546102a390600160a81b900460ff1681565b60405190151581526020015b60405180910390f35b3480156102c457600080fd5b506102d86102d33660046138e6565b61086e565b6040519081526020016102af565b3480156102f257600080fd5b506102d860cc5481565b34801561030857600080fd5b5061031c610317366004613903565b6108d0565b005b34801561032a57600080fd5b5061034a61033936600461396e565b630a85bd0160e11b95945050505050565b6040516001600160e01b031990911681526020016102af565b34801561036f57600080fd5b5061038361037e3660046139e1565b610b5f565b6040516001600160a01b0390911681526020016102af565b3480156103a757600080fd5b506103bb6103b63660046138e6565b610b87565b6040516102af9493929190613a48565b3480156103d757600080fd5b5060ca54610383906001600160a01b031681565b3480156103f757600080fd5b5061031c6104063660046138e6565b610d95565b34801561041757600080fd5b5061031c610426366004613aa0565b610e5d565b34801561043757600080fd5b506102d86104463660046138e6565b6001600160a01b0316600090815260d0602052604090205490565b34801561046d57600080fd5b506102d861047c3660046138e6565b610fc3565b61031c61048f366004613b20565b6111e8565b3480156104a057600080fd5b5060cb54610383906001600160a01b031681565b3480156104c057600080fd5b506102d86112a1565b3480156104d557600080fd5b5060cd54610383906001600160a01b031681565b3480156104f557600080fd5b50610509610504366004613c57565b611354565b6040516102af9190613ca7565b34801561052257600080fd5b506102d86105313660046139e1565b611422565b34801561054257600080fd5b506102d86201518081565b34801561055957600080fd5b5061031c610568366004613d51565b61146b565b34801561057957600080fd5b5061031c6105883660046139e1565b6114d3565b34801561059957600080fd5b5061031c61150c565b3480156105ae57600080fd5b506102d86202a30081565b3480156105c557600080fd5b5061031c6105d4366004613d9d565b611520565b3480156105e557600080fd5b5061031c6105f43660046139e1565b611a54565b34801561060557600080fd5b5061031c610614366004613c57565b611a8d565b34801561062557600080fd5b5061031c610634366004613e2e565b61210d565b34801561064557600080fd5b5060d554610383906001600160a01b031681565b34801561066557600080fd5b5061031c610674366004613e2e565b612382565b34801561068557600080fd5b506033546001600160a01b0316610383565b3480156106a357600080fd5b5061031c6106b23660046138e6565b612656565b3480156106c357600080fd5b5061031c612680565b3480156106d857600080fd5b50610383612711565b3480156106ed57600080fd5b5061031c6106fc366004613e63565b612720565b34801561070d57600080fd5b5061031c61071c366004613e7c565b612996565b34801561072d57600080fd5b5061031c61073c3660046139e1565b612ca0565b34801561074d57600080fd5b506102d8600281565b34801561076257600080fd5b5060c954610383906001600160a01b031681565b34801561078257600080fd5b5061031c6107913660046139e1565b612cd9565b3480156107a257600080fd5b5061031c612cfd565b3480156107b757600080fd5b5061031c6107c6366004613ec7565b612d26565b3480156107d757600080fd5b5061031c6107e6366004613c57565b612db7565b3480156107f757600080fd5b5060cd546102a390600160a01b900460ff1681565b34801561081857600080fd5b5061031c6108273660046138e6565b61300c565b34801561083857600080fd5b506102d8600381565b34801561084d57600080fd5b506102d861085c3660046138e6565b60ce6020526000908152604090205481565b6001600160a01b038116600090815260d4602052604081205460ff16151560010361089b57506000919050565b6108a482610fc3565b6001600160a01b038316600090815260d060205260409020600101546108ca9190613f37565b92915050565b60cd54600160a81b900460ff16156109035760405162461bcd60e51b81526004016108fa90613f4a565b60405180910390fd5b60cd54600160a01b900460ff1661092c5760405162461bcd60e51b81526004016108fa90613f72565b60c9543390610944906001600160a01b031684610b5f565b6001600160a01b0316146109915760405162461bcd60e51b81526020600482015260146024820152731099595c08189bdbdc081b9bdd081cdd185ad95960621b60448201526064016108fa565b60d5546001600160a01b0316806109ba5760405162461bcd60e51b81526004016108fa90613fa9565b33600081815260d060205260408082209051632142170760e11b815290926001600160a01b038516916342842e0e916109f99130908990600401613fcc565b600060405180830381600087803b158015610a1357600080fd5b505af1158015610a27573d6000803e3d6000fd5b505050600086815260d66020526040902054159050610a885760405162461bcd60e51b815260206004820152601b60248201527f426f7420616c72656164792068617320616e2065786f2073756974000000000060448201526064016108fa565b600085815260d660205260409020849055610aa38385611422565b610aad9082613f37565b6001600160a01b038416600090815260d160209081526040808320888452825280832080546001600160a01b0319163390811790915560d7909252909120879055909150610afa90613082565b80826000016000828254610b0e9190613f37565b9091555050604080516001600160a01b03851681526001602082015233917f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f6291015b60405180910390a25050505050565b6001600160a01b03918216600090815260d16020908152604080832093835292905220541690565b606080606080600060d06000876001600160a01b03166001600160a01b03168152602001908152602001600020600301805480602002602001604051908101604052809291908181526020018280548015610c0157602002820191906000526020600020905b815481526020019060010190808311610bed575b505050505090506000815167ffffffffffffffff811115610c2457610c24613ad9565b604051908082528060200260200182016040528015610c4d578160200160208202803683370190505b50905060005b8251811015610cb65760d66000848381518110610c7257610c72613ff0565b6020026020010151815260200190815260200160002054828281518110610c9b57610c9b613ff0565b6020908102919091010152610caf81614006565b9050610c53565b506001600160a01b038716600090815260d06020908152604080832060d883529281902060049093018054825181850281018501909352808352869491939192869290918591830182828015610d2b57602002820191906000526020600020905b815481526020019060010190808311610d17575b5050505050925081805480602002602001604051908101604052809291908181526020018280548015610d7d57602002820191906000526020600020905b815481526020019060010190808311610d69575b50505050509150955095509550955050509193509193565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610ddd5760405162461bcd60e51b81526004016108fa9061401f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610e0f6130db565b6001600160a01b031614610e355760405162461bcd60e51b81526004016108fa9061406b565b610e3e816130f7565b60408051600080825260208201909252610e5a918391906130ff565b50565b600054610100900460ff1615808015610e7d5750600054600160ff909116105b80610e975750303b158015610e97575060005460ff166001145b610efa5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016108fa565b6000805460ff191660011790558015610f1d576000805461ff0019166101001790555b60c980546001600160a01b03199081166001600160a01b03868116918217909355600090815260ce60205260409020685150ae84a8cdf00000905560cd8054909116918416919091179055610f7061326a565b610f78613299565b8015610fbe576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b038116600090815260d060209081526040808320815160a081018352815481526001820154818501526002820154818401526003820180548451818702810187019095528085528695929460608601939092919083018282801561104d57602002820191906000526020600020905b815481526020019060010190808311611039575b50505050508152602001600482018054806020026020016040519081016040528092919081815260200182805480156110a557602002820191906000526020600020905b815481526020019060010190808311611091575b505050505081525050905080604001516000036110c55750600092915050565b60cc5481604001511080156110db575060cc5442105b1561111e578051604082015160029162015180916110f990426140b7565b61110391906140ca565b61110d91906140e9565b61111791906140ca565b9392505050565b60cc548160400151108015611134575060cc5442115b156111bd5760006002620151808360000151846040015160cc5461115891906140b7565b61116291906140ca565b61116c91906140e9565b61117691906140ca565b6111809082613f37565b825160cc54919250620151809161119790426140b7565b6111a191906140ca565b6111ab91906140e9565b6111b59082613f37565b949350505050565b805160408201516201518091906111d490426140b7565b6111de91906140ca565b61111791906140e9565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036112305760405162461bcd60e51b81526004016108fa9061401f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166112626130db565b6001600160a01b0316146112885760405162461bcd60e51b81526004016108fa9061406b565b611291826130f7565b61129d828260016130ff565b5050565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146113415760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016108fa565b5060008051602061429283398151915290565b60606000825167ffffffffffffffff81111561137257611372613ad9565b60405190808252806020026020018201604052801561139b578160200160208202803683370190505b50905060005b835181101561141a576001600160a01b038516600090815260cf60205260408120855182908790859081106113d8576113d8613ff0565b60200260200101518152602001908152602001600020541182828151811061140257611402613ff0565b911515602092830291909101909101526001016113a1565b509392505050565b6001600160a01b038216600090815260cf60209081526040808320848452909152812054808203611117575050506001600160a01b0316600090815260ce602052604090205490565b6114736132c0565b60005b8251811015610fbe57600083828151811061149357611493613ff0565b6020908102919091018101516001600160a01b0316600090815260d490915260409020805460ff1916841515179055506114cc81614006565b9050611476565b6114db6132c0565b60ca80546001600160a01b039093166001600160a01b031990931683179055600091825260ce602052604090912055565b6115146132c0565b61151e600061331a565b565b846001600160a01b03811615801590611546575060c9546001600160a01b038281169116145b8061155e575060cb546001600160a01b038281169116145b80611576575060ca546001600160a01b038281169116145b8061158e575060d5546001600160a01b038281169116145b6115aa5760405162461bcd60e51b81526004016108fa9061410b565b60cd54600160a81b900460ff16156115d45760405162461bcd60e51b81526004016108fa90613f4a565b60cd54600160a01b900460ff166115fd5760405162461bcd60e51b81526004016108fa90613f72565b60cb546001600160a01b03908116908716036116515760405162461bcd60e51b81526020600482015260136024820152720aae6ca40c8cae0dee6d2e840e8deded8c4def606b1b60448201526064016108fa565b60d5546001600160a01b03908116908716036116a55760405162461bcd60e51b8152602060048201526013602482015272155cd94819195c1bdcda5d08195e1bdcdd5a5d606a1b60448201526064016108fa565b8351156117375783518551146116ee5760405162461bcd60e51b815260206004820152600e60248201526d082e4e4c2f240dad2e6dac2e8c6d60931b60448201526064016108fa565b6116fb838388888861336c565b6117375760405162461bcd60e51b815260206004820152600d60248201526c426164207369676e617475726560981b60448201526064016108fa565b33600090815260d060205260409020805460c9546001600160a01b03908116908916036117ca5733600090815260d86020526040812054600384015461177d919061340c565b33600090815260d860205260408120548a51600387015493945091926117ab926117a691613f37565b61340c565b90506117b782826140b7565b6117c19084613f37565b9250505061184f565b60ca546001600160a01b039081169089160361184f57865160048301546014916117f391613f37565b111561184f5760405162461bcd60e51b815260206004820152602560248201527f4d6178696d756d206f66203230206261747465726965732063616e20626520736044820152641d185ad95960da1b60648201526084016108fa565b60005b87518110156119f557600088828151811061186f5761186f613ff0565b60200260200101519050896001600160a01b03166342842e0e3330846040518463ffffffff1660e01b81526004016118a993929190613fcc565b600060405180830381600087803b1580156118c357600080fd5b505af11580156118d7573d6000803e3d6000fd5b505050506000885111156119345760008883815181106118f9576118f9613ff0565b6020026020010151905080600014611932576001600160a01b038b16600090815260cf6020908152604080832085845290915290208190555b505b6001600160a01b038a16600090815260d160209081526040808320848452909152902080546001600160a01b031916331790556119718a82611422565b61197b9084613f37565b60c9549093506001600160a01b03908116908b16036119b35760038401805460018101825560009182526020909120018190556119e4565b60ca546001600160a01b03908116908b16036119e45760048401805460018101825560009182526020909120018190555b506119ee81614006565b9050611852565b506119ff33613082565b8082558651604080516001600160a01b038b168152602081019290925233917f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f6291015b60405180910390a25050505050505050565b611a5c6132c0565b60cb80546001600160a01b039093166001600160a01b031990931683179055600091825260ce602052604090912055565b816001600160a01b03811615801590611ab3575060c9546001600160a01b038281169116145b80611acb575060cb546001600160a01b038281169116145b80611ae3575060ca546001600160a01b038281169116145b80611afb575060d5546001600160a01b038281169116145b611b175760405162461bcd60e51b81526004016108fa9061410b565b60cb546001600160a01b0390811690841603611b6c5760405162461bcd60e51b81526020600482015260146024820152730aae6ca40eed2e8d0c8e4c2ee40e8deded8c4def60631b60448201526064016108fa565b60d5546001600160a01b0390811690841603611bc15760405162461bcd60e51b8152602060048201526014602482015273155cd9481dda5d1a191c985dc8195e1bdcdd5a5d60621b60448201526064016108fa565b33600090815260d4602052604090205460ff1615611c165760405162461bcd60e51b8152602060048201526012602482015271556e61626c6520746f20776974686472617760701b60448201526064016108fa565b33600090815260d060205260409020805460c9546001600160a01b0390811690861603611ca05733600090815260d860205260408120546003840154611c5c919061340c565b33600090815260d86020526040812054875160038701549394509192611c85926117a6916140b7565b9050611c9181836140b7565b611c9b90846140b7565b925050505b60005b84518110156120bc57306001600160a01b0316866001600160a01b0316636352211e878481518110611cd757611cd7613ff0565b60200260200101516040518263ffffffff1660e01b8152600401611cfd91815260200190565b602060405180830381865afa158015611d1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d3e9190614135565b6001600160a01b031614611d845760405162461bcd60e51b815260206004820152600d60248201526c2737ba103a34329037bbb732b960991b60448201526064016108fa565b6001600160a01b038616600090815260d16020526040812086518290889085908110611db257611db2613ff0565b6020026020010151815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b031602179055508260000154600014611e2d576000611e1d87878481518110611e1057611e10613ff0565b6020026020010151611422565b9050611e2981846140b7565b9250505b60c9546001600160a01b0390811690871603611f715760d66000868381518110611e5957611e59613ff0565b6020026020010151815260200190815260200160002054600014611eb75760405162461bcd60e51b8152602060048201526015602482015274135d5cdd08155b9cdd185ad948115e1bc814dd5a5d605a1b60448201526064016108fa565b611f2c83600301805480602002602001604051908101604052809291908181526020018280548015611f0857602002820191906000526020600020905b815481526020019060010190808311611ef4575b5050505050868381518110611f1f57611f1f613ff0565b6020026020010151613451565b8051611f42916003860191602090910190613857565b5082600301805480611f5657611f56614152565b6001900381819060005260206000200160009055905561202e565b60ca546001600160a01b039081169087160361202e57611fed83600401805480602002602001604051908101604052809291908181526020018280548015611f085760200282019190600052602060002090815481526020019060010190808311611ef4575050505050868381518110611f1f57611f1f613ff0565b8051612003916004860191602090910190613857565b508260040180548061201757612017614152565b600190038181906000526020600020016000905590555b856001600160a01b03166342842e0e303388858151811061205157612051613ff0565b60200260200101516040518463ffffffff1660e01b815260040161207793929190613fcc565b600060405180830381600087803b15801561209157600080fd5b505af11580156120a5573d6000803e3d6000fd5b5050505080806120b490614006565b915050611ca3565b506120c633613082565b8082558351604080516001600160a01b0388168152602081019290925233917f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb9101610b50565b60cd54600160a81b900460ff16156121375760405162461bcd60e51b81526004016108fa90613f4a565b60cd54600160a01b900460ff166121605760405162461bcd60e51b81526004016108fa90613f72565b60cb546001600160a01b0316806121895760405162461bcd60e51b81526004016108fa90613fa9565b33600090815260d0602052604081206003810154909190806121e65760405162461bcd60e51b8152602060048201526016602482015275135d5cdd081a185d99481848189bdd081cdd185ad95960521b60448201526064016108fa565b33600090815260d86020526040812054905b86518110156122e757600087828151811061221557612215613ff0565b60200260200101519050866001600160a01b03166342842e0e3330846040518463ffffffff1660e01b815260040161224f93929190613fcc565b600060405180830381600087803b15801561226957600080fd5b505af115801561227d573d6000803e3d6000fd5b505033600081815260d8602090815260408083208054600181018255908452828420018790556001600160a01b038d16835260d182528083209683529590529390932080546001600160a01b031916909317909255508190506122df81614006565b9150506121f8565b5060006122f4828461340c565b9050600061230e8851846123089190613f37565b8561340c565b905061231a82826140b7565b945061232533613082565b848660000160008282546123399190613f37565b90915550508751604080516001600160a01b038a168152602081019290925233917f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f629101611a42565b60cb546001600160a01b0316806123ab5760405162461bcd60e51b81526004016108fa90613fa9565b33600090815260d060209081526040808320805460d8909352908320546003820154919390916123dc90839061340c565b905060005b86518110156125bd5760008782815181106123fe576123fe613ff0565b60200260200101519050336001600160a01b031661241c8883610b5f565b6001600160a01b0316146124625760405162461bcd60e51b815260206004820152600d60248201526c2737ba103a34329037bbb732b960991b60448201526064016108fa565b6001600160a01b038716600090815260d160209081526040808320848452825280832080546001600160a01b031916905533835260d882529182902080548351818402810184019094528084526124ee93928301828280156124e357602002820191906000526020600020905b8154815260200190600101908083116124cf575b505050505082613451565b33600090815260d86020908152604090912082516125129391929190910190613857565b5033600090815260d86020526040902080548061253157612531614152565b60019003818190600052602060002001600090559055866001600160a01b03166342842e0e3033846040518463ffffffff1660e01b815260040161257793929190613fcc565b600060405180830381600087803b15801561259157600080fd5b505af11580156125a5573d6000803e3d6000fd5b505050505080806125b590614006565b9150506123e1565b508354156125fb5760006125e18751846125d791906140b7565b600387015461340c565b90506125ed81836140b7565b6125f790856140b7565b9350505b61260433613082565b8284558551604080516001600160a01b0388168152602081019290925233917f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb910160405180910390a2505050505050565b61265e6132c0565b60cd80546001600160a01b0319166001600160a01b0392909216919091179055565b6126886132c0565b60cd54600160a01b900460ff16156126ec5760405162461bcd60e51b815260206004820152602160248201527f5374616b696e6720686173206265656e206c61756e6368656420616c726561646044820152607960f81b60648201526084016108fa565b60cd805460ff60a01b1916600160a01b17905561270c6202a30042613f37565b60cc55565b600061271b6130db565b905090565b60d5546001600160a01b0316806127495760405162461bcd60e51b81526004016108fa90613fa9565b33600090815260d060209081526040808320805486855260d7909352928190205490516331a9108f60e11b81526004810186905230906001600160a01b03861690636352211e90602401602060405180830381865afa1580156127b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127d49190614135565b6001600160a01b0316146128205760405162461bcd60e51b8152602060048201526013602482015272115e1bc81cdd5a5d081b9bdd081cdd185ad959606a1b60448201526064016108fa565b60c9543390612838906001600160a01b031683610b5f565b6001600160a01b0316146128825760405162461bcd60e51b81526020600482015260116024820152702737ba103a3432903137ba1037bbb732b960791b60448201526064016108fa565b6001600160a01b038416600090815260d160209081526040808320888452909152902080546001600160a01b03191690558254156128d65760006128c68587611422565b90506128d281846140b7565b9250505b600081815260d660205260408082209190915551632142170760e11b81526001600160a01b038516906342842e0e9061291790309033908a90600401613fcc565b600060405180830381600087803b15801561293157600080fd5b505af1158015612945573d6000803e3d6000fd5b5050505061295233613082565b818355604080516001600160a01b03861681526001602082015233917f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb9101610b50565b816001600160a01b038116158015906129bc575060c9546001600160a01b038281169116145b806129d4575060cb546001600160a01b038281169116145b806129ec575060ca546001600160a01b038281169116145b80612a04575060d5546001600160a01b038281169116145b612a205760405162461bcd60e51b81526004016108fa9061410b565b612a286132c0565b6001600160a01b038416600090815260d4602052604090205460ff16612a875760405162461bcd60e51b8152602060048201526014602482015273476174656420616464726573736573206f6e6c7960601b60448201526064016108fa565b6060600080600080612a9889610b87565b60c954939750919550935091506001600160a01b0390811690891603612ae9576001600160a01b038916600090815260d0602052604081209495508594612ae4916003909101906138a2565b612b81565b60ca546001600160a01b0390811690891603612b2b576001600160a01b038916600090815260d0602052604081209395508593612ae4916004909101906138a2565b60cb546001600160a01b0390811690891603612b67576001600160a01b038916600090815260d8602052604081209295508592612ae4916138a2565b60d5546001600160a01b0390811690891603612b81578094505b60005b8551811015612c94576000868281518110612ba157612ba1613ff0565b6020026020010151905080600003612bb95750612c82565b6001600160a01b03808b16600081815260d160209081526040808320868452909152902080546001600160a01b031916905560d5549091169003612c1e57600081815260d760205260409020548015612c1c57600081815260d660205260408120555b505b604051632142170760e11b81526001600160a01b038b16906342842e0e90612c4e9030908d908690600401613fcc565b600060405180830381600087803b158015612c6857600080fd5b505af1158015612c7c573d6000803e3d6000fd5b50505050505b80612c8c81614006565b915050612b84565b50505050505050505050565b612ca86132c0565b60d580546001600160a01b039093166001600160a01b031990931683179055600091825260ce602052604090912055565b612ce16132c0565b6001600160a01b03909116600090815260ce6020526040902055565b612d056132c0565b60cd805460ff60a81b198116600160a81b9182900460ff1615909102179055565b612d2e6132c0565b8051825114612d3c57600080fd5b60005b8251811015610fbe576000838281518110612d5c57612d5c613ff0565b60200260200101519050612d6f81613082565b828281518110612d8157612d81613ff0565b6020908102919091018101516001600160a01b03909216600090815260d09091526040902055612db081614006565b9050612d3f565b612dbf6132c0565b603281511115612e045760405162461bcd60e51b815260206004820152601060248201526f06a6040d2e640dac2f040e0cae440e8f60831b60448201526064016108fa565b60cd805460ff60a81b1916600160a81b17905560005b8151811015610fbe576001600160a01b038316600090815260d16020526040812083518290859085908110612e5157612e51613ff0565b6020908102919091018101518252810191909152604001600020546001600160a01b031690508015801590612f1e5750306001600160a01b0316846001600160a01b0316636352211e858581518110612eac57612eac613ff0565b60200260200101516040518263ffffffff1660e01b8152600401612ed291815260200190565b602060405180830381865afa158015612eef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f139190614135565b6001600160a01b0316145b15612ff957836001600160a01b03166323b872dd3083868681518110612f4657612f46613ff0565b60200260200101516040518463ffffffff1660e01b8152600401612f6c93929190613fcc565b600060405180830381600087803b158015612f8657600080fd5b505af1158015612f9a573d6000803e3d6000fd5b50505050828281518110612fb057612fb0613ff0565b6020026020010151846001600160a01b0316826001600160a01b03167ffefe036cac4ee3a4aca074a81cbcc4376e1484693289078dbec149c890101d5b60405160405180910390a45b508061300481614006565b915050612e1a565b6130146132c0565b6001600160a01b0381166130795760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016108fa565b610e5a8161331a565b61308b81610fc3565b6001600160a01b038216600090815260d06020526040812060010180549091906130b6908490613f37565b90915550506001600160a01b0316600090815260d06020526040902042600290910155565b600080516020614292833981519152546001600160a01b031690565b610e5a6132c0565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561313257610fbe8361357f565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561318c575060408051601f3d908101601f1916820190925261318991810190614168565b60015b6131ef5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016108fa565b600080516020614292833981519152811461325e5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016108fa565b50610fbe83838361361b565b600054610100900460ff166132915760405162461bcd60e51b81526004016108fa90614181565b61151e613646565b600054610100900460ff1661151e5760405162461bcd60e51b81526004016108fa90614181565b6033546001600160a01b0316331461151e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016108fa565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600080848484604051602001613384939291906141f1565b60405160208183030381529060405280519060200120905060006133d988886133d2856020527b19457468657265756d205369676e6564204d6573736167653a0a3332600052603c60042090565b9190613676565b90506001600160a01b03811615801590613400575060cd546001600160a01b038281169116145b98975050505050505050565b60008061341a6003856140e9565b60cb546001600160a01b0316600090815260ce60205260409020549091508184106134455781613447565b835b6111b591906140ca565b60606000806001855161346491906140b7565b855190915060005b818110156134b8578587828151811061348757613487613ff0565b6020026020010151036134a65761349f816001613f37565b93506134b8565b806134b081614006565b91505061346c565b50826000036135095760405162461bcd60e51b815260206004820152601b60248201527f6d73672e73656e646572206973206e6f7420746865206f776e6572000000000060448201526064016108fa565b6135146001846140b7565b92508183146135755785828151811061352f5761352f613ff0565b602002602001015186848151811061354957613549613ff0565b6020026020010181815250508486838151811061356857613568613ff0565b6020026020010181815250505b5093949350505050565b6001600160a01b0381163b6135ec5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016108fa565b60008051602061429283398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b613624836136e5565b6000825111806136315750805b15610fbe576136408383613725565b50505050565b600054610100900460ff1661366d5760405162461bcd60e51b81526004016108fa90614181565b61151e3361331a565b600060418203611117576040516040846040377f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0606051116136db5784600052604084013560001a602052602060406080600060015afa5060006060523d6060035191505b6040529392505050565b6136ee8161357f565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b61378d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016108fa565b600080846001600160a01b0316846040516137a89190614242565b600060405180830381855af49150503d80600081146137e3576040519150601f19603f3d011682016040523d82523d6000602084013e6137e8565b606091505b509150915061381082826040518060600160405280602781526020016142b260279139613819565b95945050505050565b60608315613828575081611117565b611117838381511561383d5781518083602001fd5b8060405162461bcd60e51b81526004016108fa919061425e565b828054828255906000526020600020908101928215613892579160200282015b82811115613892578251825591602001919060010190613877565b5061389e9291506138bc565b5090565b5080546000825590600052602060002090810190610e5a91905b5b8082111561389e57600081556001016138bd565b6001600160a01b0381168114610e5a57600080fd5b6000602082840312156138f857600080fd5b8135611117816138d1565b6000806040838503121561391657600080fd5b50508035926020909101359150565b60008083601f84011261393757600080fd5b50813567ffffffffffffffff81111561394f57600080fd5b60208301915083602082850101111561396757600080fd5b9250929050565b60008060008060006080868803121561398657600080fd5b8535613991816138d1565b945060208601356139a1816138d1565b935060408601359250606086013567ffffffffffffffff8111156139c457600080fd5b6139d088828901613925565b969995985093965092949392505050565b600080604083850312156139f457600080fd5b82356139ff816138d1565b946020939093013593505050565b600081518084526020808501945080840160005b83811015613a3d57815187529582019590820190600101613a21565b509495945050505050565b608081526000613a5b6080830187613a0d565b8281036020840152613a6d8187613a0d565b90508281036040840152613a818186613a0d565b90508281036060840152613a958185613a0d565b979650505050505050565b60008060408385031215613ab357600080fd5b8235613abe816138d1565b91506020830135613ace816138d1565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613b1857613b18613ad9565b604052919050565b60008060408385031215613b3357600080fd5b8235613b3e816138d1565b915060208381013567ffffffffffffffff80821115613b5c57600080fd5b818601915086601f830112613b7057600080fd5b813581811115613b8257613b82613ad9565b613b94601f8201601f19168501613aef565b91508082528784828501011115613baa57600080fd5b80848401858401376000848284010152508093505050509250929050565b600067ffffffffffffffff821115613be257613be2613ad9565b5060051b60200190565b600082601f830112613bfd57600080fd5b81356020613c12613c0d83613bc8565b613aef565b82815260059290921b84018101918181019086841115613c3157600080fd5b8286015b84811015613c4c5780358352918301918301613c35565b509695505050505050565b60008060408385031215613c6a57600080fd5b8235613c75816138d1565b9150602083013567ffffffffffffffff811115613c9157600080fd5b613c9d85828601613bec565b9150509250929050565b6020808252825182820181905260009190848201906040850190845b81811015613ce1578351151583529284019291840191600101613cc3565b50909695505050505050565b600082601f830112613cfe57600080fd5b81356020613d0e613c0d83613bc8565b82815260059290921b84018101918181019086841115613d2d57600080fd5b8286015b84811015613c4c578035613d44816138d1565b8352918301918301613d31565b60008060408385031215613d6457600080fd5b823567ffffffffffffffff811115613d7b57600080fd5b613d8785828601613ced565b92505060208301358015158114613ace57600080fd5b600080600080600060808688031215613db557600080fd5b8535613dc0816138d1565b9450602086013567ffffffffffffffff80821115613ddd57600080fd5b613de989838a01613bec565b95506040880135915080821115613dff57600080fd5b613e0b89838a01613bec565b94506060880135915080821115613e2157600080fd5b506139d088828901613925565b600060208284031215613e4057600080fd5b813567ffffffffffffffff811115613e5757600080fd5b6111b584828501613bec565b600060208284031215613e7557600080fd5b5035919050565b600080600060608486031215613e9157600080fd5b8335613e9c816138d1565b92506020840135613eac816138d1565b91506040840135613ebc816138d1565b809150509250925092565b60008060408385031215613eda57600080fd5b823567ffffffffffffffff80821115613ef257600080fd5b613efe86838701613ced565b93506020850135915080821115613f1457600080fd5b50613c9d85828601613bec565b634e487b7160e01b600052601160045260246000fd5b808201808211156108ca576108ca613f21565b6020808252600e908201526d11195c1bdcda5d081c185d5cd95960921b604082015260600190565b6020808252601b908201527f5374616b696e67206973206e6f74206c61756e63686564207965740000000000604082015260600190565b60208082526009908201526808591a5cd8589b195960ba1b604082015260600190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b634e487b7160e01b600052603260045260246000fd5b60006001820161401857614018613f21565b5060010190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b818103818111156108ca576108ca613f21565b60008160001904831182151516156140e4576140e4613f21565b500290565b60008261410657634e487b7160e01b600052601260045260246000fd5b500490565b60208082526010908201526f155b9adb9bdddb8818dbdb9d1c9858dd60821b604082015260600190565b60006020828403121561414757600080fd5b8151611117816138d1565b634e487b7160e01b600052603160045260246000fd5b60006020828403121561417a57600080fd5b5051919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b80516000906020808401838315613a3d57815187529582019590820190600101613a21565b6bffffffffffffffffffffffff198460601b168152600061381061421860148401866141cc565b846141cc565b60005b83811015614239578181015183820152602001614221565b50506000910152565b6000825161425481846020870161421e565b9190910192915050565b602081526000825180602084015261427d81604085016020870161421e565b601f01601f1916919091016040019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220a949ad4632fa2794d111f201ee4826616084e494e0cdecacfe9138d0828ace0564736f6c63430008100033
Deployed Bytecode
0x60806040526004361061027d5760003560e01c80637af617751161014f578063b5cc14b0116100c1578063df0ef69d1161007a578063df0ef69d146107ab578063dfeaa74c146107cb578063e1af5698146107eb578063f2fde38b1461080c578063f610f50a1461082c578063fa224c3f1461084157600080fd5b8063b5cc14b014610701578063bf7da66814610721578063c1c1ef9814610741578063c66a717414610756578063c68e516114610776578063d907813c1461079657600080fd5b80638ac94275116101135780638ac94275146106595780638da5cb5b146106795780638fa2a9f014610697578063a30a2474146106b7578063aaf10f42146106cc578063b396f34b146106e157600080fd5b80637af61775146105b957806381d7a7a9146105d95780638293744b146105f957806382dd013f14610619578063876a23ff1461063957600080fd5b80634d307e3f116101f357806361499ab9116101ac57806361499ab91461051657806361a52a36146105365780636d462ea31461054d5780636dea22e01461056d578063715018a61461058d5780637486560d146105a257600080fd5b80634d307e3f146104615780634f1ef28614610481578063524f76e91461049457806352d1902d146104b45780635b7633d0146104c95780635e22e16f146104e957600080fd5b80631f29d2dc116102455780631f29d2dc146103635780632161a2b61461039b57806336332028146103cb5780633659cfe6146103eb578063485cc9551461040b5780634bee21d41461042b57600080fd5b806302befd241461028257806304129667146102b857806309828c9f146102e657806312259252146102fc578063150b7a021461031e575b600080fd5b34801561028e57600080fd5b5060cd546102a390600160a81b900460ff1681565b60405190151581526020015b60405180910390f35b3480156102c457600080fd5b506102d86102d33660046138e6565b61086e565b6040519081526020016102af565b3480156102f257600080fd5b506102d860cc5481565b34801561030857600080fd5b5061031c610317366004613903565b6108d0565b005b34801561032a57600080fd5b5061034a61033936600461396e565b630a85bd0160e11b95945050505050565b6040516001600160e01b031990911681526020016102af565b34801561036f57600080fd5b5061038361037e3660046139e1565b610b5f565b6040516001600160a01b0390911681526020016102af565b3480156103a757600080fd5b506103bb6103b63660046138e6565b610b87565b6040516102af9493929190613a48565b3480156103d757600080fd5b5060ca54610383906001600160a01b031681565b3480156103f757600080fd5b5061031c6104063660046138e6565b610d95565b34801561041757600080fd5b5061031c610426366004613aa0565b610e5d565b34801561043757600080fd5b506102d86104463660046138e6565b6001600160a01b0316600090815260d0602052604090205490565b34801561046d57600080fd5b506102d861047c3660046138e6565b610fc3565b61031c61048f366004613b20565b6111e8565b3480156104a057600080fd5b5060cb54610383906001600160a01b031681565b3480156104c057600080fd5b506102d86112a1565b3480156104d557600080fd5b5060cd54610383906001600160a01b031681565b3480156104f557600080fd5b50610509610504366004613c57565b611354565b6040516102af9190613ca7565b34801561052257600080fd5b506102d86105313660046139e1565b611422565b34801561054257600080fd5b506102d86201518081565b34801561055957600080fd5b5061031c610568366004613d51565b61146b565b34801561057957600080fd5b5061031c6105883660046139e1565b6114d3565b34801561059957600080fd5b5061031c61150c565b3480156105ae57600080fd5b506102d86202a30081565b3480156105c557600080fd5b5061031c6105d4366004613d9d565b611520565b3480156105e557600080fd5b5061031c6105f43660046139e1565b611a54565b34801561060557600080fd5b5061031c610614366004613c57565b611a8d565b34801561062557600080fd5b5061031c610634366004613e2e565b61210d565b34801561064557600080fd5b5060d554610383906001600160a01b031681565b34801561066557600080fd5b5061031c610674366004613e2e565b612382565b34801561068557600080fd5b506033546001600160a01b0316610383565b3480156106a357600080fd5b5061031c6106b23660046138e6565b612656565b3480156106c357600080fd5b5061031c612680565b3480156106d857600080fd5b50610383612711565b3480156106ed57600080fd5b5061031c6106fc366004613e63565b612720565b34801561070d57600080fd5b5061031c61071c366004613e7c565b612996565b34801561072d57600080fd5b5061031c61073c3660046139e1565b612ca0565b34801561074d57600080fd5b506102d8600281565b34801561076257600080fd5b5060c954610383906001600160a01b031681565b34801561078257600080fd5b5061031c6107913660046139e1565b612cd9565b3480156107a257600080fd5b5061031c612cfd565b3480156107b757600080fd5b5061031c6107c6366004613ec7565b612d26565b3480156107d757600080fd5b5061031c6107e6366004613c57565b612db7565b3480156107f757600080fd5b5060cd546102a390600160a01b900460ff1681565b34801561081857600080fd5b5061031c6108273660046138e6565b61300c565b34801561083857600080fd5b506102d8600381565b34801561084d57600080fd5b506102d861085c3660046138e6565b60ce6020526000908152604090205481565b6001600160a01b038116600090815260d4602052604081205460ff16151560010361089b57506000919050565b6108a482610fc3565b6001600160a01b038316600090815260d060205260409020600101546108ca9190613f37565b92915050565b60cd54600160a81b900460ff16156109035760405162461bcd60e51b81526004016108fa90613f4a565b60405180910390fd5b60cd54600160a01b900460ff1661092c5760405162461bcd60e51b81526004016108fa90613f72565b60c9543390610944906001600160a01b031684610b5f565b6001600160a01b0316146109915760405162461bcd60e51b81526020600482015260146024820152731099595c08189bdbdc081b9bdd081cdd185ad95960621b60448201526064016108fa565b60d5546001600160a01b0316806109ba5760405162461bcd60e51b81526004016108fa90613fa9565b33600081815260d060205260408082209051632142170760e11b815290926001600160a01b038516916342842e0e916109f99130908990600401613fcc565b600060405180830381600087803b158015610a1357600080fd5b505af1158015610a27573d6000803e3d6000fd5b505050600086815260d66020526040902054159050610a885760405162461bcd60e51b815260206004820152601b60248201527f426f7420616c72656164792068617320616e2065786f2073756974000000000060448201526064016108fa565b600085815260d660205260409020849055610aa38385611422565b610aad9082613f37565b6001600160a01b038416600090815260d160209081526040808320888452825280832080546001600160a01b0319163390811790915560d7909252909120879055909150610afa90613082565b80826000016000828254610b0e9190613f37565b9091555050604080516001600160a01b03851681526001602082015233917f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f6291015b60405180910390a25050505050565b6001600160a01b03918216600090815260d16020908152604080832093835292905220541690565b606080606080600060d06000876001600160a01b03166001600160a01b03168152602001908152602001600020600301805480602002602001604051908101604052809291908181526020018280548015610c0157602002820191906000526020600020905b815481526020019060010190808311610bed575b505050505090506000815167ffffffffffffffff811115610c2457610c24613ad9565b604051908082528060200260200182016040528015610c4d578160200160208202803683370190505b50905060005b8251811015610cb65760d66000848381518110610c7257610c72613ff0565b6020026020010151815260200190815260200160002054828281518110610c9b57610c9b613ff0565b6020908102919091010152610caf81614006565b9050610c53565b506001600160a01b038716600090815260d06020908152604080832060d883529281902060049093018054825181850281018501909352808352869491939192869290918591830182828015610d2b57602002820191906000526020600020905b815481526020019060010190808311610d17575b5050505050925081805480602002602001604051908101604052809291908181526020018280548015610d7d57602002820191906000526020600020905b815481526020019060010190808311610d69575b50505050509150955095509550955050509193509193565b6001600160a01b037f000000000000000000000000e764829e64b96ea6890d3d9712ab9e5da7a1fcd3163003610ddd5760405162461bcd60e51b81526004016108fa9061401f565b7f000000000000000000000000e764829e64b96ea6890d3d9712ab9e5da7a1fcd36001600160a01b0316610e0f6130db565b6001600160a01b031614610e355760405162461bcd60e51b81526004016108fa9061406b565b610e3e816130f7565b60408051600080825260208201909252610e5a918391906130ff565b50565b600054610100900460ff1615808015610e7d5750600054600160ff909116105b80610e975750303b158015610e97575060005460ff166001145b610efa5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016108fa565b6000805460ff191660011790558015610f1d576000805461ff0019166101001790555b60c980546001600160a01b03199081166001600160a01b03868116918217909355600090815260ce60205260409020685150ae84a8cdf00000905560cd8054909116918416919091179055610f7061326a565b610f78613299565b8015610fbe576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b038116600090815260d060209081526040808320815160a081018352815481526001820154818501526002820154818401526003820180548451818702810187019095528085528695929460608601939092919083018282801561104d57602002820191906000526020600020905b815481526020019060010190808311611039575b50505050508152602001600482018054806020026020016040519081016040528092919081815260200182805480156110a557602002820191906000526020600020905b815481526020019060010190808311611091575b505050505081525050905080604001516000036110c55750600092915050565b60cc5481604001511080156110db575060cc5442105b1561111e578051604082015160029162015180916110f990426140b7565b61110391906140ca565b61110d91906140e9565b61111791906140ca565b9392505050565b60cc548160400151108015611134575060cc5442115b156111bd5760006002620151808360000151846040015160cc5461115891906140b7565b61116291906140ca565b61116c91906140e9565b61117691906140ca565b6111809082613f37565b825160cc54919250620151809161119790426140b7565b6111a191906140ca565b6111ab91906140e9565b6111b59082613f37565b949350505050565b805160408201516201518091906111d490426140b7565b6111de91906140ca565b61111791906140e9565b6001600160a01b037f000000000000000000000000e764829e64b96ea6890d3d9712ab9e5da7a1fcd31630036112305760405162461bcd60e51b81526004016108fa9061401f565b7f000000000000000000000000e764829e64b96ea6890d3d9712ab9e5da7a1fcd36001600160a01b03166112626130db565b6001600160a01b0316146112885760405162461bcd60e51b81526004016108fa9061406b565b611291826130f7565b61129d828260016130ff565b5050565b6000306001600160a01b037f000000000000000000000000e764829e64b96ea6890d3d9712ab9e5da7a1fcd316146113415760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016108fa565b5060008051602061429283398151915290565b60606000825167ffffffffffffffff81111561137257611372613ad9565b60405190808252806020026020018201604052801561139b578160200160208202803683370190505b50905060005b835181101561141a576001600160a01b038516600090815260cf60205260408120855182908790859081106113d8576113d8613ff0565b60200260200101518152602001908152602001600020541182828151811061140257611402613ff0565b911515602092830291909101909101526001016113a1565b509392505050565b6001600160a01b038216600090815260cf60209081526040808320848452909152812054808203611117575050506001600160a01b0316600090815260ce602052604090205490565b6114736132c0565b60005b8251811015610fbe57600083828151811061149357611493613ff0565b6020908102919091018101516001600160a01b0316600090815260d490915260409020805460ff1916841515179055506114cc81614006565b9050611476565b6114db6132c0565b60ca80546001600160a01b039093166001600160a01b031990931683179055600091825260ce602052604090912055565b6115146132c0565b61151e600061331a565b565b846001600160a01b03811615801590611546575060c9546001600160a01b038281169116145b8061155e575060cb546001600160a01b038281169116145b80611576575060ca546001600160a01b038281169116145b8061158e575060d5546001600160a01b038281169116145b6115aa5760405162461bcd60e51b81526004016108fa9061410b565b60cd54600160a81b900460ff16156115d45760405162461bcd60e51b81526004016108fa90613f4a565b60cd54600160a01b900460ff166115fd5760405162461bcd60e51b81526004016108fa90613f72565b60cb546001600160a01b03908116908716036116515760405162461bcd60e51b81526020600482015260136024820152720aae6ca40c8cae0dee6d2e840e8deded8c4def606b1b60448201526064016108fa565b60d5546001600160a01b03908116908716036116a55760405162461bcd60e51b8152602060048201526013602482015272155cd94819195c1bdcda5d08195e1bdcdd5a5d606a1b60448201526064016108fa565b8351156117375783518551146116ee5760405162461bcd60e51b815260206004820152600e60248201526d082e4e4c2f240dad2e6dac2e8c6d60931b60448201526064016108fa565b6116fb838388888861336c565b6117375760405162461bcd60e51b815260206004820152600d60248201526c426164207369676e617475726560981b60448201526064016108fa565b33600090815260d060205260409020805460c9546001600160a01b03908116908916036117ca5733600090815260d86020526040812054600384015461177d919061340c565b33600090815260d860205260408120548a51600387015493945091926117ab926117a691613f37565b61340c565b90506117b782826140b7565b6117c19084613f37565b9250505061184f565b60ca546001600160a01b039081169089160361184f57865160048301546014916117f391613f37565b111561184f5760405162461bcd60e51b815260206004820152602560248201527f4d6178696d756d206f66203230206261747465726965732063616e20626520736044820152641d185ad95960da1b60648201526084016108fa565b60005b87518110156119f557600088828151811061186f5761186f613ff0565b60200260200101519050896001600160a01b03166342842e0e3330846040518463ffffffff1660e01b81526004016118a993929190613fcc565b600060405180830381600087803b1580156118c357600080fd5b505af11580156118d7573d6000803e3d6000fd5b505050506000885111156119345760008883815181106118f9576118f9613ff0565b6020026020010151905080600014611932576001600160a01b038b16600090815260cf6020908152604080832085845290915290208190555b505b6001600160a01b038a16600090815260d160209081526040808320848452909152902080546001600160a01b031916331790556119718a82611422565b61197b9084613f37565b60c9549093506001600160a01b03908116908b16036119b35760038401805460018101825560009182526020909120018190556119e4565b60ca546001600160a01b03908116908b16036119e45760048401805460018101825560009182526020909120018190555b506119ee81614006565b9050611852565b506119ff33613082565b8082558651604080516001600160a01b038b168152602081019290925233917f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f6291015b60405180910390a25050505050505050565b611a5c6132c0565b60cb80546001600160a01b039093166001600160a01b031990931683179055600091825260ce602052604090912055565b816001600160a01b03811615801590611ab3575060c9546001600160a01b038281169116145b80611acb575060cb546001600160a01b038281169116145b80611ae3575060ca546001600160a01b038281169116145b80611afb575060d5546001600160a01b038281169116145b611b175760405162461bcd60e51b81526004016108fa9061410b565b60cb546001600160a01b0390811690841603611b6c5760405162461bcd60e51b81526020600482015260146024820152730aae6ca40eed2e8d0c8e4c2ee40e8deded8c4def60631b60448201526064016108fa565b60d5546001600160a01b0390811690841603611bc15760405162461bcd60e51b8152602060048201526014602482015273155cd9481dda5d1a191c985dc8195e1bdcdd5a5d60621b60448201526064016108fa565b33600090815260d4602052604090205460ff1615611c165760405162461bcd60e51b8152602060048201526012602482015271556e61626c6520746f20776974686472617760701b60448201526064016108fa565b33600090815260d060205260409020805460c9546001600160a01b0390811690861603611ca05733600090815260d860205260408120546003840154611c5c919061340c565b33600090815260d86020526040812054875160038701549394509192611c85926117a6916140b7565b9050611c9181836140b7565b611c9b90846140b7565b925050505b60005b84518110156120bc57306001600160a01b0316866001600160a01b0316636352211e878481518110611cd757611cd7613ff0565b60200260200101516040518263ffffffff1660e01b8152600401611cfd91815260200190565b602060405180830381865afa158015611d1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d3e9190614135565b6001600160a01b031614611d845760405162461bcd60e51b815260206004820152600d60248201526c2737ba103a34329037bbb732b960991b60448201526064016108fa565b6001600160a01b038616600090815260d16020526040812086518290889085908110611db257611db2613ff0565b6020026020010151815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b031602179055508260000154600014611e2d576000611e1d87878481518110611e1057611e10613ff0565b6020026020010151611422565b9050611e2981846140b7565b9250505b60c9546001600160a01b0390811690871603611f715760d66000868381518110611e5957611e59613ff0565b6020026020010151815260200190815260200160002054600014611eb75760405162461bcd60e51b8152602060048201526015602482015274135d5cdd08155b9cdd185ad948115e1bc814dd5a5d605a1b60448201526064016108fa565b611f2c83600301805480602002602001604051908101604052809291908181526020018280548015611f0857602002820191906000526020600020905b815481526020019060010190808311611ef4575b5050505050868381518110611f1f57611f1f613ff0565b6020026020010151613451565b8051611f42916003860191602090910190613857565b5082600301805480611f5657611f56614152565b6001900381819060005260206000200160009055905561202e565b60ca546001600160a01b039081169087160361202e57611fed83600401805480602002602001604051908101604052809291908181526020018280548015611f085760200282019190600052602060002090815481526020019060010190808311611ef4575050505050868381518110611f1f57611f1f613ff0565b8051612003916004860191602090910190613857565b508260040180548061201757612017614152565b600190038181906000526020600020016000905590555b856001600160a01b03166342842e0e303388858151811061205157612051613ff0565b60200260200101516040518463ffffffff1660e01b815260040161207793929190613fcc565b600060405180830381600087803b15801561209157600080fd5b505af11580156120a5573d6000803e3d6000fd5b5050505080806120b490614006565b915050611ca3565b506120c633613082565b8082558351604080516001600160a01b0388168152602081019290925233917f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb9101610b50565b60cd54600160a81b900460ff16156121375760405162461bcd60e51b81526004016108fa90613f4a565b60cd54600160a01b900460ff166121605760405162461bcd60e51b81526004016108fa90613f72565b60cb546001600160a01b0316806121895760405162461bcd60e51b81526004016108fa90613fa9565b33600090815260d0602052604081206003810154909190806121e65760405162461bcd60e51b8152602060048201526016602482015275135d5cdd081a185d99481848189bdd081cdd185ad95960521b60448201526064016108fa565b33600090815260d86020526040812054905b86518110156122e757600087828151811061221557612215613ff0565b60200260200101519050866001600160a01b03166342842e0e3330846040518463ffffffff1660e01b815260040161224f93929190613fcc565b600060405180830381600087803b15801561226957600080fd5b505af115801561227d573d6000803e3d6000fd5b505033600081815260d8602090815260408083208054600181018255908452828420018790556001600160a01b038d16835260d182528083209683529590529390932080546001600160a01b031916909317909255508190506122df81614006565b9150506121f8565b5060006122f4828461340c565b9050600061230e8851846123089190613f37565b8561340c565b905061231a82826140b7565b945061232533613082565b848660000160008282546123399190613f37565b90915550508751604080516001600160a01b038a168152602081019290925233917f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f629101611a42565b60cb546001600160a01b0316806123ab5760405162461bcd60e51b81526004016108fa90613fa9565b33600090815260d060209081526040808320805460d8909352908320546003820154919390916123dc90839061340c565b905060005b86518110156125bd5760008782815181106123fe576123fe613ff0565b60200260200101519050336001600160a01b031661241c8883610b5f565b6001600160a01b0316146124625760405162461bcd60e51b815260206004820152600d60248201526c2737ba103a34329037bbb732b960991b60448201526064016108fa565b6001600160a01b038716600090815260d160209081526040808320848452825280832080546001600160a01b031916905533835260d882529182902080548351818402810184019094528084526124ee93928301828280156124e357602002820191906000526020600020905b8154815260200190600101908083116124cf575b505050505082613451565b33600090815260d86020908152604090912082516125129391929190910190613857565b5033600090815260d86020526040902080548061253157612531614152565b60019003818190600052602060002001600090559055866001600160a01b03166342842e0e3033846040518463ffffffff1660e01b815260040161257793929190613fcc565b600060405180830381600087803b15801561259157600080fd5b505af11580156125a5573d6000803e3d6000fd5b505050505080806125b590614006565b9150506123e1565b508354156125fb5760006125e18751846125d791906140b7565b600387015461340c565b90506125ed81836140b7565b6125f790856140b7565b9350505b61260433613082565b8284558551604080516001600160a01b0388168152602081019290925233917f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb910160405180910390a2505050505050565b61265e6132c0565b60cd80546001600160a01b0319166001600160a01b0392909216919091179055565b6126886132c0565b60cd54600160a01b900460ff16156126ec5760405162461bcd60e51b815260206004820152602160248201527f5374616b696e6720686173206265656e206c61756e6368656420616c726561646044820152607960f81b60648201526084016108fa565b60cd805460ff60a01b1916600160a01b17905561270c6202a30042613f37565b60cc55565b600061271b6130db565b905090565b60d5546001600160a01b0316806127495760405162461bcd60e51b81526004016108fa90613fa9565b33600090815260d060209081526040808320805486855260d7909352928190205490516331a9108f60e11b81526004810186905230906001600160a01b03861690636352211e90602401602060405180830381865afa1580156127b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127d49190614135565b6001600160a01b0316146128205760405162461bcd60e51b8152602060048201526013602482015272115e1bc81cdd5a5d081b9bdd081cdd185ad959606a1b60448201526064016108fa565b60c9543390612838906001600160a01b031683610b5f565b6001600160a01b0316146128825760405162461bcd60e51b81526020600482015260116024820152702737ba103a3432903137ba1037bbb732b960791b60448201526064016108fa565b6001600160a01b038416600090815260d160209081526040808320888452909152902080546001600160a01b03191690558254156128d65760006128c68587611422565b90506128d281846140b7565b9250505b600081815260d660205260408082209190915551632142170760e11b81526001600160a01b038516906342842e0e9061291790309033908a90600401613fcc565b600060405180830381600087803b15801561293157600080fd5b505af1158015612945573d6000803e3d6000fd5b5050505061295233613082565b818355604080516001600160a01b03861681526001602082015233917f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb9101610b50565b816001600160a01b038116158015906129bc575060c9546001600160a01b038281169116145b806129d4575060cb546001600160a01b038281169116145b806129ec575060ca546001600160a01b038281169116145b80612a04575060d5546001600160a01b038281169116145b612a205760405162461bcd60e51b81526004016108fa9061410b565b612a286132c0565b6001600160a01b038416600090815260d4602052604090205460ff16612a875760405162461bcd60e51b8152602060048201526014602482015273476174656420616464726573736573206f6e6c7960601b60448201526064016108fa565b6060600080600080612a9889610b87565b60c954939750919550935091506001600160a01b0390811690891603612ae9576001600160a01b038916600090815260d0602052604081209495508594612ae4916003909101906138a2565b612b81565b60ca546001600160a01b0390811690891603612b2b576001600160a01b038916600090815260d0602052604081209395508593612ae4916004909101906138a2565b60cb546001600160a01b0390811690891603612b67576001600160a01b038916600090815260d8602052604081209295508592612ae4916138a2565b60d5546001600160a01b0390811690891603612b81578094505b60005b8551811015612c94576000868281518110612ba157612ba1613ff0565b6020026020010151905080600003612bb95750612c82565b6001600160a01b03808b16600081815260d160209081526040808320868452909152902080546001600160a01b031916905560d5549091169003612c1e57600081815260d760205260409020548015612c1c57600081815260d660205260408120555b505b604051632142170760e11b81526001600160a01b038b16906342842e0e90612c4e9030908d908690600401613fcc565b600060405180830381600087803b158015612c6857600080fd5b505af1158015612c7c573d6000803e3d6000fd5b50505050505b80612c8c81614006565b915050612b84565b50505050505050505050565b612ca86132c0565b60d580546001600160a01b039093166001600160a01b031990931683179055600091825260ce602052604090912055565b612ce16132c0565b6001600160a01b03909116600090815260ce6020526040902055565b612d056132c0565b60cd805460ff60a81b198116600160a81b9182900460ff1615909102179055565b612d2e6132c0565b8051825114612d3c57600080fd5b60005b8251811015610fbe576000838281518110612d5c57612d5c613ff0565b60200260200101519050612d6f81613082565b828281518110612d8157612d81613ff0565b6020908102919091018101516001600160a01b03909216600090815260d09091526040902055612db081614006565b9050612d3f565b612dbf6132c0565b603281511115612e045760405162461bcd60e51b815260206004820152601060248201526f06a6040d2e640dac2f040e0cae440e8f60831b60448201526064016108fa565b60cd805460ff60a81b1916600160a81b17905560005b8151811015610fbe576001600160a01b038316600090815260d16020526040812083518290859085908110612e5157612e51613ff0565b6020908102919091018101518252810191909152604001600020546001600160a01b031690508015801590612f1e5750306001600160a01b0316846001600160a01b0316636352211e858581518110612eac57612eac613ff0565b60200260200101516040518263ffffffff1660e01b8152600401612ed291815260200190565b602060405180830381865afa158015612eef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f139190614135565b6001600160a01b0316145b15612ff957836001600160a01b03166323b872dd3083868681518110612f4657612f46613ff0565b60200260200101516040518463ffffffff1660e01b8152600401612f6c93929190613fcc565b600060405180830381600087803b158015612f8657600080fd5b505af1158015612f9a573d6000803e3d6000fd5b50505050828281518110612fb057612fb0613ff0565b6020026020010151846001600160a01b0316826001600160a01b03167ffefe036cac4ee3a4aca074a81cbcc4376e1484693289078dbec149c890101d5b60405160405180910390a45b508061300481614006565b915050612e1a565b6130146132c0565b6001600160a01b0381166130795760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016108fa565b610e5a8161331a565b61308b81610fc3565b6001600160a01b038216600090815260d06020526040812060010180549091906130b6908490613f37565b90915550506001600160a01b0316600090815260d06020526040902042600290910155565b600080516020614292833981519152546001600160a01b031690565b610e5a6132c0565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561313257610fbe8361357f565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561318c575060408051601f3d908101601f1916820190925261318991810190614168565b60015b6131ef5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016108fa565b600080516020614292833981519152811461325e5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016108fa565b50610fbe83838361361b565b600054610100900460ff166132915760405162461bcd60e51b81526004016108fa90614181565b61151e613646565b600054610100900460ff1661151e5760405162461bcd60e51b81526004016108fa90614181565b6033546001600160a01b0316331461151e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016108fa565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600080848484604051602001613384939291906141f1565b60405160208183030381529060405280519060200120905060006133d988886133d2856020527b19457468657265756d205369676e6564204d6573736167653a0a3332600052603c60042090565b9190613676565b90506001600160a01b03811615801590613400575060cd546001600160a01b038281169116145b98975050505050505050565b60008061341a6003856140e9565b60cb546001600160a01b0316600090815260ce60205260409020549091508184106134455781613447565b835b6111b591906140ca565b60606000806001855161346491906140b7565b855190915060005b818110156134b8578587828151811061348757613487613ff0565b6020026020010151036134a65761349f816001613f37565b93506134b8565b806134b081614006565b91505061346c565b50826000036135095760405162461bcd60e51b815260206004820152601b60248201527f6d73672e73656e646572206973206e6f7420746865206f776e6572000000000060448201526064016108fa565b6135146001846140b7565b92508183146135755785828151811061352f5761352f613ff0565b602002602001015186848151811061354957613549613ff0565b6020026020010181815250508486838151811061356857613568613ff0565b6020026020010181815250505b5093949350505050565b6001600160a01b0381163b6135ec5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016108fa565b60008051602061429283398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b613624836136e5565b6000825111806136315750805b15610fbe576136408383613725565b50505050565b600054610100900460ff1661366d5760405162461bcd60e51b81526004016108fa90614181565b61151e3361331a565b600060418203611117576040516040846040377f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0606051116136db5784600052604084013560001a602052602060406080600060015afa5060006060523d6060035191505b6040529392505050565b6136ee8161357f565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b61378d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016108fa565b600080846001600160a01b0316846040516137a89190614242565b600060405180830381855af49150503d80600081146137e3576040519150601f19603f3d011682016040523d82523d6000602084013e6137e8565b606091505b509150915061381082826040518060600160405280602781526020016142b260279139613819565b95945050505050565b60608315613828575081611117565b611117838381511561383d5781518083602001fd5b8060405162461bcd60e51b81526004016108fa919061425e565b828054828255906000526020600020908101928215613892579160200282015b82811115613892578251825591602001919060010190613877565b5061389e9291506138bc565b5090565b5080546000825590600052602060002090810190610e5a91905b5b8082111561389e57600081556001016138bd565b6001600160a01b0381168114610e5a57600080fd5b6000602082840312156138f857600080fd5b8135611117816138d1565b6000806040838503121561391657600080fd5b50508035926020909101359150565b60008083601f84011261393757600080fd5b50813567ffffffffffffffff81111561394f57600080fd5b60208301915083602082850101111561396757600080fd5b9250929050565b60008060008060006080868803121561398657600080fd5b8535613991816138d1565b945060208601356139a1816138d1565b935060408601359250606086013567ffffffffffffffff8111156139c457600080fd5b6139d088828901613925565b969995985093965092949392505050565b600080604083850312156139f457600080fd5b82356139ff816138d1565b946020939093013593505050565b600081518084526020808501945080840160005b83811015613a3d57815187529582019590820190600101613a21565b509495945050505050565b608081526000613a5b6080830187613a0d565b8281036020840152613a6d8187613a0d565b90508281036040840152613a818186613a0d565b90508281036060840152613a958185613a0d565b979650505050505050565b60008060408385031215613ab357600080fd5b8235613abe816138d1565b91506020830135613ace816138d1565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613b1857613b18613ad9565b604052919050565b60008060408385031215613b3357600080fd5b8235613b3e816138d1565b915060208381013567ffffffffffffffff80821115613b5c57600080fd5b818601915086601f830112613b7057600080fd5b813581811115613b8257613b82613ad9565b613b94601f8201601f19168501613aef565b91508082528784828501011115613baa57600080fd5b80848401858401376000848284010152508093505050509250929050565b600067ffffffffffffffff821115613be257613be2613ad9565b5060051b60200190565b600082601f830112613bfd57600080fd5b81356020613c12613c0d83613bc8565b613aef565b82815260059290921b84018101918181019086841115613c3157600080fd5b8286015b84811015613c4c5780358352918301918301613c35565b509695505050505050565b60008060408385031215613c6a57600080fd5b8235613c75816138d1565b9150602083013567ffffffffffffffff811115613c9157600080fd5b613c9d85828601613bec565b9150509250929050565b6020808252825182820181905260009190848201906040850190845b81811015613ce1578351151583529284019291840191600101613cc3565b50909695505050505050565b600082601f830112613cfe57600080fd5b81356020613d0e613c0d83613bc8565b82815260059290921b84018101918181019086841115613d2d57600080fd5b8286015b84811015613c4c578035613d44816138d1565b8352918301918301613d31565b60008060408385031215613d6457600080fd5b823567ffffffffffffffff811115613d7b57600080fd5b613d8785828601613ced565b92505060208301358015158114613ace57600080fd5b600080600080600060808688031215613db557600080fd5b8535613dc0816138d1565b9450602086013567ffffffffffffffff80821115613ddd57600080fd5b613de989838a01613bec565b95506040880135915080821115613dff57600080fd5b613e0b89838a01613bec565b94506060880135915080821115613e2157600080fd5b506139d088828901613925565b600060208284031215613e4057600080fd5b813567ffffffffffffffff811115613e5757600080fd5b6111b584828501613bec565b600060208284031215613e7557600080fd5b5035919050565b600080600060608486031215613e9157600080fd5b8335613e9c816138d1565b92506020840135613eac816138d1565b91506040840135613ebc816138d1565b809150509250925092565b60008060408385031215613eda57600080fd5b823567ffffffffffffffff80821115613ef257600080fd5b613efe86838701613ced565b93506020850135915080821115613f1457600080fd5b50613c9d85828601613bec565b634e487b7160e01b600052601160045260246000fd5b808201808211156108ca576108ca613f21565b6020808252600e908201526d11195c1bdcda5d081c185d5cd95960921b604082015260600190565b6020808252601b908201527f5374616b696e67206973206e6f74206c61756e63686564207965740000000000604082015260600190565b60208082526009908201526808591a5cd8589b195960ba1b604082015260600190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b634e487b7160e01b600052603260045260246000fd5b60006001820161401857614018613f21565b5060010190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b818103818111156108ca576108ca613f21565b60008160001904831182151516156140e4576140e4613f21565b500290565b60008261410657634e487b7160e01b600052601260045260246000fd5b500490565b60208082526010908201526f155b9adb9bdddb8818dbdb9d1c9858dd60821b604082015260600190565b60006020828403121561414757600080fd5b8151611117816138d1565b634e487b7160e01b600052603160045260246000fd5b60006020828403121561417a57600080fd5b5051919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b80516000906020808401838315613a3d57815187529582019590820190600101613a21565b6bffffffffffffffffffffffff198460601b168152600061381061421860148401866141cc565b846141cc565b60005b83811015614239578181015183820152602001614221565b50506000910152565b6000825161425481846020870161421e565b9190910192915050565b602081526000825180602084015261427d81604085016020870161421e565b601f01601f1916919091016040019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220a949ad4632fa2794d111f201ee4826616084e494e0cdecacfe9138d0828ace0564736f6c63430008100033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 25 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.