Overview
APE Balance
APE Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Multichain Info
Latest 25 from a total of 8,104 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Set Approval For... | 32753922 | 11 hrs ago | IN | 0 APE | 0.00269713 | ||||
| Set Approval For... | 32735100 | 19 hrs ago | IN | 0 APE | 0.00491666 | ||||
| Safe Transfer Fr... | 32653691 | 2 days ago | IN | 0 APE | 0.00668004 | ||||
| Set Approval For... | 32653499 | 2 days ago | IN | 0 APE | 0.00491666 | ||||
| Safe Transfer Fr... | 32642499 | 3 days ago | IN | 0 APE | 0.00667994 | ||||
| Set Approval For... | 32602841 | 4 days ago | IN | 0 APE | 0.0049252 | ||||
| Safe Transfer Fr... | 32600314 | 4 days ago | IN | 0 APE | 0.00494127 | ||||
| Safe Transfer Fr... | 32600291 | 4 days ago | IN | 0 APE | 0.00716812 | ||||
| Set Approval For... | 32596653 | 4 days ago | IN | 0 APE | 0.00491666 | ||||
| Set Approval For... | 32581336 | 4 days ago | IN | 0 APE | 0.00491666 | ||||
| Set Approval For... | 32575179 | 4 days ago | IN | 0 APE | 0.0049252 | ||||
| Set Approval For... | 32572191 | 4 days ago | IN | 0 APE | 0.00269713 | ||||
| Set Approval For... | 32547892 | 5 days ago | IN | 0 APE | 0.0049252 | ||||
| Set Approval For... | 32538408 | 5 days ago | IN | 0 APE | 0.00491666 | ||||
| Set Approval For... | 32524813 | 6 days ago | IN | 0 APE | 0.00491666 | ||||
| Set Approval For... | 32504102 | 6 days ago | IN | 0 APE | 0.00491666 | ||||
| Safe Transfer Fr... | 32503066 | 6 days ago | IN | 0 APE | 0.00668004 | ||||
| Set Approval For... | 32475100 | 7 days ago | IN | 0 APE | 0.0049252 | ||||
| Set Approval For... | 32471811 | 7 days ago | IN | 0 APE | 0.00491666 | ||||
| Set Approval For... | 32456430 | 7 days ago | IN | 0 APE | 0.00491666 | ||||
| Set Approval For... | 32443510 | 8 days ago | IN | 0 APE | 0.00491666 | ||||
| Set Approval For... | 32438635 | 8 days ago | IN | 0 APE | 0.00491666 | ||||
| Set Approval For... | 32438411 | 8 days ago | IN | 0 APE | 0.00491666 | ||||
| Set Approval For... | 32437651 | 8 days ago | IN | 0 APE | 0.00491666 | ||||
| Set Approval For... | 32425459 | 8 days ago | IN | 0 APE | 0.00491666 |
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 32047669 | 18 days ago | 3 APE | ||||
| 32047669 | 18 days ago | 9 APE | ||||
| 32047664 | 18 days ago | 3 APE | ||||
| 32047664 | 18 days ago | 9 APE | ||||
| 32047662 | 18 days ago | 3 APE | ||||
| 32047662 | 18 days ago | 9 APE | ||||
| 32047647 | 18 days ago | 3 APE | ||||
| 32047647 | 18 days ago | 9 APE | ||||
| 32047624 | 18 days ago | 3 APE | ||||
| 32047624 | 18 days ago | 9 APE | ||||
| 32047621 | 18 days ago | 3 APE | ||||
| 32047621 | 18 days ago | 9 APE | ||||
| 32047619 | 18 days ago | 3 APE | ||||
| 32047619 | 18 days ago | 9 APE | ||||
| 32047618 | 18 days ago | 3 APE | ||||
| 32047618 | 18 days ago | 9 APE | ||||
| 32047605 | 18 days ago | 3 APE | ||||
| 32047605 | 18 days ago | 9 APE | ||||
| 32047598 | 18 days ago | 3 APE | ||||
| 32047598 | 18 days ago | 9 APE | ||||
| 32047585 | 18 days ago | 3 APE | ||||
| 32047585 | 18 days ago | 9 APE | ||||
| 32047582 | 18 days ago | 3 APE | ||||
| 32047582 | 18 days ago | 9 APE | ||||
| 32047579 | 18 days ago | 3 APE |
Cross-Chain Transactions
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Royalty.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/interfaces/IERC2981.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "../src/libs/SaleTimeAndPrice.sol";
import "../src/libs/Treasury.sol";
/**
* @title EspNFT — ERC721 with role-restricted minting, base-IPFS tokenImage token generation and onchain metadata.
* @notice Minting restricted to espHypErc20 caller.
* @dev Uses OpenZeppelin ERC721 + AccessControl
*/
contract EspNFT is ERC721, SaleTimeAndPrice, Treasury, AccessControl, IERC2981 {
using Strings for uint256;
using Strings for string;
bytes32 public constant PRICE_ADMIN_ROLE = keccak256("PRICE_ADMIN_ROLE");
address public espHypErc20;
address public royaltyReceiver;
uint96 public royaltyFeeNumerator;
uint96 public constant DEFAULT_ROYALTY_BPS = 500; // 5%
uint256 public lastTokenId;
string private baseImageURI;
string private chainName;
mapping(uint256 tokenId => uint256 machineType) public machineTypes;
event TokenMinted(address indexed to, uint256 indexed tokenId, uint256 machineType);
event BaseImageUriChanged(string oldBaseImageUri, string newBaseImageUri);
event TreasurySet(address treasuryAddress);
event NativeBuy(address to, uint256 tokenId, uint256 price);
event DefaultRoyaltySet(address indexed receiver, uint96 feeNumerator);
event DefaultRoyaltyDeleted();
error NftPriceExceedsMsgValue(uint256 nftPrice, uint256 msgValue);
error UriQueryNotExist(uint256 tokenId);
error CallerIsNotAnTokenOwnerOrApproved(address caller, uint256 tokenId);
error TreasuryPaymentFailed(address treasury);
error RoyaltyFeeTooHigh();
constructor(
string memory _name,
string memory _symbol,
string memory _baseImageURI,
string memory _chainName,
address _espHypErc20,
address _priceAdmin,
TreasuryConfig memory _treasury,
uint256 _nftSalePrice,
uint256 _startSale,
uint256 _endSale
) ERC721(_name, _symbol) SaleTimeAndPrice(_startSale, _endSale, _nftSalePrice) {
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
_setupRole(PRICE_ADMIN_ROLE, _priceAdmin);
baseImageURI = _baseImageURI;
chainName = _chainName;
espHypErc20 = _espHypErc20;
_setTreasury(_treasury);
_setDefaultRoyalty(_treasury.espresso, DEFAULT_ROYALTY_BPS);
}
/**
* @notice Mint token on 'to' address
* If caller is not EspHypERC20 (not xchain mint) we charge caller
* to pay for NFT in native currency in the same chain.
* Sale is only open during 3 weeks after sale starts.
* @dev Only espHypErc20 contract allowed to call without native currency payment.
*/
function mint(address to) external payable {
bool xChainMint = msg.sender == espHypErc20;
uint256 tokenId = ++lastTokenId;
if (!xChainMint) _nativeBuy(to, tokenId);
uint256 machineType = _generateMachineType(tokenId);
_safeMint(to, tokenId);
emit TokenMinted(to, tokenId, machineType);
}
/**
* @notice Set base image URI (e.g. "ipfs://Qm.../") — imageUrl will be baseImageURI + machineTheme + .png
* @dev Only DEFAULT_ADMIN_ROLE can change
*/
function setBaseImageUri(string calldata newImageURI) external onlyRole(DEFAULT_ADMIN_ROLE) {
string memory old = baseImageURI;
baseImageURI = newImageURI;
emit BaseImageUriChanged(old, baseImageURI);
}
function setSalePrice(uint256 _nftSalePrice) external onlyRole(PRICE_ADMIN_ROLE) {
_setPrice(_nftSalePrice);
}
function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal {
if (receiver == address(0)) revert ZeroAddress();
if (feeNumerator > ONE_HUNDRED_PERCENT) revert RoyaltyFeeTooHigh();
royaltyReceiver = receiver;
royaltyFeeNumerator = feeNumerator;
emit DefaultRoyaltySet(receiver, feeNumerator);
}
function setDefaultRoyalty(address receiver, uint96 feeNumerator) external onlyRole(PRICE_ADMIN_ROLE) {
if (receiver == address(0)) revert ZeroAddress();
_setDefaultRoyalty(receiver, feeNumerator);
emit DefaultRoyaltySet(receiver, feeNumerator);
}
/**
* @notice tokenURI returns composed metadata json NFT.
* ===========================
* tokenURI management and generation
* ===========================
*/
function tokenURI(uint256 tokenId) public view override returns (string memory) {
if (!_exists(tokenId)) revert UriQueryNotExist(tokenId);
if (bytes(baseImageURI).length == 0) {
return string(abi.encodePacked(tokenId.toString()));
}
string memory machineTheme = _getMachineTheme(tokenId);
// Image URL example "ipfs://img123abc/Future.png"
string memory imageURL = string(abi.encodePacked(baseImageURI, machineTheme, ".png"));
// Compose the metadata JSON
string memory json = string(
abi.encodePacked(
"{",
'"name": "',
chainName,
" Espresso Machine #",
tokenId.toString(),
'","description": "Mint across chains without bridging with Presto. Powered by Espresso, ApeChain, and RARI Chain to showcase seamless, composable NFT minting.","image": "',
imageURL,
'","attributes": [{ "trait_type": "Theme", "value": "',
machineTheme,
'" }]}'
)
);
// Encode JSON to base64 for full ERC721 compliance
return string(abi.encodePacked("data:application/json;utf8,", json));
}
// @notice Burn token (owner or approved)
function burn(uint256 tokenId) external {
if (!_isApprovedOrOwner(msg.sender, tokenId)) revert CallerIsNotAnTokenOwnerOrApproved(msg.sender, tokenId);
_burn(tokenId);
}
function _generateMachineType(uint256 tokenId) internal returns (uint256) {
uint8 machineType = uint8((uint256(keccak256(abi.encodePacked(block.timestamp, msg.sender, tokenId))) % 5) + 1);
machineTypes[tokenId] = machineType;
return machineType;
}
function _nativeBuy(address to, uint256 tokenId) internal whenSaleOpen {
if (msg.value != nftSalePriceWei) revert NftPriceExceedsMsgValue(nftSalePriceWei, msg.value);
uint256 mainAmount = nftSalePriceWei * treasury.percentageEspresso / ONE_HUNDRED_PERCENT;
(bool success,) = treasury.espresso.call{value: mainAmount}("");
if (!success) revert TreasuryPaymentFailed(treasury.espresso);
if (treasury.percentageEspresso != ONE_HUNDRED_PERCENT) {
(success,) = treasury.partner.call{value: nftSalePriceWei - mainAmount}("");
if (!success) revert TreasuryPaymentFailed(treasury.partner);
}
emit NativeBuy(to, tokenId, nftSalePriceWei);
}
function _getMachineTheme(uint256 tokenId) internal view returns (string memory) {
uint256 machineType = machineTypes[tokenId];
if (machineType == 1) {
return "Future";
} else if (machineType == 2) {
return "Classic";
} else if (machineType == 3) {
return "Industrial";
} else if (machineType == 4) {
return "Organic";
} else {
return "Mythic";
}
}
// @dev the first parameter is the tokenId, but we don't use it here
// @dev the second parameter is the salePrice
// @dev returns the royalty receiver and the royalty amount
function royaltyInfo(uint256, uint256 salePrice)
external
view
override
returns (address receiver, uint256 royaltyAmount)
{
return (royaltyReceiver, (salePrice * royaltyFeeNumerator) / ONE_HUNDRED_PERCENT);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, AccessControl, IERC165)
returns (bool)
{
if (interfaceId == type(IERC2981).interfaceId) {
return true;
}
if (interfaceId == type(IERC165).interfaceId) {
return true;
}
if (interfaceId == type(IERC721).interfaceId) {
return true;
}
if (interfaceId == type(IAccessControl).interfaceId) {
return true;
}
return super.supportsInterface(interfaceId);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/ERC721Royalty.sol)
pragma solidity ^0.8.0;
import "../ERC721.sol";
import "../../common/ERC2981.sol";
import "../../../utils/introspection/ERC165.sol";
/**
* @dev Extension of ERC721 with the ERC2981 NFT Royalty Standard, a standardized way to retrieve royalty payment
* information.
*
* Royalty information can be specified globally for all token ids via {ERC2981-_setDefaultRoyalty}, and/or individually for
* specific token ids via {ERC2981-_setTokenRoyalty}. The latter takes precedence over the first.
*
* IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
* https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to
* voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
*
* _Available since v4.5._
*/
abstract contract ERC721Royalty is ERC2981, ERC721 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC2981) returns (bool) {
return super.supportsInterface(interfaceId);
}
/**
* @dev See {ERC721-_burn}. This override additionally clears the royalty information for the token.
*/
function _burn(uint256 tokenId) internal virtual override {
super._burn(tokenId);
_resetTokenRoyalty(tokenId);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with a standardized message including the required role.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*
* _Available since v4.1._
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
return _roles[role].members[account];
}
/**
* @dev Revert with a standard message if `_msgSender()` is missing `role`.
* Overriding this function changes the behavior of the {onlyRole} modifier.
*
* Format of the revert message is described in {_checkRole}.
*
* _Available since v4.6._
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Revert with a standard message if `account` is missing `role`.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(account),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* May emit a {RoleGranted} event.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
* up the initial roles for the system.
*
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*
* NOTE: This function is deprecated in favor of {_grantRole}.
*/
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Grants `role` to `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
/**
* @dev Revokes `role` from `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
import "./math/Math.sol";
import "./math/SignedMath.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toString(int256 value) internal pure returns (string memory) {
return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return keccak256(bytes(a)) == keccak256(bytes(b));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC2981.sol)
pragma solidity ^0.8.0;
import "../utils/introspection/IERC165.sol";
/**
* @dev Interface for the NFT Royalty Standard.
*
* A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
* support for royalty payments across all NFT marketplaces and ecosystem participants.
*
* _Available since v4.5._
*/
interface IERC2981 is IERC165 {
/**
* @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
* exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
*/
function royaltyInfo(
uint256 tokenId,
uint256 salePrice
) external view returns (address receiver, uint256 royaltyAmount);
}// 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;
}
}pragma solidity 0.8.30;
abstract contract SaleTimeAndPrice {
uint256 public constant MIN_PRICE_WEI = 1000; // 0,000001 ETH
uint256 public startSale;
uint256 public endSale;
uint256 public nftSalePriceWei;
// Commented out: allows redeployment after sale start date has passed (sale starts immediately)
// error StartDateInPastNotAllowed(uint256 startSale, uint256 currentTime);
error EndDateLessThanStartDateNotAllowed(uint256 startSale, uint256 endSale);
error SaleFinishedOrNotStarted(uint256 startSale, uint256 endSale, uint256 currentTime);
error LowPriceInWei(uint256 minPriceWei, uint256 nftSalePriceWei);
event SaleTimelinesSet(uint256 startSale, uint256 endSale);
event NftSalePriceSet(uint256 price);
modifier whenSaleOpen() {
if (!isSaleOpen()) revert SaleFinishedOrNotStarted(startSale, endSale, block.timestamp);
_;
}
constructor(uint256 _startSale, uint256 _endSale, uint256 _nftSalePriceWei) {
_setSaleTimelines(_startSale, _endSale);
_setPrice(_nftSalePriceWei);
}
function _setSaleTimelines(uint256 _startSale, uint256 _endSale) internal {
// Commented out: allows redeployment after sale start date has passed (sale starts immediately)
// if (_startSale < block.timestamp) revert StartDateInPastNotAllowed(_startSale, block.timestamp);
if (_endSale <= _startSale) revert EndDateLessThanStartDateNotAllowed(_startSale, _endSale);
startSale = _startSale;
endSale = _endSale;
emit SaleTimelinesSet(startSale, endSale);
}
function _setPrice(uint256 _nftSalePriceWei) internal {
if (_nftSalePriceWei < MIN_PRICE_WEI) revert LowPriceInWei(MIN_PRICE_WEI, _nftSalePriceWei);
nftSalePriceWei = _nftSalePriceWei;
emit NftSalePriceSet(_nftSalePriceWei);
}
function isSaleOpen() public view returns (bool) {
return block.timestamp >= startSale && block.timestamp <= endSale;
}
}pragma solidity 0.8.30;
abstract contract Treasury {
uint256 public constant ONE_HUNDRED_PERCENT = 10000; // 100%
struct TreasuryConfig {
address payable espresso;
address payable partner;
uint256 percentageEspresso;
}
TreasuryConfig internal treasury;
error NotValidTreasuryPercentage();
error ZeroAddress();
event TreasurysSet(address main, address secondary, uint256 percentageEspresso);
function _setTreasury(TreasuryConfig memory _treasury) internal {
if (_treasury.espresso == address(0) || _treasury.partner == address(0)) revert ZeroAddress();
if (_treasury.percentageEspresso > ONE_HUNDRED_PERCENT) revert NotValidTreasuryPercentage();
treasury = _treasury;
emit TreasurysSet(_treasury.espresso, _treasury.partner, _treasury.percentageEspresso);
}
function getTreasury() public view returns (address, address, uint256) {
return (treasury.espresso, treasury.partner, treasury.percentageEspresso);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/ERC721.sol)
pragma solidity ^0.8.0;
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
// Mapping from token ID to owner address
mapping(uint256 => address) private _owners;
// Mapping owner address to token count
mapping(address => uint256) private _balances;
// Mapping from token ID to approved address
mapping(uint256 => address) private _tokenApprovals;
// Mapping from owner to operator approvals
mapping(address => mapping(address => bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: address zero is not a valid owner");
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _ownerOf(tokenId);
require(owner != address(0), "ERC721: invalid token ID");
return owner;
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
_requireMinted(tokenId);
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overridden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return "";
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not token owner or approved for all"
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual override returns (address) {
_requireMinted(tokenId);
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(address from, address to, uint256 tokenId) public virtual override {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
_safeTransfer(from, to, tokenId, data);
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* `data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
*/
function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
return _owners[tokenId];
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted (`_mint`),
* and stop existing when they are burned (`_burn`).
*/
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _ownerOf(tokenId) != address(0);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId, 1);
// Check that tokenId was not minted by `_beforeTokenTransfer` hook
require(!_exists(tokenId), "ERC721: token already minted");
unchecked {
// Will not overflow unless all 2**256 token ids are minted to the same owner.
// Given that tokens are minted one by one, it is impossible in practice that
// this ever happens. Might change if we allow batch minting.
// The ERC fails to describe this case.
_balances[to] += 1;
}
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId, 1);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
* This is an internal function that does not check if the sender is authorized to operate on the token.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId, 1);
// Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook
owner = ERC721.ownerOf(tokenId);
// Clear approvals
delete _tokenApprovals[tokenId];
unchecked {
// Cannot overflow, as that would require more tokens to be burned/transferred
// out than the owner initially received through minting and transferring in.
_balances[owner] -= 1;
}
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), tokenId, 1);
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(address from, address to, uint256 tokenId) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId, 1);
// Check that tokenId was not transferred by `_beforeTokenTransfer` hook
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
// Clear approvals from the previous owner
delete _tokenApprovals[tokenId];
unchecked {
// `_balances[from]` cannot overflow for the same reason as described in `_burn`:
// `from`'s balance is the number of token held, which is at least one before the current
// transfer.
// `_balances[to]` could overflow in the conditions described in `_mint`. That would require
// all 2**256 token ids to be minted, which in practice is impossible.
_balances[from] -= 1;
_balances[to] += 1;
}
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId, 1);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits an {Approval} event.
*/
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Emits an {ApprovalForAll} event.
*/
function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
require(owner != operator, "ERC721: approve to caller");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Reverts if the `tokenId` has not been minted yet.
*/
function _requireMinted(uint256 tokenId) internal view virtual {
require(_exists(tokenId), "ERC721: invalid token ID");
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
/// @solidity memory-safe-assembly
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
/**
* @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is
* used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.
* - When `from` is zero, the tokens will be minted for `to`.
* - When `to` is zero, ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
* - `batchSize` is non-zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}
/**
* @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is
* used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.
* - When `from` is zero, the tokens were minted for `to`.
* - When `to` is zero, ``from``'s tokens were burned.
* - `from` and `to` are never both zero.
* - `batchSize` is non-zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}
/**
* @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
*
* WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant
* being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such
* that `ownerOf(tokenId)` is `a`.
*/
// solhint-disable-next-line func-name-mixedcase
function __unsafe_increaseBalance(address account, uint256 amount) internal {
_balances[account] += amount;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/common/ERC2981.sol)
pragma solidity ^0.8.0;
import "../../interfaces/IERC2981.sol";
import "../../utils/introspection/ERC165.sol";
/**
* @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.
*
* Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
* specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
*
* Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the
* fee is specified in basis points by default.
*
* IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
* https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to
* voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
*
* _Available since v4.5._
*/
abstract contract ERC2981 is IERC2981, ERC165 {
struct RoyaltyInfo {
address receiver;
uint96 royaltyFraction;
}
RoyaltyInfo private _defaultRoyaltyInfo;
mapping(uint256 => RoyaltyInfo) private _tokenRoyaltyInfo;
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @inheritdoc IERC2981
*/
function royaltyInfo(uint256 tokenId, uint256 salePrice) public view virtual override returns (address, uint256) {
RoyaltyInfo memory royalty = _tokenRoyaltyInfo[tokenId];
if (royalty.receiver == address(0)) {
royalty = _defaultRoyaltyInfo;
}
uint256 royaltyAmount = (salePrice * royalty.royaltyFraction) / _feeDenominator();
return (royalty.receiver, royaltyAmount);
}
/**
* @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a
* fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an
* override.
*/
function _feeDenominator() internal pure virtual returns (uint96) {
return 10000;
}
/**
* @dev Sets the royalty information that all ids in this contract will default to.
*
* Requirements:
*
* - `receiver` cannot be the zero address.
* - `feeNumerator` cannot be greater than the fee denominator.
*/
function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {
require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
require(receiver != address(0), "ERC2981: invalid receiver");
_defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
}
/**
* @dev Removes default royalty information.
*/
function _deleteDefaultRoyalty() internal virtual {
delete _defaultRoyaltyInfo;
}
/**
* @dev Sets the royalty information for a specific token id, overriding the global default.
*
* Requirements:
*
* - `receiver` cannot be the zero address.
* - `feeNumerator` cannot be greater than the fee denominator.
*/
function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal virtual {
require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
require(receiver != address(0), "ERC2981: Invalid parameters");
_tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
}
/**
* @dev Resets royalty information for the token id back to the global default.
*/
function _resetTokenRoyalty(uint256 tokenId) internal virtual {
delete _tokenRoyaltyInfo[tokenId];
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (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;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`
return uint256(n >= 0 ? n : -n);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Metadata is IERC721 {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}{
"remappings": [
"@hyperlane-core/=dependencies/@hyperlane-core-7.1.8/",
"@openzeppelin-contracts-upgradeable/=dependencies/@openzeppelin-contracts-upgradeable-4.9.6/",
"@openzeppelin-contracts/=dependencies/@openzeppelin-contracts-4.9.6/",
"@openzeppelin/contracts-upgradeable/=dependencies/@openzeppelin-contracts-upgradeable-4.9.6/",
"@openzeppelin/contracts/=dependencies/@openzeppelin-contracts-4.9.6/",
"espresso-tee-contracts/=dependencies/espresso-tee-contracts-main/",
"forge-std/=dependencies/forge-std-1.10.0/",
"solady/=dependencies/espresso-tee-contracts-main/lib/automata-dcap-attestation/lib/automata-on-chain-pccs/lib/solady/src/",
"@automata-network/dcap-attestation/contracts/=dependencies/espresso-tee-contracts-main/lib/automata-dcap-attestation/contracts/",
"@automata-network/dcap-attestation/test/=dependencies/espresso-tee-contracts-main/lib/automata-dcap-attestation/forge-test/",
"@automata-network/on-chain-pccs/=dependencies/espresso-tee-contracts-main/lib/automata-dcap-attestation/lib/automata-on-chain-pccs/src/",
"@hyperlane-core-7.1.8/=dependencies/@hyperlane-core-7.1.8/",
"@moka-main/=dependencies/@moka-main/src/",
"@nitro-validator/=dependencies/espresso-tee-contracts-main/lib/nitro-validator/src/",
"@openzeppelin-contracts-4.9.6/=dependencies/@openzeppelin-contracts-4.9.6/",
"@openzeppelin-contracts-upgradeable-4.9.6/=dependencies/@openzeppelin-contracts-upgradeable-4.9.6/",
"@solarity/=dependencies/espresso-tee-contracts-main/lib/nitro-validator/lib/solidity-lib/contracts/",
"@sp1-contracts/=dependencies/espresso-tee-contracts-main/lib/automata-dcap-attestation/lib/sp1-contracts/contracts/src/",
"automata-dcap-attestation/=dependencies/espresso-tee-contracts-main/lib/automata-dcap-attestation/",
"automata-on-chain-pccs/=dependencies/espresso-tee-contracts-main/lib/automata-dcap-attestation/lib/automata-on-chain-pccs/",
"ds-test/=dependencies/espresso-tee-contracts-main/lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=dependencies/espresso-tee-contracts-main/lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
"espresso-tee-contracts-main/=dependencies/espresso-tee-contracts-main/",
"forge-std-1.10.0/=dependencies/forge-std-1.10.0/src/",
"forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/",
"halmos-cheatcodes/=dependencies/espresso-tee-contracts-main/lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/",
"moka-main/=dependencies/moka-main/",
"nitro-validator/=dependencies/espresso-tee-contracts-main/lib/nitro-validator/src/",
"openzeppelin-contracts-upgradeable/=dependencies/espresso-tee-contracts-main/lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts/=dependencies/espresso-tee-contracts-main/lib/openzeppelin-contracts/",
"openzeppelin/=dependencies/moka-main/dependencies/@openzeppelin-contracts-4.9.6/contracts/",
"p256-verifier/=dependencies/espresso-tee-contracts-main/lib/automata-dcap-attestation/lib/automata-on-chain-pccs/lib/p256-verifier/src/",
"risc0-ethereum/=dependencies/espresso-tee-contracts-main/lib/automata-dcap-attestation/lib/risc0-ethereum/",
"risc0/=dependencies/espresso-tee-contracts-main/lib/automata-dcap-attestation/lib/risc0-ethereum/contracts/src/",
"solidity-lib/=dependencies/espresso-tee-contracts-main/lib/nitro-validator/lib/solidity-lib/contracts/",
"sp1-contracts/=dependencies/espresso-tee-contracts-main/lib/automata-dcap-attestation/lib/sp1-contracts/contracts/"
],
"optimizer": {
"enabled": false,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "prague",
"viaIR": true
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"string","name":"_baseImageURI","type":"string"},{"internalType":"string","name":"_chainName","type":"string"},{"internalType":"address","name":"_espHypErc20","type":"address"},{"internalType":"address","name":"_priceAdmin","type":"address"},{"components":[{"internalType":"address payable","name":"espresso","type":"address"},{"internalType":"address payable","name":"partner","type":"address"},{"internalType":"uint256","name":"percentageEspresso","type":"uint256"}],"internalType":"struct Treasury.TreasuryConfig","name":"_treasury","type":"tuple"},{"internalType":"uint256","name":"_nftSalePrice","type":"uint256"},{"internalType":"uint256","name":"_startSale","type":"uint256"},{"internalType":"uint256","name":"_endSale","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"CallerIsNotAnTokenOwnerOrApproved","type":"error"},{"inputs":[{"internalType":"uint256","name":"startSale","type":"uint256"},{"internalType":"uint256","name":"endSale","type":"uint256"}],"name":"EndDateLessThanStartDateNotAllowed","type":"error"},{"inputs":[{"internalType":"uint256","name":"minPriceWei","type":"uint256"},{"internalType":"uint256","name":"nftSalePriceWei","type":"uint256"}],"name":"LowPriceInWei","type":"error"},{"inputs":[{"internalType":"uint256","name":"nftPrice","type":"uint256"},{"internalType":"uint256","name":"msgValue","type":"uint256"}],"name":"NftPriceExceedsMsgValue","type":"error"},{"inputs":[],"name":"NotValidTreasuryPercentage","type":"error"},{"inputs":[],"name":"RoyaltyFeeTooHigh","type":"error"},{"inputs":[{"internalType":"uint256","name":"startSale","type":"uint256"},{"internalType":"uint256","name":"endSale","type":"uint256"},{"internalType":"uint256","name":"currentTime","type":"uint256"}],"name":"SaleFinishedOrNotStarted","type":"error"},{"inputs":[{"internalType":"address","name":"treasury","type":"address"}],"name":"TreasuryPaymentFailed","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"UriQueryNotExist","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"oldBaseImageUri","type":"string"},{"indexed":false,"internalType":"string","name":"newBaseImageUri","type":"string"}],"name":"BaseImageUriChanged","type":"event"},{"anonymous":false,"inputs":[],"name":"DefaultRoyaltyDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"DefaultRoyaltySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"NativeBuy","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"NftSalePriceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"startSale","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endSale","type":"uint256"}],"name":"SaleTimelinesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"machineType","type":"uint256"}],"name":"TokenMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"treasuryAddress","type":"address"}],"name":"TreasurySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"main","type":"address"},{"indexed":false,"internalType":"address","name":"secondary","type":"address"},{"indexed":false,"internalType":"uint256","name":"percentageEspresso","type":"uint256"}],"name":"TreasurysSet","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ROYALTY_BPS","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_PRICE_WEI","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE_HUNDRED_PERCENT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRICE_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"endSale","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"espHypErc20","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTreasury","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isSaleOpen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"machineTypes","outputs":[{"internalType":"uint256","name":"machineType","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nftSalePriceWei","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"royaltyFeeNumerator","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"royaltyReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newImageURI","type":"string"}],"name":"setBaseImageUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"setDefaultRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nftSalePrice","type":"uint256"}],"name":"setSalePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startSale","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60806040523461003c57610026610014610314565b989790979691969592959493946106ac565b61002e610041565b614b73610ef38239614b7390f35b610047565b60405190565b5f80fd5b601f801991011690565b634e487b7160e01b5f52604160045260245ffd5b906100739061004b565b810190811060018060401b0382111761008b57604052565b610055565b906100a361009c610041565b9283610069565b565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b60018060401b0381116100d1576100cd60209161004b565b0190565b610055565b90825f9392825e0152565b909291926100f66100f1826100b5565b610090565b9381855260208501908284011161011257610110926100d6565b565b6100b1565b9080601f8301121561013557816020610132935191016100e1565b90565b6100ad565b60018060a01b031690565b61014e9061013a565b90565b61015a81610145565b0361016157565b5f80fd5b9050519061017282610151565b565b5f80fd5b6101819061013a565b90565b61018d81610178565b0361019457565b5f80fd5b905051906101a582610184565b565b90565b6101b3816101a7565b036101ba57565b5f80fd5b905051906101cb826101aa565b565b919060608382031261021957610212906101e76060610090565b936101f4825f8301610198565b5f8601526102058260208301610198565b60208601526040016101be565b6040830152565b610174565b6101808183031261030f575f81015160018060401b03811161030a5782610246918301610117565b92602082015160018060401b0381116103055783610265918401610117565b92604083015160018060401b0381116103005781610284918501610117565b92606081015160018060401b0381116102fb57826102a3918301610117565b926102b18360808401610165565b926102bf8160a08501610165565b926102cd8260c083016101cd565b926102f86102df8461012085016101be565b936102ee8161014086016101be565b93610160016101be565b90565b6100a9565b6100a9565b6100a9565b6100a9565b6100a5565b610332615a668038038061032781610090565b92833981019061021e565b90919293949596979899565b90565b90565b5f1b90565b61035d6103586103629261033e565b610344565b610341565b90565b61036e5f610349565b90565b7fa84abcdbbbe6d3064a118960a591ebcfeb4901477f8843988e1c9d9365bbf7ac90565b5190565b634e487b7160e01b5f52602260045260245ffd5b90600160028304921680156103cd575b60208310146103c857565b610399565b91607f16916103bd565b5f5260205f2090565b601f602091010490565b1b90565b919060086104099102916104035f19846103ea565b926103ea565b9181191691161790565b90565b61042a61042561042f926101a7565b610413565b6101a7565b90565b90565b919061044b61044661045393610416565b610432565b9083546103ee565b9055565b5f90565b61046d91610467610457565b91610435565b565b5b81811061047b575050565b806104885f60019361045b565b01610470565b9190601f811161049e575b505050565b6104aa6104cf936103d7565b9060206104b6846103e0565b830193106104d7575b6104c8906103e0565b019061046f565b5f8080610499565b91506104c8819290506104bf565b1c90565b906104f9905f19906008026104e5565b191690565b81610508916104e9565b906002021790565b9061051a81610395565b9060018060401b0382116105d85761053c8261053685546103ad565b8561048e565b602090601f83116001146105705791809161055f935f92610564575b50506104fe565b90555b565b90915001515f80610558565b601f1983169161057f856103d7565b925f5b8181106105c0575091600293918560019694106105a6575b50505002019055610562565b6105b6910151601f8416906104e9565b90555f808061059a565b91936020600181928787015181550195019201610582565b610055565b906105e791610510565b565b906105fa60018060a01b0391610344565b9181191691161790565b61061861061361061d9261013a565b610413565b61013a565b90565b61062990610604565b90565b61063590610620565b90565b90565b9061065061064b6106579261062c565b610638565b82546105e9565b9055565b6106659051610178565b90565b90565b60018060601b031690565b61068a61068561068f92610668565b610413565b61066b565b90565b61069d6101f4610676565b90565b6106a990610620565b90565b916106f3610708966106d461072d9c6106fa9561070198975f9d6107179f939091929361072f565b6106e66106df610365565b3390610790565b6106ee610371565b610790565b60106105dd565b60116105dd565b600d61063b565b61071181610918565b0161065b565b610728610722610692565b916106a0565b610ae2565b565b9061073c9493929161073e565b565b9061074b9493929161074d565b565b9061075a9493929161075c565b565b61076d610777956107729495610779565b610bff565b610cdd565b565b9061078761078e925f6105dd565b60016105dd565b565b9061079a91610dea565b565b6107b06107ab6107b59261033e565b610413565b61013a565b90565b6107c19061079c565b90565b5f0190565b6107d390516101a7565b90565b90565b6107ed6107e86107f2926107d6565b610413565b6101a7565b90565b6108006127106107d9565b90565b61080c90610604565b90565b61081890610803565b90565b90565b9061083361082e61083a9261080f565b61081b565b82546105e9565b9055565b9061084a5f1991610344565b9181191691161790565b9061086961086461087092610416565b610432565b825461083e565b9055565b906108b8604060026108be946108975f82016108915f880161065b565b9061081e565b6108b0600182016108aa6020880161065b565b9061081e565b0192016107c9565b90610854565b565b906108ca91610874565b565b6108d5906106a0565b9052565b6108e2906101a7565b9052565b60409061090f610916949695939661090560608401985f8501906108cc565b60208301906108cc565b01906108d9565b565b6109235f820161065b565b61093d6109376109325f6107b8565b610145565b916106a0565b148015610a16575b6109fa57610955604082016107c9565b61096e6109686109636107f5565b6101a7565b916101a7565b116109de5761097e8160096108c0565b6109895f820161065b565b906109a2604061099b6020840161065b565b92016107c9565b916109d97fd838d8574aebe2f28e7ba7056f491af660215f37fe2053a5b7312ed8b2ffbafc936109d0610041565b938493846108e6565b0390a1565b5f63a6afd76360e01b8152806109f6600482016107c4565b0390fd5b5f63d92e233d60e01b815280610a12600482016107c4565b0390fd5b50610a236020820161065b565b610a3d610a37610a325f6107b8565b610145565b916106a0565b14610945565b610a57610a52610a5c9261066b565b610413565b6101a7565b90565b60a01b90565b90610a7760018060a01b031991610a5f565b9181191691161790565b610a95610a90610a9a9261066b565b610413565b61066b565b90565b90565b90610ab5610ab0610abc92610a81565b610a9d565b8254610a65565b9055565b610ac99061066b565b9052565b9190610ae0905f60208501940190610ac0565b565b80610afd610af7610af25f6107b8565b610145565b91610145565b14610b975781610b1c610b16610b116107f5565b6101a7565b91610a43565b11610b7b57610b2c81600e61063b565b610b3782600e610aa0565b610b76610b647f8a8bae378cb731c5c40b632330c6836c2f916f48edb967699c86736f9a6a76ef9261062c565b92610b6d610041565b91829182610acd565b0390a2565b5f63112e4ee960e21b815280610b93600482016107c4565b0390fd5b5f63d92e233d60e01b815280610baf600482016107c4565b0390fd5b916020610bd4929493610bcd60408201965f8301906108d9565b01906108d9565b565b5f1c90565b90565b610bea610bef91610bd6565b610bdb565b90565b610bfc9054610bde565b90565b81610c12610c0c836101a7565b916101a7565b1115610c7d5790610c27610c2e926006610854565b6007610854565b610c386006610bf2565b610c426007610bf2565b7f93e2baa5ac2ad694cf3a6c3e260e965dceb44365d5fabe357a05b8cc820fa46f91610c78610c6f610041565b92839283610bb3565b0390a1565b610c975f9283926376a11da360e11b845260048401610bb3565b0390fd5b90565b610cb2610cad610cb792610c9b565b610413565b6101a7565b90565b610cc56103e8610c9e565b90565b9190610cdb905f602085019401906108d9565b565b80610cf7610cf1610cec610cba565b6101a7565b916101a7565b10610d4257610d07816008610854565b610d3d7f3ff866e5ec857d83f0a1b06183af69f1b685c0f6ebd98e0d69e2a83e5744ea9191610d34610041565b91829182610cc8565b0390a1565b610d4a610cba565b610d645f928392633fe6a78560e21b845260048401610bb3565b0390fd5b151590565b610d7690610341565b90565b90610d8390610d6d565b5f5260205260405f2090565b90610d999061062c565b5f5260205260405f2090565b90610db160ff91610344565b9181191691161790565b610dc490610d68565b90565b90565b90610ddf610dda610de692610dbb565b610dc7565b8254610da5565b9055565b610dfe610df8828490610eb7565b15610d68565b610e07575b5050565b610e296001610e245f610e1c600c8690610d79565b018590610d8f565b610dca565b90610e32610ee5565b90610e6f610e69610e637f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d95610d6d565b9261062c565b9261062c565b92610e78610041565b80610e82816107c4565b0390a45f80610e03565b5f90565b60ff1690565b610ea2610ea791610bd6565b610e90565b90565b610eb49054610e96565b90565b610ede915f610ed3610ed993610ecb610e8c565b50600c610d79565b01610d8f565b610eaa565b90565b5f90565b610eed610ee1565b50339056fe60806040526004361015610013575b611312565b61001d5f3561028c565b806301ffc9a71461028757806304634d8d1461028257806306fdde031461027d578063081812fc14610278578063095ea7b3146102735780631919fed71461026e5780631a0813301461026957806323b872dd14610264578063248a9ca31461025f5780632a55205a1461025a5780632f2ff15d1461025557806336568abe14610250578063380d831b1461024b5780633b19e84a146102465780633c7cfbd21461024157806342842e0e1461023c57806342966c681461023757806346cf358c146102325780634c46c1151461022d578063524308f8146102285780635b1ab434146102235780635ee912281461021e5780636352211e146102195780636a6278421461021457806370a082311461020f57806381ddcc1f1461020a57806391d148541461020557806395d89b41146102005780639fbc8713146101fb578063a217fddf146101f6578063a22cb465146101f1578063b66a0e5d146101ec578063b88d4fde146101e7578063c236bfd0146101e2578063c87b56dd146101dd578063d547741f146101d8578063dd0081c7146101d3578063e985e9c5146101ce5763f84ddf0b0361000e576112dd565b611298565b611236565b6111ca565b611195565b611160565b6110de565b610f6d565b610f2a565b610ea5565b610e35565b610df1565b610dbb565b610d86565b610d0a565b610ce1565b610c8e565b610c5a565b610ba4565b610b15565b610ab1565b610a6d565b6109ff565b6109cb565b610996565b61091e565b6108b7565b610832565b6107fe565b61079a565b610708565b61066e565b6105ff565b6105cc565b610598565b610536565b61049b565b6103ed565b610318565b60e01c90565b60405190565b5f80fd5b5f80fd5b5f80fd5b63ffffffff60e01b1690565b6102b9816102a4565b036102c057565b5f80fd5b905035906102d1826102b0565b565b906020828203126102ec576102e9915f016102c4565b90565b61029c565b151590565b6102ff906102f1565b9052565b9190610316905f602085019401906102f6565b565b346103485761034461033361032e3660046102d3565b61131a565b61033b610292565b91829182610303565b0390f35b610298565b60018060a01b031690565b6103619061034d565b90565b61036d81610358565b0361037457565b5f80fd5b9050359061038582610364565b565b6bffffffffffffffffffffffff1690565b6103a181610387565b036103a857565b5f80fd5b905035906103b982610398565b565b91906040838203126103e357806103d76103e0925f8601610378565b936020016103ac565b90565b61029c565b5f0190565b3461041c576104066104003660046103bb565b906114c6565b61040e610292565b80610418816103e8565b0390f35b610298565b5f91031261042b57565b61029c565b5190565b60209181520190565b90825f9392825e0152565b601f801991011690565b61047161047a60209361047f9361046881610430565b93848093610434565b9586910161043d565b610448565b0190565b6104989160208201915f818403910152610452565b90565b346104cb576104ab366004610421565b6104c76104b66115ee565b6104be610292565b91829182610483565b0390f35b610298565b90565b6104dc816104d0565b036104e357565b5f80fd5b905035906104f4826104d3565b565b9060208282031261050f5761050c915f016104e7565b90565b61029c565b61051d90610358565b9052565b9190610534905f60208501940190610514565b565b346105665761056261055161054c3660046104f6565b611643565b610559610292565b91829182610521565b0390f35b610298565b91906040838203126105935780610587610590925f8601610378565b936020016104e7565b90565b61029c565b346105c7576105b16105ab36600461056b565b906117bb565b6105b9610292565b806105c3816103e8565b0390f35b610298565b346105fa576105e46105df3660046104f6565b611858565b6105ec610292565b806105f6816103e8565b0390f35b610298565b3461062f5761060f366004610421565b61062b61061a611884565b610622610292565b91829182610303565b0390f35b610298565b90916060828403126106695761066661064f845f8501610378565b9361065d8160208601610378565b936040016104e7565b90565b61029c565b3461069d57610687610681366004610634565b91611980565b61068f610292565b80610699816103e8565b0390f35b610298565b90565b6106ae816106a2565b036106b557565b5f80fd5b905035906106c6826106a5565b565b906020828203126106e1576106de915f016106b9565b90565b61029c565b6106ef906106a2565b9052565b9190610706905f602085019401906106e6565b565b346107385761073461072361071e3660046106c8565b6119f3565b61072b610292565b918291826106f3565b0390f35b610298565b91906040838203126107655780610759610762925f86016104e7565b936020016104e7565b90565b61029c565b610773906104d0565b9052565b91602061079892949361079160408201965f830190610514565b019061076a565b565b346107cc576107b36107ad36600461073d565b90611adb565b906107c86107bf610292565b92839283610777565b0390f35b610298565b91906040838203126107f957806107ed6107f6925f86016106b9565b93602001610378565b90565b61029c565b3461082d576108176108113660046107d1565b90611b52565b61081f610292565b80610829816103e8565b0390f35b610298565b346108615761084b6108453660046107d1565b90611c06565b610853610292565b8061085d816103e8565b0390f35b610298565b1c90565b90565b61087d9060086108829302610866565b61086a565b90565b90610890915461086d565b90565b61089f60075f90610885565b90565b91906108b5905f6020850194019061076a565b565b346108e7576108c7366004610421565b6108e36108d2610893565b6108da610292565b918291826108a2565b0390f35b610298565b60409061091561091c949695939661090b60608401985f850190610514565b6020830190610514565b019061076a565b565b346109515761092e366004610421565b61094d610939611c6d565b610944939193610292565b938493846108ec565b0390f35b610298565b60018060a01b031690565b6109719060086109769302610866565b610956565b90565b906109849154610961565b90565b610993600d5f90610979565b90565b346109c6576109a6366004610421565b6109c26109b1610987565b6109b9610292565b91829182610521565b0390f35b610298565b346109fa576109e46109de366004610634565b91611d16565b6109ec610292565b806109f6816103e8565b0390f35b610298565b34610a2d57610a17610a123660046104f6565b611d2c565b610a1f610292565b80610a29816103e8565b0390f35b610298565b90565b90565b610a4c610a47610a5192610a32565b610a35565b6104d0565b90565b610a5f6103e8610a38565b90565b610a6a610a54565b90565b34610a9d57610a7d366004610421565b610a99610a88610a62565b610a90610292565b918291826108a2565b0390f35b610298565b610aae60085f90610885565b90565b34610ae157610ac1366004610421565b610add610acc610aa2565b610ad4610292565b918291826108a2565b0390f35b610298565b7fa84abcdbbbe6d3064a118960a591ebcfeb4901477f8843988e1c9d9365bbf7ac90565b610b12610ae6565b90565b34610b4557610b25366004610421565b610b41610b30610b0a565b610b38610292565b918291826106f3565b0390f35b610298565b90565b610b61610b5c610b6692610b4a565b610a35565b610387565b90565b610b746101f4610b4d565b90565b610b7f610b69565b90565b610b8b90610387565b9052565b9190610ba2905f60208501940190610b82565b565b34610bd457610bb4366004610421565b610bd0610bbf610b77565b610bc7610292565b91829182610b8f565b0390f35b610298565b5f80fd5b5f80fd5b5f80fd5b909182601f83011215610c1f5781359167ffffffffffffffff8311610c1a576020019260018302840111610c1557565b610be1565b610bdd565b610bd9565b90602082820312610c55575f82013567ffffffffffffffff8111610c5057610c4c9201610be5565b9091565b6102a0565b61029c565b34610c8957610c73610c6d366004610c24565b9061207e565b610c7b610292565b80610c85816103e8565b0390f35b610298565b34610cbe57610cba610ca9610ca43660046104f6565b61210c565b610cb1610292565b91829182610521565b0390f35b610298565b90602082820312610cdc57610cd9915f01610378565b90565b61029c565b610cf4610cef366004610cc3565b612198565b610cfc610292565b80610d06816103e8565b0390f35b34610d3a57610d36610d25610d20366004610cc3565b612315565b610d2d610292565b918291826108a2565b0390f35b610298565b6bffffffffffffffffffffffff1690565b610d60906008610d659302610866565b610d3f565b90565b90610d739154610d50565b90565b610d83600e601490610d68565b90565b34610db657610d96366004610421565b610db2610da1610d76565b610da9610292565b91829182610b8f565b0390f35b610298565b34610dec57610de8610dd7610dd13660046107d1565b90612396565b610ddf610292565b91829182610303565b0390f35b610298565b34610e2157610e01366004610421565b610e1d610e0c6123c0565b610e14610292565b91829182610483565b0390f35b610298565b610e32600e5f90610979565b90565b34610e6557610e45366004610421565b610e61610e50610e26565b610e58610292565b91829182610521565b0390f35b610298565b90565b5f1b90565b610e86610e81610e8b92610e6a565b610e6d565b6106a2565b90565b610e975f610e72565b90565b610ea2610e8e565b90565b34610ed557610eb5366004610421565b610ed1610ec0610e9a565b610ec8610292565b918291826106f3565b0390f35b610298565b610ee3816102f1565b03610eea57565b5f80fd5b90503590610efb82610eda565b565b9190604083820312610f255780610f19610f22925f8601610378565b93602001610eee565b90565b61029c565b34610f5957610f43610f3d366004610efd565b906123d6565b610f4b610292565b80610f55816103e8565b0390f35b610298565b610f6a60065f90610885565b90565b34610f9d57610f7d366004610421565b610f99610f88610f5e565b610f90610292565b918291826108a2565b0390f35b610298565b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b90610fc490610448565b810190811067ffffffffffffffff821117610fde57604052565b610fa6565b90610ff6610fef610292565b9283610fba565b565b67ffffffffffffffff811161101657611012602091610448565b0190565b610fa6565b90825f939282370152565b9092919261103b61103682610ff8565b610fe3565b93818552602085019082840111611057576110559261101b565b565b610fa2565b9080601f8301121561107a5781602061107793359101611026565b90565b610bd9565b906080828203126110d957611096815f8401610378565b926110a48260208501610378565b926110b283604083016104e7565b92606082013567ffffffffffffffff81116110d4576110d1920161105c565b90565b6102a0565b61029c565b34611110576110fa6110f136600461107f565b929190916123ec565b611102610292565b8061110c816103e8565b0390f35b610298565b61112961112461112e926104d0565b610a35565b6104d0565b90565b9061113b90611115565b5f5260205260405f2090565b61115d906111586012915f92611131565b610885565b90565b346111905761118c61117b6111763660046104f6565b611147565b611183610292565b918291826108a2565b0390f35b610298565b346111c5576111c16111b06111ab3660046104f6565b612834565b6111b8610292565b91829182610483565b0390f35b610298565b346111f9576111e36111dd3660046107d1565b906129b3565b6111eb610292565b806111f5816103e8565b0390f35b610298565b90565b61121561121061121a926111fe565b610a35565b6104d0565b90565b611228612710611201565b90565b61123361121d565b90565b3461126657611246366004610421565b61126261125161122b565b611259610292565b918291826108a2565b0390f35b610298565b91906040838203126112935780611287611290925f8601610378565b93602001610378565b90565b61029c565b346112c9576112c56112b46112ae36600461126b565b906129d5565b6112bc610292565b91829182610303565b0390f35b610298565b6112da600f5f90610885565b90565b3461130d576112ed366004610421565b6113096112f86112ce565b611300610292565b918291826108a2565b0390f35b610298565b5f80fd5b5f90565b611322611316565b508061133d61133763152a902d60e11b6102a4565b916102a4565b146113bd578061135c6113566301ffc9a760e01b6102a4565b916102a4565b146113b7578061137b6113756380ac58cd60e01b6102a4565b916102a4565b146113b1578061139a611394637965db0b60e01b6102a4565b916102a4565b146113ab576113a8906129fd565b90565b50600190565b50600190565b50600190565b50600190565b906113dd916113d86113d3610ae6565b612a3d565b61143b565b565b6113f36113ee6113f892610e6a565b610a35565b61034d565b90565b611404906113df565b90565b61141b6114166114209261034d565b610a35565b61034d565b90565b61142c90611407565b90565b61143890611423565b90565b8061145661145061144b5f6113fb565b610358565b91610358565b146114aa57611466818390612af8565b6114a56114937f8a8bae378cb731c5c40b632330c6836c2f916f48edb967699c86736f9a6a76ef9261142f565b9261149c610292565b91829182610b8f565b0390a2565b5f63d92e233d60e01b8152806114c2600482016103e8565b0390fd5b906114d0916113c3565b565b606090565b634e487b7160e01b5f52602260045260245ffd5b906001600283049216801561150b575b602083101461150657565b6114d7565b91607f16916114fb565b60209181520190565b5f5260205f2090565b905f929180549061154161153a836114eb565b8094611515565b916001811690815f14611598575060011461155c575b505050565b611569919293945061151e565b915f925b81841061158057505001905f8080611557565b6001816020929593955484860152019101929061156d565b92949550505060ff19168252151560200201905f8080611557565b906115bd91611527565b90565b906115e06115d9926115d0610292565b938480926115b3565b0383610fba565b565b6115eb906115c0565b90565b6115f66114d2565b506116005f6115e2565b90565b5f90565b9061161190611115565b5f5260205260405f2090565b5f1c90565b61162e6116339161161d565b610956565b90565b6116409054611622565b90565b61166361166891611652611603565b5061165c81612bc9565b6004611607565b611636565b90565b60207f7200000000000000000000000000000000000000000000000000000000000000917f4552433732313a20617070726f76616c20746f2063757272656e74206f776e655f8201520152565b6116c56021604092610434565b6116ce8161166b565b0190565b6116e79060208101905f8183039101526116b8565b90565b156116f157565b6116f9610292565b62461bcd60e51b81528061170f600482016116d2565b0390fd5b60207f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000917f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f5f8201520152565b61176d603d604092610434565b61177681611713565b0190565b61178f9060208101905f818303910152611760565b90565b1561179957565b6117a1610292565b62461bcd60e51b8152806117b76004820161177a565b0390fd5b90611817916118126117cc8361210c565b6117e9836117e26117dc84610358565b91610358565b14156116ea565b6117f1612bdc565b6118036117fd83610358565b91610358565b14908115611819575b50611792565b612be9565b565b61182c9150611826612bdc565b906129d5565b5f61180c565b61184b90611846611841610ae6565b612a3d565b61184d565b565b61185690612c80565b565b61186190611832565b565b61186f6118749161161d565b61086a565b90565b6118819054611863565b90565b61188c611316565b50426118a96118a361189e6006611877565b6104d0565b916104d0565b1015806118b4575b90565b50426118d16118cb6118c66007611877565b6104d0565b916104d0565b11156118b1565b60207f72206f7220617070726f76656400000000000000000000000000000000000000917f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e655f8201520152565b611932602d604092610434565b61193b816118d8565b0190565b6119549060208101905f818303910152611925565b90565b1561195e57565b611966610292565b62461bcd60e51b81528061197c6004820161193f565b0390fd5b916119a79261199f61199a611993612bdc565b8490612d0b565b611957565b919091612f6a565b565b5f90565b6119b6906106a2565b90565b906119c3906119ad565b5f5260205260405f2090565b90565b6119de6119e39161161d565b6119cf565b90565b6119f090546119d2565b90565b6001611a0c611a1292611a046119a9565b50600c6119b9565b016119e6565b90565b5f90565b60a01c90565b611a2b611a3091611a19565b610d3f565b90565b611a3d9054611a1f565b90565b611a54611a4f611a5992610387565b610a35565b6104d0565b90565b634e487b7160e01b5f52601160045260245ffd5b611a7f611a85919392936104d0565b926104d0565b91611a918382026104d0565b928184041490151715611aa057565b611a5c565b634e487b7160e01b5f52601260045260245ffd5b611ac5611acb916104d0565b916104d0565b908115611ad6570490565b611aa5565b5090611ae5611603565b50611aee611a15565b50611b26611b18611aff600e611636565b93611b12611b0d600e611a33565b611a40565b90611a70565b611b2061121d565b90611ab9565b90565b90611b4491611b3f611b3a826119f3565b612a3d565b611b46565b565b90611b5091613100565b565b90611b5c91611b29565b565b60207f20726f6c657320666f722073656c660000000000000000000000000000000000917f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e63655f8201520152565b611bb8602f604092610434565b611bc181611b5e565b0190565b611bda9060208101905f818303910152611bab565b90565b15611be457565b611bec610292565b62461bcd60e51b815280611c0260048201611bc5565b0390fd5b90611c3391611c2e82611c28611c22611c1d612bdc565b610358565b91610358565b14611bdd565b6131a2565b565b60018060a01b031690565b611c4c611c519161161d565b611c35565b90565b611c5e9054611c40565b90565b611c6a90611423565b90565b611c75611603565b50611c7e611603565b50611c87611a15565b50611c945f600901611c54565b611ca16001600901611c54565b91611cc1611cbb611cb56002600901611877565b93611c61565b93611c61565b9190565b67ffffffffffffffff8111611ce357611cdf602091610448565b0190565b610fa6565b90611cfa611cf583611cc5565b610fe3565b918252565b611d085f611ce8565b90565b611d13611cff565b90565b91611d2a9291611d24611d0b565b926123ec565b565b611d40611d3a338390612d0b565b156102f1565b611d4f57611d4d9061323a565b565b33611d6a5f92839263879581bb60e01b845260048401610777565b0390fd5b90611d8891611d83611d7e610e8e565b612a3d565b61202a565b565b5090565b601f602091010490565b1b90565b91906008611db7910291611db15f1984611d98565b92611d98565b9181191691161790565b90565b9190611dda611dd5611de293611115565b611dc1565b908354611d9c565b9055565b611df891611df2611a15565b91611dc4565b565b5b818110611e06575050565b80611e135f600193611de6565b01611dfb565b9190601f8111611e29575b505050565b611e35611e5a9361151e565b906020611e4184611d8e565b83019310611e62575b611e5390611d8e565b0190611dfa565b5f8080611e24565b9150611e5381929050611e4a565b90611e80905f1990600802610866565b191690565b81611e8f91611e70565b906002021790565b91611ea29082611d8a565b9067ffffffffffffffff8211611f6157611ec682611ec085546114eb565b85611e19565b5f90601f8311600114611ef957918091611ee8935f92611eed575b5050611e85565b90555b565b90915001355f80611ee1565b601f19831691611f088561151e565b925f5b818110611f4957509160029391856001969410611f2f575b50505002019055611eeb565b611f3f910135601f841690611e70565b90555f8080611f23565b91936020600181928787013581550195019201611f0b565b610fa6565b90611f719291611e97565b565b905f9291805490611f8d611f86836114eb565b8094610434565b916001811690815f14611fe45750600114611fa8575b505050565b611fb5919293945061151e565b915f925b818410611fcc57505001905f8080611fa3565b60018160209295939554848601520191019290611fb9565b92949550505060ff19168252151560200201905f8080611fa3565b90916120196120279360408401908482035f860152610452565b916020818403910152611f73565b90565b906120419061203960106115e2565b926010611f66565b60107f8707270b94fb021ec97d74c5e8079e2cdcbee5ab8640da702fe2dc986ed1c86091612079612070610292565b92839283611fff565b0390a1565b9061208891611d6e565b565b5f7f4552433732313a20696e76616c696420746f6b656e2049440000000000000000910152565b6120be6018602092610434565b6120c78161208a565b0190565b6120e09060208101905f8183039101526120b1565b90565b156120ea57565b6120f2610292565b62461bcd60e51b815280612108600482016120cb565b0390fd5b61211e90612118611603565b50613306565b6121438161213c6121366121315f6113fb565b610358565b91610358565b14156120e3565b90565b61214f906104d0565b5f19811461215d5760010190565b611a5c565b9061216e5f1991610e6d565b9181191691161790565b9061218d61218861219492611115565b611dc1565b8254612162565b9055565b336121b46121ae6121a9600d611636565b610358565b91610358565b14906121dd6121cb6121c6600f611877565b612146565b6121d681600f612178565b92156102f1565b612247575b6121eb826137b6565b906121f781849061385e565b91909161224261223061222a7f96234cb3d6c373a1aaa06497a540bc166d4b0359243a088eaf95e21d7253d0be9361142f565b93611115565b93612239610292565b918291826108a2565b0390a3565b612252818390613671565b6121e2565b60207f6c6964206f776e65720000000000000000000000000000000000000000000000917f4552433732313a2061646472657373207a65726f206973206e6f7420612076615f8201520152565b6122b16029604092610434565b6122ba81612257565b0190565b6122d39060208101905f8183039101526122a4565b90565b156122dd57565b6122e5610292565b62461bcd60e51b8152806122fb600482016122be565b0390fd5b906123099061142f565b5f5260205260405f2090565b61235161235691612324611a15565b5061234a8161234361233d6123385f6113fb565b610358565b91610358565b14156122d6565b60036122ff565b611877565b90565b906123639061142f565b5f5260205260405f2090565b60ff1690565b6123816123869161161d565b61236f565b90565b6123939054612375565b90565b6123bd915f6123b26123b8936123aa611316565b50600c6119b9565b01612359565b612389565b90565b6123c86114d2565b506123d360016115e2565b90565b6123ea916123e2612bdc565b9190916138f6565b565b9161241693919261240d612408612401612bdc565b8490612d0b565b611957565b92909192613a2d565b565b90565b61242590546114eb565b90565b61243c61243761244192610e6a565b610a35565b6104d0565b90565b905090565b61246e6124659260209261245c81610430565b94858093612444565b9384910161043d565b0190565b61247b91612449565b90565b90565b905f929180549061249b612494836114eb565b8094612444565b916001811690815f146124ed57506001146124b6575b505050565b6124c3919293945061151e565b5f905b8382106124d957505001905f80806124b1565b6001816020925484860152019101906124c6565b92949550505060ff191682528015150201905f80806124b1565b5f7f2e706e6700000000000000000000000000000000000000000000000000000000910152565b61253a60048092612444565b61254381612507565b0190565b916125586125639361255e93612481565b90612449565b61252e565b90565b5f7f7b00000000000000000000000000000000000000000000000000000000000000910152565b61259960018092612444565b6125a281612566565b0190565b5f68113730b6b2911d101160b91b910152565b6125c560098092612444565b6125ce816125a6565b0190565b5f7f20457370726573736f204d616368696e65202300000000000000000000000000910152565b61260560138092612444565b61260e816125d2565b0190565b7f222c226465736372697074696f6e223a20224d696e74206163726f73732063685f8201527f61696e7320776974686f7574206272696467696e67207769746820507265737460208201527f6f2e20506f776572656420627920457370726573736f2c20417065436861696e60408201527f2c20616e64205241524920436861696e20746f2073686f77636173652073656160608201527f6d6c6573732c20636f6d706f7361626c65204e4654206d696e74696e672e222c608082015260a0691134b6b0b3b2911d101160b11b910152565b6126f060aa8092612444565b6126f981612612565b0190565b7f222c2261747472696275746573223a205b7b202274726169745f74797065223a5f82015260207310112a3432b6b2911610113b30b63ab2911d101160611b910152565b61274d60348092612444565b612756816126fd565b0190565b5f6422207d5d7d60d81b910152565b61277560058092612444565b61277e8161275a565b0190565b6127d6936127c56127c06127db97956127ba6127b56127d0976127af6127aa6127cb9961258d565b6125b9565b90612481565b6125f9565b90612449565b6126e4565b90612449565b612741565b90612449565b612769565b90565b5f7f646174613a6170706c69636174696f6e2f6a736f6e3b757466382c0000000000910152565b612811601b8092612444565b61281a816127de565b0190565b9061282b61283192612805565b90612449565b90565b61283c6114d2565b5061284f61284982613a52565b156102f1565b61296b576128656128606010612418565b61241b565b6128776128715f612428565b916104d0565b1461292e57612917612926612903836128fe61289561292b96613d7c565b916128ef6128ce60106128c986916128ba6128ae610292565b93849260208401612547565b60208201810382520382610fba565b61247e565b936128da601193613aff565b946128e3610292565b95869460208601612782565b60208201810382520382610fba565b61247e565b61290b610292565b9283916020830161281e565b60208201810382520382610fba565b61247e565b90565b61295461296361294061296893613aff565b612948610292565b92839160208301612472565b60208201810382520382610fba565b61247e565b90565b612986905f9182916331b1cacd60e11b8352600483016108a2565b0390fd5b906129a5916129a061299b826119f3565b612a3d565b6129a7565b565b906129b1916131a2565b565b906129bd9161298a565b565b906129c99061142f565b5f5260205260405f2090565b6129fa916129f06129f5926129e8611316565b5060056129bf565b612359565b612389565b90565b612a05611316565b5080612a20612a1a637965db0b60e01b6102a4565b916102a4565b14908115612a2d575b5090565b612a379150613e3d565b5f612a29565b612a4f90612a49612bdc565b90613f6c565b565b90612a6260018060a01b0391610e6d565b9181191691161790565b90565b90612a84612a7f612a8b9261142f565b612a6c565b8254612a51565b9055565b60a01b90565b90612aaf6bffffffffffffffffffffffff60a01b91612a8f565b9181191691161790565b612acd612ac8612ad292610387565b610a35565b610387565b90565b90565b90612aed612ae8612af492612ab9565b612ad5565b8254612a95565b9055565b80612b13612b0d612b085f6113fb565b610358565b91610358565b14612bad5781612b32612b2c612b2761121d565b6104d0565b91611a40565b11612b9157612b4281600e612a6f565b612b4d82600e612ad8565b612b8c612b7a7f8a8bae378cb731c5c40b632330c6836c2f916f48edb967699c86736f9a6a76ef9261142f565b92612b83610292565b91829182610b8f565b0390a2565b5f63112e4ee960e21b815280612ba9600482016103e8565b0390fd5b5f63d92e233d60e01b815280612bc5600482016103e8565b0390fd5b612bd5612bda91613a52565b6120e3565b565b612be4611603565b503390565b90612bff82612bfa60048490611607565b612a6f565b612c088161210c565b91612c45612c3f612c397f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259561142f565b9261142f565b92611115565b92612c4e610292565b80612c58816103e8565b0390a4565b916020612c7e929493612c7760408201965f83019061076a565b019061076a565b565b80612c9a612c94612c8f610a54565b6104d0565b916104d0565b10612ce557612caa816008612178565b612ce07f3ff866e5ec857d83f0a1b06183af69f1b685c0f6ebd98e0d69e2a83e5744ea9191612cd7610292565b918291826108a2565b0390a1565b612ced610a54565b612d075f928392633fe6a78560e21b845260048401612c5d565b0390fd5b612d13611316565b50612d1d8261210c565b81612d30612d2a83610358565b91610358565b14908115612d6d575b50918215612d47575b505090565b612d65919250612d59612d5f91611643565b92610358565b91610358565b145f80612d42565b612d79915082906129d5565b5f612d39565b60207f6f776e6572000000000000000000000000000000000000000000000000000000917f4552433732313a207472616e736665722066726f6d20696e636f7272656374205f8201520152565b612dd96025604092610434565b612de281612d7f565b0190565b612dfb9060208101905f818303910152612dcc565b90565b15612e0557565b612e0d610292565b62461bcd60e51b815280612e2360048201612de6565b0390fd5b60207f7265737300000000000000000000000000000000000000000000000000000000917f4552433732313a207472616e7366657220746f20746865207a65726f206164645f8201520152565b612e816024604092610434565b612e8a81612e27565b0190565b612ea39060208101905f818303910152612e74565b90565b15612ead57565b612eb5610292565b62461bcd60e51b815280612ecb60048201612e8e565b0390fd5b90565b612ee6612ee1612eeb92612ecf565b610a35565b6104d0565b90565b91906008612f0e910291612f0860018060a01b0384611d98565b92611d98565b9181191691161790565b9190612f2e612f29612f369361142f565b612a6c565b908354612eee565b9055565b612f4c91612f46611603565b91612f18565b565b90612f5991036104d0565b90565b90612f6791016104d0565b90565b919091612f91612f798361210c565b612f8b612f8584610358565b91610358565b14612dfe565b612fb683612faf612fa9612fa45f6113fb565b610358565b91610358565b1415612ea6565b612fda612fc28361210c565b612fd4612fce84610358565b91610358565b14612dfe565b612fef5f612fea60048590611607565b612f3a565b613020612ffc6001612ed2565b61301a61300b600385906122ff565b9161301583611877565b612f4e565b90612178565b61305161302d6001612ed2565b61304b61303c600387906122ff565b9161304683611877565b612f5c565b90612178565b6130668361306160028590611607565b612a6f565b916130a361309d6130977fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9561142f565b9261142f565b92611115565b926130ac610292565b806130b6816103e8565b0390a4565b906130c760ff91610e6d565b9181191691161790565b6130da906102f1565b90565b90565b906130f56130f06130fc926130d1565b6130dd565b82546130bb565b9055565b61311461310e828490612396565b156102f1565b61311d575b5050565b61313f600161313a5f613132600c86906119b9565b018590612359565b6130e0565b90613148612bdc565b9061318561317f6131797f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d956119ad565b9261142f565b9261142f565b9261318e610292565b80613198816103e8565b0390a45f80613119565b6131ad818390612396565b6131b6575b5050565b6131d75f6131d25f6131ca600c86906119b9565b018590612359565b6130e0565b906131e0612bdc565b9061321d6132176132117ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b956119ad565b9261142f565b9261142f565b92613226610292565b80613230816103e8565b0390a45f806131b2565b6132438161210c565b5061324d8161210c565b6132625f61325d60048590611607565b612f3a565b61329361326f6001612ed2565b61328d61327e600385906122ff565b9161328883611877565b612f4e565b90612178565b6132a85f6132a360028590611607565b612f3a565b906132b25f6113fb565b6132ee6132e86132e27fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9561142f565b9261142f565b92611115565b926132f7610292565b80613301816103e8565b0390a4565b61331d61332291613315611603565b506002611607565b611636565b90565b60409061334e613355949695939661334460608401985f85019061076a565b602083019061076a565b019061076a565b565b90613369613363611884565b156102f1565b613378576133769161348a565b565b6133826006611877565b61338c6007611877565b906133a8425f93849363657bd80360e11b855260048501613325565b0390fd5b905090565b6133bc5f80926133ac565b0190565b6133c9906133b1565b90565b906133de6133d983610ff8565b610fe3565b918252565b606090565b3d5f14613403576133f83d6133cc565b903d5f602084013e5b565b61340b6133e3565b90613401565b61341a90611c61565b9052565b9190613431905f60208501940190613411565b565b613442613448919392936104d0565b926104d0565b820391821161345357565b611a5c565b604090613481613488949695939661347760608401985f850190610514565b602083019061076a565b019061076a565b565b346134a66134a061349b6008611877565b6104d0565b916104d0565b03613647576134dc6134ce6134bb6008611877565b6134c86002600901611877565b90611a70565b6134d661121d565b90611ab9565b61351c5f806134f56134f082600901611c54565b611c61565b846134fe610292565b9081613509816133c0565b03925af16135156133e8565b50156102f1565b61361d5761352d6002600901611877565b61354661354061353b61121d565b6104d0565b916104d0565b03613594575b50906135586008611877565b9161358f7f0bfc06de9d7140d29ad4067e15d229191159e8b0e0c60fc0a569cf63e9745fca93613586610292565b93849384613458565b0390a1565b5f806135e8926135c26135b26135ad6001600901611c54565b611c61565b916135bd6008611877565b613433565b6135ca610292565b90816135d5816133c0565b03925af16135e16133e8565b50156102f1565b6135f2575f61354c565b6136196136026001600901611c54565b5f918291631a1dc3c960e11b83526004830161341e565b0390fd5b61364361362c5f600901611c54565b5f918291631a1dc3c960e11b83526004830161341e565b0390fd5b6136516008611877565b349061366d5f9283926304cb94e560e01b845260048401612c5d565b0390fd5b9061367b91613357565b565b90565b61368c613691916104d0565b61367d565b9052565b60601b90565b6136a490613695565b90565b6136b09061369b565b90565b6136bf6136c491610358565b6136a7565b9052565b602093926136e885836136e06014956136f097613680565b0180926136b3565b018092613680565b0190565b60200190565b5190565b61370a61370f9161161d565b611115565b90565b90565b61372961372461372e92613712565b610a35565b6104d0565b90565b61373d613743916104d0565b916104d0565b90811561374e570690565b611aa5565b613762613768919392936104d0565b926104d0565b820180921161377357565b611a5c565b60ff1690565b61379261378d613797926104d0565b610a35565b613778565b90565b6137ae6137a96137b392613778565b610a35565b6104d0565b90565b61385b906137c2611a15565b5061385661383c613837613827613817426137ff33916137f0896137e4610292565b948593602085016136c8565b60208201810382520382610fba565b61381161380b826136fa565b916136f4565b206136fe565b6138216005613715565b90613731565b6138316001612ed2565b90613753565b61377e565b916138516138498461379a565b916012611131565b612178565b61379a565b90565b90613872919061386c611d0b565b91614005565b565b5f7f4552433732313a20617070726f766520746f2063616c6c657200000000000000910152565b6138a86019602092610434565b6138b181613874565b0190565b6138ca9060208101905f81830391015261389b565b90565b156138d457565b6138dc610292565b62461bcd60e51b8152806138f2600482016138b5565b0390fd5b9190916139168161390f61390986610358565b91610358565b14156138cd565b61393582613930613929600585906129bf565b8690612359565b6130e0565b91909161398061396e6139687f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319361142f565b9361142f565b93613977610292565b91829182610303565b0390a3565b60207f63656976657220696d706c656d656e7465720000000000000000000000000000917f4552433732313a207472616e7366657220746f206e6f6e2045524337323152655f8201520152565b6139df6032604092610434565b6139e881613985565b0190565b613a019060208101905f8183039101526139d2565b90565b15613a0b57565b613a13610292565b62461bcd60e51b815280613a29600482016139ec565b0390fd5b92613a4b92613a5094613a4281858491612f6a565b92909192614105565b613a04565b565b613a6490613a5e611316565b50613306565b613a7e613a78613a735f6113fb565b610358565b91610358565b141590565b369037565b90613aad613a9583611ce8565b92602080613aa38693611cc5565b9201910390613a83565b565b6001613abb91036104d0565b90565b90565b613ad5613ad0613ada92613abe565b610a35565b6104d0565b90565b613ae9613aef916104d0565b916104d0565b908115613afa570490565b611aa5565b613b076114d2565b50613b24613b1482614331565b613b1e6001612ed2565b90612f5c565b90613b2e82613a88565b91613b37611a15565b5060200182015b600115613ba157613b51613b7d91613aaf565b916f181899199a1a9b1b9c1cb0b131b232b360811b600a82061a8353613b77600a613ac1565b90613add565b80613b90613b8a5f612428565b916104d0565b14613b9b5790613b3e565b50505b90565b5050613b9e565b90565b613bbf613bba613bc492613ba8565b610a35565b6104d0565b90565b90565b613bde613bd9613be392613bc7565b610a35565b6104d0565b90565b90565b613bfd613bf8613c0292613be6565b610a35565b6104d0565b90565b5f7f4d79746869630000000000000000000000000000000000000000000000000000910152565b613c366006611ce8565b90613c4360208301613c05565b565b613c4d613c2c565b90565b5f7f4f7267616e696300000000000000000000000000000000000000000000000000910152565b613c816007611ce8565b90613c8e60208301613c50565b565b613c98613c77565b90565b5f7f496e647573747269616c00000000000000000000000000000000000000000000910152565b613ccc600a611ce8565b90613cd960208301613c9b565b565b613ce3613cc2565b90565b5f7f436c617373696300000000000000000000000000000000000000000000000000910152565b613d176007611ce8565b90613d2460208301613ce6565b565b613d2e613d0d565b90565b5f7f4675747572650000000000000000000000000000000000000000000000000000910152565b613d626006611ce8565b90613d6f60208301613d31565b565b613d79613d58565b90565b613d93613d9891613d8b6114d2565b506012611131565b611877565b80613dac613da66001612ed2565b916104d0565b145f14613dbf5750613dbc613d71565b90565b80613dd3613dcd6002613bab565b916104d0565b145f14613de65750613de3613d26565b90565b80613dfa613df46003613bca565b916104d0565b145f14613e0d5750613e0a613cdb565b90565b613e20613e1a6004613be9565b916104d0565b145f14613e3257613e2f613c90565b90565b613e3a613c45565b90565b613e45611316565b5080613e60613e5a6380ac58cd60e01b6102a4565b916102a4565b148015613e84575b908115613e74575b5090565b613e7e9150614592565b5f613e70565b5080613e9f613e99635b5e139f60e01b6102a4565b916102a4565b14613e68565b90565b613ebc613eb7613ec192613ea5565b610a35565b6104d0565b90565b5f7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000910152565b613ef760178092612444565b613f0081613ec4565b0190565b5f7f206973206d697373696e6720726f6c6520000000000000000000000000000000910152565b613f3760118092612444565b613f4081613f04565b0190565b613f5e613f699392613f58613f6393613eeb565b90612449565b613f2b565b90612449565b90565b90613f81613f7b838390612396565b156102f1565b613f89575050565b61400191613fdf613fb8613fa8613fa2613fe49561460c565b936136fe565b613fb26020613ea8565b906147d5565b91613fd0613fc4610292565b93849260208401613f44565b60208201810382520382610fba565b61247e565b613fec610292565b91829162461bcd60e51b835260048301610483565b0390fd5b61402f9261402a92614018838290614a1f565b6140215f6113fb565b92909192614105565b613a04565b565b61403a90611407565b90565b61404690614031565b90565b61405290611423565b90565b60e01b90565b90505190614068826102b0565b565b9060208282031261408357614080915f0161405b565b90565b61029c565b60209181520190565b6140b06140b96020936140be936140a7816136fa565b93848093614088565b9586910161043d565b610448565b0190565b90926140f5906140eb61410296946140e160808601975f870190610514565b6020850190610514565b604083019061076a565b6060818403910152614091565b90565b909392614110611316565b9461411a81614b1d565b5f1461422e57906141615f6141396141346020969561403d565b614049565b9261416c63150b7a029161414b612bdc565b9698614155610292565b998a9889978896614055565b8652600486016140c2565b03925af180915f926141fe575b50155f146141de5750600161418a57565b6141926133e8565b61419b816136fa565b6141ad6141a75f612428565b916104d0565b145f146141d6576141bc610292565b62461bcd60e51b8152806141d2600482016139ec565b0390fd5b805190602001fd5b9091506141fa6141f4630a85bd0160e11b6102a4565b916102a4565b1490565b61422091925060203d8111614227575b6142188183610fba565b81019061406a565b905f614179565b503d61420e565b505050509050600190565b90565b61425061424b61425592614239565b610a35565b6104d0565b90565b90565b61426f61426a61427492614258565b610a35565b6104d0565b90565b90565b61428e61428961429392614277565b610a35565b6104d0565b90565b90565b6142ad6142a86142b292614296565b610a35565b6104d0565b90565b90565b6142cc6142c76142d1926142b5565b610a35565b6104d0565b90565b90565b6142eb6142e66142f0926142d4565b610a35565b6104d0565b90565b90565b61430a61430561430f926142f3565b610a35565b6104d0565b90565b90565b61432961432461432e92614312565b610a35565b6104d0565b90565b614339611a15565b506143435f612428565b908061437261436c7a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000061423c565b916104d0565b101561454a575b8061439a6143946d04ee2d6d415b85acef810000000061427a565b916104d0565b101561450f575b806143bb6143b5662386f26fc10000614299565b916104d0565b10156144db575b806143d96143d36305f5e1006142d7565b916104d0565b10156144aa575b806143f56143ef612710611201565b916104d0565b101561447b575b8061441061440a6064614315565b916104d0565b101561444d575b61442a614424600a613ac1565b916104d0565b1015614434575b90565b614448906144426001612ed2565b90612f5c565b614431565b6144646144759161445e6064614315565b90613add565b9161446f6002613bab565b90612f5c565b90614417565b6144936144a49161448d612710611201565b90613add565b9161449e6004613be9565b90612f5c565b906143fc565b6144c46144d5916144be6305f5e1006142d7565b90613add565b916144cf60086142f6565b90612f5c565b906143e0565b6144f8614509916144f2662386f26fc10000614299565b90613add565b9161450360106142b8565b90612f5c565b906143c2565b6145336145449161452d6d04ee2d6d415b85acef810000000061427a565b90613add565b9161453e6020613ea8565b90612f5c565b906143a1565b61457b61458c916145757a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000061423c565b90613add565b91614586604061425b565b90612f5c565b90614379565b61459a611316565b506145b46145ae6301ffc9a760e01b6102a4565b916102a4565b1490565b6145c190611407565b90565b6145d86145d36145dd9261034d565b610a35565b6104d0565b90565b90565b6145f76145f26145fc926145e0565b610a35565b613778565b90565b61460960146145e3565b90565b61462961462461463f9261461e6114d2565b506145b8565b6145c4565b6146396146346145ff565b61379a565b906147d5565b90565b9061466761464f836133cc565b9260208061465d8693610ff8565b9201910390613a83565b565b600360fc1b90565b634e487b7160e01b5f52603260045260245ffd5b9061468f826136fa565b8110156146a157600160209102010190565b614671565b600f60fb1b90565b6146b7906104d0565b5f81146146c5576001900390565b611a5c565b6f181899199a1a9b1b9c1cb0b131b232b360811b90565b6146e96146ca565b90565b90565b6147036146fe614708926146ec565b610a35565b6104d0565b90565b60f81b90565b61472561472061472a92613be6565b610a35565b613778565b90565b61474c9061474661474061475194613778565b916104d0565b90610866565b6104d0565b90565b5f7f537472696e67733a20686578206c656e67746820696e73756666696369656e74910152565b61478760208092610434565b61479081614754565b0190565b6147a99060208101905f81830391015261477b565b90565b156147b357565b6147bb610292565b62461bcd60e51b8152806147d160048201614794565b0390fd5b91906147df6114d2565b5061487661486661481561481061480060026147fb8791613bab565b611a70565b61480a6002613bab565b90613753565b614642565b9261481e614669565b6148358561482f5f935f1a93612428565b90614685565b5361483e6146a6565b614856856148506001935f1a93612ed2565b90614685565b536148616002613bab565b611a70565b6148706001612ed2565b90613753565b925b8361488c6148866001612ed2565b916104d0565b11156148f25761489a6146e1565b816148a5600f6146ef565b169160108310156148ed576148c16148e1926148e7941a61470b565b6148d0859188905f1a92614685565b536148db6004614711565b9061472d565b936146ae565b92614878565b614671565b6149199293506149149061490e6149085f612428565b916104d0565b146147ac565b61247e565b90565b5f7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373910152565b61494f60208092610434565b6149588161491c565b0190565b6149719060208101905f818303910152614943565b90565b1561497b57565b614983610292565b62461bcd60e51b8152806149996004820161495c565b0390fd5b5f7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000910152565b6149d1601c602092610434565b6149da8161499d565b0190565b6149f39060208101905f8183039101526149c4565b90565b156149fd57565b614a05610292565b62461bcd60e51b815280614a1b600482016149de565b0390fd5b90614a4582614a3e614a38614a335f6113fb565b610358565b91610358565b1415614974565b614a5f614a5a614a5483613a52565b156102f1565b6149f6565b614a79614a74614a6e83613a52565b156102f1565b6149f6565b614aaa614a866001612ed2565b614aa4614a95600386906122ff565b91614a9f83611877565b612f5c565b90612178565b614abf82614aba60028490611607565b612a6f565b614ac85f6113fb565b91614b05614aff614af97fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9561142f565b9261142f565b92611115565b92614b0e610292565b80614b18816103e8565b0390a4565b614b25611316565b503b614b39614b335f612428565b916104d0565b119056fea26469706673582212209f3d897270eed2192a73e3d69dd3280d8dbfc0ff77942a77be089496807c3c2164736f6c634300081e0033000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002600000000000000000000000003e08ad7c3fd70d08cdd2a11247dae18eb06434fd000000000000000000000000d50a66b631544454b21bc32f5a2723428dbf3073000000000000000000000000d3f14acb49456bc41912e6580614ad4b6d49a720000000000000000000000000053f171c0d0cc9d76247d4d1cddb280bf11313900000000000000000000000000000000000000000000000000000000000001d4c000000000000000000000000000000000000000000000000a688906bd8b00000000000000000000000000000000000000000000000000000000000006936d9e000000000000000000000000000000000000000000000000000000000695be0000000000000000000000000000000000000000000000000000000000000000013457370726573736f20427265777320526172690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044252455700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003368747470733a2f2f78636861696e2d6e66742e73332e75732d656173742d322e616d617a6f6e6177732e636f6d2f726172692f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045261726900000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x60806040526004361015610013575b611312565b61001d5f3561028c565b806301ffc9a71461028757806304634d8d1461028257806306fdde031461027d578063081812fc14610278578063095ea7b3146102735780631919fed71461026e5780631a0813301461026957806323b872dd14610264578063248a9ca31461025f5780632a55205a1461025a5780632f2ff15d1461025557806336568abe14610250578063380d831b1461024b5780633b19e84a146102465780633c7cfbd21461024157806342842e0e1461023c57806342966c681461023757806346cf358c146102325780634c46c1151461022d578063524308f8146102285780635b1ab434146102235780635ee912281461021e5780636352211e146102195780636a6278421461021457806370a082311461020f57806381ddcc1f1461020a57806391d148541461020557806395d89b41146102005780639fbc8713146101fb578063a217fddf146101f6578063a22cb465146101f1578063b66a0e5d146101ec578063b88d4fde146101e7578063c236bfd0146101e2578063c87b56dd146101dd578063d547741f146101d8578063dd0081c7146101d3578063e985e9c5146101ce5763f84ddf0b0361000e576112dd565b611298565b611236565b6111ca565b611195565b611160565b6110de565b610f6d565b610f2a565b610ea5565b610e35565b610df1565b610dbb565b610d86565b610d0a565b610ce1565b610c8e565b610c5a565b610ba4565b610b15565b610ab1565b610a6d565b6109ff565b6109cb565b610996565b61091e565b6108b7565b610832565b6107fe565b61079a565b610708565b61066e565b6105ff565b6105cc565b610598565b610536565b61049b565b6103ed565b610318565b60e01c90565b60405190565b5f80fd5b5f80fd5b5f80fd5b63ffffffff60e01b1690565b6102b9816102a4565b036102c057565b5f80fd5b905035906102d1826102b0565b565b906020828203126102ec576102e9915f016102c4565b90565b61029c565b151590565b6102ff906102f1565b9052565b9190610316905f602085019401906102f6565b565b346103485761034461033361032e3660046102d3565b61131a565b61033b610292565b91829182610303565b0390f35b610298565b60018060a01b031690565b6103619061034d565b90565b61036d81610358565b0361037457565b5f80fd5b9050359061038582610364565b565b6bffffffffffffffffffffffff1690565b6103a181610387565b036103a857565b5f80fd5b905035906103b982610398565b565b91906040838203126103e357806103d76103e0925f8601610378565b936020016103ac565b90565b61029c565b5f0190565b3461041c576104066104003660046103bb565b906114c6565b61040e610292565b80610418816103e8565b0390f35b610298565b5f91031261042b57565b61029c565b5190565b60209181520190565b90825f9392825e0152565b601f801991011690565b61047161047a60209361047f9361046881610430565b93848093610434565b9586910161043d565b610448565b0190565b6104989160208201915f818403910152610452565b90565b346104cb576104ab366004610421565b6104c76104b66115ee565b6104be610292565b91829182610483565b0390f35b610298565b90565b6104dc816104d0565b036104e357565b5f80fd5b905035906104f4826104d3565b565b9060208282031261050f5761050c915f016104e7565b90565b61029c565b61051d90610358565b9052565b9190610534905f60208501940190610514565b565b346105665761056261055161054c3660046104f6565b611643565b610559610292565b91829182610521565b0390f35b610298565b91906040838203126105935780610587610590925f8601610378565b936020016104e7565b90565b61029c565b346105c7576105b16105ab36600461056b565b906117bb565b6105b9610292565b806105c3816103e8565b0390f35b610298565b346105fa576105e46105df3660046104f6565b611858565b6105ec610292565b806105f6816103e8565b0390f35b610298565b3461062f5761060f366004610421565b61062b61061a611884565b610622610292565b91829182610303565b0390f35b610298565b90916060828403126106695761066661064f845f8501610378565b9361065d8160208601610378565b936040016104e7565b90565b61029c565b3461069d57610687610681366004610634565b91611980565b61068f610292565b80610699816103e8565b0390f35b610298565b90565b6106ae816106a2565b036106b557565b5f80fd5b905035906106c6826106a5565b565b906020828203126106e1576106de915f016106b9565b90565b61029c565b6106ef906106a2565b9052565b9190610706905f602085019401906106e6565b565b346107385761073461072361071e3660046106c8565b6119f3565b61072b610292565b918291826106f3565b0390f35b610298565b91906040838203126107655780610759610762925f86016104e7565b936020016104e7565b90565b61029c565b610773906104d0565b9052565b91602061079892949361079160408201965f830190610514565b019061076a565b565b346107cc576107b36107ad36600461073d565b90611adb565b906107c86107bf610292565b92839283610777565b0390f35b610298565b91906040838203126107f957806107ed6107f6925f86016106b9565b93602001610378565b90565b61029c565b3461082d576108176108113660046107d1565b90611b52565b61081f610292565b80610829816103e8565b0390f35b610298565b346108615761084b6108453660046107d1565b90611c06565b610853610292565b8061085d816103e8565b0390f35b610298565b1c90565b90565b61087d9060086108829302610866565b61086a565b90565b90610890915461086d565b90565b61089f60075f90610885565b90565b91906108b5905f6020850194019061076a565b565b346108e7576108c7366004610421565b6108e36108d2610893565b6108da610292565b918291826108a2565b0390f35b610298565b60409061091561091c949695939661090b60608401985f850190610514565b6020830190610514565b019061076a565b565b346109515761092e366004610421565b61094d610939611c6d565b610944939193610292565b938493846108ec565b0390f35b610298565b60018060a01b031690565b6109719060086109769302610866565b610956565b90565b906109849154610961565b90565b610993600d5f90610979565b90565b346109c6576109a6366004610421565b6109c26109b1610987565b6109b9610292565b91829182610521565b0390f35b610298565b346109fa576109e46109de366004610634565b91611d16565b6109ec610292565b806109f6816103e8565b0390f35b610298565b34610a2d57610a17610a123660046104f6565b611d2c565b610a1f610292565b80610a29816103e8565b0390f35b610298565b90565b90565b610a4c610a47610a5192610a32565b610a35565b6104d0565b90565b610a5f6103e8610a38565b90565b610a6a610a54565b90565b34610a9d57610a7d366004610421565b610a99610a88610a62565b610a90610292565b918291826108a2565b0390f35b610298565b610aae60085f90610885565b90565b34610ae157610ac1366004610421565b610add610acc610aa2565b610ad4610292565b918291826108a2565b0390f35b610298565b7fa84abcdbbbe6d3064a118960a591ebcfeb4901477f8843988e1c9d9365bbf7ac90565b610b12610ae6565b90565b34610b4557610b25366004610421565b610b41610b30610b0a565b610b38610292565b918291826106f3565b0390f35b610298565b90565b610b61610b5c610b6692610b4a565b610a35565b610387565b90565b610b746101f4610b4d565b90565b610b7f610b69565b90565b610b8b90610387565b9052565b9190610ba2905f60208501940190610b82565b565b34610bd457610bb4366004610421565b610bd0610bbf610b77565b610bc7610292565b91829182610b8f565b0390f35b610298565b5f80fd5b5f80fd5b5f80fd5b909182601f83011215610c1f5781359167ffffffffffffffff8311610c1a576020019260018302840111610c1557565b610be1565b610bdd565b610bd9565b90602082820312610c55575f82013567ffffffffffffffff8111610c5057610c4c9201610be5565b9091565b6102a0565b61029c565b34610c8957610c73610c6d366004610c24565b9061207e565b610c7b610292565b80610c85816103e8565b0390f35b610298565b34610cbe57610cba610ca9610ca43660046104f6565b61210c565b610cb1610292565b91829182610521565b0390f35b610298565b90602082820312610cdc57610cd9915f01610378565b90565b61029c565b610cf4610cef366004610cc3565b612198565b610cfc610292565b80610d06816103e8565b0390f35b34610d3a57610d36610d25610d20366004610cc3565b612315565b610d2d610292565b918291826108a2565b0390f35b610298565b6bffffffffffffffffffffffff1690565b610d60906008610d659302610866565b610d3f565b90565b90610d739154610d50565b90565b610d83600e601490610d68565b90565b34610db657610d96366004610421565b610db2610da1610d76565b610da9610292565b91829182610b8f565b0390f35b610298565b34610dec57610de8610dd7610dd13660046107d1565b90612396565b610ddf610292565b91829182610303565b0390f35b610298565b34610e2157610e01366004610421565b610e1d610e0c6123c0565b610e14610292565b91829182610483565b0390f35b610298565b610e32600e5f90610979565b90565b34610e6557610e45366004610421565b610e61610e50610e26565b610e58610292565b91829182610521565b0390f35b610298565b90565b5f1b90565b610e86610e81610e8b92610e6a565b610e6d565b6106a2565b90565b610e975f610e72565b90565b610ea2610e8e565b90565b34610ed557610eb5366004610421565b610ed1610ec0610e9a565b610ec8610292565b918291826106f3565b0390f35b610298565b610ee3816102f1565b03610eea57565b5f80fd5b90503590610efb82610eda565b565b9190604083820312610f255780610f19610f22925f8601610378565b93602001610eee565b90565b61029c565b34610f5957610f43610f3d366004610efd565b906123d6565b610f4b610292565b80610f55816103e8565b0390f35b610298565b610f6a60065f90610885565b90565b34610f9d57610f7d366004610421565b610f99610f88610f5e565b610f90610292565b918291826108a2565b0390f35b610298565b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b90610fc490610448565b810190811067ffffffffffffffff821117610fde57604052565b610fa6565b90610ff6610fef610292565b9283610fba565b565b67ffffffffffffffff811161101657611012602091610448565b0190565b610fa6565b90825f939282370152565b9092919261103b61103682610ff8565b610fe3565b93818552602085019082840111611057576110559261101b565b565b610fa2565b9080601f8301121561107a5781602061107793359101611026565b90565b610bd9565b906080828203126110d957611096815f8401610378565b926110a48260208501610378565b926110b283604083016104e7565b92606082013567ffffffffffffffff81116110d4576110d1920161105c565b90565b6102a0565b61029c565b34611110576110fa6110f136600461107f565b929190916123ec565b611102610292565b8061110c816103e8565b0390f35b610298565b61112961112461112e926104d0565b610a35565b6104d0565b90565b9061113b90611115565b5f5260205260405f2090565b61115d906111586012915f92611131565b610885565b90565b346111905761118c61117b6111763660046104f6565b611147565b611183610292565b918291826108a2565b0390f35b610298565b346111c5576111c16111b06111ab3660046104f6565b612834565b6111b8610292565b91829182610483565b0390f35b610298565b346111f9576111e36111dd3660046107d1565b906129b3565b6111eb610292565b806111f5816103e8565b0390f35b610298565b90565b61121561121061121a926111fe565b610a35565b6104d0565b90565b611228612710611201565b90565b61123361121d565b90565b3461126657611246366004610421565b61126261125161122b565b611259610292565b918291826108a2565b0390f35b610298565b91906040838203126112935780611287611290925f8601610378565b93602001610378565b90565b61029c565b346112c9576112c56112b46112ae36600461126b565b906129d5565b6112bc610292565b91829182610303565b0390f35b610298565b6112da600f5f90610885565b90565b3461130d576112ed366004610421565b6113096112f86112ce565b611300610292565b918291826108a2565b0390f35b610298565b5f80fd5b5f90565b611322611316565b508061133d61133763152a902d60e11b6102a4565b916102a4565b146113bd578061135c6113566301ffc9a760e01b6102a4565b916102a4565b146113b7578061137b6113756380ac58cd60e01b6102a4565b916102a4565b146113b1578061139a611394637965db0b60e01b6102a4565b916102a4565b146113ab576113a8906129fd565b90565b50600190565b50600190565b50600190565b50600190565b906113dd916113d86113d3610ae6565b612a3d565b61143b565b565b6113f36113ee6113f892610e6a565b610a35565b61034d565b90565b611404906113df565b90565b61141b6114166114209261034d565b610a35565b61034d565b90565b61142c90611407565b90565b61143890611423565b90565b8061145661145061144b5f6113fb565b610358565b91610358565b146114aa57611466818390612af8565b6114a56114937f8a8bae378cb731c5c40b632330c6836c2f916f48edb967699c86736f9a6a76ef9261142f565b9261149c610292565b91829182610b8f565b0390a2565b5f63d92e233d60e01b8152806114c2600482016103e8565b0390fd5b906114d0916113c3565b565b606090565b634e487b7160e01b5f52602260045260245ffd5b906001600283049216801561150b575b602083101461150657565b6114d7565b91607f16916114fb565b60209181520190565b5f5260205f2090565b905f929180549061154161153a836114eb565b8094611515565b916001811690815f14611598575060011461155c575b505050565b611569919293945061151e565b915f925b81841061158057505001905f8080611557565b6001816020929593955484860152019101929061156d565b92949550505060ff19168252151560200201905f8080611557565b906115bd91611527565b90565b906115e06115d9926115d0610292565b938480926115b3565b0383610fba565b565b6115eb906115c0565b90565b6115f66114d2565b506116005f6115e2565b90565b5f90565b9061161190611115565b5f5260205260405f2090565b5f1c90565b61162e6116339161161d565b610956565b90565b6116409054611622565b90565b61166361166891611652611603565b5061165c81612bc9565b6004611607565b611636565b90565b60207f7200000000000000000000000000000000000000000000000000000000000000917f4552433732313a20617070726f76616c20746f2063757272656e74206f776e655f8201520152565b6116c56021604092610434565b6116ce8161166b565b0190565b6116e79060208101905f8183039101526116b8565b90565b156116f157565b6116f9610292565b62461bcd60e51b81528061170f600482016116d2565b0390fd5b60207f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000917f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f5f8201520152565b61176d603d604092610434565b61177681611713565b0190565b61178f9060208101905f818303910152611760565b90565b1561179957565b6117a1610292565b62461bcd60e51b8152806117b76004820161177a565b0390fd5b90611817916118126117cc8361210c565b6117e9836117e26117dc84610358565b91610358565b14156116ea565b6117f1612bdc565b6118036117fd83610358565b91610358565b14908115611819575b50611792565b612be9565b565b61182c9150611826612bdc565b906129d5565b5f61180c565b61184b90611846611841610ae6565b612a3d565b61184d565b565b61185690612c80565b565b61186190611832565b565b61186f6118749161161d565b61086a565b90565b6118819054611863565b90565b61188c611316565b50426118a96118a361189e6006611877565b6104d0565b916104d0565b1015806118b4575b90565b50426118d16118cb6118c66007611877565b6104d0565b916104d0565b11156118b1565b60207f72206f7220617070726f76656400000000000000000000000000000000000000917f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e655f8201520152565b611932602d604092610434565b61193b816118d8565b0190565b6119549060208101905f818303910152611925565b90565b1561195e57565b611966610292565b62461bcd60e51b81528061197c6004820161193f565b0390fd5b916119a79261199f61199a611993612bdc565b8490612d0b565b611957565b919091612f6a565b565b5f90565b6119b6906106a2565b90565b906119c3906119ad565b5f5260205260405f2090565b90565b6119de6119e39161161d565b6119cf565b90565b6119f090546119d2565b90565b6001611a0c611a1292611a046119a9565b50600c6119b9565b016119e6565b90565b5f90565b60a01c90565b611a2b611a3091611a19565b610d3f565b90565b611a3d9054611a1f565b90565b611a54611a4f611a5992610387565b610a35565b6104d0565b90565b634e487b7160e01b5f52601160045260245ffd5b611a7f611a85919392936104d0565b926104d0565b91611a918382026104d0565b928184041490151715611aa057565b611a5c565b634e487b7160e01b5f52601260045260245ffd5b611ac5611acb916104d0565b916104d0565b908115611ad6570490565b611aa5565b5090611ae5611603565b50611aee611a15565b50611b26611b18611aff600e611636565b93611b12611b0d600e611a33565b611a40565b90611a70565b611b2061121d565b90611ab9565b90565b90611b4491611b3f611b3a826119f3565b612a3d565b611b46565b565b90611b5091613100565b565b90611b5c91611b29565b565b60207f20726f6c657320666f722073656c660000000000000000000000000000000000917f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e63655f8201520152565b611bb8602f604092610434565b611bc181611b5e565b0190565b611bda9060208101905f818303910152611bab565b90565b15611be457565b611bec610292565b62461bcd60e51b815280611c0260048201611bc5565b0390fd5b90611c3391611c2e82611c28611c22611c1d612bdc565b610358565b91610358565b14611bdd565b6131a2565b565b60018060a01b031690565b611c4c611c519161161d565b611c35565b90565b611c5e9054611c40565b90565b611c6a90611423565b90565b611c75611603565b50611c7e611603565b50611c87611a15565b50611c945f600901611c54565b611ca16001600901611c54565b91611cc1611cbb611cb56002600901611877565b93611c61565b93611c61565b9190565b67ffffffffffffffff8111611ce357611cdf602091610448565b0190565b610fa6565b90611cfa611cf583611cc5565b610fe3565b918252565b611d085f611ce8565b90565b611d13611cff565b90565b91611d2a9291611d24611d0b565b926123ec565b565b611d40611d3a338390612d0b565b156102f1565b611d4f57611d4d9061323a565b565b33611d6a5f92839263879581bb60e01b845260048401610777565b0390fd5b90611d8891611d83611d7e610e8e565b612a3d565b61202a565b565b5090565b601f602091010490565b1b90565b91906008611db7910291611db15f1984611d98565b92611d98565b9181191691161790565b90565b9190611dda611dd5611de293611115565b611dc1565b908354611d9c565b9055565b611df891611df2611a15565b91611dc4565b565b5b818110611e06575050565b80611e135f600193611de6565b01611dfb565b9190601f8111611e29575b505050565b611e35611e5a9361151e565b906020611e4184611d8e565b83019310611e62575b611e5390611d8e565b0190611dfa565b5f8080611e24565b9150611e5381929050611e4a565b90611e80905f1990600802610866565b191690565b81611e8f91611e70565b906002021790565b91611ea29082611d8a565b9067ffffffffffffffff8211611f6157611ec682611ec085546114eb565b85611e19565b5f90601f8311600114611ef957918091611ee8935f92611eed575b5050611e85565b90555b565b90915001355f80611ee1565b601f19831691611f088561151e565b925f5b818110611f4957509160029391856001969410611f2f575b50505002019055611eeb565b611f3f910135601f841690611e70565b90555f8080611f23565b91936020600181928787013581550195019201611f0b565b610fa6565b90611f719291611e97565b565b905f9291805490611f8d611f86836114eb565b8094610434565b916001811690815f14611fe45750600114611fa8575b505050565b611fb5919293945061151e565b915f925b818410611fcc57505001905f8080611fa3565b60018160209295939554848601520191019290611fb9565b92949550505060ff19168252151560200201905f8080611fa3565b90916120196120279360408401908482035f860152610452565b916020818403910152611f73565b90565b906120419061203960106115e2565b926010611f66565b60107f8707270b94fb021ec97d74c5e8079e2cdcbee5ab8640da702fe2dc986ed1c86091612079612070610292565b92839283611fff565b0390a1565b9061208891611d6e565b565b5f7f4552433732313a20696e76616c696420746f6b656e2049440000000000000000910152565b6120be6018602092610434565b6120c78161208a565b0190565b6120e09060208101905f8183039101526120b1565b90565b156120ea57565b6120f2610292565b62461bcd60e51b815280612108600482016120cb565b0390fd5b61211e90612118611603565b50613306565b6121438161213c6121366121315f6113fb565b610358565b91610358565b14156120e3565b90565b61214f906104d0565b5f19811461215d5760010190565b611a5c565b9061216e5f1991610e6d565b9181191691161790565b9061218d61218861219492611115565b611dc1565b8254612162565b9055565b336121b46121ae6121a9600d611636565b610358565b91610358565b14906121dd6121cb6121c6600f611877565b612146565b6121d681600f612178565b92156102f1565b612247575b6121eb826137b6565b906121f781849061385e565b91909161224261223061222a7f96234cb3d6c373a1aaa06497a540bc166d4b0359243a088eaf95e21d7253d0be9361142f565b93611115565b93612239610292565b918291826108a2565b0390a3565b612252818390613671565b6121e2565b60207f6c6964206f776e65720000000000000000000000000000000000000000000000917f4552433732313a2061646472657373207a65726f206973206e6f7420612076615f8201520152565b6122b16029604092610434565b6122ba81612257565b0190565b6122d39060208101905f8183039101526122a4565b90565b156122dd57565b6122e5610292565b62461bcd60e51b8152806122fb600482016122be565b0390fd5b906123099061142f565b5f5260205260405f2090565b61235161235691612324611a15565b5061234a8161234361233d6123385f6113fb565b610358565b91610358565b14156122d6565b60036122ff565b611877565b90565b906123639061142f565b5f5260205260405f2090565b60ff1690565b6123816123869161161d565b61236f565b90565b6123939054612375565b90565b6123bd915f6123b26123b8936123aa611316565b50600c6119b9565b01612359565b612389565b90565b6123c86114d2565b506123d360016115e2565b90565b6123ea916123e2612bdc565b9190916138f6565b565b9161241693919261240d612408612401612bdc565b8490612d0b565b611957565b92909192613a2d565b565b90565b61242590546114eb565b90565b61243c61243761244192610e6a565b610a35565b6104d0565b90565b905090565b61246e6124659260209261245c81610430565b94858093612444565b9384910161043d565b0190565b61247b91612449565b90565b90565b905f929180549061249b612494836114eb565b8094612444565b916001811690815f146124ed57506001146124b6575b505050565b6124c3919293945061151e565b5f905b8382106124d957505001905f80806124b1565b6001816020925484860152019101906124c6565b92949550505060ff191682528015150201905f80806124b1565b5f7f2e706e6700000000000000000000000000000000000000000000000000000000910152565b61253a60048092612444565b61254381612507565b0190565b916125586125639361255e93612481565b90612449565b61252e565b90565b5f7f7b00000000000000000000000000000000000000000000000000000000000000910152565b61259960018092612444565b6125a281612566565b0190565b5f68113730b6b2911d101160b91b910152565b6125c560098092612444565b6125ce816125a6565b0190565b5f7f20457370726573736f204d616368696e65202300000000000000000000000000910152565b61260560138092612444565b61260e816125d2565b0190565b7f222c226465736372697074696f6e223a20224d696e74206163726f73732063685f8201527f61696e7320776974686f7574206272696467696e67207769746820507265737460208201527f6f2e20506f776572656420627920457370726573736f2c20417065436861696e60408201527f2c20616e64205241524920436861696e20746f2073686f77636173652073656160608201527f6d6c6573732c20636f6d706f7361626c65204e4654206d696e74696e672e222c608082015260a0691134b6b0b3b2911d101160b11b910152565b6126f060aa8092612444565b6126f981612612565b0190565b7f222c2261747472696275746573223a205b7b202274726169745f74797065223a5f82015260207310112a3432b6b2911610113b30b63ab2911d101160611b910152565b61274d60348092612444565b612756816126fd565b0190565b5f6422207d5d7d60d81b910152565b61277560058092612444565b61277e8161275a565b0190565b6127d6936127c56127c06127db97956127ba6127b56127d0976127af6127aa6127cb9961258d565b6125b9565b90612481565b6125f9565b90612449565b6126e4565b90612449565b612741565b90612449565b612769565b90565b5f7f646174613a6170706c69636174696f6e2f6a736f6e3b757466382c0000000000910152565b612811601b8092612444565b61281a816127de565b0190565b9061282b61283192612805565b90612449565b90565b61283c6114d2565b5061284f61284982613a52565b156102f1565b61296b576128656128606010612418565b61241b565b6128776128715f612428565b916104d0565b1461292e57612917612926612903836128fe61289561292b96613d7c565b916128ef6128ce60106128c986916128ba6128ae610292565b93849260208401612547565b60208201810382520382610fba565b61247e565b936128da601193613aff565b946128e3610292565b95869460208601612782565b60208201810382520382610fba565b61247e565b61290b610292565b9283916020830161281e565b60208201810382520382610fba565b61247e565b90565b61295461296361294061296893613aff565b612948610292565b92839160208301612472565b60208201810382520382610fba565b61247e565b90565b612986905f9182916331b1cacd60e11b8352600483016108a2565b0390fd5b906129a5916129a061299b826119f3565b612a3d565b6129a7565b565b906129b1916131a2565b565b906129bd9161298a565b565b906129c99061142f565b5f5260205260405f2090565b6129fa916129f06129f5926129e8611316565b5060056129bf565b612359565b612389565b90565b612a05611316565b5080612a20612a1a637965db0b60e01b6102a4565b916102a4565b14908115612a2d575b5090565b612a379150613e3d565b5f612a29565b612a4f90612a49612bdc565b90613f6c565b565b90612a6260018060a01b0391610e6d565b9181191691161790565b90565b90612a84612a7f612a8b9261142f565b612a6c565b8254612a51565b9055565b60a01b90565b90612aaf6bffffffffffffffffffffffff60a01b91612a8f565b9181191691161790565b612acd612ac8612ad292610387565b610a35565b610387565b90565b90565b90612aed612ae8612af492612ab9565b612ad5565b8254612a95565b9055565b80612b13612b0d612b085f6113fb565b610358565b91610358565b14612bad5781612b32612b2c612b2761121d565b6104d0565b91611a40565b11612b9157612b4281600e612a6f565b612b4d82600e612ad8565b612b8c612b7a7f8a8bae378cb731c5c40b632330c6836c2f916f48edb967699c86736f9a6a76ef9261142f565b92612b83610292565b91829182610b8f565b0390a2565b5f63112e4ee960e21b815280612ba9600482016103e8565b0390fd5b5f63d92e233d60e01b815280612bc5600482016103e8565b0390fd5b612bd5612bda91613a52565b6120e3565b565b612be4611603565b503390565b90612bff82612bfa60048490611607565b612a6f565b612c088161210c565b91612c45612c3f612c397f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259561142f565b9261142f565b92611115565b92612c4e610292565b80612c58816103e8565b0390a4565b916020612c7e929493612c7760408201965f83019061076a565b019061076a565b565b80612c9a612c94612c8f610a54565b6104d0565b916104d0565b10612ce557612caa816008612178565b612ce07f3ff866e5ec857d83f0a1b06183af69f1b685c0f6ebd98e0d69e2a83e5744ea9191612cd7610292565b918291826108a2565b0390a1565b612ced610a54565b612d075f928392633fe6a78560e21b845260048401612c5d565b0390fd5b612d13611316565b50612d1d8261210c565b81612d30612d2a83610358565b91610358565b14908115612d6d575b50918215612d47575b505090565b612d65919250612d59612d5f91611643565b92610358565b91610358565b145f80612d42565b612d79915082906129d5565b5f612d39565b60207f6f776e6572000000000000000000000000000000000000000000000000000000917f4552433732313a207472616e736665722066726f6d20696e636f7272656374205f8201520152565b612dd96025604092610434565b612de281612d7f565b0190565b612dfb9060208101905f818303910152612dcc565b90565b15612e0557565b612e0d610292565b62461bcd60e51b815280612e2360048201612de6565b0390fd5b60207f7265737300000000000000000000000000000000000000000000000000000000917f4552433732313a207472616e7366657220746f20746865207a65726f206164645f8201520152565b612e816024604092610434565b612e8a81612e27565b0190565b612ea39060208101905f818303910152612e74565b90565b15612ead57565b612eb5610292565b62461bcd60e51b815280612ecb60048201612e8e565b0390fd5b90565b612ee6612ee1612eeb92612ecf565b610a35565b6104d0565b90565b91906008612f0e910291612f0860018060a01b0384611d98565b92611d98565b9181191691161790565b9190612f2e612f29612f369361142f565b612a6c565b908354612eee565b9055565b612f4c91612f46611603565b91612f18565b565b90612f5991036104d0565b90565b90612f6791016104d0565b90565b919091612f91612f798361210c565b612f8b612f8584610358565b91610358565b14612dfe565b612fb683612faf612fa9612fa45f6113fb565b610358565b91610358565b1415612ea6565b612fda612fc28361210c565b612fd4612fce84610358565b91610358565b14612dfe565b612fef5f612fea60048590611607565b612f3a565b613020612ffc6001612ed2565b61301a61300b600385906122ff565b9161301583611877565b612f4e565b90612178565b61305161302d6001612ed2565b61304b61303c600387906122ff565b9161304683611877565b612f5c565b90612178565b6130668361306160028590611607565b612a6f565b916130a361309d6130977fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9561142f565b9261142f565b92611115565b926130ac610292565b806130b6816103e8565b0390a4565b906130c760ff91610e6d565b9181191691161790565b6130da906102f1565b90565b90565b906130f56130f06130fc926130d1565b6130dd565b82546130bb565b9055565b61311461310e828490612396565b156102f1565b61311d575b5050565b61313f600161313a5f613132600c86906119b9565b018590612359565b6130e0565b90613148612bdc565b9061318561317f6131797f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d956119ad565b9261142f565b9261142f565b9261318e610292565b80613198816103e8565b0390a45f80613119565b6131ad818390612396565b6131b6575b5050565b6131d75f6131d25f6131ca600c86906119b9565b018590612359565b6130e0565b906131e0612bdc565b9061321d6132176132117ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b956119ad565b9261142f565b9261142f565b92613226610292565b80613230816103e8565b0390a45f806131b2565b6132438161210c565b5061324d8161210c565b6132625f61325d60048590611607565b612f3a565b61329361326f6001612ed2565b61328d61327e600385906122ff565b9161328883611877565b612f4e565b90612178565b6132a85f6132a360028590611607565b612f3a565b906132b25f6113fb565b6132ee6132e86132e27fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9561142f565b9261142f565b92611115565b926132f7610292565b80613301816103e8565b0390a4565b61331d61332291613315611603565b506002611607565b611636565b90565b60409061334e613355949695939661334460608401985f85019061076a565b602083019061076a565b019061076a565b565b90613369613363611884565b156102f1565b613378576133769161348a565b565b6133826006611877565b61338c6007611877565b906133a8425f93849363657bd80360e11b855260048501613325565b0390fd5b905090565b6133bc5f80926133ac565b0190565b6133c9906133b1565b90565b906133de6133d983610ff8565b610fe3565b918252565b606090565b3d5f14613403576133f83d6133cc565b903d5f602084013e5b565b61340b6133e3565b90613401565b61341a90611c61565b9052565b9190613431905f60208501940190613411565b565b613442613448919392936104d0565b926104d0565b820391821161345357565b611a5c565b604090613481613488949695939661347760608401985f850190610514565b602083019061076a565b019061076a565b565b346134a66134a061349b6008611877565b6104d0565b916104d0565b03613647576134dc6134ce6134bb6008611877565b6134c86002600901611877565b90611a70565b6134d661121d565b90611ab9565b61351c5f806134f56134f082600901611c54565b611c61565b846134fe610292565b9081613509816133c0565b03925af16135156133e8565b50156102f1565b61361d5761352d6002600901611877565b61354661354061353b61121d565b6104d0565b916104d0565b03613594575b50906135586008611877565b9161358f7f0bfc06de9d7140d29ad4067e15d229191159e8b0e0c60fc0a569cf63e9745fca93613586610292565b93849384613458565b0390a1565b5f806135e8926135c26135b26135ad6001600901611c54565b611c61565b916135bd6008611877565b613433565b6135ca610292565b90816135d5816133c0565b03925af16135e16133e8565b50156102f1565b6135f2575f61354c565b6136196136026001600901611c54565b5f918291631a1dc3c960e11b83526004830161341e565b0390fd5b61364361362c5f600901611c54565b5f918291631a1dc3c960e11b83526004830161341e565b0390fd5b6136516008611877565b349061366d5f9283926304cb94e560e01b845260048401612c5d565b0390fd5b9061367b91613357565b565b90565b61368c613691916104d0565b61367d565b9052565b60601b90565b6136a490613695565b90565b6136b09061369b565b90565b6136bf6136c491610358565b6136a7565b9052565b602093926136e885836136e06014956136f097613680565b0180926136b3565b018092613680565b0190565b60200190565b5190565b61370a61370f9161161d565b611115565b90565b90565b61372961372461372e92613712565b610a35565b6104d0565b90565b61373d613743916104d0565b916104d0565b90811561374e570690565b611aa5565b613762613768919392936104d0565b926104d0565b820180921161377357565b611a5c565b60ff1690565b61379261378d613797926104d0565b610a35565b613778565b90565b6137ae6137a96137b392613778565b610a35565b6104d0565b90565b61385b906137c2611a15565b5061385661383c613837613827613817426137ff33916137f0896137e4610292565b948593602085016136c8565b60208201810382520382610fba565b61381161380b826136fa565b916136f4565b206136fe565b6138216005613715565b90613731565b6138316001612ed2565b90613753565b61377e565b916138516138498461379a565b916012611131565b612178565b61379a565b90565b90613872919061386c611d0b565b91614005565b565b5f7f4552433732313a20617070726f766520746f2063616c6c657200000000000000910152565b6138a86019602092610434565b6138b181613874565b0190565b6138ca9060208101905f81830391015261389b565b90565b156138d457565b6138dc610292565b62461bcd60e51b8152806138f2600482016138b5565b0390fd5b9190916139168161390f61390986610358565b91610358565b14156138cd565b61393582613930613929600585906129bf565b8690612359565b6130e0565b91909161398061396e6139687f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319361142f565b9361142f565b93613977610292565b91829182610303565b0390a3565b60207f63656976657220696d706c656d656e7465720000000000000000000000000000917f4552433732313a207472616e7366657220746f206e6f6e2045524337323152655f8201520152565b6139df6032604092610434565b6139e881613985565b0190565b613a019060208101905f8183039101526139d2565b90565b15613a0b57565b613a13610292565b62461bcd60e51b815280613a29600482016139ec565b0390fd5b92613a4b92613a5094613a4281858491612f6a565b92909192614105565b613a04565b565b613a6490613a5e611316565b50613306565b613a7e613a78613a735f6113fb565b610358565b91610358565b141590565b369037565b90613aad613a9583611ce8565b92602080613aa38693611cc5565b9201910390613a83565b565b6001613abb91036104d0565b90565b90565b613ad5613ad0613ada92613abe565b610a35565b6104d0565b90565b613ae9613aef916104d0565b916104d0565b908115613afa570490565b611aa5565b613b076114d2565b50613b24613b1482614331565b613b1e6001612ed2565b90612f5c565b90613b2e82613a88565b91613b37611a15565b5060200182015b600115613ba157613b51613b7d91613aaf565b916f181899199a1a9b1b9c1cb0b131b232b360811b600a82061a8353613b77600a613ac1565b90613add565b80613b90613b8a5f612428565b916104d0565b14613b9b5790613b3e565b50505b90565b5050613b9e565b90565b613bbf613bba613bc492613ba8565b610a35565b6104d0565b90565b90565b613bde613bd9613be392613bc7565b610a35565b6104d0565b90565b90565b613bfd613bf8613c0292613be6565b610a35565b6104d0565b90565b5f7f4d79746869630000000000000000000000000000000000000000000000000000910152565b613c366006611ce8565b90613c4360208301613c05565b565b613c4d613c2c565b90565b5f7f4f7267616e696300000000000000000000000000000000000000000000000000910152565b613c816007611ce8565b90613c8e60208301613c50565b565b613c98613c77565b90565b5f7f496e647573747269616c00000000000000000000000000000000000000000000910152565b613ccc600a611ce8565b90613cd960208301613c9b565b565b613ce3613cc2565b90565b5f7f436c617373696300000000000000000000000000000000000000000000000000910152565b613d176007611ce8565b90613d2460208301613ce6565b565b613d2e613d0d565b90565b5f7f4675747572650000000000000000000000000000000000000000000000000000910152565b613d626006611ce8565b90613d6f60208301613d31565b565b613d79613d58565b90565b613d93613d9891613d8b6114d2565b506012611131565b611877565b80613dac613da66001612ed2565b916104d0565b145f14613dbf5750613dbc613d71565b90565b80613dd3613dcd6002613bab565b916104d0565b145f14613de65750613de3613d26565b90565b80613dfa613df46003613bca565b916104d0565b145f14613e0d5750613e0a613cdb565b90565b613e20613e1a6004613be9565b916104d0565b145f14613e3257613e2f613c90565b90565b613e3a613c45565b90565b613e45611316565b5080613e60613e5a6380ac58cd60e01b6102a4565b916102a4565b148015613e84575b908115613e74575b5090565b613e7e9150614592565b5f613e70565b5080613e9f613e99635b5e139f60e01b6102a4565b916102a4565b14613e68565b90565b613ebc613eb7613ec192613ea5565b610a35565b6104d0565b90565b5f7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000910152565b613ef760178092612444565b613f0081613ec4565b0190565b5f7f206973206d697373696e6720726f6c6520000000000000000000000000000000910152565b613f3760118092612444565b613f4081613f04565b0190565b613f5e613f699392613f58613f6393613eeb565b90612449565b613f2b565b90612449565b90565b90613f81613f7b838390612396565b156102f1565b613f89575050565b61400191613fdf613fb8613fa8613fa2613fe49561460c565b936136fe565b613fb26020613ea8565b906147d5565b91613fd0613fc4610292565b93849260208401613f44565b60208201810382520382610fba565b61247e565b613fec610292565b91829162461bcd60e51b835260048301610483565b0390fd5b61402f9261402a92614018838290614a1f565b6140215f6113fb565b92909192614105565b613a04565b565b61403a90611407565b90565b61404690614031565b90565b61405290611423565b90565b60e01b90565b90505190614068826102b0565b565b9060208282031261408357614080915f0161405b565b90565b61029c565b60209181520190565b6140b06140b96020936140be936140a7816136fa565b93848093614088565b9586910161043d565b610448565b0190565b90926140f5906140eb61410296946140e160808601975f870190610514565b6020850190610514565b604083019061076a565b6060818403910152614091565b90565b909392614110611316565b9461411a81614b1d565b5f1461422e57906141615f6141396141346020969561403d565b614049565b9261416c63150b7a029161414b612bdc565b9698614155610292565b998a9889978896614055565b8652600486016140c2565b03925af180915f926141fe575b50155f146141de5750600161418a57565b6141926133e8565b61419b816136fa565b6141ad6141a75f612428565b916104d0565b145f146141d6576141bc610292565b62461bcd60e51b8152806141d2600482016139ec565b0390fd5b805190602001fd5b9091506141fa6141f4630a85bd0160e11b6102a4565b916102a4565b1490565b61422091925060203d8111614227575b6142188183610fba565b81019061406a565b905f614179565b503d61420e565b505050509050600190565b90565b61425061424b61425592614239565b610a35565b6104d0565b90565b90565b61426f61426a61427492614258565b610a35565b6104d0565b90565b90565b61428e61428961429392614277565b610a35565b6104d0565b90565b90565b6142ad6142a86142b292614296565b610a35565b6104d0565b90565b90565b6142cc6142c76142d1926142b5565b610a35565b6104d0565b90565b90565b6142eb6142e66142f0926142d4565b610a35565b6104d0565b90565b90565b61430a61430561430f926142f3565b610a35565b6104d0565b90565b90565b61432961432461432e92614312565b610a35565b6104d0565b90565b614339611a15565b506143435f612428565b908061437261436c7a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000061423c565b916104d0565b101561454a575b8061439a6143946d04ee2d6d415b85acef810000000061427a565b916104d0565b101561450f575b806143bb6143b5662386f26fc10000614299565b916104d0565b10156144db575b806143d96143d36305f5e1006142d7565b916104d0565b10156144aa575b806143f56143ef612710611201565b916104d0565b101561447b575b8061441061440a6064614315565b916104d0565b101561444d575b61442a614424600a613ac1565b916104d0565b1015614434575b90565b614448906144426001612ed2565b90612f5c565b614431565b6144646144759161445e6064614315565b90613add565b9161446f6002613bab565b90612f5c565b90614417565b6144936144a49161448d612710611201565b90613add565b9161449e6004613be9565b90612f5c565b906143fc565b6144c46144d5916144be6305f5e1006142d7565b90613add565b916144cf60086142f6565b90612f5c565b906143e0565b6144f8614509916144f2662386f26fc10000614299565b90613add565b9161450360106142b8565b90612f5c565b906143c2565b6145336145449161452d6d04ee2d6d415b85acef810000000061427a565b90613add565b9161453e6020613ea8565b90612f5c565b906143a1565b61457b61458c916145757a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000061423c565b90613add565b91614586604061425b565b90612f5c565b90614379565b61459a611316565b506145b46145ae6301ffc9a760e01b6102a4565b916102a4565b1490565b6145c190611407565b90565b6145d86145d36145dd9261034d565b610a35565b6104d0565b90565b90565b6145f76145f26145fc926145e0565b610a35565b613778565b90565b61460960146145e3565b90565b61462961462461463f9261461e6114d2565b506145b8565b6145c4565b6146396146346145ff565b61379a565b906147d5565b90565b9061466761464f836133cc565b9260208061465d8693610ff8565b9201910390613a83565b565b600360fc1b90565b634e487b7160e01b5f52603260045260245ffd5b9061468f826136fa565b8110156146a157600160209102010190565b614671565b600f60fb1b90565b6146b7906104d0565b5f81146146c5576001900390565b611a5c565b6f181899199a1a9b1b9c1cb0b131b232b360811b90565b6146e96146ca565b90565b90565b6147036146fe614708926146ec565b610a35565b6104d0565b90565b60f81b90565b61472561472061472a92613be6565b610a35565b613778565b90565b61474c9061474661474061475194613778565b916104d0565b90610866565b6104d0565b90565b5f7f537472696e67733a20686578206c656e67746820696e73756666696369656e74910152565b61478760208092610434565b61479081614754565b0190565b6147a99060208101905f81830391015261477b565b90565b156147b357565b6147bb610292565b62461bcd60e51b8152806147d160048201614794565b0390fd5b91906147df6114d2565b5061487661486661481561481061480060026147fb8791613bab565b611a70565b61480a6002613bab565b90613753565b614642565b9261481e614669565b6148358561482f5f935f1a93612428565b90614685565b5361483e6146a6565b614856856148506001935f1a93612ed2565b90614685565b536148616002613bab565b611a70565b6148706001612ed2565b90613753565b925b8361488c6148866001612ed2565b916104d0565b11156148f25761489a6146e1565b816148a5600f6146ef565b169160108310156148ed576148c16148e1926148e7941a61470b565b6148d0859188905f1a92614685565b536148db6004614711565b9061472d565b936146ae565b92614878565b614671565b6149199293506149149061490e6149085f612428565b916104d0565b146147ac565b61247e565b90565b5f7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373910152565b61494f60208092610434565b6149588161491c565b0190565b6149719060208101905f818303910152614943565b90565b1561497b57565b614983610292565b62461bcd60e51b8152806149996004820161495c565b0390fd5b5f7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000910152565b6149d1601c602092610434565b6149da8161499d565b0190565b6149f39060208101905f8183039101526149c4565b90565b156149fd57565b614a05610292565b62461bcd60e51b815280614a1b600482016149de565b0390fd5b90614a4582614a3e614a38614a335f6113fb565b610358565b91610358565b1415614974565b614a5f614a5a614a5483613a52565b156102f1565b6149f6565b614a79614a74614a6e83613a52565b156102f1565b6149f6565b614aaa614a866001612ed2565b614aa4614a95600386906122ff565b91614a9f83611877565b612f5c565b90612178565b614abf82614aba60028490611607565b612a6f565b614ac85f6113fb565b91614b05614aff614af97fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9561142f565b9261142f565b92611115565b92614b0e610292565b80614b18816103e8565b0390a4565b614b25611316565b503b614b39614b335f612428565b916104d0565b119056fea26469706673582212209f3d897270eed2192a73e3d69dd3280d8dbfc0ff77942a77be089496807c3c2164736f6c634300081e0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002600000000000000000000000003e08ad7c3fd70d08cdd2a11247dae18eb06434fd000000000000000000000000d50a66b631544454b21bc32f5a2723428dbf3073000000000000000000000000d3f14acb49456bc41912e6580614ad4b6d49a720000000000000000000000000053f171c0d0cc9d76247d4d1cddb280bf11313900000000000000000000000000000000000000000000000000000000000001d4c000000000000000000000000000000000000000000000000a688906bd8b00000000000000000000000000000000000000000000000000000000000006936d9e000000000000000000000000000000000000000000000000000000000695be0000000000000000000000000000000000000000000000000000000000000000013457370726573736f20427265777320526172690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044252455700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003368747470733a2f2f78636861696e2d6e66742e73332e75732d656173742d322e616d617a6f6e6177732e636f6d2f726172692f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045261726900000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _name (string): Espresso Brews Rari
Arg [1] : _symbol (string): BREW
Arg [2] : _baseImageURI (string): https://xchain-nft.s3.us-east-2.amazonaws.com/rari/
Arg [3] : _chainName (string): Rari
Arg [4] : _espHypErc20 (address): 0x3e08Ad7C3fD70D08CdD2a11247dae18Eb06434FD
Arg [5] : _priceAdmin (address): 0xD50a66B631544454b21BC32f5A2723428dbf3073
Arg [6] : _treasury (tuple):
Arg [1] : espresso (address): 0xD3F14acB49456Bc41912e6580614Ad4b6D49a720
Arg [2] : partner (address): 0x053F171c0D0Cc9d76247D4d1CdDb280bf1131390
Arg [3] : percentageEspresso (uint256): 7500
Arg [7] : _nftSalePrice (uint256): 12000000000000000000
Arg [8] : _startSale (uint256): 1765202400
Arg [9] : _endSale (uint256): 1767628800
-----Encoded View---------------
21 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000180
Arg [1] : 00000000000000000000000000000000000000000000000000000000000001c0
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000200
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000260
Arg [4] : 0000000000000000000000003e08ad7c3fd70d08cdd2a11247dae18eb06434fd
Arg [5] : 000000000000000000000000d50a66b631544454b21bc32f5a2723428dbf3073
Arg [6] : 000000000000000000000000d3f14acb49456bc41912e6580614ad4b6d49a720
Arg [7] : 000000000000000000000000053f171c0d0cc9d76247d4d1cddb280bf1131390
Arg [8] : 0000000000000000000000000000000000000000000000000000000000001d4c
Arg [9] : 000000000000000000000000000000000000000000000000a688906bd8b00000
Arg [10] : 000000000000000000000000000000000000000000000000000000006936d9e0
Arg [11] : 00000000000000000000000000000000000000000000000000000000695be000
Arg [12] : 0000000000000000000000000000000000000000000000000000000000000013
Arg [13] : 457370726573736f204272657773205261726900000000000000000000000000
Arg [14] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [15] : 4252455700000000000000000000000000000000000000000000000000000000
Arg [16] : 0000000000000000000000000000000000000000000000000000000000000033
Arg [17] : 68747470733a2f2f78636861696e2d6e66742e73332e75732d656173742d322e
Arg [18] : 616d617a6f6e6177732e636f6d2f726172692f00000000000000000000000000
Arg [19] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [20] : 5261726900000000000000000000000000000000000000000000000000000000
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.