More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 2,383 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Claim | 21280016 | 1 hr ago | IN | 0 ETH | 0.001522 | ||||
Stake | 21277727 | 9 hrs ago | IN | 0 ETH | 0.00624961 | ||||
Unstake | 21277668 | 9 hrs ago | IN | 0 ETH | 0.00354395 | ||||
Claim | 21277647 | 9 hrs ago | IN | 0 ETH | 0.00098546 | ||||
Stake | 21274442 | 20 hrs ago | IN | 0 ETH | 0.0016987 | ||||
Initial Stake | 21272435 | 26 hrs ago | IN | 0 ETH | 0.00500798 | ||||
Stake | 21272432 | 26 hrs ago | IN | 0 ETH | 0.00553934 | ||||
Initial Stake | 21272317 | 27 hrs ago | IN | 0 ETH | 0.00348639 | ||||
Claim | 21271343 | 30 hrs ago | IN | 0 ETH | 0.00072684 | ||||
Claim | 21270813 | 32 hrs ago | IN | 0 ETH | 0.00094021 | ||||
Initial Stake | 21269965 | 35 hrs ago | IN | 0 ETH | 0.00231172 | ||||
Claim | 21269635 | 36 hrs ago | IN | 0 ETH | 0.00049422 | ||||
Claim | 21269257 | 37 hrs ago | IN | 0 ETH | 0.00042163 | ||||
Claim | 21268468 | 40 hrs ago | IN | 0 ETH | 0.00054347 | ||||
Claim | 21267942 | 42 hrs ago | IN | 0 ETH | 0.0006981 | ||||
Claim | 21263331 | 2 days ago | IN | 0 ETH | 0.00052452 | ||||
Claim | 21259284 | 2 days ago | IN | 0 ETH | 0.00074327 | ||||
Claim | 21258816 | 3 days ago | IN | 0 ETH | 0.00070313 | ||||
Initial Stake | 21258278 | 3 days ago | IN | 0 ETH | 0.00154089 | ||||
Claim | 21256623 | 3 days ago | IN | 0 ETH | 0.00061573 | ||||
Claim | 21256161 | 3 days ago | IN | 0 ETH | 0.00054701 | ||||
Unstake | 21255203 | 3 days ago | IN | 0 ETH | 0.00256615 | ||||
Claim | 21255189 | 3 days ago | IN | 0 ETH | 0.00081935 | ||||
Initial Stake | 21252267 | 3 days ago | IN | 0 ETH | 0.00264484 | ||||
Claim | 21251539 | 4 days ago | IN | 0 ETH | 0.00169374 |
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:
AvatarsEscrow
Compiler Version
v0.8.18+commit.87f61d96
Optimization Enabled:
Yes with 800 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import "@openzeppelin/contracts/utils/Context.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "@openzeppelin/contracts/utils/math/SafeCast.sol"; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "./modules/Ownable/Ownable.sol"; import "./modules/Upgradeable/Upgradeable.sol"; import "./TransferHelper.sol"; import "./IAvatarsEscrow.sol"; import "./IAvatarsRental.sol"; import "./IAvatars_ERC721.sol"; import "./AvatarsEscrowStorage.sol"; contract AvatarsEscrow is Context, ERC165, IAvatarsEscrow, Ownable, ReentrancyGuard, Upgradeable { using SafeCast for uint256; using ECDSA for bytes32; using EnumerableSet for EnumerableSet.UintSet; // ======== Admin functions ======== constructor(address _rewardTokenAddress, address _avatars) { require(_rewardTokenAddress != address(0), "E0"); // E0: addr err require(address(_avatars) != address(0), "E0"); AvatarsEscrowStorage.layout().rewardTokenAddress = _rewardTokenAddress; AvatarsEscrowStorage.layout().Avatars_ERC721 = IAvatars_ERC721(_avatars); } // Set a rewards schedule // rate is in wei per second for all users // This must be called AFTER some avatars are staked (or ensure at least 1 avatar is staked before the start timestamp) function setRewards(uint32 _start, uint32 _end, uint96 _rate) external onlyOwner checkForUpgrade { require(_start <= _end, "E1"); // E1: Incorrect input // some safeguard, value TBD. (2b over 5 years is 12.68 per sec) require(_rate > 0.03 ether && _rate < 30 ether, "E2"); // E2: Rate incorrect require(AvatarsEscrowStorage.layout().rewardTokenAddress != address(0), "E3"); // E3: Rewards token not set require( block.timestamp.toUint32() < AvatarsEscrowStorage.layout().rewardsPeriod.start || block.timestamp.toUint32() > AvatarsEscrowStorage.layout().rewardsPeriod.end, "E4" ); // E4: Rewards already set AvatarsEscrowStorage.layout().rewardsPeriod.start = _start; AvatarsEscrowStorage.layout().rewardsPeriod.end = _end; AvatarsEscrowStorage.layout().rewardsPerWeight.lastUpdated = _start; AvatarsEscrowStorage.layout().rewardsPerWeight.rate = _rate; emit RewardsSet(_start, _end, _rate); } function setWeight(uint256[] calldata _tokenIds, uint256[] calldata _weights) external onlyOwner checkForUpgrade { require(_tokenIds.length == _weights.length, "E6"); for (uint256 i = 0; i < _tokenIds.length; i++) { uint256 tokenId = _tokenIds[i]; require(AvatarsEscrowStorage.layout().avatarInfo[tokenId].weight == 0, "E8"); AvatarsEscrowStorage.layout().avatarInfo[tokenId].weight = _weights[i].toUint16(); } } function setSigner(address _signer) external onlyOwner checkForUpgrade { AvatarsEscrowStorage.layout().signer = _signer; } function setRentalContract(IAvatarsRental _rental) external onlyOwner checkForUpgrade { require(_rental.supportsInterface(type(IAvatarsRental).interfaceId), "E0"); AvatarsEscrowStorage.layout().AvatarsRental = _rental; } function setRewardTokenAddress(address _rewardTokenAddress) external onlyOwner checkForUpgrade { AvatarsEscrowStorage.layout().rewardTokenAddress = _rewardTokenAddress; } function setAvatarsERC721(IAvatars_ERC721 _avatars) external onlyOwner checkForUpgrade { AvatarsEscrowStorage.layout().Avatars_ERC721 = _avatars; } function setAvatarsRental(IAvatarsRental _rental) external onlyOwner checkForUpgrade { AvatarsEscrowStorage.layout().AvatarsRental = _rental; } // ======== Public functions ======== // Stake avatars for a first time. You may optionally stake to a different wallet. Ownership will be transferred to the stakeTo address. // Initial weights passed as input parameters, which are secured by a dev signature. weight = 60003 - 3 * rank // When you stake you can set rental conditions for all of them. // Initialized and uninitialized stake can be mixed into one tx using this method. // If you set rentalPerDay to 0 and rentableUntil to some time in the future, then anyone can rent for free // until the rentableUntil timestamp with no way of backing out function initialStake( uint256[] calldata _tokenIds, uint256[] calldata _weights, address _stakeTo, uint16 _deposit, uint16 _rentalPerDay, uint16 _minRentDays, uint32 _rentableUntil, uint32 _maxTimestamp, bytes calldata _signature ) external nonReentrant checkForUpgrade { require(uint256(_deposit) <= uint256(_rentalPerDay) * (uint256(_minRentDays) + 1), "ER"); // ER: Rental rate incorrect // security measure against input length attack require(_tokenIds.length == _weights.length, "E6"); // E6: Input length mismatch require(block.timestamp <= _maxTimestamp, "EX"); // EX: Signature expired // verifying signature here is much cheaper than verifying merkle root require( _verifySignerSignature( keccak256(abi.encode(_tokenIds, _weights, _msgSender(), _maxTimestamp, address(this))), _signature ), "E7" ); // E7: Invalid signature // ensure stakeTo is EOA or ERC721Receiver to avoid token lockup _ensureEOAorERC721Receiver(_stakeTo); require(_stakeTo != address(this), "ES"); // ES: Stake to escrow uint256 totalWeights = 0; for (uint256 i = 0; i < _tokenIds.length; i++) { { // scope to avoid stack too deep errors uint256 tokenId = _tokenIds[i]; uint256 _weight = AvatarsEscrowStorage.layout().avatarInfo[tokenId].weight; require(_weight == 0 || _weight == _weights[i], "E8"); // E8: Initialized weight cannot be changed require(AvatarsEscrowStorage.layout().Avatars_ERC721.ownerOf(tokenId) == _msgSender(), "E9"); // E9: Not your avatar AvatarsEscrowStorage.layout().Avatars_ERC721.safeTransferFrom(_msgSender(), address(this), tokenId); emit AvatarStaked(tokenId, _stakeTo); } AvatarsEscrowStorage.layout().avatarInfo[_tokenIds[i]] = AvatarInfo(_weights[i].toUint16(), _stakeTo, _deposit, _rentalPerDay, _minRentDays, _rentableUntil); AvatarsEscrowStorage.layout().userStakes[_stakeTo].add(_tokenIds[i]); totalWeights += _weights[i]; } // update rewards _updateRewardsPerWeight(totalWeights.toUint32(), true); _updateUserRewards(_stakeTo, totalWeights.toUint32(), true); } // subsequent staking does not require dev signature function stake( uint256[] calldata _tokenIds, address _stakeTo, uint16 _deposit, uint16 _rentalPerDay, uint16 _minRentDays, uint32 _rentableUntil ) external nonReentrant checkForUpgrade { require(uint256(_deposit) <= uint256(_rentalPerDay) * (uint256(_minRentDays) + 1), "ER"); // ER: Rental rate incorrect // ensure stakeTo is EOA or ERC721Receiver to avoid token lockup _ensureEOAorERC721Receiver(_stakeTo); require(_stakeTo != address(this), "ES"); // ES: Stake to escrow uint256 totalWeights = 0; for (uint256 i = 0; i < _tokenIds.length; i++) { uint256 tokenId = _tokenIds[i]; uint16 _weight = AvatarsEscrowStorage.layout().avatarInfo[tokenId].weight; require(_weight != 0, "EA"); // EA: Weight not initialized require(AvatarsEscrowStorage.layout().Avatars_ERC721.ownerOf(tokenId) == _msgSender(), "E9"); // E9: Not your avatar AvatarsEscrowStorage.layout().Avatars_ERC721.safeTransferFrom(_msgSender(), address(this), tokenId); totalWeights += _weight; AvatarsEscrowStorage.layout().avatarInfo[tokenId] = AvatarInfo(_weight, _stakeTo, _deposit, _rentalPerDay, _minRentDays, _rentableUntil); AvatarsEscrowStorage.layout().userStakes[_stakeTo].add(tokenId); emit AvatarStaked(tokenId, _stakeTo); } // update rewards _updateRewardsPerWeight(totalWeights.toUint32(), true); _updateUserRewards(_stakeTo, totalWeights.toUint32(), true); } // Update rental conditions as long as therer's no ongoing rent. // setting rentableUntil to 0 makes the avatar unrentable. function updateRent( uint256[] calldata _tokenIds, uint16 _deposit, uint16 _rentalPerDay, uint16 _minRentDays, uint32 _rentableUntil ) external checkForUpgrade { require(uint256(_deposit) <= uint256(_rentalPerDay) * (uint256(_minRentDays) + 1), "ER"); // ER: Rental rate incorrect for (uint256 i = 0; i < _tokenIds.length; i++) { uint256 tokenId = _tokenIds[i]; AvatarInfo storage avatarInfo_ = AvatarsEscrowStorage.layout().avatarInfo[tokenId]; require(avatarInfo_.weight != 0, "EA"); // EA: Weight not initialized require( AvatarsEscrowStorage.layout().Avatars_ERC721.ownerOf(tokenId) == address(this) && avatarInfo_.owner == _msgSender(), "E9" ); // E9: Not your avatar require(!AvatarsEscrowStorage.layout().AvatarsRental.isRentActive(tokenId), "EB"); // EB: Ongoing rent avatarInfo_.deposit = _deposit; avatarInfo_.rentalPerDay = _rentalPerDay; avatarInfo_.minRentDays = _minRentDays; avatarInfo_.rentableUntil = _rentableUntil; } } // Extend rental period of ongoing rent function extendRentalPeriod(uint256 _tokenId, uint32 _rentableUntil) external checkForUpgrade { AvatarInfo storage avatarInfo_ = AvatarsEscrowStorage.layout().avatarInfo[_tokenId]; require(avatarInfo_.weight != 0, "EA"); // EA: Weight not initialized require( AvatarsEscrowStorage.layout().Avatars_ERC721.ownerOf(_tokenId) == address(this) && avatarInfo_.owner == _msgSender(), "E9" ); // E9: Not your avatar avatarInfo_.rentableUntil = _rentableUntil; } function unstake(uint256[] calldata _tokenIds, address _unstakeTo) external nonReentrant checkForUpgrade { // ensure unstakeTo is EOA or ERC721Receiver to avoid token lockup _ensureEOAorERC721Receiver(_unstakeTo); require(_unstakeTo != address(this), "ES"); // ES: Unstake to escrow uint256 totalWeights = 0; for (uint256 i = 0; i < _tokenIds.length; i++) { uint256 tokenId = _tokenIds[i]; require(AvatarsEscrowStorage.layout().avatarInfo[tokenId].owner == _msgSender(), "E9"); // E9: Not your avatar require(!AvatarsEscrowStorage.layout().AvatarsRental.isRentActive(tokenId), "EB"); // EB: Ongoing rent AvatarsEscrowStorage.layout().Avatars_ERC721.safeTransferFrom(address(this), _unstakeTo, tokenId); uint16 _weight = AvatarsEscrowStorage.layout().avatarInfo[tokenId].weight; totalWeights += _weight; AvatarsEscrowStorage.layout().avatarInfo[tokenId] = AvatarInfo(_weight, address(0), 0, 0, 0, 0); AvatarsEscrowStorage.layout().userStakes[_msgSender()].remove(tokenId); emit AvatarUnstaked(tokenId, _msgSender()); // Avatar `id` unstaked from `address` } // update rewards _updateRewardsPerWeight(totalWeights.toUint32(), false); _updateUserRewards(_msgSender(), totalWeights.toUint32(), false); } function updateAvatar( uint256 _tokenId, string calldata _ipfsHash, uint256 _nonce, bytes calldata _updateApproverSignature ) external checkForUpgrade { require( ( AvatarsEscrowStorage.layout().avatarInfo[_tokenId].owner == _msgSender() && !AvatarsEscrowStorage.layout().AvatarsRental.isRentActive(_tokenId) ) || ( AvatarsEscrowStorage.layout().avatarInfo[_tokenId].owner != address(0) && AvatarsEscrowStorage.layout().AvatarsRental.getTenant(_tokenId) == _msgSender() ), "EH" ); // EH: Not your avatar or not rented AvatarsEscrowStorage.layout().Avatars_ERC721.updateAvatar(_tokenId, _ipfsHash, _nonce, _updateApproverSignature); } // Claim all rewards from caller into a given address function claim(address _to) external nonReentrant checkForUpgrade { _updateRewardsPerWeight(0, false); uint256 rewardAmount = _updateUserRewards(_msgSender(), 0, false); AvatarsEscrowStorage.layout().rewards[_msgSender()].accumulated = 0; TransferHelper.safeTransfer(AvatarsEscrowStorage.layout().rewardTokenAddress, _to, rewardAmount); emit RewardClaimed(_to, rewardAmount); } // ======== View only functions ======== function getAvatarInfo(uint256 _tokenId) external view override returns (AvatarInfo memory) { return AvatarsEscrowStorage.layout().avatarInfo[_tokenId]; } function checkUserRewards(address _user) external view returns (uint256) { RewardsPerWeight memory rewardsPerWeight_ = AvatarsEscrowStorage.layout().rewardsPerWeight; UserRewards memory userRewards_ = AvatarsEscrowStorage.layout().rewards[_user]; // Find out the unaccounted time uint32 end = min(block.timestamp.toUint32(), AvatarsEscrowStorage.layout().rewardsPeriod.end); uint256 unaccountedTime = end - rewardsPerWeight_.lastUpdated; // Cast to uint256 to avoid overflows later on if (unaccountedTime != 0) { // Calculate and update the new value of the accumulator. unaccountedTime casts it into uint256, which is desired. // If the first mint happens mid-program, we don't update the accumulator, no one gets the rewards for that period. if (rewardsPerWeight_.totalWeight != 0) { rewardsPerWeight_.accumulated = ( rewardsPerWeight_.accumulated + unaccountedTime * rewardsPerWeight_.rate / rewardsPerWeight_.totalWeight ).toUint96(); } } // Calculate and update the new value user reserves. userRewards_.stakedWeight casts it into uint256, which is desired. return userRewards_.accumulated + userRewards_.stakedWeight * (rewardsPerWeight_.accumulated - userRewards_.checkpoint); } function rewardsPeriod() external view returns (IAvatarsEscrow.RewardsPeriod memory) { return AvatarsEscrowStorage.layout().rewardsPeriod; } function rewardsPerWeight() external view returns (IAvatarsEscrow.RewardsPerWeight memory) { return AvatarsEscrowStorage.layout().rewardsPerWeight; } function rewards(address user) external view returns (UserRewards memory) { return AvatarsEscrowStorage.layout().rewards[user]; } function userStakedAvatars(address _user) external view returns (uint256[] memory) { uint256 length = AvatarsEscrowStorage.layout().userStakes[_user].length(); uint256[] memory stakedAvatars = new uint256[](length); for (uint256 i = 0; i < length; i++) { stakedAvatars[i] = AvatarsEscrowStorage.layout().userStakes[_user].at(i); } return stakedAvatars; } function supportsInterface(bytes4 _interfaceId) public view override(ERC165, IERC165) returns (bool) { return _interfaceId == type(IAvatarsEscrow).interfaceId || super.supportsInterface(_interfaceId); } // ======== internal functions ======== function _verifySignerSignature(bytes32 _hash, bytes calldata _signature) internal view returns (bool) { return _hash.toEthSignedMessageHash().recover(_signature) == AvatarsEscrowStorage.layout().signer; } function min(uint32 _x, uint32 _y) internal pure returns (uint32 z) { z = (_x < _y) ? _x : _y; } // Updates the rewards per weight accumulator. // Needs to be called on each staking/unstaking event. function _updateRewardsPerWeight(uint32 _weight, bool _increase) internal checkForUpgrade { RewardsPerWeight memory rewardsPerWeight_ = AvatarsEscrowStorage.layout().rewardsPerWeight; RewardsPeriod memory rewardsPeriod_ = AvatarsEscrowStorage.layout().rewardsPeriod; // We skip the update if the program hasn't started if (block.timestamp.toUint32() >= rewardsPeriod_.start) { // Find out the unaccounted time uint32 end = min(block.timestamp.toUint32(), rewardsPeriod_.end); uint256 unaccountedTime = end - rewardsPerWeight_.lastUpdated; // Cast to uint256 to avoid overflows later on if (unaccountedTime != 0) { // Calculate and update the new value of the accumulator. // If the first mint happens mid-program, we don't update the accumulator, no one gets the rewards for that period. if (rewardsPerWeight_.totalWeight != 0) { rewardsPerWeight_.accumulated = ( rewardsPerWeight_.accumulated + unaccountedTime * rewardsPerWeight_.rate / rewardsPerWeight_.totalWeight ).toUint96(); } rewardsPerWeight_.lastUpdated = end; } } if (_increase) { rewardsPerWeight_.totalWeight += _weight; } else { rewardsPerWeight_.totalWeight -= _weight; } AvatarsEscrowStorage.layout().rewardsPerWeight = rewardsPerWeight_; emit RewardsPerWeightUpdated(rewardsPerWeight_.accumulated); } // Accumulate rewards for an user. // Needs to be called on each staking/unstaking event. function _updateUserRewards( address _user, uint32 _weight, bool _increase ) internal checkForUpgrade returns (uint96) { UserRewards memory userRewards_ = AvatarsEscrowStorage.layout().rewards[_user]; RewardsPerWeight memory rewardsPerWeight_ = AvatarsEscrowStorage.layout().rewardsPerWeight; // Calculate and update the new value user reserves. userRewards_.accumulated = userRewards_.accumulated + userRewards_.stakedWeight * (rewardsPerWeight_.accumulated - userRewards_.checkpoint); userRewards_.checkpoint = rewardsPerWeight_.accumulated; if (_weight != 0) { if (_increase) { userRewards_.stakedWeight += _weight; } else { userRewards_.stakedWeight -= _weight; } emit WeightUpdated(_user, _increase, _weight, block.timestamp); } AvatarsEscrowStorage.layout().rewards[_user] = userRewards_; emit UserRewardsUpdated(_user, userRewards_.accumulated, userRewards_.checkpoint); return userRewards_.accumulated; } function _ensureEOAorERC721Receiver(address _to) internal checkForUpgrade { uint32 size; assembly { size := extcodesize(_to) } if (size > 0) { try IERC721Receiver(_to).onERC721Received(address(this), address(this), 0, "") returns (bytes4 retval) { require(retval == IERC721Receiver.onERC721Received.selector, "ET"); // ET: neither EOA nor ERC721Receiver } catch (bytes memory) { revert("ET"); // ET: neither EOA nor ERC721Receiver } } } // ======== function overrides ======== // Prevent sending ERC721 tokens directly to this contract function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external view override returns (bytes4) { from; tokenId; data; // supress solidity warnings if (operator == address(this)) { return this.onERC721Received.selector; } else { return 0x00000000; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } else if (error == RecoverError.InvalidSignatureV) { revert("ECDSA: invalid signature 'v' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { // Check the signature length // - case 65: r,s,v signature (standard) // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._ if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else if (signature.length == 64) { bytes32 r; bytes32 vs; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly { r := mload(add(signature, 0x20)) vs := mload(add(signature, 0x40)) } return tryRecover(hash, r, vs); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } if (v != 27 && v != 28) { return (address(0), RecoverError.InvalidSignatureV); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/math/SafeCast.sol) pragma solidity ^0.8.0; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` and then downcasting. */ library SafeCast { /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits */ function toUint224(uint256 value) internal pure returns (uint224) { require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits"); return uint224(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits */ function toUint96(uint256 value) internal pure returns (uint96) { require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits"); return uint96(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits. */ function toUint8(uint256 value) internal pure returns (uint8) { require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits"); return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, "SafeCast: value must be positive"); return uint256(value); } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v3.1._ */ function toInt128(int256 value) internal pure returns (int128) { require(value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits"); return int128(value); } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v3.1._ */ function toInt64(int256 value) internal pure returns (int64) { require(value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits"); return int64(value); } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v3.1._ */ function toInt32(int256 value) internal pure returns (int32) { require(value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits"); return int32(value); } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v3.1._ */ function toInt16(int256 value) internal pure returns (int16) { require(value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits"); return int16(value); } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits. * * _Available since v3.1._ */ function toInt8(int256 value) internal pure returns (int8) { require(value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits"); return int8(value); } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256"); return int256(value); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/structs/EnumerableSet.sol) pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.18; import "@openzeppelin/contracts/utils/Context.sol"; import "./OwnableStorage.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return OwnableStorage.layout().owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = OwnableStorage.layout().owner; OwnableStorage.layout().owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; import "../Ownable/Ownable.sol"; import "./UpgradeableStorage.sol"; contract Upgradeable is Ownable { function setUpgrade(bytes4 _sig, address _target) external onlyOwner { UpgradeableStorage.layout().upgrades[_sig] = _target; } function hasUpgrade(bytes4 _sig) private view returns (bool) { return UpgradeableStorage.layout().upgrades[_sig] != address(0); } function executeUpgrade(bytes4 _sig) private returns (bool) { address target = UpgradeableStorage.layout().upgrades[_sig]; assembly { calldatacopy(0, 0, calldatasize()) let result := delegatecall(gas(), target, 0, calldatasize(), 0, 0) returndatacopy(0, 0, returndatasize()) switch result case 0 {revert(0, returndatasize())} default {return (0, returndatasize())} } } modifier checkForUpgrade() { if (hasUpgrade(msg.sig)) { executeUpgrade(msg.sig); } else { _; } } fallback() external payable { require(hasUpgrade(msg.sig)); executeUpgrade(msg.sig); } receive() external payable {} }
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; /** helper methods for interacting with ERC20 tokens that do not consistently return true/false with the addition of a transfer function to send eth or an erc20 token */ library TransferHelper { function safeTransfer(address _token, address _to, uint _value) internal { (bool success, bytes memory data) = _token.call(abi.encodeWithSelector(0xa9059cbb, _to, _value)); require(success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper: TRANSFER_FAILED"); } function safeTransferFrom(address _token, address _from, address _to, uint _value) internal { (bool success, bytes memory data) = _token.call(abi.encodeWithSelector(0x23b872dd, _from, _to, _value)); require(success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper: TRANSFER_FROM_FAILED"); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; interface IAvatarsEscrow is IERC165, IERC721Receiver { event WeightUpdated(address indexed user, bool increase, uint weight, uint timestamp); event AvatarStaked(uint256 indexed tokenId, address indexed user); event AvatarUnstaked(uint256 indexed tokenId, address indexed user); event RewardsSet(uint32 start, uint32 end, uint256 rate); event RewardsUpdated(uint32 start, uint32 end, uint256 rate); event RewardsPerWeightUpdated(uint256 accumulated); event UserRewardsUpdated(address user, uint256 userRewards, uint256 paidRewardPerWeight); event RewardClaimed(address receiver, uint256 claimed); struct AvatarInfo { uint16 weight; // weight based on rarity address owner; // staked to, otherwise owner == 0 uint16 deposit; // unit is ether, paid in WRLD. The deposit is deducted from the last payment(s) since the deposit is non-custodial uint16 rentalPerDay; // unit is ether, paid in WRLD. Total is deposit + rentalPerDay * days uint16 minRentDays; // must rent for at least min rent days, otherwise deposit is forfeited up to this amount uint32 rentableUntil; // timestamp in unix epoch } struct RewardsPeriod { uint32 start; // reward start time, in unix epoch uint32 end; // reward end time, in unix epoch } struct RewardsPerWeight { uint32 totalWeight; uint96 accumulated; uint32 lastUpdated; uint96 rate; } struct UserRewards { uint32 stakedWeight; uint96 accumulated; uint96 checkpoint; } // view functions function getAvatarInfo(uint _tokenId) external view returns(AvatarInfo memory); function checkUserRewards(address _user) external view returns(uint); function rewardsPeriod() external view returns (IAvatarsEscrow.RewardsPeriod memory); function rewardsPerWeight() external view returns(RewardsPerWeight memory); function rewards(address _user) external view returns (UserRewards memory); function userStakedAvatars(address _user) external view returns (uint256[] memory); function onERC721Received(address, address, uint256, bytes calldata) external view override returns(bytes4); // public functions function initialStake( uint[] calldata _tokenIds, uint[] calldata _weights, address _stakeTo, uint16 _deposit, uint16 _rentalPerDay, uint16 _minRentDays, uint32 _rentableUntil, uint32 _maxTimestamp, bytes calldata _signature ) external; function stake( uint[] calldata _tokenIds, address _stakeTo, uint16 _deposit, uint16 _rentalPerDay, uint16 _minRentDays, uint32 _rentableUntil ) external; function updateRent( uint[] calldata _tokenIds, uint16 _deposit, uint16 _rentalPerDay, uint16 _minRentDays, uint32 _rentableUntil ) external; function extendRentalPeriod(uint _tokenId, uint32 _rentableUntil) external; function unstake(uint[] calldata _tokenIds, address unstakeTo) external; function claim(address _to) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; interface IAvatarsRental is IERC165 { event AvatarRented(uint256 indexed tokenId, address indexed tenant, uint256 payment); event RentalPaid(uint256 indexed tokenId, address indexed tenant, uint256 payment); event RentalTerminated(uint256 indexed tokenId, address indexed tenant); struct AvatarRentInfo { address tenant; // rented to, otherwise tenant == 0 uint32 rentStartTime; // timestamp in unix epoch uint32 rentalPaid; // total rental paid since the beginning including the deposit uint32 paymentAlert; // alert time before next rent payment in seconds (used by frontend only) } function isRentActive(uint _tokenId) external view returns(bool); function getTenant(uint _tokenId) external view returns(address); function rentedByIndex(address _tenant, uint _index) external view returns(uint); function isRentable(uint _tokenId) external view returns(bool state); function rentalPaidUntil(uint _tokenId) external view returns(uint paidUntil); function rentAvatar(uint _tokenId, uint32 _paymentAlert, uint32 initialPayment) external; function payRent(uint _tokenId, uint32 _payment) external; function terminateRental(uint _tokenId) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; interface IAvatars_ERC721 is IERC721 { function updateAvatar( uint _tokenId, string calldata _ipfsHash, uint256 _nonce, bytes calldata _updateApproverSignature ) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; import "./IAvatars_ERC721.sol"; import "./IAvatarsEscrow.sol"; import "./IAvatarsRental.sol"; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; library AvatarsEscrowStorage { bytes32 private constant STORAGE_SLOT = keccak256("slot.avatars.escrow"); struct Layout { address rewardTokenAddress; IAvatars_ERC721 Avatars_ERC721; IAvatarsRental AvatarsRental; IAvatarsEscrow.AvatarInfo[15000] avatarInfo; // Avatar tokenId is in N [0,15000] IAvatarsEscrow.RewardsPeriod rewardsPeriod; IAvatarsEscrow.RewardsPerWeight rewardsPerWeight; mapping(address => IAvatarsEscrow.UserRewards) rewards; mapping(address => EnumerableSet.UintSet) userStakes; address signer; } function layout() internal pure returns (Layout storage _layout) { bytes32 slot = STORAGE_SLOT; assembly { _layout.slot := slot } } }
// 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 v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; library OwnableStorage { bytes32 private constant STORAGE_SLOT = keccak256("gg.topia.worlds.Ownable"); struct Layout { address owner; } function layout() internal pure returns (Layout storage _layout) { bytes32 slot = STORAGE_SLOT; assembly { _layout.slot := slot } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; library UpgradeableStorage { bytes32 private constant STORAGE_SLOT = keccak256("gg.topia.worlds.Upgradeable"); struct Layout { mapping(bytes4 => address) upgrades; } function layout() internal pure returns (Layout storage _layout) { bytes32 slot = STORAGE_SLOT; assembly { _layout.slot := slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (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 `IERC721.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/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`, 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 be 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: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * 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 Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @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 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); /** * @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; }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "hardhat/=node_modules/hardhat/", "@create3-factory/=lib/create3-factory/src/", "src/=src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/" ], "optimizer": { "enabled": true, "runs": 800 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_rewardTokenAddress","type":"address"},{"internalType":"address","name":"_avatars","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"AvatarStaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"AvatarUnstaked","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":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"claimed","type":"uint256"}],"name":"RewardClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"accumulated","type":"uint256"}],"name":"RewardsPerWeightUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"start","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"end","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"rate","type":"uint256"}],"name":"RewardsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"start","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"end","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"rate","type":"uint256"}],"name":"RewardsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"userRewards","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"paidRewardPerWeight","type":"uint256"}],"name":"UserRewardsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"bool","name":"increase","type":"bool"},{"indexed":false,"internalType":"uint256","name":"weight","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"WeightUpdated","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"checkUserRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint32","name":"_rentableUntil","type":"uint32"}],"name":"extendRentalPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getAvatarInfo","outputs":[{"components":[{"internalType":"uint16","name":"weight","type":"uint16"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint16","name":"deposit","type":"uint16"},{"internalType":"uint16","name":"rentalPerDay","type":"uint16"},{"internalType":"uint16","name":"minRentDays","type":"uint16"},{"internalType":"uint32","name":"rentableUntil","type":"uint32"}],"internalType":"struct IAvatarsEscrow.AvatarInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_weights","type":"uint256[]"},{"internalType":"address","name":"_stakeTo","type":"address"},{"internalType":"uint16","name":"_deposit","type":"uint16"},{"internalType":"uint16","name":"_rentalPerDay","type":"uint16"},{"internalType":"uint16","name":"_minRentDays","type":"uint16"},{"internalType":"uint32","name":"_rentableUntil","type":"uint32"},{"internalType":"uint32","name":"_maxTimestamp","type":"uint32"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"initialStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"rewards","outputs":[{"components":[{"internalType":"uint32","name":"stakedWeight","type":"uint32"},{"internalType":"uint96","name":"accumulated","type":"uint96"},{"internalType":"uint96","name":"checkpoint","type":"uint96"}],"internalType":"struct IAvatarsEscrow.UserRewards","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsPerWeight","outputs":[{"components":[{"internalType":"uint32","name":"totalWeight","type":"uint32"},{"internalType":"uint96","name":"accumulated","type":"uint96"},{"internalType":"uint32","name":"lastUpdated","type":"uint32"},{"internalType":"uint96","name":"rate","type":"uint96"}],"internalType":"struct IAvatarsEscrow.RewardsPerWeight","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsPeriod","outputs":[{"components":[{"internalType":"uint32","name":"start","type":"uint32"},{"internalType":"uint32","name":"end","type":"uint32"}],"internalType":"struct IAvatarsEscrow.RewardsPeriod","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IAvatars_ERC721","name":"_avatars","type":"address"}],"name":"setAvatarsERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IAvatarsRental","name":"_rental","type":"address"}],"name":"setAvatarsRental","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IAvatarsRental","name":"_rental","type":"address"}],"name":"setRentalContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rewardTokenAddress","type":"address"}],"name":"setRewardTokenAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_start","type":"uint32"},{"internalType":"uint32","name":"_end","type":"uint32"},{"internalType":"uint96","name":"_rate","type":"uint96"}],"name":"setRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_signer","type":"address"}],"name":"setSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_sig","type":"bytes4"},{"internalType":"address","name":"_target","type":"address"}],"name":"setUpgrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_weights","type":"uint256[]"}],"name":"setWeight","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"address","name":"_stakeTo","type":"address"},{"internalType":"uint16","name":"_deposit","type":"uint16"},{"internalType":"uint16","name":"_rentalPerDay","type":"uint16"},{"internalType":"uint16","name":"_minRentDays","type":"uint16"},{"internalType":"uint32","name":"_rentableUntil","type":"uint32"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"address","name":"_unstakeTo","type":"address"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"string","name":"_ipfsHash","type":"string"},{"internalType":"uint256","name":"_nonce","type":"uint256"},{"internalType":"bytes","name":"_updateApproverSignature","type":"bytes"}],"name":"updateAvatar","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"uint16","name":"_deposit","type":"uint16"},{"internalType":"uint16","name":"_rentalPerDay","type":"uint16"},{"internalType":"uint16","name":"_minRentDays","type":"uint16"},{"internalType":"uint32","name":"_rentableUntil","type":"uint32"}],"name":"updateRent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"userStakedAvatars","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60806040523480156200001157600080fd5b5060405162004b8838038062004b8883398101604081905262000034916200022c565b6200003f336200013f565b60016000556001600160a01b038216620000855760405162461bcd60e51b8152602060048201526002602482015261045360f41b60448201526064015b60405180910390fd5b6001600160a01b038116620000c25760405162461bcd60e51b8152602060048201526002602482015261045360f41b60448201526064016200007c565b81620000d8620001c760201b62002e7c1760201c565b60000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508062000115620001c760201b62002e7c1760201c565b60010180546001600160a01b0319166001600160a01b039290921691909117905550620002649050565b600062000156620001eb60201b62002e8e1760201c565b546001600160a01b031690508162000179620001eb602090811b62002e8e17901c565b80546001600160a01b0319166001600160a01b03928316179055604051838216918316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b7fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a15623990565b7f2964b7e756c43d7fc626c76da5b94aa9f7f497362e81c25e47dc710c9dbd2bc690565b80516001600160a01b03811681146200022757600080fd5b919050565b600080604083850312156200024057600080fd5b6200024b836200020f565b91506200025b602084016200020f565b90509250929050565b61491480620002746000396000f3fe6080604052600436106101a55760003560e01c80636c19e783116100e15780639a1e9c331161008a578063dbb37abf11610064578063dbb37abf14610698578063f2fde38b146106b8578063f507e8d8146106d8578063fc196d0814610705576101ac565b80639a1e9c331461062a5780639a6acf2014610658578063a354f39e14610678576101ac565b80637b892e00116100bb5780637b892e00146105a35780638b5f855b146105c35780638da5cb5b146105e3576101ac565b80636c19e7831461054e5780636e68dbeb1461056e578063715018a61461058e576101ac565b806326ae2b781161014e57806343a92f241161012857806343a92f24146104675780635a63427e146104ee57806364fe85771461050e578063683b22ec1461052e576101ac565b806326ae2b78146103aa5780632cd8d4d7146104275780633633152114610447576101ac565b8063150b7a021161017f578063150b7a021461033157806317224a6d1461036a5780631e83409a1461038a576101ac565b806301ffc9a7146101fc5780630700037d146102315780630d30417c14610311576101ac565b366101ac57005b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b03166101e557600080fd5b6101fa6000356001600160e01b0319166107cc565b005b34801561020857600080fd5b5061021c610217366004613f7e565b61081f565b60405190151581526020015b60405180910390f35b34801561023d57600080fd5b506102d861024c366004613fc0565b6040805160608082018352600080835260208084018290529284018190526001600160a01b039490941684527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd6825292829020825193840183525463ffffffff811684526001600160601b036401000000008204811692850192909252600160801b9004169082015290565b60408051825163ffffffff1681526020808401516001600160601b03908116918301919091529282015190921690820152606001610228565b34801561031d57600080fd5b506101fa61032c366004613fc0565b610856565b34801561033d57600080fd5b5061035161034c36600461401f565b6108ea565b6040516001600160e01b03199091168152602001610228565b34801561037657600080fd5b506101fa610385366004614092565b610917565b34801561039657600080fd5b506101fa6103a5366004613fc0565b610be4565b3480156103b657600080fd5b506040805180820182526000808252602091820152815180830183527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd45463ffffffff8082168084526401000000009092048116928401928352845191825291519091169181019190915201610228565b34801561043357600080fd5b506101fa610442366004614180565b610d63565b34801561045357600080fd5b506101fa610462366004614205565b611094565b34801561047357600080fd5b5061048761048236600461425c565b61156d565b6040516102289190600060c08201905061ffff8084511683526001600160a01b0360208501511660208401528060408501511660408401528060608501511660608401528060808501511660808401525063ffffffff60a08401511660a083015292915050565b3480156104fa57600080fd5b506101fa610509366004613fc0565b611643565b34801561051a57600080fd5b506101fa610529366004614275565b611776565b34801561053a57600080fd5b506101fa610549366004614385565b611dff565b34801561055a57600080fd5b506101fa610569366004613fc0565b611e4e565b34801561057a57600080fd5b506101fa6105893660046143be565b611ee1565b34801561059a57600080fd5b506101fa612097565b3480156105af57600080fd5b506101fa6105be3660046143ea565b6120ab565b3480156105cf57600080fd5b506101fa6105de366004613fc0565b612239565b3480156105ef57600080fd5b507f2964b7e756c43d7fc626c76da5b94aa9f7f497362e81c25e47dc710c9dbd2bc6546040516001600160a01b039091168152602001610228565b34801561063657600080fd5b5061064a610645366004613fc0565b61228b565b604051908152602001610228565b34801561066457600080fd5b506101fa610673366004613fc0565b61246c565b34801561068457600080fd5b506101fa610693366004614456565b6124ed565b3480156106a457600080fd5b506101fa6106b336600461449e565b6127c8565b3480156106c457600080fd5b506101fa6106d3366004613fc0565b612cdf565b3480156106e457600080fd5b506106f86106f3366004613fc0565b612d6c565b6040516102289190614536565b34801561071157600080fd5b50604080516080808201835260008083526020808401829052838501829052606093840191909152835180830185527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd55463ffffffff8082168084526001600160601b0364010000000084048116858701908152600160801b85048416868b01908152600160a01b90950482169589019586528951928352518116958201959095529151169581019590955251169183019190915201610228565b6001600160e01b0319811660009081526000805160206148bf83398151915260205260408120546001600160a01b031636828037600080366000845af43d6000803e80801561081a573d6000f35b3d6000fd5b60006001600160e01b03198216633141c18f60e01b148061085057506301ffc9a760e01b6001600160e01b03198316145b92915050565b61085e612eb2565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b0316156108ac576108a86000356001600160e01b0319166107cc565b5050565b7fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a15623a80546001600160a01b0319166001600160a01b0383161790555b50565b6000306001600160a01b0387160361090a5750630a85bd0160e11b61090e565b5060005b95945050505050565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b031615610967576109616000356001600160e01b0319166107cc565b50610bdc565b337fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a15623c87613a98811061099b5761099b61457a565b01546201000090046001600160a01b0316148015610a33575060008051602061489f83398151915260020154604051633339a29360e11b8152600481018890526001600160a01b0390911690636673452690602401602060405180830381865afa158015610a0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a319190614590565b155b80610b1a575060007fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a15623c87613a988110610a6e57610a6e61457a565b01546201000090046001600160a01b031614801590610b1a5750336001600160a01b031660008051602061489f833981519152600201546040516355fd83e560e01b8152600481018990526001600160a01b03909116906355fd83e590602401602060405180830381865afa158015610aeb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0f91906145b2565b6001600160a01b0316145b610b505760405162461bcd60e51b815260206004820152600260248201526108a960f31b60448201526064015b60405180910390fd5b7fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a15623a546040516317224a6d60e01b81526001600160a01b03909116906317224a6d90610ba9908990899089908990899089906004016145f8565b600060405180830381600087803b158015610bc357600080fd5b505af1158015610bd7573d6000803e3d6000fd5b505050505b505050505050565b600260005403610c365760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b47565b600260009081556001600160e01b031981351681526000805160206148bf83398151915260205260409020546001600160a01b031615610c8b57610c856000356001600160e01b0319166107cc565b50610d5b565b610c96600080612f3a565b6000610ca4336000806131f4565b3360009081527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd66020526040902080546fffffffffffffffffffffffff00000000191690556001600160601b03169050610d1760008051602061489f833981519152546001600160a01b031683836134fc565b604080516001600160a01b0384168152602081018390527f106f923f993c2149d49b4255ff723acafa1f2d94393f561d3eda32ae348f7241910160405180910390a1505b506001600055565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b031615610dad576109616000356001600160e01b0319166107cc565b610dbc61ffff8316600161464e565b610dca9061ffff8516614661565b8461ffff161115610e025760405162461bcd60e51b815260206004820152600260248201526122a960f11b6044820152606401610b47565b60005b8581101561108b576000878783818110610e2157610e2161457a565b9050602002013590506000610e4160008051602061489f83398151915290565b60030182613a988110610e5657610e5661457a565b01805490915061ffff16600003610e945760405162461bcd60e51b8152602060048201526002602482015261454160f01b6044820152606401610b47565b3060008051602061489f833981519152600101546040516331a9108f60e11b8152600481018590526001600160a01b0390911690636352211e90602401602060405180830381865afa158015610eee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f1291906145b2565b6001600160a01b0316148015610f38575080546001600160a01b03620100009091041633145b610f695760405162461bcd60e51b8152602060048201526002602482015261453960f01b6044820152606401610b47565b60008051602061489f83398151915260020154604051633339a29360e11b8152600481018490526001600160a01b0390911690636673452690602401602060405180830381865afa158015610fc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fe69190614590565b156110185760405162461bcd60e51b815260206004820152600260248201526122a160f11b6044820152606401610b47565b805463ffffffff60b01b1916600160b01b61ffff8981169190910261ffff60c01b191691909117600160c01b88831602176001600160d01b0316600160d01b918716919091026001600160e01b031617600160e01b63ffffffff861602179055508061108381614678565b915050610e05565b50505050505050565b6002600054036110e65760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b47565b600260009081556001600160e01b031981351681526000805160206148bf83398151915260205260409020546001600160a01b03161561113b576111356000356001600160e01b0319166107cc565b50611563565b61114481613610565b306001600160a01b038216036111815760405162461bcd60e51b8152602060048201526002602482015261455360f01b6044820152606401610b47565b6000805b838110156115385760008585838181106111a1576111a161457a565b9050602002013590506111b13390565b6001600160a01b03167fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a15623c82613a9881106111ed576111ed61457a565b01546201000090046001600160a01b0316146112305760405162461bcd60e51b8152602060048201526002602482015261453960f01b6044820152606401610b47565b60008051602061489f83398151915260020154604051633339a29360e11b8152600481018390526001600160a01b0390911690636673452690602401602060405180830381865afa158015611289573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ad9190614590565b156112df5760405162461bcd60e51b815260206004820152600260248201526122a160f11b6044820152606401610b47565b60008051602061489f83398151915260010154604051632142170760e11b81523060048201526001600160a01b03868116602483015260448201849052909116906342842e0e90606401600060405180830381600087803b15801561134357600080fd5b505af1158015611357573d6000803e3d6000fd5b50505050600061137260008051602061489f83398151915290565b60030182613a9881106113875761138761457a565b015461ffff169050611399818561464e565b6040805160c08101825261ffff84168152600060208201819052918101829052606081018290526080810182905260a08101919091529094507fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a15623c83613a9881106114055761140561457a565b825191018054602084015160408501516060860151608087015160a09097015163ffffffff16600160e01b026001600160e01b0361ffff988916600160d01b02166001600160d01b03928916600160c01b0261ffff60c01b19948a16600160b01b029490941663ffffffff60b01b196001600160a01b03909616620100000275ffffffffffffffffffffffffffffffffffffffffffff1990971699909816989098179490941792909216949094179390931792909216929092171790556114f5826114db60008051602061489f83398151915290565b336000908152613a9e91909101602052604090209061378c565b50604051339083907ffc52eee0edb488f7e56636618794f0c0b30044b2f0e81b4242787d1feff50f9590600090a35050808061153090614678565b915050611185565b5061154c61154582613798565b6000612f3a565b6115603361155983613798565b60006131f4565b50505b5050600160005550565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a15623c82613a9881106115d2576115d261457a565b6040805160c081018252929091015461ffff80821684526001600160a01b03620100008304166020850152600160b01b8204811692840192909252600160c01b810482166060840152600160d01b8104909116608083015263ffffffff600160e01b9091041660a082015292915050565b61164b612eb2565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b031615611695576108a86000356001600160e01b0319166107cc565b6040516301ffc9a760e01b815263ddb05bc160e01b60048201526001600160a01b038216906301ffc9a790602401602060405180830381865afa1580156116e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117049190614590565b6117355760405162461bcd60e51b8152602060048201526002602482015261045360f41b6044820152606401610b47565b7fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a15623b80546001600160a01b0319166001600160a01b0392909216919091179055565b6002600054036117c85760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b47565b600260009081556001600160e01b031981351681526000805160206148bf83398151915260205260409020546001600160a01b03161561181d576118176000356001600160e01b0319166107cc565b50611dec565b61182c61ffff8616600161464e565b61183a9061ffff8816614661565b8761ffff1611156118725760405162461bcd60e51b815260206004820152600260248201526122a960f11b6044820152606401610b47565b8a89146118a65760405162461bcd60e51b8152602060048201526002602482015261229b60f11b6044820152606401610b47565b8263ffffffff164211156118e15760405162461bcd60e51b815260206004820152600260248201526108ab60f31b6044820152606401610b47565b61191e8c8c8c8c33883060405160200161190197969594939291906146dc565b604051602081830303815290604052805190602001208383613818565b61194f5760405162461bcd60e51b8152602060048201526002602482015261453760f01b6044820152606401610b47565b61195888613610565b306001600160a01b038916036119955760405162461bcd60e51b8152602060048201526002602482015261455360f01b6044820152606401610b47565b6000805b8c811015611dc15760008e8e838181106119b5576119b561457a565b90506020020135905060006119d560008051602061489f83398151915290565b60030182613a9881106119ea576119ea61457a565b015461ffff169050801580611a1657508d8d84818110611a0c57611a0c61457a565b9050602002013581145b611a475760405162461bcd60e51b815260206004820152600260248201526108a760f31b6044820152606401610b47565b336001600160a01b031660008051602061489f833981519152600101546040516331a9108f60e11b8152600481018590526001600160a01b0390911690636352211e90602401602060405180830381865afa158015611aaa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ace91906145b2565b6001600160a01b031614611b095760405162461bcd60e51b8152602060048201526002602482015261453960f01b6044820152606401610b47565b60008051602061489f833981519152600101546001600160a01b03166342842e0e336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015230602482015260448101859052606401600060405180830381600087803b158015611b7957600080fd5b505af1158015611b8d573d6000803e3d6000fd5b50506040516001600160a01b038f1692508491507f7536c5f8fc3c7e1e44540eb857fb8c7c98a2b91016ee9b65a0969f8630d84cbe90600090a350506040518060c00160405280611bf58e8e85818110611be957611be961457a565b905060200201356138a3565b61ffff1681526020018b6001600160a01b031681526020018a61ffff1681526020018961ffff1681526020018861ffff1681526020018763ffffffff16815250611c4a60008051602061489f83398151915290565b6003018f8f84818110611c5f57611c5f61457a565b90506020020135613a988110611c7757611c7761457a565b825191018054602084015160408501516060860151608087015160a09097015163ffffffff16600160e01b026001600160e01b0361ffff988916600160d01b02166001600160d01b03928916600160c01b0261ffff60c01b19948a16600160b01b029490941663ffffffff60b01b196001600160a01b03909616620100000275ffffffffffffffffffffffffffffffffffffffffffff199097169990981698909817949094179290921694909417939093179290921692909217179055611d888e8e83818110611d4957611d4961457a565b90506020020135611d6560008051602061489f83398151915290565b6001600160a01b038d166000908152613a9e919091016020526040902090613906565b508b8b82818110611d9b57611d9b61457a565b9050602002013582611dad919061464e565b915080611db981614678565b915050611999565b50611dd5611dce82613798565b6001612f3a565b611de989611de283613798565b60016131f4565b50505b5050600160005550505050505050505050565b611e07612eb2565b6001600160e01b03199190911660009081526000805160206148bf8339815191526020526040902080546001600160a01b0319166001600160a01b03909216919091179055565b611e56612eb2565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b031615611ea0576108a86000356001600160e01b0319166107cc565b7fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd880546001600160a01b0319166001600160a01b0392909216919091179055565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b031615611f3057611f2b6000356001600160e01b0319166107cc565b505050565b60007fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a15623c83613a988110611f6557611f6561457a565b01805490915061ffff16600003611fa35760405162461bcd60e51b8152602060048201526002602482015261454160f01b6044820152606401610b47565b3060008051602061489f833981519152600101546040516331a9108f60e11b8152600481018690526001600160a01b0390911690636352211e90602401602060405180830381865afa158015611ffd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061202191906145b2565b6001600160a01b0316148015612047575080546001600160a01b03620100009091041633145b6120785760405162461bcd60e51b8152602060048201526002602482015261453960f01b6044820152606401610b47565b80546001600160e01b0316600160e01b63ffffffff8416021790555050565b61209f612eb2565b6120a96000613912565b565b6120b3612eb2565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b031615612103576120fd6000356001600160e01b0319166107cc565b50612233565b8281146121375760405162461bcd60e51b8152602060048201526002602482015261229b60f11b6044820152606401610b47565b60005b838110156122315760008585838181106121565761215661457a565b90506020020135905061217460008051602061489f83398151915290565b60030181613a9881106121895761218961457a565b015461ffff16156121c15760405162461bcd60e51b815260206004820152600260248201526108a760f31b6044820152606401610b47565b6121d6848484818110611be957611be961457a565b7fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a15623c82613a9881106122095761220961457a565b01805461ffff191661ffff92909216919091179055508061222981614678565b91505061213a565b505b50505050565b612241612eb2565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b031615611735576108a86000356001600160e01b0319166107cc565b604080516080810182527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd55463ffffffff80821683526001600160601b036401000000008084048216602080870191909152600160801b808604851687890152600160a01b90950483166060808801919091526001600160a01b03891660009081527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd6835288812089519283018a525495861682529285048416918101919091529390920416938201939093528261239a61236542613798565b7fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd454640100000000900463ffffffff16613983565b905060008360400151826123ae9190614736565b63ffffffff169050801561242457835163ffffffff161561242457835160608501516124159163ffffffff16906123ee906001600160601b031684614661565b6123f89190614753565b85602001516001600160601b0316612410919061464e565b6139a5565b6001600160601b031660208501525b826040015184602001516124389190614775565b835161244a919063ffffffff16614795565b836020015161245991906147c0565b6001600160601b03169695505050505050565b612474612eb2565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b0316156124be576108a86000356001600160e01b0319166107cc565b60008051602061489f83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6124f5612eb2565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b03161561253f576122336000356001600160e01b0319166107cc565b8163ffffffff168363ffffffff1611156125805760405162461bcd60e51b8152602060048201526002602482015261453160f01b6044820152606401610b47565b666a94d74f430000816001600160601b03161180156125b057506801a055690d9db80000816001600160601b0316105b6125e15760405162461bcd60e51b8152602060048201526002602482015261229960f11b6044820152606401610b47565b60008051602061489f833981519152546001600160a01b031661262b5760405162461bcd60e51b8152602060048201526002602482015261453360f01b6044820152606401610b47565b7fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd45463ffffffff1661265c42613798565b63ffffffff1610806126aa57507fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd454640100000000900463ffffffff166126a242613798565b63ffffffff16115b6126db5760405162461bcd60e51b8152602060048201526002602482015261114d60f21b6044820152606401610b47565b7fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd4805467ffffffffffffffff191663ffffffff858116918217640100000000918616918202179092557fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd580546fffffffffffffffffffffffffffffffff16600160801b83026001600160a01b031617600160a01b6001600160601b038616908102919091179091556040805192835260208301939093528183015290517f95efd8a2a0aa591f48fd9673cf5d13c2150ca7a1fe1cbe438dd3f0ae47064663916060908290030190a1505050565b60026000540361281a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b47565b600260009081556001600160e01b031981351681526000805160206148bf83398151915260205260409020546001600160a01b03161561286f576128696000356001600160e01b0319166107cc565b50612cd1565b61287e61ffff8316600161464e565b61288c9061ffff8516614661565b8461ffff1611156128c45760405162461bcd60e51b815260206004820152600260248201526122a960f11b6044820152606401610b47565b6128cd85613610565b306001600160a01b0386160361290a5760405162461bcd60e51b8152602060048201526002602482015261455360f01b6044820152606401610b47565b6000805b87811015612cb457600089898381811061292a5761292a61457a565b905060200201359050600061294a60008051602061489f83398151915290565b60030182613a98811061295f5761295f61457a565b015461ffff169050600081900361299d5760405162461bcd60e51b8152602060048201526002602482015261454160f01b6044820152606401610b47565b336001600160a01b031660008051602061489f833981519152600101546040516331a9108f60e11b8152600481018590526001600160a01b0390911690636352211e90602401602060405180830381865afa158015612a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2491906145b2565b6001600160a01b031614612a5f5760405162461bcd60e51b8152602060048201526002602482015261453960f01b6044820152606401610b47565b60008051602061489f833981519152600101546001600160a01b03166342842e0e336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015230602482015260448101859052606401600060405180830381600087803b158015612acf57600080fd5b505af1158015612ae3573d6000803e3d6000fd5b505050508061ffff1684612af7919061464e565b93506040518060c001604052808261ffff1681526020018a6001600160a01b031681526020018961ffff1681526020018861ffff1681526020018761ffff1681526020018663ffffffff16815250612b5a60008051602061489f83398151915290565b60030183613a988110612b6f57612b6f61457a565b825191018054602084015160408501516060860151608087015160a09097015163ffffffff16600160e01b026001600160e01b0361ffff988916600160d01b02166001600160d01b03928916600160c01b0261ffff60c01b19948a16600160b01b029490941663ffffffff60b01b196001600160a01b03909616620100000275ffffffffffffffffffffffffffffffffffffffffffff199097169990981698909817949094179290921694909417939093179290921692909217179055612c6882612c4560008051602061489f83398151915290565b6001600160a01b038c166000908152613a9e919091016020526040902090613906565b506040516001600160a01b038a169083907f7536c5f8fc3c7e1e44540eb857fb8c7c98a2b91016ee9b65a0969f8630d84cbe90600090a350508080612cac90614678565b91505061290e565b50612cc1611dce82613798565b612cce86611de283613798565b50505b505060016000555050505050565b612ce7612eb2565b6001600160a01b038116612d635760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610b47565b6108e781613912565b6001600160a01b03811660009081527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd76020526040812060609190612db090613a0d565b905060008167ffffffffffffffff811115612dcd57612dcd6147e0565b604051908082528060200260200182016040528015612df6578160200160208202803683370190505b50905060005b82811015612e74576001600160a01b03851660009081527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd760205260409020612e459082613a17565b828281518110612e5757612e5761457a565b602090810291909101015280612e6c81614678565b915050612dfc565b509392505050565b60008051602061489f83398151915290565b7f2964b7e756c43d7fc626c76da5b94aa9f7f497362e81c25e47dc710c9dbd2bc690565b33612ee47f2964b7e756c43d7fc626c76da5b94aa9f7f497362e81c25e47dc710c9dbd2bc6546001600160a01b031690565b6001600160a01b0316146120a95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b47565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b031615612f8457611f2b6000356001600160e01b0319166107cc565b604080516080810182527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd55463ffffffff80821683526401000000008083046001600160601b03908116602080870191909152600160801b8504841686880152600160a01b90940416606085015284518086019095527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd4548083168087529190049091169184019190915290919061303b42613798565b63ffffffff16106130d157600061305e61305442613798565b8360200151613983565b905060008360400151826130729190614736565b63ffffffff16905080156130ce57835163ffffffff16156130c157835160608501516130b29163ffffffff16906123ee906001600160601b031684614661565b6001600160601b031660208501525b63ffffffff821660408501525b50505b82156130f75783826000018181516130e991906147f6565b63ffffffff16905250613113565b83826000018181516131099190614736565b63ffffffff169052505b81517fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd5805460208086015160408088015160608901516001600160601b03908116600160a01b026001600160a01b0363ffffffff938416600160801b02166fffffffffffffffffffffffffffffffff9290951664010000000081026fffffffffffffffffffffffffffffffff199098169390991692909217959095179490941691909117929092179092558051928352517faac1802288db8019f8ec43430efc11a152c72473c57d6ddcde3b6dd0c89260679281900390910190a150505050565b600080356001600160e01b03191681526000805160206148bf83398151915260205260408120546001600160a01b0316156132445761323e6000356001600160e01b0319166107cc565b506134f5565b6001600160a01b03841660009081527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd66020908152604091829020825160608082018552915463ffffffff80821683526401000000008083046001600160601b0390811685880152600160801b9384900481168589019081528851608081018a527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd5548086168252938404831698810189905294830490931697840197909752600160a01b900490951692810192909252925190916133239190614775565b8251613335919063ffffffff16614795565b826020015161334491906147c0565b6001600160601b0390811660208085019190915282015116604083015263ffffffff85161561340257831561339357848260000181815161338591906147f6565b63ffffffff169052506133af565b84826000018181516133a59190614736565b63ffffffff169052505b60408051851515815263ffffffff87166020820152428183015290516001600160a01b038816917fb1de227711aba68cec92891ccaabad9474a3f417d166ca8f57e7d616f467d343919081900360600190a25b6001600160a01b03861660008181527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd660209081526040918290208551815483880151858901516001600160601b03908116600160801b81027fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff9290931664010000000081026fffffffffffffffffffffffffffffffff1990951663ffffffff9096169590951793909317161790925583519485529184019190915282820152517f5b9aaf4cc5141c090a75f8b8a627863eba92df81f0c83c096350da9b79aedd049181900360600190a1506020015190505b9392505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916135589190614813565b6000604051808303816000865af19150503d8060008114613595576040519150601f19603f3d011682016040523d82523d6000602084013e61359a565b606091505b50915091508180156135c45750805115806135c45750808060200190518101906135c49190614590565b6122315760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610b47565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b03161561365a576108a86000356001600160e01b0319166107cc565b803b63ffffffff8116156108a857604051630a85bd0160e11b8152306004820181905260248201526000604482018190526080606483015260848201526001600160a01b0383169063150b7a029060a4016020604051808303816000875af19250505080156136e6575060408051601f3d908101601f191682019092526136e391810190614842565b60015b613747573d808015613714576040519150601f19603f3d011682016040523d82523d6000602084013e613719565b606091505b5060405162461bcd60e51b8152602060048201526002602482015261115560f21b6044820152606401610b47565b6001600160e01b03198116630a85bd0160e11b14611f2b5760405162461bcd60e51b8152602060048201526002602482015261115560f21b6044820152606401610b47565b60006134f58383613a23565b600063ffffffff8211156138145760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201527f32206269747300000000000000000000000000000000000000000000000000006064820152608401610b47565b5090565b7fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd854604080516020601f85018190048102820181019092528381526000926001600160a01b0316916138919190869086908190840183828082843760009201919091525061388b9250899150613b1d9050565b90613b70565b6001600160a01b031614949350505050565b600061ffff8211156138145760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203160448201526536206269747360d01b6064820152608401610b47565b60006134f58383613b8c565b7f2964b7e756c43d7fc626c76da5b94aa9f7f497362e81c25e47dc710c9dbd2bc680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60008163ffffffff168363ffffffff161061399e57816134f5565b5090919050565b60006001600160601b038211156138145760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201526536206269747360d01b6064820152608401610b47565b6000610850825490565b60006134f58383613bdb565b60008181526001830160205260408120548015613b0c576000613a4760018361485f565b8554909150600090613a5b9060019061485f565b9050818114613ac0576000866000018281548110613a7b57613a7b61457a565b9060005260206000200154905080876000018481548110613a9e57613a9e61457a565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613ad157613ad1614872565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610850565b6000915050610850565b5092915050565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b6000806000613b7f8585613c05565b91509150612e7481613c73565b6000818152600183016020526040812054613bd357508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610850565b506000610850565b6000826000018281548110613bf257613bf261457a565b9060005260206000200154905092915050565b6000808251604103613c3b5760208301516040840151606085015160001a613c2f87828585613e29565b94509450505050613c6c565b8251604003613c645760208301516040840151613c59868383613f16565b935093505050613c6c565b506000905060025b9250929050565b6000816004811115613c8757613c87614888565b03613c8f5750565b6001816004811115613ca357613ca3614888565b03613cf05760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610b47565b6002816004811115613d0457613d04614888565b03613d515760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610b47565b6003816004811115613d6557613d65614888565b03613dbd5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610b47565b6004816004811115613dd157613dd1614888565b036108e75760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610b47565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115613e605750600090506003613f0d565b8460ff16601b14158015613e7857508460ff16601c14155b15613e895750600090506004613f0d565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015613edd573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116613f0657600060019250925050613f0d565b9150600090505b94509492505050565b6000807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831681613f4c60ff86901c601b61464e565b9050613f5a87828885613e29565b935093505050935093915050565b6001600160e01b0319811681146108e757600080fd5b600060208284031215613f9057600080fd5b81356134f581613f68565b6001600160a01b03811681146108e757600080fd5b8035613fbb81613f9b565b919050565b600060208284031215613fd257600080fd5b81356134f581613f9b565b60008083601f840112613fef57600080fd5b50813567ffffffffffffffff81111561400757600080fd5b602083019150836020828501011115613c6c57600080fd5b60008060008060006080868803121561403757600080fd5b853561404281613f9b565b9450602086013561405281613f9b565b935060408601359250606086013567ffffffffffffffff81111561407557600080fd5b61408188828901613fdd565b969995985093965092949392505050565b600080600080600080608087890312156140ab57600080fd5b86359550602087013567ffffffffffffffff808211156140ca57600080fd5b6140d68a838b01613fdd565b90975095506040890135945060608901359150808211156140f657600080fd5b5061410389828a01613fdd565b979a9699509497509295939492505050565b60008083601f84011261412757600080fd5b50813567ffffffffffffffff81111561413f57600080fd5b6020830191508360208260051b8501011115613c6c57600080fd5b803561ffff81168114613fbb57600080fd5b803563ffffffff81168114613fbb57600080fd5b60008060008060008060a0878903121561419957600080fd5b863567ffffffffffffffff8111156141b057600080fd5b6141bc89828a01614115565b90975095506141cf90506020880161415a565b93506141dd6040880161415a565b92506141eb6060880161415a565b91506141f96080880161416c565b90509295509295509295565b60008060006040848603121561421a57600080fd5b833567ffffffffffffffff81111561423157600080fd5b61423d86828701614115565b909450925050602084013561425181613f9b565b809150509250925092565b60006020828403121561426e57600080fd5b5035919050565b6000806000806000806000806000806000806101208d8f03121561429857600080fd5b67ffffffffffffffff8d3511156142ae57600080fd5b6142bb8e8e358f01614115565b909c509a5067ffffffffffffffff60208e013511156142d957600080fd5b6142e98e60208f01358f01614115565b909a5098506142fa60408e01613fb0565b975061430860608e0161415a565b965061431660808e0161415a565b955061432460a08e0161415a565b945061433260c08e0161416c565b935061434060e08e0161416c565b925067ffffffffffffffff6101008e0135111561435c57600080fd5b61436d8e6101008f01358f01613fdd565b81935080925050509295989b509295989b509295989b565b6000806040838503121561439857600080fd5b82356143a381613f68565b915060208301356143b381613f9b565b809150509250929050565b600080604083850312156143d157600080fd5b823591506143e16020840161416c565b90509250929050565b6000806000806040858703121561440057600080fd5b843567ffffffffffffffff8082111561441857600080fd5b61442488838901614115565b9096509450602087013591508082111561443d57600080fd5b5061444a87828801614115565b95989497509550505050565b60008060006060848603121561446b57600080fd5b6144748461416c565b92506144826020850161416c565b915060408401356001600160601b038116811461425157600080fd5b600080600080600080600060c0888a0312156144b957600080fd5b873567ffffffffffffffff8111156144d057600080fd5b6144dc8a828b01614115565b90985096505060208801356144f081613f9b565b94506144fe6040890161415a565b935061450c6060890161415a565b925061451a6080890161415a565b915061452860a0890161416c565b905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b8181101561456e57835183529284019291840191600101614552565b50909695505050505050565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156145a257600080fd5b815180151581146134f557600080fd5b6000602082840312156145c457600080fd5b81516134f581613f9b565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b8681526080602082015260006146126080830187896145cf565b856040840152828103606084015261462b8185876145cf565b9998505050505050505050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561085057610850614638565b808202811582820484141761085057610850614638565b60006001820161468a5761468a614638565b5060010190565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156146c357600080fd5b8260051b80836020870137939093016020019392505050565b60a0815260006146f060a08301898b614691565b828103602084015261470381888a614691565b6001600160a01b03968716604085015263ffffffff95909516606084015250509216608090920191909152949350505050565b63ffffffff828116828216039080821115613b1657613b16614638565b60008261477057634e487b7160e01b600052601260045260246000fd5b500490565b6001600160601b03828116828216039080821115613b1657613b16614638565b6001600160601b038181168382160280821691908281146147b8576147b8614638565b505092915050565b6001600160601b03818116838216019080821115613b1657613b16614638565b634e487b7160e01b600052604160045260246000fd5b63ffffffff818116838216019080821115613b1657613b16614638565b6000825160005b81811015614834576020818601810151858301520161481a565b506000920191825250919050565b60006020828403121561485457600080fd5b81516134f581613f68565b8181038181111561085057610850614638565b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052602160045260246000fdfebae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a156239465c35ad1d12a6f76ffabe3e9eca16a7f4fd728d9969a9386eb4f7d2c55ac80da26469706673582212208614dd274a93e6c702cade7fb2b85b354d97c2643af8679054d245a9368fc2a664736f6c63430008120033000000000000000000000000ccccb68e1a848cbdb5b60a974e07aae143ed40c300000000000000000000000005745e72fb8b4a9b51118a168d956760e4a36444
Deployed Bytecode
0x6080604052600436106101a55760003560e01c80636c19e783116100e15780639a1e9c331161008a578063dbb37abf11610064578063dbb37abf14610698578063f2fde38b146106b8578063f507e8d8146106d8578063fc196d0814610705576101ac565b80639a1e9c331461062a5780639a6acf2014610658578063a354f39e14610678576101ac565b80637b892e00116100bb5780637b892e00146105a35780638b5f855b146105c35780638da5cb5b146105e3576101ac565b80636c19e7831461054e5780636e68dbeb1461056e578063715018a61461058e576101ac565b806326ae2b781161014e57806343a92f241161012857806343a92f24146104675780635a63427e146104ee57806364fe85771461050e578063683b22ec1461052e576101ac565b806326ae2b78146103aa5780632cd8d4d7146104275780633633152114610447576101ac565b8063150b7a021161017f578063150b7a021461033157806317224a6d1461036a5780631e83409a1461038a576101ac565b806301ffc9a7146101fc5780630700037d146102315780630d30417c14610311576101ac565b366101ac57005b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b03166101e557600080fd5b6101fa6000356001600160e01b0319166107cc565b005b34801561020857600080fd5b5061021c610217366004613f7e565b61081f565b60405190151581526020015b60405180910390f35b34801561023d57600080fd5b506102d861024c366004613fc0565b6040805160608082018352600080835260208084018290529284018190526001600160a01b039490941684527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd6825292829020825193840183525463ffffffff811684526001600160601b036401000000008204811692850192909252600160801b9004169082015290565b60408051825163ffffffff1681526020808401516001600160601b03908116918301919091529282015190921690820152606001610228565b34801561031d57600080fd5b506101fa61032c366004613fc0565b610856565b34801561033d57600080fd5b5061035161034c36600461401f565b6108ea565b6040516001600160e01b03199091168152602001610228565b34801561037657600080fd5b506101fa610385366004614092565b610917565b34801561039657600080fd5b506101fa6103a5366004613fc0565b610be4565b3480156103b657600080fd5b506040805180820182526000808252602091820152815180830183527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd45463ffffffff8082168084526401000000009092048116928401928352845191825291519091169181019190915201610228565b34801561043357600080fd5b506101fa610442366004614180565b610d63565b34801561045357600080fd5b506101fa610462366004614205565b611094565b34801561047357600080fd5b5061048761048236600461425c565b61156d565b6040516102289190600060c08201905061ffff8084511683526001600160a01b0360208501511660208401528060408501511660408401528060608501511660608401528060808501511660808401525063ffffffff60a08401511660a083015292915050565b3480156104fa57600080fd5b506101fa610509366004613fc0565b611643565b34801561051a57600080fd5b506101fa610529366004614275565b611776565b34801561053a57600080fd5b506101fa610549366004614385565b611dff565b34801561055a57600080fd5b506101fa610569366004613fc0565b611e4e565b34801561057a57600080fd5b506101fa6105893660046143be565b611ee1565b34801561059a57600080fd5b506101fa612097565b3480156105af57600080fd5b506101fa6105be3660046143ea565b6120ab565b3480156105cf57600080fd5b506101fa6105de366004613fc0565b612239565b3480156105ef57600080fd5b507f2964b7e756c43d7fc626c76da5b94aa9f7f497362e81c25e47dc710c9dbd2bc6546040516001600160a01b039091168152602001610228565b34801561063657600080fd5b5061064a610645366004613fc0565b61228b565b604051908152602001610228565b34801561066457600080fd5b506101fa610673366004613fc0565b61246c565b34801561068457600080fd5b506101fa610693366004614456565b6124ed565b3480156106a457600080fd5b506101fa6106b336600461449e565b6127c8565b3480156106c457600080fd5b506101fa6106d3366004613fc0565b612cdf565b3480156106e457600080fd5b506106f86106f3366004613fc0565b612d6c565b6040516102289190614536565b34801561071157600080fd5b50604080516080808201835260008083526020808401829052838501829052606093840191909152835180830185527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd55463ffffffff8082168084526001600160601b0364010000000084048116858701908152600160801b85048416868b01908152600160a01b90950482169589019586528951928352518116958201959095529151169581019590955251169183019190915201610228565b6001600160e01b0319811660009081526000805160206148bf83398151915260205260408120546001600160a01b031636828037600080366000845af43d6000803e80801561081a573d6000f35b3d6000fd5b60006001600160e01b03198216633141c18f60e01b148061085057506301ffc9a760e01b6001600160e01b03198316145b92915050565b61085e612eb2565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b0316156108ac576108a86000356001600160e01b0319166107cc565b5050565b7fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a15623a80546001600160a01b0319166001600160a01b0383161790555b50565b6000306001600160a01b0387160361090a5750630a85bd0160e11b61090e565b5060005b95945050505050565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b031615610967576109616000356001600160e01b0319166107cc565b50610bdc565b337fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a15623c87613a98811061099b5761099b61457a565b01546201000090046001600160a01b0316148015610a33575060008051602061489f83398151915260020154604051633339a29360e11b8152600481018890526001600160a01b0390911690636673452690602401602060405180830381865afa158015610a0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a319190614590565b155b80610b1a575060007fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a15623c87613a988110610a6e57610a6e61457a565b01546201000090046001600160a01b031614801590610b1a5750336001600160a01b031660008051602061489f833981519152600201546040516355fd83e560e01b8152600481018990526001600160a01b03909116906355fd83e590602401602060405180830381865afa158015610aeb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0f91906145b2565b6001600160a01b0316145b610b505760405162461bcd60e51b815260206004820152600260248201526108a960f31b60448201526064015b60405180910390fd5b7fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a15623a546040516317224a6d60e01b81526001600160a01b03909116906317224a6d90610ba9908990899089908990899089906004016145f8565b600060405180830381600087803b158015610bc357600080fd5b505af1158015610bd7573d6000803e3d6000fd5b505050505b505050505050565b600260005403610c365760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b47565b600260009081556001600160e01b031981351681526000805160206148bf83398151915260205260409020546001600160a01b031615610c8b57610c856000356001600160e01b0319166107cc565b50610d5b565b610c96600080612f3a565b6000610ca4336000806131f4565b3360009081527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd66020526040902080546fffffffffffffffffffffffff00000000191690556001600160601b03169050610d1760008051602061489f833981519152546001600160a01b031683836134fc565b604080516001600160a01b0384168152602081018390527f106f923f993c2149d49b4255ff723acafa1f2d94393f561d3eda32ae348f7241910160405180910390a1505b506001600055565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b031615610dad576109616000356001600160e01b0319166107cc565b610dbc61ffff8316600161464e565b610dca9061ffff8516614661565b8461ffff161115610e025760405162461bcd60e51b815260206004820152600260248201526122a960f11b6044820152606401610b47565b60005b8581101561108b576000878783818110610e2157610e2161457a565b9050602002013590506000610e4160008051602061489f83398151915290565b60030182613a988110610e5657610e5661457a565b01805490915061ffff16600003610e945760405162461bcd60e51b8152602060048201526002602482015261454160f01b6044820152606401610b47565b3060008051602061489f833981519152600101546040516331a9108f60e11b8152600481018590526001600160a01b0390911690636352211e90602401602060405180830381865afa158015610eee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f1291906145b2565b6001600160a01b0316148015610f38575080546001600160a01b03620100009091041633145b610f695760405162461bcd60e51b8152602060048201526002602482015261453960f01b6044820152606401610b47565b60008051602061489f83398151915260020154604051633339a29360e11b8152600481018490526001600160a01b0390911690636673452690602401602060405180830381865afa158015610fc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fe69190614590565b156110185760405162461bcd60e51b815260206004820152600260248201526122a160f11b6044820152606401610b47565b805463ffffffff60b01b1916600160b01b61ffff8981169190910261ffff60c01b191691909117600160c01b88831602176001600160d01b0316600160d01b918716919091026001600160e01b031617600160e01b63ffffffff861602179055508061108381614678565b915050610e05565b50505050505050565b6002600054036110e65760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b47565b600260009081556001600160e01b031981351681526000805160206148bf83398151915260205260409020546001600160a01b03161561113b576111356000356001600160e01b0319166107cc565b50611563565b61114481613610565b306001600160a01b038216036111815760405162461bcd60e51b8152602060048201526002602482015261455360f01b6044820152606401610b47565b6000805b838110156115385760008585838181106111a1576111a161457a565b9050602002013590506111b13390565b6001600160a01b03167fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a15623c82613a9881106111ed576111ed61457a565b01546201000090046001600160a01b0316146112305760405162461bcd60e51b8152602060048201526002602482015261453960f01b6044820152606401610b47565b60008051602061489f83398151915260020154604051633339a29360e11b8152600481018390526001600160a01b0390911690636673452690602401602060405180830381865afa158015611289573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ad9190614590565b156112df5760405162461bcd60e51b815260206004820152600260248201526122a160f11b6044820152606401610b47565b60008051602061489f83398151915260010154604051632142170760e11b81523060048201526001600160a01b03868116602483015260448201849052909116906342842e0e90606401600060405180830381600087803b15801561134357600080fd5b505af1158015611357573d6000803e3d6000fd5b50505050600061137260008051602061489f83398151915290565b60030182613a9881106113875761138761457a565b015461ffff169050611399818561464e565b6040805160c08101825261ffff84168152600060208201819052918101829052606081018290526080810182905260a08101919091529094507fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a15623c83613a9881106114055761140561457a565b825191018054602084015160408501516060860151608087015160a09097015163ffffffff16600160e01b026001600160e01b0361ffff988916600160d01b02166001600160d01b03928916600160c01b0261ffff60c01b19948a16600160b01b029490941663ffffffff60b01b196001600160a01b03909616620100000275ffffffffffffffffffffffffffffffffffffffffffff1990971699909816989098179490941792909216949094179390931792909216929092171790556114f5826114db60008051602061489f83398151915290565b336000908152613a9e91909101602052604090209061378c565b50604051339083907ffc52eee0edb488f7e56636618794f0c0b30044b2f0e81b4242787d1feff50f9590600090a35050808061153090614678565b915050611185565b5061154c61154582613798565b6000612f3a565b6115603361155983613798565b60006131f4565b50505b5050600160005550565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a15623c82613a9881106115d2576115d261457a565b6040805160c081018252929091015461ffff80821684526001600160a01b03620100008304166020850152600160b01b8204811692840192909252600160c01b810482166060840152600160d01b8104909116608083015263ffffffff600160e01b9091041660a082015292915050565b61164b612eb2565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b031615611695576108a86000356001600160e01b0319166107cc565b6040516301ffc9a760e01b815263ddb05bc160e01b60048201526001600160a01b038216906301ffc9a790602401602060405180830381865afa1580156116e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117049190614590565b6117355760405162461bcd60e51b8152602060048201526002602482015261045360f41b6044820152606401610b47565b7fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a15623b80546001600160a01b0319166001600160a01b0392909216919091179055565b6002600054036117c85760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b47565b600260009081556001600160e01b031981351681526000805160206148bf83398151915260205260409020546001600160a01b03161561181d576118176000356001600160e01b0319166107cc565b50611dec565b61182c61ffff8616600161464e565b61183a9061ffff8816614661565b8761ffff1611156118725760405162461bcd60e51b815260206004820152600260248201526122a960f11b6044820152606401610b47565b8a89146118a65760405162461bcd60e51b8152602060048201526002602482015261229b60f11b6044820152606401610b47565b8263ffffffff164211156118e15760405162461bcd60e51b815260206004820152600260248201526108ab60f31b6044820152606401610b47565b61191e8c8c8c8c33883060405160200161190197969594939291906146dc565b604051602081830303815290604052805190602001208383613818565b61194f5760405162461bcd60e51b8152602060048201526002602482015261453760f01b6044820152606401610b47565b61195888613610565b306001600160a01b038916036119955760405162461bcd60e51b8152602060048201526002602482015261455360f01b6044820152606401610b47565b6000805b8c811015611dc15760008e8e838181106119b5576119b561457a565b90506020020135905060006119d560008051602061489f83398151915290565b60030182613a9881106119ea576119ea61457a565b015461ffff169050801580611a1657508d8d84818110611a0c57611a0c61457a565b9050602002013581145b611a475760405162461bcd60e51b815260206004820152600260248201526108a760f31b6044820152606401610b47565b336001600160a01b031660008051602061489f833981519152600101546040516331a9108f60e11b8152600481018590526001600160a01b0390911690636352211e90602401602060405180830381865afa158015611aaa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ace91906145b2565b6001600160a01b031614611b095760405162461bcd60e51b8152602060048201526002602482015261453960f01b6044820152606401610b47565b60008051602061489f833981519152600101546001600160a01b03166342842e0e336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015230602482015260448101859052606401600060405180830381600087803b158015611b7957600080fd5b505af1158015611b8d573d6000803e3d6000fd5b50506040516001600160a01b038f1692508491507f7536c5f8fc3c7e1e44540eb857fb8c7c98a2b91016ee9b65a0969f8630d84cbe90600090a350506040518060c00160405280611bf58e8e85818110611be957611be961457a565b905060200201356138a3565b61ffff1681526020018b6001600160a01b031681526020018a61ffff1681526020018961ffff1681526020018861ffff1681526020018763ffffffff16815250611c4a60008051602061489f83398151915290565b6003018f8f84818110611c5f57611c5f61457a565b90506020020135613a988110611c7757611c7761457a565b825191018054602084015160408501516060860151608087015160a09097015163ffffffff16600160e01b026001600160e01b0361ffff988916600160d01b02166001600160d01b03928916600160c01b0261ffff60c01b19948a16600160b01b029490941663ffffffff60b01b196001600160a01b03909616620100000275ffffffffffffffffffffffffffffffffffffffffffff199097169990981698909817949094179290921694909417939093179290921692909217179055611d888e8e83818110611d4957611d4961457a565b90506020020135611d6560008051602061489f83398151915290565b6001600160a01b038d166000908152613a9e919091016020526040902090613906565b508b8b82818110611d9b57611d9b61457a565b9050602002013582611dad919061464e565b915080611db981614678565b915050611999565b50611dd5611dce82613798565b6001612f3a565b611de989611de283613798565b60016131f4565b50505b5050600160005550505050505050505050565b611e07612eb2565b6001600160e01b03199190911660009081526000805160206148bf8339815191526020526040902080546001600160a01b0319166001600160a01b03909216919091179055565b611e56612eb2565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b031615611ea0576108a86000356001600160e01b0319166107cc565b7fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd880546001600160a01b0319166001600160a01b0392909216919091179055565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b031615611f3057611f2b6000356001600160e01b0319166107cc565b505050565b60007fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a15623c83613a988110611f6557611f6561457a565b01805490915061ffff16600003611fa35760405162461bcd60e51b8152602060048201526002602482015261454160f01b6044820152606401610b47565b3060008051602061489f833981519152600101546040516331a9108f60e11b8152600481018690526001600160a01b0390911690636352211e90602401602060405180830381865afa158015611ffd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061202191906145b2565b6001600160a01b0316148015612047575080546001600160a01b03620100009091041633145b6120785760405162461bcd60e51b8152602060048201526002602482015261453960f01b6044820152606401610b47565b80546001600160e01b0316600160e01b63ffffffff8416021790555050565b61209f612eb2565b6120a96000613912565b565b6120b3612eb2565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b031615612103576120fd6000356001600160e01b0319166107cc565b50612233565b8281146121375760405162461bcd60e51b8152602060048201526002602482015261229b60f11b6044820152606401610b47565b60005b838110156122315760008585838181106121565761215661457a565b90506020020135905061217460008051602061489f83398151915290565b60030181613a9881106121895761218961457a565b015461ffff16156121c15760405162461bcd60e51b815260206004820152600260248201526108a760f31b6044820152606401610b47565b6121d6848484818110611be957611be961457a565b7fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a15623c82613a9881106122095761220961457a565b01805461ffff191661ffff92909216919091179055508061222981614678565b91505061213a565b505b50505050565b612241612eb2565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b031615611735576108a86000356001600160e01b0319166107cc565b604080516080810182527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd55463ffffffff80821683526001600160601b036401000000008084048216602080870191909152600160801b808604851687890152600160a01b90950483166060808801919091526001600160a01b03891660009081527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd6835288812089519283018a525495861682529285048416918101919091529390920416938201939093528261239a61236542613798565b7fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd454640100000000900463ffffffff16613983565b905060008360400151826123ae9190614736565b63ffffffff169050801561242457835163ffffffff161561242457835160608501516124159163ffffffff16906123ee906001600160601b031684614661565b6123f89190614753565b85602001516001600160601b0316612410919061464e565b6139a5565b6001600160601b031660208501525b826040015184602001516124389190614775565b835161244a919063ffffffff16614795565b836020015161245991906147c0565b6001600160601b03169695505050505050565b612474612eb2565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b0316156124be576108a86000356001600160e01b0319166107cc565b60008051602061489f83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6124f5612eb2565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b03161561253f576122336000356001600160e01b0319166107cc565b8163ffffffff168363ffffffff1611156125805760405162461bcd60e51b8152602060048201526002602482015261453160f01b6044820152606401610b47565b666a94d74f430000816001600160601b03161180156125b057506801a055690d9db80000816001600160601b0316105b6125e15760405162461bcd60e51b8152602060048201526002602482015261229960f11b6044820152606401610b47565b60008051602061489f833981519152546001600160a01b031661262b5760405162461bcd60e51b8152602060048201526002602482015261453360f01b6044820152606401610b47565b7fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd45463ffffffff1661265c42613798565b63ffffffff1610806126aa57507fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd454640100000000900463ffffffff166126a242613798565b63ffffffff16115b6126db5760405162461bcd60e51b8152602060048201526002602482015261114d60f21b6044820152606401610b47565b7fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd4805467ffffffffffffffff191663ffffffff858116918217640100000000918616918202179092557fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd580546fffffffffffffffffffffffffffffffff16600160801b83026001600160a01b031617600160a01b6001600160601b038616908102919091179091556040805192835260208301939093528183015290517f95efd8a2a0aa591f48fd9673cf5d13c2150ca7a1fe1cbe438dd3f0ae47064663916060908290030190a1505050565b60026000540361281a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b47565b600260009081556001600160e01b031981351681526000805160206148bf83398151915260205260409020546001600160a01b03161561286f576128696000356001600160e01b0319166107cc565b50612cd1565b61287e61ffff8316600161464e565b61288c9061ffff8516614661565b8461ffff1611156128c45760405162461bcd60e51b815260206004820152600260248201526122a960f11b6044820152606401610b47565b6128cd85613610565b306001600160a01b0386160361290a5760405162461bcd60e51b8152602060048201526002602482015261455360f01b6044820152606401610b47565b6000805b87811015612cb457600089898381811061292a5761292a61457a565b905060200201359050600061294a60008051602061489f83398151915290565b60030182613a98811061295f5761295f61457a565b015461ffff169050600081900361299d5760405162461bcd60e51b8152602060048201526002602482015261454160f01b6044820152606401610b47565b336001600160a01b031660008051602061489f833981519152600101546040516331a9108f60e11b8152600481018590526001600160a01b0390911690636352211e90602401602060405180830381865afa158015612a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2491906145b2565b6001600160a01b031614612a5f5760405162461bcd60e51b8152602060048201526002602482015261453960f01b6044820152606401610b47565b60008051602061489f833981519152600101546001600160a01b03166342842e0e336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015230602482015260448101859052606401600060405180830381600087803b158015612acf57600080fd5b505af1158015612ae3573d6000803e3d6000fd5b505050508061ffff1684612af7919061464e565b93506040518060c001604052808261ffff1681526020018a6001600160a01b031681526020018961ffff1681526020018861ffff1681526020018761ffff1681526020018663ffffffff16815250612b5a60008051602061489f83398151915290565b60030183613a988110612b6f57612b6f61457a565b825191018054602084015160408501516060860151608087015160a09097015163ffffffff16600160e01b026001600160e01b0361ffff988916600160d01b02166001600160d01b03928916600160c01b0261ffff60c01b19948a16600160b01b029490941663ffffffff60b01b196001600160a01b03909616620100000275ffffffffffffffffffffffffffffffffffffffffffff199097169990981698909817949094179290921694909417939093179290921692909217179055612c6882612c4560008051602061489f83398151915290565b6001600160a01b038c166000908152613a9e919091016020526040902090613906565b506040516001600160a01b038a169083907f7536c5f8fc3c7e1e44540eb857fb8c7c98a2b91016ee9b65a0969f8630d84cbe90600090a350508080612cac90614678565b91505061290e565b50612cc1611dce82613798565b612cce86611de283613798565b50505b505060016000555050505050565b612ce7612eb2565b6001600160a01b038116612d635760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610b47565b6108e781613912565b6001600160a01b03811660009081527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd76020526040812060609190612db090613a0d565b905060008167ffffffffffffffff811115612dcd57612dcd6147e0565b604051908082528060200260200182016040528015612df6578160200160208202803683370190505b50905060005b82811015612e74576001600160a01b03851660009081527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd760205260409020612e459082613a17565b828281518110612e5757612e5761457a565b602090810291909101015280612e6c81614678565b915050612dfc565b509392505050565b60008051602061489f83398151915290565b7f2964b7e756c43d7fc626c76da5b94aa9f7f497362e81c25e47dc710c9dbd2bc690565b33612ee47f2964b7e756c43d7fc626c76da5b94aa9f7f497362e81c25e47dc710c9dbd2bc6546001600160a01b031690565b6001600160a01b0316146120a95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b47565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b031615612f8457611f2b6000356001600160e01b0319166107cc565b604080516080810182527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd55463ffffffff80821683526401000000008083046001600160601b03908116602080870191909152600160801b8504841686880152600160a01b90940416606085015284518086019095527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd4548083168087529190049091169184019190915290919061303b42613798565b63ffffffff16106130d157600061305e61305442613798565b8360200151613983565b905060008360400151826130729190614736565b63ffffffff16905080156130ce57835163ffffffff16156130c157835160608501516130b29163ffffffff16906123ee906001600160601b031684614661565b6001600160601b031660208501525b63ffffffff821660408501525b50505b82156130f75783826000018181516130e991906147f6565b63ffffffff16905250613113565b83826000018181516131099190614736565b63ffffffff169052505b81517fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd5805460208086015160408088015160608901516001600160601b03908116600160a01b026001600160a01b0363ffffffff938416600160801b02166fffffffffffffffffffffffffffffffff9290951664010000000081026fffffffffffffffffffffffffffffffff199098169390991692909217959095179490941691909117929092179092558051928352517faac1802288db8019f8ec43430efc11a152c72473c57d6ddcde3b6dd0c89260679281900390910190a150505050565b600080356001600160e01b03191681526000805160206148bf83398151915260205260408120546001600160a01b0316156132445761323e6000356001600160e01b0319166107cc565b506134f5565b6001600160a01b03841660009081527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd66020908152604091829020825160608082018552915463ffffffff80821683526401000000008083046001600160601b0390811685880152600160801b9384900481168589019081528851608081018a527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd5548086168252938404831698810189905294830490931697840197909752600160a01b900490951692810192909252925190916133239190614775565b8251613335919063ffffffff16614795565b826020015161334491906147c0565b6001600160601b0390811660208085019190915282015116604083015263ffffffff85161561340257831561339357848260000181815161338591906147f6565b63ffffffff169052506133af565b84826000018181516133a59190614736565b63ffffffff169052505b60408051851515815263ffffffff87166020820152428183015290516001600160a01b038816917fb1de227711aba68cec92891ccaabad9474a3f417d166ca8f57e7d616f467d343919081900360600190a25b6001600160a01b03861660008181527fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd660209081526040918290208551815483880151858901516001600160601b03908116600160801b81027fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff9290931664010000000081026fffffffffffffffffffffffffffffffff1990951663ffffffff9096169590951793909317161790925583519485529184019190915282820152517f5b9aaf4cc5141c090a75f8b8a627863eba92df81f0c83c096350da9b79aedd049181900360600190a1506020015190505b9392505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916135589190614813565b6000604051808303816000865af19150503d8060008114613595576040519150601f19603f3d011682016040523d82523d6000602084013e61359a565b606091505b50915091508180156135c45750805115806135c45750808060200190518101906135c49190614590565b6122315760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610b47565b600080356001600160e01b03191681526000805160206148bf83398151915260205260409020546001600160a01b03161561365a576108a86000356001600160e01b0319166107cc565b803b63ffffffff8116156108a857604051630a85bd0160e11b8152306004820181905260248201526000604482018190526080606483015260848201526001600160a01b0383169063150b7a029060a4016020604051808303816000875af19250505080156136e6575060408051601f3d908101601f191682019092526136e391810190614842565b60015b613747573d808015613714576040519150601f19603f3d011682016040523d82523d6000602084013e613719565b606091505b5060405162461bcd60e51b8152602060048201526002602482015261115560f21b6044820152606401610b47565b6001600160e01b03198116630a85bd0160e11b14611f2b5760405162461bcd60e51b8152602060048201526002602482015261115560f21b6044820152606401610b47565b60006134f58383613a23565b600063ffffffff8211156138145760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201527f32206269747300000000000000000000000000000000000000000000000000006064820152608401610b47565b5090565b7fbae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a159cd854604080516020601f85018190048102820181019092528381526000926001600160a01b0316916138919190869086908190840183828082843760009201919091525061388b9250899150613b1d9050565b90613b70565b6001600160a01b031614949350505050565b600061ffff8211156138145760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203160448201526536206269747360d01b6064820152608401610b47565b60006134f58383613b8c565b7f2964b7e756c43d7fc626c76da5b94aa9f7f497362e81c25e47dc710c9dbd2bc680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60008163ffffffff168363ffffffff161061399e57816134f5565b5090919050565b60006001600160601b038211156138145760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201526536206269747360d01b6064820152608401610b47565b6000610850825490565b60006134f58383613bdb565b60008181526001830160205260408120548015613b0c576000613a4760018361485f565b8554909150600090613a5b9060019061485f565b9050818114613ac0576000866000018281548110613a7b57613a7b61457a565b9060005260206000200154905080876000018481548110613a9e57613a9e61457a565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613ad157613ad1614872565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610850565b6000915050610850565b5092915050565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b6000806000613b7f8585613c05565b91509150612e7481613c73565b6000818152600183016020526040812054613bd357508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610850565b506000610850565b6000826000018281548110613bf257613bf261457a565b9060005260206000200154905092915050565b6000808251604103613c3b5760208301516040840151606085015160001a613c2f87828585613e29565b94509450505050613c6c565b8251604003613c645760208301516040840151613c59868383613f16565b935093505050613c6c565b506000905060025b9250929050565b6000816004811115613c8757613c87614888565b03613c8f5750565b6001816004811115613ca357613ca3614888565b03613cf05760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610b47565b6002816004811115613d0457613d04614888565b03613d515760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610b47565b6003816004811115613d6557613d65614888565b03613dbd5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610b47565b6004816004811115613dd157613dd1614888565b036108e75760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610b47565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115613e605750600090506003613f0d565b8460ff16601b14158015613e7857508460ff16601c14155b15613e895750600090506004613f0d565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015613edd573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116613f0657600060019250925050613f0d565b9150600090505b94509492505050565b6000807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831681613f4c60ff86901c601b61464e565b9050613f5a87828885613e29565b935093505050935093915050565b6001600160e01b0319811681146108e757600080fd5b600060208284031215613f9057600080fd5b81356134f581613f68565b6001600160a01b03811681146108e757600080fd5b8035613fbb81613f9b565b919050565b600060208284031215613fd257600080fd5b81356134f581613f9b565b60008083601f840112613fef57600080fd5b50813567ffffffffffffffff81111561400757600080fd5b602083019150836020828501011115613c6c57600080fd5b60008060008060006080868803121561403757600080fd5b853561404281613f9b565b9450602086013561405281613f9b565b935060408601359250606086013567ffffffffffffffff81111561407557600080fd5b61408188828901613fdd565b969995985093965092949392505050565b600080600080600080608087890312156140ab57600080fd5b86359550602087013567ffffffffffffffff808211156140ca57600080fd5b6140d68a838b01613fdd565b90975095506040890135945060608901359150808211156140f657600080fd5b5061410389828a01613fdd565b979a9699509497509295939492505050565b60008083601f84011261412757600080fd5b50813567ffffffffffffffff81111561413f57600080fd5b6020830191508360208260051b8501011115613c6c57600080fd5b803561ffff81168114613fbb57600080fd5b803563ffffffff81168114613fbb57600080fd5b60008060008060008060a0878903121561419957600080fd5b863567ffffffffffffffff8111156141b057600080fd5b6141bc89828a01614115565b90975095506141cf90506020880161415a565b93506141dd6040880161415a565b92506141eb6060880161415a565b91506141f96080880161416c565b90509295509295509295565b60008060006040848603121561421a57600080fd5b833567ffffffffffffffff81111561423157600080fd5b61423d86828701614115565b909450925050602084013561425181613f9b565b809150509250925092565b60006020828403121561426e57600080fd5b5035919050565b6000806000806000806000806000806000806101208d8f03121561429857600080fd5b67ffffffffffffffff8d3511156142ae57600080fd5b6142bb8e8e358f01614115565b909c509a5067ffffffffffffffff60208e013511156142d957600080fd5b6142e98e60208f01358f01614115565b909a5098506142fa60408e01613fb0565b975061430860608e0161415a565b965061431660808e0161415a565b955061432460a08e0161415a565b945061433260c08e0161416c565b935061434060e08e0161416c565b925067ffffffffffffffff6101008e0135111561435c57600080fd5b61436d8e6101008f01358f01613fdd565b81935080925050509295989b509295989b509295989b565b6000806040838503121561439857600080fd5b82356143a381613f68565b915060208301356143b381613f9b565b809150509250929050565b600080604083850312156143d157600080fd5b823591506143e16020840161416c565b90509250929050565b6000806000806040858703121561440057600080fd5b843567ffffffffffffffff8082111561441857600080fd5b61442488838901614115565b9096509450602087013591508082111561443d57600080fd5b5061444a87828801614115565b95989497509550505050565b60008060006060848603121561446b57600080fd5b6144748461416c565b92506144826020850161416c565b915060408401356001600160601b038116811461425157600080fd5b600080600080600080600060c0888a0312156144b957600080fd5b873567ffffffffffffffff8111156144d057600080fd5b6144dc8a828b01614115565b90985096505060208801356144f081613f9b565b94506144fe6040890161415a565b935061450c6060890161415a565b925061451a6080890161415a565b915061452860a0890161416c565b905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b8181101561456e57835183529284019291840191600101614552565b50909695505050505050565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156145a257600080fd5b815180151581146134f557600080fd5b6000602082840312156145c457600080fd5b81516134f581613f9b565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b8681526080602082015260006146126080830187896145cf565b856040840152828103606084015261462b8185876145cf565b9998505050505050505050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561085057610850614638565b808202811582820484141761085057610850614638565b60006001820161468a5761468a614638565b5060010190565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156146c357600080fd5b8260051b80836020870137939093016020019392505050565b60a0815260006146f060a08301898b614691565b828103602084015261470381888a614691565b6001600160a01b03968716604085015263ffffffff95909516606084015250509216608090920191909152949350505050565b63ffffffff828116828216039080821115613b1657613b16614638565b60008261477057634e487b7160e01b600052601260045260246000fd5b500490565b6001600160601b03828116828216039080821115613b1657613b16614638565b6001600160601b038181168382160280821691908281146147b8576147b8614638565b505092915050565b6001600160601b03818116838216019080821115613b1657613b16614638565b634e487b7160e01b600052604160045260246000fd5b63ffffffff818116838216019080821115613b1657613b16614638565b6000825160005b81811015614834576020818601810151858301520161481a565b506000920191825250919050565b60006020828403121561485457600080fd5b81516134f581613f68565b8181038181111561085057610850614638565b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052602160045260246000fdfebae811979e977556ab990fceef6abee72bd3547b44420fd648f4e3b87a156239465c35ad1d12a6f76ffabe3e9eca16a7f4fd728d9969a9386eb4f7d2c55ac80da26469706673582212208614dd274a93e6c702cade7fb2b85b354d97c2643af8679054d245a9368fc2a664736f6c63430008120033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ccccb68e1a848cbdb5b60a974e07aae143ed40c300000000000000000000000005745e72fb8b4a9b51118a168d956760e4a36444
-----Decoded View---------------
Arg [0] : _rewardTokenAddress (address): 0xcccCb68e1A848CBDB5b60a974E07aAE143ed40C3
Arg [1] : _avatars (address): 0x05745e72fB8b4a9b51118A168D956760e4a36444
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000ccccb68e1a848cbdb5b60a974e07aae143ed40c3
Arg [1] : 00000000000000000000000005745e72fb8b4a9b51118a168d956760e4a36444
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $0.013228 | 1,091,532.3274 | $14,438.81 |
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.