Overview
ETH Balance
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 51,268 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Batch Set Bid Pr... | 424099157 | 3 days ago | IN | 0 ETH | 0.0000035 | ||||
| Batch Set Bid Pr... | 418351747 | 20 days ago | IN | 0 ETH | 0.00000173 | ||||
| Batch Set Bid Pr... | 412010884 | 38 days ago | IN | 0 ETH | 0.00000173 | ||||
| Batch Set Bid Pr... | 407105080 | 52 days ago | IN | 0 ETH | 0.0000105 | ||||
| Batch Set Bid Pr... | 402795943 | 65 days ago | IN | 0 ETH | 0.00000174 | ||||
| Batch Set Bid Pr... | 401786961 | 67 days ago | IN | 0 ETH | 0.00000204 | ||||
| Batch Set Bid Pr... | 396959333 | 81 days ago | IN | 0 ETH | 0.00000176 | ||||
| Set Bid Price | 393628518 | 91 days ago | IN | 0 ETH | 0.0000004 | ||||
| Set Bid Price | 393624672 | 91 days ago | IN | 0 ETH | 0.00000036 | ||||
| Set Bid Price | 393624616 | 91 days ago | IN | 0 ETH | 0.00000036 | ||||
| Set Bid Price | 393624560 | 91 days ago | IN | 0 ETH | 0.00000036 | ||||
| Set Bid Price | 393624179 | 91 days ago | IN | 0 ETH | 0.00000036 | ||||
| Set Bid Price | 393624099 | 91 days ago | IN | 0 ETH | 0.00000036 | ||||
| Batch Set Bid Pr... | 390588376 | 100 days ago | IN | 0 ETH | 0.00000177 | ||||
| Complete Ask Min... | 389390397 | 103 days ago | IN | 0 ETH | 0.00000581 | ||||
| Ask Mint | 389390387 | 103 days ago | IN | 0.004 ETH | 0.00000378 | ||||
| Batch Set Bid Pr... | 389261515 | 104 days ago | IN | 0 ETH | 0.00000174 | ||||
| Complete Ask Min... | 389056317 | 104 days ago | IN | 0 ETH | 0.000004 | ||||
| Ask Mint | 389056276 | 104 days ago | IN | 0.0032 ETH | 0.00000269 | ||||
| Buy | 388685932 | 105 days ago | IN | 0.0518 ETH | 0.00000695 | ||||
| Batch Set Bid Pr... | 388525872 | 106 days ago | IN | 0 ETH | 0.00001752 | ||||
| Batch Set Bid Pr... | 369928035 | 160 days ago | IN | 0 ETH | 0.00000175 | ||||
| Batch Set Bid Pr... | 368226892 | 164 days ago | IN | 0 ETH | 0.00000178 | ||||
| Batch Set Bid Pr... | 366625744 | 169 days ago | IN | 0 ETH | 0.00000187 | ||||
| Batch Set Bid Pr... | 359101783 | 191 days ago | IN | 0 ETH | 0.00000316 |
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 389390387 | 103 days ago | 0.004 ETH | ||||
| 389056276 | 104 days ago | 0.0032 ETH | ||||
| 388685932 | 105 days ago | 0.05 ETH | ||||
| 388685932 | 105 days ago | 0.0018 ETH | ||||
| 350839101 | 215 days ago | 0.004 ETH | ||||
| 350707804 | 215 days ago | 0.004 ETH | ||||
| 350695510 | 215 days ago | 0.004 ETH | ||||
| 350684740 | 215 days ago | 0.004 ETH | ||||
| 350678607 | 215 days ago | 0.004 ETH | ||||
| 350675733 | 215 days ago | 0.004 ETH | ||||
| 350671473 | 215 days ago | 0.004 ETH | ||||
| 350666415 | 215 days ago | 0.004 ETH | ||||
| 350639741 | 215 days ago | 0.004 ETH | ||||
| 350547914 | 216 days ago | 0.004 ETH | ||||
| 350541952 | 216 days ago | 0.004 ETH | ||||
| 350492038 | 216 days ago | 0.004 ETH | ||||
| 350491969 | 216 days ago | 0.004 ETH | ||||
| 350489477 | 216 days ago | 0.004 ETH | ||||
| 350471118 | 216 days ago | 0.004 ETH | ||||
| 350470696 | 216 days ago | 0.004 ETH | ||||
| 350469293 | 216 days ago | 0.004 ETH | ||||
| 350467031 | 216 days ago | 0.004 ETH | ||||
| 350464966 | 216 days ago | 0.004 ETH | ||||
| 350463152 | 216 days ago | 0.004 ETH | ||||
| 350462023 | 216 days ago | 0.004 ETH |
Cross-Chain Transactions
Contract Source Code (Solidity)
/**
*Submitted for verification at Arbiscan.io on 2025-02-15
*/
pragma solidity 0.8.28;
abstract contract A_Base{
}
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https: *
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
interface I_Dust{
function getETHDust() external;
function getTokenDust(IERC20 token) external;
receive() external payable;
fallback() external payable;
}
/**
* @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;
}
}
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
abstract contract A_Dust is A_Base, Ownable, I_Dust{
function getETHDust() external onlyOwner {
payable(owner()).transfer(address(this).balance);
}
function getTokenDust(IERC20 token) external onlyOwner {
token.transfer(owner(), token.balanceOf(address(this)));
}
receive() external payable {
_receive();
}
function _receive() internal virtual {
payable(owner()).transfer(msg.value);
}
fallback() external payable{
payable(owner()).transfer(msg.value);
}
}
interface I_Math{
struct Fraction{
uint256 numerator;
uint256 denominator;
}
}
/**
* @custom:security-contact [email protected]
*/
interface I_Runbot_Fees is I_Math, I_Dust {
event PendingBuyTransferClaimed(address indexed owner, address indexed to, uint256 amount);
struct BorrowFees{
uint256 feesMin;
uint256 feesMax;
uint256 durationMin; uint256 durationMax; }
struct RoyaltyFees{
address receiver;
Fraction fees;
}
struct StackingTier{
uint256 minAmount;
uint256 minDuration;
Fraction mintFeeReduction;
Fraction buyFeeReduction; }
function setStackingContract(address stackingContract_) external;
function setStackingTier(uint256 index, uint256 amount, uint256 duration, uint256 feesMintNumerator, uint256 feesMintDenominator, uint256 feesBuyNumerator, uint256 feesBuyDenominator) external;
function getStackingTier(uint256 index) external view returns (StackingTier memory);
function setTransferFees(uint256 fees) external ;
function getTransferFees(address transferer) external view returns (uint256);
function getFeesBase(uint256 nftType) external view returns (uint256, Fraction memory, BorrowFees memory);
function getFeesAddBase(uint256 nftType, uint256 nftSubType) external view returns (uint256, Fraction memory, BorrowFees memory);
function getMintFeesType(uint256 nftType) external view returns (uint256);
function getMintFeesTypeAdd(uint256 nftType, uint256 nftSubType) external view returns (uint256);
function setFundingFees(uint256 nftType, uint256 numerator, uint256 denominator) external;
function setFundingFeesAdd(uint256 nftType, uint256 nftSubType, uint256 numerator, uint256 denominator) external;
function setMintFeesRebate(uint256 nbMint, uint256 numerator, uint256 denominator) external;
function getMintFeesRebate(address minter) external view returns (uint256, Fraction memory);
function setBaseFees(uint256 nftType, uint256 fees) external;
function setBaseFeesAdd(uint256 nftType, uint256 nftSubType, uint256 fees) external;
function setBorrowFees(uint256 nftType, uint256 feesMin, uint256 feesMax, uint256 durationMin, uint256 durationMax) external;
function setBorrowFeesAdd(uint256 nftType, uint256 nftSubType, uint256 feesMin, uint256 feesMax, uint256 durationMin, uint256 durationMax) external;
function setMintTypeFees(uint256 nftType, uint256 feesType) external;
function setMintTypeFeesAdd(uint256 nftType, uint256 nftSubType, uint256 feesType) external;
function addRoyaltyFees(uint256 nftType, address receiver, uint256 numerator, uint256 denominator) external;
function addRoyaltyFeesAdd(uint256 nftType, uint256 nftSubType, address receiver, uint256 numerator, uint256 denominator) external;
function updateRoyaltyFees(uint256 nftType, uint256 index, address receiver, uint256 numerator, uint256 denominator) external;
function updateRoyaltyFeesAdd(uint256 nftType, uint256 nftSubType, uint256 index, address receiver, uint256 numerator, uint256 denominator) external;
function deleteRoyaltyFees(uint256 nftType, uint256 index) external;
function deleteRoyaltyFeesAdd(uint256 nftType, uint256 nftSubType, uint256 index) external;
function getNbRoyaltyFees(uint256 nftType) external view returns (uint256);
function getNbRoyaltyFeesAdd(uint256 nftType, uint256 nftSubType) external view returns (uint256);
function getRoyaltyFees(uint256 nftType, uint256 index) external view returns (RoyaltyFees memory);
function getRoyaltyFeesAdd(uint256 nftType, uint256 nftSubType, uint256 index) external view returns (RoyaltyFees memory);
function getBaseFees(uint256 nftType, uint256 nftSubType, uint256 borrowDuration, bool isMint, uint256 mintNb, address minter) external view returns (uint256);
function getFees(uint256 nftType, uint256 nftSubType, uint256 bidPrice, bool withFirstBuyRebate, uint256 initialBorrowDuration, uint256 currentBorrowDuration, address seller, address buyer) external view returns (uint256);
function dispatchRoyaltyTransferFees(uint256 nftType, uint256 nftSubType, address transferer) external payable;
function dispatchRoyaltySellFees(uint256 nftType, uint256 nftSubType, address seller, address buyer) external payable;
function dispatchRoyaltyMintFees(uint256 nftType, uint256 nftSubType, address minter) external payable;
function claimPendingRoyaltyTransfer(address to) external;
}
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https: *
* 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: * 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);
}
/**
* @dev Required interface of an ERC-721 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 ERC-721 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 ERC-721
* 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 address zero.
*
* 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);
}
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https: */
interface IERC721Enumerable is IERC721 {
/**
* @dev Returns the total amount of tokens stored by the contract.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}
/**
* @custom:security-contact [email protected]
*/
interface I_Runbot_NFTs is I_Dust, IERC721, IERC721Enumerable {
event SetBidPrice(address indexed owner, uint256 indexed tokenId, uint256 bidPrice);
event Buy(address indexed buyer, address indexed seller, uint256 indexed tokenId, uint256 bidPrice, uint256 fees);
event Mint(address indexed minter, uint256 tokenId, uint256 nftType, uint256 nftSubType, uint256 bidPrice, uint256 borrowDuration, uint256 lockTimeout, bool withFirstBidRebate);
event Move(address indexed from, address indexed to, uint256 indexed tokenId);
event TransferAsked(uint256 askId, address indexed asker, address indexed receiver, uint256 indexed tokenId);
event MintAsked(uint256 mintId, address indexed asker, uint256 nb, uint256 nftType, uint256 nftSubType, uint256 borrowDuration, uint256 bidPrice);
event PendingBuyTransferClaimed(address indexed owner, address indexed to, uint256 amount);
struct MintAsk{
address asker;
uint256 nb;
uint256 nftType;
uint256 nftSubType;
uint256 borrowDuration;
uint256 bidPrice;
}
struct TransferAsk{
address asker;
address receiver;
uint256 tokenId;
}
function feesModel() external view returns (I_Runbot_Fees);
function setFeesModel(I_Runbot_Fees feesModel_) external;
function setBaseURI(string memory baseURI) external;
function askTransfer(address receiver, uint256 tokenId) external payable returns (uint256);
function getNbTransferAsks() external view returns (uint256);
function getFirstTransferAsk() external view returns (uint256, TransferAsk memory);
function completeTransferAsking(uint256 transferId, bool isApproved) external;
function migrateFromPreviousContract(I_Runbot_NFTs previousContract, uint256 nbtokens) external;
function askMint(uint256 nb, uint256 nftType, uint256 nftSubType, uint256 borrowDuration, uint256 bidPrice) external payable returns (uint256);
function getNbMintAsks() external view returns (uint256);
function getFirstMintAsk() external view returns (uint256, MintAsk memory);
function completeAskMint(uint256 mintId, uint256 lockTimeout, bool withFirstBidRebate, bool isApproved) external;
function batchSafeMint(uint256 nb, address to, uint256 nftType, uint256 nftSubType, uint256 bidPrice, uint256 borrowDuration, uint256 lockTimeout, bool withFirstBidRebate) external;
function batchSafeMintLinear(uint256 nb, address to, uint256 nftType, uint256 nftSubTypeStart, uint256 nftSubTypeAdd, uint256 bidPriceStart, uint256 bidPriceAdd, uint256 borrowDurationStart, uint256 borrowDurationAdd, uint256 lockTimeoutStart, uint256 lockTimeoutAdd, bool withFirstBidRebate) external;
function safeMint(address to, uint256 nftType, uint256 nftSubType, uint256 bidPrice, uint256 borrowDuration, uint256 lockTimeout, bool withFirstBidRebate) external;
function getNbMintedTokens() external view returns (uint256);
function getNbMintedTokensByType(uint256 nftType) external view returns (uint256);
function getNbMintedTokensBySubType(uint256 nftType, uint256 nftSubType) external view returns (uint256);
function getTokenIdByType(uint256 nfttype, uint256 index) external view returns (uint256);
function getTokenIdBySubType(uint256 nfttype, uint256 nftSubType, uint256 index) external view returns (uint256);
function setBidPrice(uint256 tokenId, uint256 bidPrice) external;
function batchSetBidPrice(uint256[] memory tokenIds, uint256[] memory bidPrices) external;
function getBidPrice(uint256 tokenId) external view returns (uint256);
function getInfos(uint256 tokenId) external view returns(uint256, uint256, uint256, uint256, bool, bool, uint256);
function getFees(uint256 tokenId) external view returns (uint256);
function buy(uint256 tokenId) external payable;
function buyTo(address to, uint256 tokenId) external payable;
function getBaseURI() external view returns (string memory);
function claimPendingBuyTransfer(address to) external;
}
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https: */
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);
}
/**
* @title ERC-721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC-721 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);
}
/**
* @dev Standard ERC-20 Errors
* Interface of the https: */
interface IERC20Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC20InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC20InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `spender`\u2019s `allowance`. Used in transfers.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC20InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `spender` to be approved. Used in approvals.
* @param spender Address that may be allowed to operate on tokens without being their owner.
*/
error ERC20InvalidSpender(address spender);
}
/**
* @dev Standard ERC-721 Errors
* Interface of the https: */
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
* Used in balance queries.
* @param owner Address of the current owner of a token.
*/
error ERC721InvalidOwner(address owner);
/**
* @dev Indicates a `tokenId` whose `owner` is the zero address.
* @param tokenId Identifier number of a token.
*/
error ERC721NonexistentToken(uint256 tokenId);
/**
* @dev Indicates an error related to the ownership over a particular token. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param tokenId Identifier number of a token.
* @param owner Address of the current owner of a token.
*/
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC721InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC721InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`\u2019s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param tokenId Identifier number of a token.
*/
error ERC721InsufficientApproval(address operator, uint256 tokenId);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC721InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC721InvalidOperator(address operator);
}
/**
* @dev Standard ERC-1155 Errors
* Interface of the https: */
interface IERC1155Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
* @param tokenId Identifier number of a token.
*/
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC1155InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC1155InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`\u2019s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param owner Address of the current owner of a token.
*/
error ERC1155MissingApprovalForAll(address operator, address owner);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC1155InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC1155InvalidOperator(address operator);
/**
* @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
* Used in batch transfers.
* @param idsLength Length of the array of token identifiers
* @param valuesLength Length of the array of token amounts
*/
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}
/**
* @dev Library that provide common ERC-721 utility functions.
*
* See https: *
* _Available since v5.1._
*/
library ERC721Utils {
/**
* @dev Performs an acceptance check for the provided `operator` by calling {IERC721-onERC721Received}
* on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).
*
* The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).
* Otherwise, the recipient must implement {IERC721Receiver-onERC721Received} and return the acceptance magic value to accept
* the transfer.
*/
function checkOnERC721Received(
address operator,
address from,
address to,
uint256 tokenId,
bytes memory data
) internal {
if (to.code.length > 0) {
try IERC721Receiver(to).onERC721Received(operator, from, tokenId, data) returns (bytes4 retval) {
if (retval != IERC721Receiver.onERC721Received.selector) {
revert IERC721Errors.ERC721InvalidReceiver(to);
}
} catch (bytes memory reason) {
if (reason.length == 0) {
revert IERC721Errors.ERC721InvalidReceiver(to);
} else {
assembly ("memory-safe") {
revert(add(32, reason), mload(reason))
}
}
}
}
}
}
/**
* @dev Helper library for emitting standardized panic codes.
*
* ```solidity
* contract Example {
* using Panic for uint256;
*
* * function foo() { Panic.GENERIC.panic(); }
*
* * function foo() { Panic.panic(Panic.GENERIC); }
* }
* ```
*
* Follows the list from https: *
* _Available since v5.1._
*/
library Panic {
uint256 internal constant GENERIC = 0x00;
uint256 internal constant ASSERT = 0x01;
uint256 internal constant UNDER_OVERFLOW = 0x11;
uint256 internal constant DIVISION_BY_ZERO = 0x12;
uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;
uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;
uint256 internal constant EMPTY_ARRAY_POP = 0x31;
uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;
uint256 internal constant RESOURCE_ERROR = 0x41;
uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;
function panic(uint256 code) internal pure {
assembly ("memory-safe") {
mstore(0x00, 0x4e487b71)
mstore(0x20, code)
revert(0x1c, 0x24)
}
}
}
/**
* @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeCast {
/**
* @dev Value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);
/**
* @dev An int value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedIntToUint(int256 value);
/**
* @dev Value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);
/**
* @dev An uint value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedUintToInt(uint256 value);
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toUint248(uint256 value) internal pure returns (uint248) {
if (value > type(uint248).max) {
revert SafeCastOverflowedUintDowncast(248, value);
}
return uint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toUint240(uint256 value) internal pure returns (uint240) {
if (value > type(uint240).max) {
revert SafeCastOverflowedUintDowncast(240, value);
}
return uint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toUint232(uint256 value) internal pure returns (uint232) {
if (value > type(uint232).max) {
revert SafeCastOverflowedUintDowncast(232, value);
}
return uint232(value);
}
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toUint224(uint256 value) internal pure returns (uint224) {
if (value > type(uint224).max) {
revert SafeCastOverflowedUintDowncast(224, value);
}
return uint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toUint216(uint256 value) internal pure returns (uint216) {
if (value > type(uint216).max) {
revert SafeCastOverflowedUintDowncast(216, value);
}
return uint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toUint208(uint256 value) internal pure returns (uint208) {
if (value > type(uint208).max) {
revert SafeCastOverflowedUintDowncast(208, value);
}
return uint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toUint200(uint256 value) internal pure returns (uint200) {
if (value > type(uint200).max) {
revert SafeCastOverflowedUintDowncast(200, value);
}
return uint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toUint192(uint256 value) internal pure returns (uint192) {
if (value > type(uint192).max) {
revert SafeCastOverflowedUintDowncast(192, value);
}
return uint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toUint184(uint256 value) internal pure returns (uint184) {
if (value > type(uint184).max) {
revert SafeCastOverflowedUintDowncast(184, value);
}
return uint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toUint176(uint256 value) internal pure returns (uint176) {
if (value > type(uint176).max) {
revert SafeCastOverflowedUintDowncast(176, value);
}
return uint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toUint168(uint256 value) internal pure returns (uint168) {
if (value > type(uint168).max) {
revert SafeCastOverflowedUintDowncast(168, value);
}
return uint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toUint160(uint256 value) internal pure returns (uint160) {
if (value > type(uint160).max) {
revert SafeCastOverflowedUintDowncast(160, value);
}
return uint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidity's `uint152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toUint152(uint256 value) internal pure returns (uint152) {
if (value > type(uint152).max) {
revert SafeCastOverflowedUintDowncast(152, value);
}
return uint152(value);
}
/**
* @dev Returns the downcasted uint144 from uint256, reverting on
* overflow (when the input is greater than largest uint144).
*
* Counterpart to Solidity's `uint144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toUint144(uint256 value) internal pure returns (uint144) {
if (value > type(uint144).max) {
revert SafeCastOverflowedUintDowncast(144, value);
}
return uint144(value);
}
/**
* @dev Returns the downcasted uint136 from uint256, reverting on
* overflow (when the input is greater than largest uint136).
*
* Counterpart to Solidity's `uint136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toUint136(uint256 value) internal pure returns (uint136) {
if (value > type(uint136).max) {
revert SafeCastOverflowedUintDowncast(136, value);
}
return uint136(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
if (value > type(uint128).max) {
revert SafeCastOverflowedUintDowncast(128, value);
}
return uint128(value);
}
/**
* @dev Returns the downcasted uint120 from uint256, reverting on
* overflow (when the input is greater than largest uint120).
*
* Counterpart to Solidity's `uint120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toUint120(uint256 value) internal pure returns (uint120) {
if (value > type(uint120).max) {
revert SafeCastOverflowedUintDowncast(120, value);
}
return uint120(value);
}
/**
* @dev Returns the downcasted uint112 from uint256, reverting on
* overflow (when the input is greater than largest uint112).
*
* Counterpart to Solidity's `uint112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toUint112(uint256 value) internal pure returns (uint112) {
if (value > type(uint112).max) {
revert SafeCastOverflowedUintDowncast(112, value);
}
return uint112(value);
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toUint104(uint256 value) internal pure returns (uint104) {
if (value > type(uint104).max) {
revert SafeCastOverflowedUintDowncast(104, value);
}
return uint104(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toUint96(uint256 value) internal pure returns (uint96) {
if (value > type(uint96).max) {
revert SafeCastOverflowedUintDowncast(96, value);
}
return uint96(value);
}
/**
* @dev Returns the downcasted uint88 from uint256, reverting on
* overflow (when the input is greater than largest uint88).
*
* Counterpart to Solidity's `uint88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toUint88(uint256 value) internal pure returns (uint88) {
if (value > type(uint88).max) {
revert SafeCastOverflowedUintDowncast(88, value);
}
return uint88(value);
}
/**
* @dev Returns the downcasted uint80 from uint256, reverting on
* overflow (when the input is greater than largest uint80).
*
* Counterpart to Solidity's `uint80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toUint80(uint256 value) internal pure returns (uint80) {
if (value > type(uint80).max) {
revert SafeCastOverflowedUintDowncast(80, value);
}
return uint80(value);
}
/**
* @dev Returns the downcasted uint72 from uint256, reverting on
* overflow (when the input is greater than largest uint72).
*
* Counterpart to Solidity's `uint72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toUint72(uint256 value) internal pure returns (uint72) {
if (value > type(uint72).max) {
revert SafeCastOverflowedUintDowncast(72, value);
}
return uint72(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
if (value > type(uint64).max) {
revert SafeCastOverflowedUintDowncast(64, value);
}
return uint64(value);
}
/**
* @dev Returns the downcasted uint56 from uint256, reverting on
* overflow (when the input is greater than largest uint56).
*
* Counterpart to Solidity's `uint56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toUint56(uint256 value) internal pure returns (uint56) {
if (value > type(uint56).max) {
revert SafeCastOverflowedUintDowncast(56, value);
}
return uint56(value);
}
/**
* @dev Returns the downcasted uint48 from uint256, reverting on
* overflow (when the input is greater than largest uint48).
*
* Counterpart to Solidity's `uint48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toUint48(uint256 value) internal pure returns (uint48) {
if (value > type(uint48).max) {
revert SafeCastOverflowedUintDowncast(48, value);
}
return uint48(value);
}
/**
* @dev Returns the downcasted uint40 from uint256, reverting on
* overflow (when the input is greater than largest uint40).
*
* Counterpart to Solidity's `uint40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toUint40(uint256 value) internal pure returns (uint40) {
if (value > type(uint40).max) {
revert SafeCastOverflowedUintDowncast(40, value);
}
return uint40(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toUint32(uint256 value) internal pure returns (uint32) {
if (value > type(uint32).max) {
revert SafeCastOverflowedUintDowncast(32, value);
}
return uint32(value);
}
/**
* @dev Returns the downcasted uint24 from uint256, reverting on
* overflow (when the input is greater than largest uint24).
*
* Counterpart to Solidity's `uint24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toUint24(uint256 value) internal pure returns (uint24) {
if (value > type(uint24).max) {
revert SafeCastOverflowedUintDowncast(24, value);
}
return uint24(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
if (value > type(uint16).max) {
revert SafeCastOverflowedUintDowncast(16, value);
}
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toUint8(uint256 value) internal pure returns (uint8) {
if (value > type(uint8).max) {
revert SafeCastOverflowedUintDowncast(8, value);
}
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
if (value < 0) {
revert SafeCastOverflowedIntToUint(value);
}
return uint256(value);
}
/**
* @dev Returns the downcasted int248 from int256, reverting on
* overflow (when the input is less than smallest int248 or
* greater than largest int248).
*
* Counterpart to Solidity's `int248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(248, value);
}
}
/**
* @dev Returns the downcasted int240 from int256, reverting on
* overflow (when the input is less than smallest int240 or
* greater than largest int240).
*
* Counterpart to Solidity's `int240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(240, value);
}
}
/**
* @dev Returns the downcasted int232 from int256, reverting on
* overflow (when the input is less than smallest int232 or
* greater than largest int232).
*
* Counterpart to Solidity's `int232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(232, value);
}
}
/**
* @dev Returns the downcasted int224 from int256, reverting on
* overflow (when the input is less than smallest int224 or
* greater than largest int224).
*
* Counterpart to Solidity's `int224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(224, value);
}
}
/**
* @dev Returns the downcasted int216 from int256, reverting on
* overflow (when the input is less than smallest int216 or
* greater than largest int216).
*
* Counterpart to Solidity's `int216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(216, value);
}
}
/**
* @dev Returns the downcasted int208 from int256, reverting on
* overflow (when the input is less than smallest int208 or
* greater than largest int208).
*
* Counterpart to Solidity's `int208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(208, value);
}
}
/**
* @dev Returns the downcasted int200 from int256, reverting on
* overflow (when the input is less than smallest int200 or
* greater than largest int200).
*
* Counterpart to Solidity's `int200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(200, value);
}
}
/**
* @dev Returns the downcasted int192 from int256, reverting on
* overflow (when the input is less than smallest int192 or
* greater than largest int192).
*
* Counterpart to Solidity's `int192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(192, value);
}
}
/**
* @dev Returns the downcasted int184 from int256, reverting on
* overflow (when the input is less than smallest int184 or
* greater than largest int184).
*
* Counterpart to Solidity's `int184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(184, value);
}
}
/**
* @dev Returns the downcasted int176 from int256, reverting on
* overflow (when the input is less than smallest int176 or
* greater than largest int176).
*
* Counterpart to Solidity's `int176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(176, value);
}
}
/**
* @dev Returns the downcasted int168 from int256, reverting on
* overflow (when the input is less than smallest int168 or
* greater than largest int168).
*
* Counterpart to Solidity's `int168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(168, value);
}
}
/**
* @dev Returns the downcasted int160 from int256, reverting on
* overflow (when the input is less than smallest int160 or
* greater than largest int160).
*
* Counterpart to Solidity's `int160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(160, value);
}
}
/**
* @dev Returns the downcasted int152 from int256, reverting on
* overflow (when the input is less than smallest int152 or
* greater than largest int152).
*
* Counterpart to Solidity's `int152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(152, value);
}
}
/**
* @dev Returns the downcasted int144 from int256, reverting on
* overflow (when the input is less than smallest int144 or
* greater than largest int144).
*
* Counterpart to Solidity's `int144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(144, value);
}
}
/**
* @dev Returns the downcasted int136 from int256, reverting on
* overflow (when the input is less than smallest int136 or
* greater than largest int136).
*
* Counterpart to Solidity's `int136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(136, value);
}
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(128, value);
}
}
/**
* @dev Returns the downcasted int120 from int256, reverting on
* overflow (when the input is less than smallest int120 or
* greater than largest int120).
*
* Counterpart to Solidity's `int120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(120, value);
}
}
/**
* @dev Returns the downcasted int112 from int256, reverting on
* overflow (when the input is less than smallest int112 or
* greater than largest int112).
*
* Counterpart to Solidity's `int112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(112, value);
}
}
/**
* @dev Returns the downcasted int104 from int256, reverting on
* overflow (when the input is less than smallest int104 or
* greater than largest int104).
*
* Counterpart to Solidity's `int104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(104, value);
}
}
/**
* @dev Returns the downcasted int96 from int256, reverting on
* overflow (when the input is less than smallest int96 or
* greater than largest int96).
*
* Counterpart to Solidity's `int96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(96, value);
}
}
/**
* @dev Returns the downcasted int88 from int256, reverting on
* overflow (when the input is less than smallest int88 or
* greater than largest int88).
*
* Counterpart to Solidity's `int88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(88, value);
}
}
/**
* @dev Returns the downcasted int80 from int256, reverting on
* overflow (when the input is less than smallest int80 or
* greater than largest int80).
*
* Counterpart to Solidity's `int80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(80, value);
}
}
/**
* @dev Returns the downcasted int72 from int256, reverting on
* overflow (when the input is less than smallest int72 or
* greater than largest int72).
*
* Counterpart to Solidity's `int72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(72, value);
}
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(64, value);
}
}
/**
* @dev Returns the downcasted int56 from int256, reverting on
* overflow (when the input is less than smallest int56 or
* greater than largest int56).
*
* Counterpart to Solidity's `int56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(56, value);
}
}
/**
* @dev Returns the downcasted int48 from int256, reverting on
* overflow (when the input is less than smallest int48 or
* greater than largest int48).
*
* Counterpart to Solidity's `int48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(48, value);
}
}
/**
* @dev Returns the downcasted int40 from int256, reverting on
* overflow (when the input is less than smallest int40 or
* greater than largest int40).
*
* Counterpart to Solidity's `int40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(40, value);
}
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(32, value);
}
}
/**
* @dev Returns the downcasted int24 from int256, reverting on
* overflow (when the input is less than smallest int24 or
* greater than largest int24).
*
* Counterpart to Solidity's `int24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(24, value);
}
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(16, value);
}
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(8, value);
}
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
if (value > uint256(type(int256).max)) {
revert SafeCastOverflowedUintToInt(value);
}
return int256(value);
}
/**
* @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
*/
function toUint(bool b) internal pure returns (uint256 u) {
assembly ("memory-safe") {
u := iszero(iszero(b))
}
}
}
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Floor, Ceil, Trunc, Expand }
/**
* @dev Returns the addition of two unsigned integers, with an success flag (no overflow).
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an success flag (no overflow).
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an success flag (no overflow).
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a success flag (no division by zero).
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
*
* IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
* However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
* one branch when needed, making this function more expensive.
*/
function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {
unchecked {
return b ^ ((a ^ b) * SafeCast.toUint(condition));
}
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return ternary(a > b, a, b);
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return ternary(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) {
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 towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
unchecked {
return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);
}
}
/**
* @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
*
* Original credit to Remco Bloemen under MIT license (https: * Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
uint256 prod0 = x * y; uint256 prod1; assembly {
let mm := mulmod(x, y, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 == 0) {
return prod0 / denominator;
}
if (denominator <= prod1) {
Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));
}
uint256 remainder;
assembly {
remainder := mulmod(x, y, denominator)
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
uint256 twos = denominator & (0 - denominator);
assembly {
denominator := div(denominator, twos)
prod0 := div(prod0, twos)
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
uint256 inverse = (3 * denominator) ^ 2;
inverse *= 2 - denominator * inverse; inverse *= 2 - denominator * inverse; inverse *= 2 - denominator * inverse; inverse *= 2 - denominator * inverse; inverse *= 2 - denominator * inverse; inverse *= 2 - denominator * inverse;
result = prod0 * inverse;
return result;
}
}
/**
* @dev 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) {
return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);
}
/**
* @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
*
* If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.
* If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.
*
* If the input value is not inversible, 0 is returned.
*
* NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the
* inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.
*/
function invMod(uint256 a, uint256 n) internal pure returns (uint256) {
unchecked {
if (n == 0) return 0;
uint256 remainder = a % n;
uint256 gcd = n;
int256 x = 0;
int256 y = 1;
while (remainder != 0) {
uint256 quotient = gcd / remainder;
(gcd, remainder) = (
remainder,
gcd - remainder * quotient
);
(x, y) = (
y,
x - y * int256(quotient)
);
}
if (gcd != 1) return 0; return ternary(x < 0, n - uint256(-x), uint256(x)); }
}
/**
* @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.
*
* From https: * prime, then `a**(p-1) \u2261 1 mod p`. As a consequence, we have `a * a**(p-2) \u2261 1 mod p`, which means that
* `a**(p-2)` is the modular multiplicative inverse of a in Fp.
*
* NOTE: this function does NOT check that `p` is a prime greater than `2`.
*/
function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {
unchecked {
return Math.modExp(a, p - 2, p);
}
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)
*
* Requirements:
* - modulus can't be zero
* - underlying staticcall to precompile must succeed
*
* IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make
* sure the chain you're using it on supports the precompiled contract for modular exponentiation
* at address 0x05 as specified in https: * the underlying function will succeed given the lack of a revert, but the result may be incorrectly
* interpreted as 0.
*/
function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {
(bool success, uint256 result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).
* It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying
* to operate modulo 0 or if the underlying precompile reverted.
*
* IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain
* you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in
* https: * of a revert, but the result may be incorrectly interpreted as 0.
*/
function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {
if (m == 0) return (false, 0);
assembly ("memory-safe") {
let ptr := mload(0x40)
mstore(ptr, 0x20)
mstore(add(ptr, 0x20), 0x20)
mstore(add(ptr, 0x40), 0x20)
mstore(add(ptr, 0x60), b)
mstore(add(ptr, 0x80), e)
mstore(add(ptr, 0xa0), m)
success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)
result := mload(0x00)
}
}
/**
* @dev Variant of {modExp} that supports inputs of arbitrary length.
*/
function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {
(bool success, bytes memory result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Variant of {tryModExp} that supports inputs of arbitrary length.
*/
function tryModExp(
bytes memory b,
bytes memory e,
bytes memory m
) internal view returns (bool success, bytes memory result) {
if (_zeroBytes(m)) return (false, new bytes(0));
uint256 mLen = m.length;
result = abi.encodePacked(b.length, e.length, mLen, b, e, m);
assembly ("memory-safe") {
let dataPtr := add(result, 0x20)
success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)
mstore(result, mLen)
mstore(0x40, add(dataPtr, mLen))
}
}
/**
* @dev Returns whether the provided byte array is zero.
*/
function _zeroBytes(bytes memory byteArray) private pure returns (bool) {
for (uint256 i = 0; i < byteArray.length; ++i) {
if (byteArray[i] != 0) {
return false;
}
}
return true;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
* towards zero.
*
* This method is based on Newton's method for computing square roots; the algorithm is restricted to only
* using integer operations.
*/
function sqrt(uint256 a) internal pure returns (uint256) {
unchecked {
if (a <= 1) {
return a;
}
uint256 aa = a;
uint256 xn = 1;
if (aa >= (1 << 128)) {
aa >>= 128;
xn <<= 64;
}
if (aa >= (1 << 64)) {
aa >>= 64;
xn <<= 32;
}
if (aa >= (1 << 32)) {
aa >>= 32;
xn <<= 16;
}
if (aa >= (1 << 16)) {
aa >>= 16;
xn <<= 8;
}
if (aa >= (1 << 8)) {
aa >>= 8;
xn <<= 4;
}
if (aa >= (1 << 4)) {
aa >>= 4;
xn <<= 2;
}
if (aa >= (1 << 2)) {
xn <<= 1;
}
xn = (3 * xn) >> 1;
xn = (xn + a / xn) >> 1; xn = (xn + a / xn) >> 1; xn = (xn + a / xn) >> 1; xn = (xn + a / xn) >> 1; xn = (xn + a / xn) >> 1; xn = (xn + a / xn) >> 1;
return xn - SafeCast.toUint(xn > a / xn);
}
}
/**
* @dev 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
uint256 exp;
unchecked {
exp = 128 * SafeCast.toUint(value > (1 << 128) - 1);
value >>= exp;
result += exp;
exp = 64 * SafeCast.toUint(value > (1 << 64) - 1);
value >>= exp;
result += exp;
exp = 32 * SafeCast.toUint(value > (1 << 32) - 1);
value >>= exp;
result += exp;
exp = 16 * SafeCast.toUint(value > (1 << 16) - 1);
value >>= exp;
result += exp;
exp = 8 * SafeCast.toUint(value > (1 << 8) - 1);
value >>= exp;
result += exp;
exp = 4 * SafeCast.toUint(value > (1 << 4) - 1);
value >>= exp;
result += exp;
exp = 2 * SafeCast.toUint(value > (1 << 2) - 1);
value >>= exp;
result += exp;
result += SafeCast.toUint(value > 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* 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;
uint256 isGt;
unchecked {
isGt = SafeCast.toUint(value > (1 << 128) - 1);
value >>= isGt * 128;
result += isGt * 16;
isGt = SafeCast.toUint(value > (1 << 64) - 1);
value >>= isGt * 64;
result += isGt * 8;
isGt = SafeCast.toUint(value > (1 << 32) - 1);
value >>= isGt * 32;
result += isGt * 4;
isGt = SafeCast.toUint(value > (1 << 16) - 1);
value >>= isGt * 16;
result += isGt * 2;
result += SafeCast.toUint(value > (1 << 8) - 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
*
* IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
* However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
* one branch when needed, making this function more expensive.
*/
function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) {
unchecked {
return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));
}
}
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return ternary(a > b, a, b);
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return ternary(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) {
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 {
int256 mask = n >> 255;
return uint256((n + mask) ^ mask);
}
}
}
/**
* @dev String operations.
*/
library Strings {
using SafeCast for *;
bytes16 private constant HEX_DIGITS = "0123456789abcdef";
uint8 private constant ADDRESS_LENGTH = 20;
/**
* @dev The `value` string doesn't fit in the specified `length`.
*/
error StringsInsufficientHexLength(uint256 value, uint256 length);
/**
* @dev The string being parsed contains characters that are not in scope of the given base.
*/
error StringsInvalidChar();
/**
* @dev The string being parsed is not a properly formatted address.
*/
error StringsInvalidAddressFormat();
/**
* @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;
assembly ("memory-safe") {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
assembly ("memory-safe") {
mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toStringSigned(int256 value) internal pure returns (string memory) {
return string.concat(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) {
uint256 localValue = value;
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = HEX_DIGITS[localValue & 0xf];
localValue >>= 4;
}
if (localValue != 0) {
revert StringsInsufficientHexLength(value, length);
}
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 Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal
* representation, according to EIP-55.
*/
function toChecksumHexString(address addr) internal pure returns (string memory) {
bytes memory buffer = bytes(toHexString(addr));
uint256 hashValue;
assembly ("memory-safe") {
hashValue := shr(96, keccak256(add(buffer, 0x22), 40))
}
for (uint256 i = 41; i > 1; --i) {
if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {
buffer[i] ^= 0x20;
}
hashValue >>= 4;
}
return string(buffer);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
}
/**
* @dev Parse a decimal string and returns the value as a `uint256`.
*
* Requirements:
* - The string must be formatted as `[0-9]*`
* - The result must fit into an `uint256` type
*/
function parseUint(string memory input) internal pure returns (uint256) {
return parseUint(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseUint} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `[0-9]*`
* - The result must fit into an `uint256` type
*/
function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {
(bool success, uint256 value) = tryParseUint(input, begin, end);
if (!success) revert StringsInvalidChar();
return value;
}
/**
* @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) {
return _tryParseUintUncheckedBounds(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid
* character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseUint(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, uint256 value) {
if (end > bytes(input).length || begin > end) return (false, 0);
return _tryParseUintUncheckedBounds(input, begin, end);
}
/**
* @dev Implementation of {tryParseUint} that does not check bounds. Caller should make sure that
* `begin <= end <= input.length`. Other inputs would result in undefined behavior.
*/
function _tryParseUintUncheckedBounds(
string memory input,
uint256 begin,
uint256 end
) private pure returns (bool success, uint256 value) {
bytes memory buffer = bytes(input);
uint256 result = 0;
for (uint256 i = begin; i < end; ++i) {
uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));
if (chr > 9) return (false, 0);
result *= 10;
result += chr;
}
return (true, result);
}
/**
* @dev Parse a decimal string and returns the value as a `int256`.
*
* Requirements:
* - The string must be formatted as `[-+]?[0-9]*`
* - The result must fit in an `int256` type.
*/
function parseInt(string memory input) internal pure returns (int256) {
return parseInt(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `[-+]?[0-9]*`
* - The result must fit in an `int256` type.
*/
function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) {
(bool success, int256 value) = tryParseInt(input, begin, end);
if (!success) revert StringsInvalidChar();
return value;
}
/**
* @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if
* the result does not fit in a `int256`.
*
* NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.
*/
function tryParseInt(string memory input) internal pure returns (bool success, int256 value) {
return _tryParseIntUncheckedBounds(input, 0, bytes(input).length);
}
uint256 private constant ABS_MIN_INT256 = 2 ** 255;
/**
* @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid
* character or if the result does not fit in a `int256`.
*
* NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.
*/
function tryParseInt(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, int256 value) {
if (end > bytes(input).length || begin > end) return (false, 0);
return _tryParseIntUncheckedBounds(input, begin, end);
}
/**
* @dev Implementation of {tryParseInt} that does not check bounds. Caller should make sure that
* `begin <= end <= input.length`. Other inputs would result in undefined behavior.
*/
function _tryParseIntUncheckedBounds(
string memory input,
uint256 begin,
uint256 end
) private pure returns (bool success, int256 value) {
bytes memory buffer = bytes(input);
bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); bool positiveSign = sign == bytes1("+");
bool negativeSign = sign == bytes1("-");
uint256 offset = (positiveSign || negativeSign).toUint();
(bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end);
if (absSuccess && absValue < ABS_MIN_INT256) {
return (true, negativeSign ? -int256(absValue) : int256(absValue));
} else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) {
return (true, type(int256).min);
} else return (false, 0);
}
/**
* @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as a `uint256`.
*
* Requirements:
* - The string must be formatted as `(0x)?[0-9a-fA-F]*`
* - The result must fit in an `uint256` type.
*/
function parseHexUint(string memory input) internal pure returns (uint256) {
return parseHexUint(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseHexUint} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `(0x)?[0-9a-fA-F]*`
* - The result must fit in an `uint256` type.
*/
function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {
(bool success, uint256 value) = tryParseHexUint(input, begin, end);
if (!success) revert StringsInvalidChar();
return value;
}
/**
* @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) {
return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an
* invalid character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseHexUint(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, uint256 value) {
if (end > bytes(input).length || begin > end) return (false, 0);
return _tryParseHexUintUncheckedBounds(input, begin, end);
}
/**
* @dev Implementation of {tryParseHexUint} that does not check bounds. Caller should make sure that
* `begin <= end <= input.length`. Other inputs would result in undefined behavior.
*/
function _tryParseHexUintUncheckedBounds(
string memory input,
uint256 begin,
uint256 end
) private pure returns (bool success, uint256 value) {
bytes memory buffer = bytes(input);
bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2("0x"); uint256 offset = hasPrefix.toUint() * 2;
uint256 result = 0;
for (uint256 i = begin + offset; i < end; ++i) {
uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));
if (chr > 15) return (false, 0);
result *= 16;
unchecked {
result += chr;
}
}
return (true, result);
}
/**
* @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as an `address`.
*
* Requirements:
* - The string must be formatted as `(0x)?[0-9a-fA-F]{40}`
*/
function parseAddress(string memory input) internal pure returns (address) {
return parseAddress(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseAddress} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}`
*/
function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) {
(bool success, address value) = tryParseAddress(input, begin, end);
if (!success) revert StringsInvalidAddressFormat();
return value;
}
/**
* @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly
* formatted address. See {parseAddress} requirements.
*/
function tryParseAddress(string memory input) internal pure returns (bool success, address value) {
return tryParseAddress(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly
* formatted address. See {parseAddress} requirements.
*/
function tryParseAddress(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, address value) {
if (end > bytes(input).length || begin > end) return (false, address(0));
bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2("0x"); uint256 expectedLength = 40 + hasPrefix.toUint() * 2;
if (end - begin == expectedLength) {
(bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end);
return (s, address(uint160(v)));
} else {
return (false, address(0));
}
}
function _tryParseChr(bytes1 chr) private pure returns (uint8) {
uint8 value = uint8(chr);
unchecked {
if (value > 47 && value < 58) value -= 48;
else if (value > 96 && value < 103) value -= 87;
else if (value > 64 && value < 71) value -= 55;
else return type(uint8).max;
}
return value;
}
/**
* @dev Reads a bytes32 from a bytes array without bounds checking.
*
* NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the
* assembly block as such would prevent some optimizations.
*/
function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {
assembly ("memory-safe") {
value := mload(add(buffer, add(0x20, offset)))
}
}
}
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC-165 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);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
/**
* @dev Implementation of https: * the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors {
using Strings for uint256;
string private _name;
string private _symbol;
mapping(uint256 tokenId => address) private _owners;
mapping(address owner => uint256) private _balances;
mapping(uint256 tokenId => address) private _tokenApprovals;
mapping(address owner => mapping(address operator => 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 returns (uint256) {
if (owner == address(0)) {
revert ERC721InvalidOwner(address(0));
}
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual returns (address) {
return _requireOwned(tokenId);
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual returns (string memory) {
_requireOwned(tokenId);
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string.concat(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 {
_approve(to, tokenId, _msgSender());
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual returns (address) {
_requireOwned(tokenId);
return _getApproved(tokenId);
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(address from, address to, uint256 tokenId) public virtual {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, _msgSender());
if (previousOwner != from) {
revert ERC721IncorrectOwner(from, tokenId, previousOwner);
}
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) public virtual {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual {
transferFrom(from, to, tokenId);
ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data);
}
/**
* @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
*
* IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the
* core ERC-721 logic MUST be matched with the use of {_increaseBalance} to keep balances
* consistent with ownership. The invariant to preserve is 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`.
*/
function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
return _owners[tokenId];
}
/**
* @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted.
*/
function _getApproved(uint256 tokenId) internal view virtual returns (address) {
return _tokenApprovals[tokenId];
}
/**
* @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in
* particular (ignoring whether it is owned by `owner`).
*
* WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
* assumption.
*/
function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) {
return
spender != address(0) &&
(owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender);
}
/**
* @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner.
* Reverts if:
* - `spender` does not have approval from `owner` for `tokenId`.
* - `spender` does not have approval to manage all of `owner`'s assets.
*
* WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
* assumption.
*/
function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual {
if (!_isAuthorized(owner, spender, tokenId)) {
if (owner == address(0)) {
revert ERC721NonexistentToken(tokenId);
} else {
revert ERC721InsufficientApproval(spender, tokenId);
}
}
}
/**
* @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
*
* NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that
* a uint256 would ever overflow from increments when these increments are bounded to uint128 values.
*
* WARNING: Increasing an account's balance using this function tends to be paired with an override of the
* {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership
* remain consistent with one another.
*/
function _increaseBalance(address account, uint128 value) internal virtual {
unchecked {
_balances[account] += value;
}
}
/**
* @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner
* (or `to`) is the zero address. Returns the owner of the `tokenId` before the update.
*
* The `auth` argument is optional. If the value passed is non 0, then this function will check that
* `auth` is either the owner of the token, or approved to operate on the token (by the owner).
*
* Emits a {Transfer} event.
*
* NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}.
*/
function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) {
address from = _ownerOf(tokenId);
if (auth != address(0)) {
_checkAuthorized(from, auth, tokenId);
}
if (from != address(0)) {
_approve(address(0), tokenId, address(0), false);
unchecked {
_balances[from] -= 1;
}
}
if (to != address(0)) {
unchecked {
_balances[to] += 1;
}
}
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
return from;
}
/**
* @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 {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, address(0));
if (previousOwner != address(0)) {
revert ERC721InvalidSender(address(0));
}
}
/**
* @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance.
*
* 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 {
_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);
ERC721Utils.checkOnERC721Received(_msgSender(), address(0), to, tokenId, data);
}
/**
* @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 {
address previousOwner = _update(address(0), tokenId, address(0));
if (previousOwner == address(0)) {
revert ERC721NonexistentToken(tokenId);
}
}
/**
* @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 {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, address(0));
if (previousOwner == address(0)) {
revert ERC721NonexistentToken(tokenId);
} else if (previousOwner != from) {
revert ERC721IncorrectOwner(from, tokenId, previousOwner);
}
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients
* are aware of the ERC-721 standard 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 like {safeTransferFrom} in the sense that it invokes
* {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `tokenId` token must exist and be owned by `from`.
* - `to` cannot be the zero address.
* - `from` cannot be the zero address.
* - 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) internal {
_safeTransfer(from, to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {
_transfer(from, to, tokenId);
ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is
* either the owner of the token, or approved to operate on all tokens held by this owner.
*
* Emits an {Approval} event.
*
* Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
*/
function _approve(address to, uint256 tokenId, address auth) internal {
_approve(to, tokenId, auth, true);
}
/**
* @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not
* emitted in the context of transfers.
*/
function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual {
if (emitEvent || auth != address(0)) {
address owner = _requireOwned(tokenId);
if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) {
revert ERC721InvalidApprover(auth);
}
if (emitEvent) {
emit Approval(owner, to, tokenId);
}
}
_tokenApprovals[tokenId] = to;
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Requirements:
* - operator can't be the address zero.
*
* Emits an {ApprovalForAll} event.
*/
function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
if (operator == address(0)) {
revert ERC721InvalidOperator(operator);
}
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned).
* Returns the owner.
*
* Overrides to ownership logic should be done to {_ownerOf}.
*/
function _requireOwned(uint256 tokenId) internal view returns (address) {
address owner = _ownerOf(tokenId);
if (owner == address(0)) {
revert ERC721NonexistentToken(tokenId);
}
return owner;
}
}
/**
* @dev This implements an optional extension of {ERC721} defined in the ERC that adds enumerability
* of all the token ids in the contract as well as all token ids owned by each account.
*
* CAUTION: {ERC721} extensions that implement custom `balanceOf` logic, such as {ERC721Consecutive},
* interfere with enumerability and should not be used together with {ERC721Enumerable}.
*/
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
mapping(address owner => mapping(uint256 index => uint256)) private _ownedTokens;
mapping(uint256 tokenId => uint256) private _ownedTokensIndex;
uint256[] private _allTokens;
mapping(uint256 tokenId => uint256) private _allTokensIndex;
/**
* @dev An `owner`'s token query was out of bounds for `index`.
*
* NOTE: The owner being `address(0)` indicates a global out of bounds index.
*/
error ERC721OutOfBoundsIndex(address owner, uint256 index);
/**
* @dev Batch mint is not allowed.
*/
error ERC721EnumerableForbiddenBatchMint();
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual returns (uint256) {
if (index >= balanceOf(owner)) {
revert ERC721OutOfBoundsIndex(owner, index);
}
return _ownedTokens[owner][index];
}
/**
* @dev See {IERC721Enumerable-totalSupply}.
*/
function totalSupply() public view virtual returns (uint256) {
return _allTokens.length;
}
/**
* @dev See {IERC721Enumerable-tokenByIndex}.
*/
function tokenByIndex(uint256 index) public view virtual returns (uint256) {
if (index >= totalSupply()) {
revert ERC721OutOfBoundsIndex(address(0), index);
}
return _allTokens[index];
}
/**
* @dev See {ERC721-_update}.
*/
function _update(address to, uint256 tokenId, address auth) internal virtual override returns (address) {
address previousOwner = super._update(to, tokenId, auth);
if (previousOwner == address(0)) {
_addTokenToAllTokensEnumeration(tokenId);
} else if (previousOwner != to) {
_removeTokenFromOwnerEnumeration(previousOwner, tokenId);
}
if (to == address(0)) {
_removeTokenFromAllTokensEnumeration(tokenId);
} else if (previousOwner != to) {
_addTokenToOwnerEnumeration(to, tokenId);
}
return previousOwner;
}
/**
* @dev Private function to add a token to this extension's ownership-tracking data structures.
* @param to address representing the new owner of the given token ID
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address
*/
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
uint256 length = balanceOf(to) - 1;
_ownedTokens[to][length] = tokenId;
_ownedTokensIndex[tokenId] = length;
}
/**
* @dev Private function to add a token to this extension's token tracking data structures.
* @param tokenId uint256 ID of the token to be added to the tokens list
*/
function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
/**
* @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
* while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
* gas optimizations e.g. when performing a transfer operation (avoiding double writes).
* This has O(1) time complexity, but alters the order of the _ownedTokens array.
* @param from address representing the previous owner of the given token ID
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
*/
function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
uint256 lastTokenIndex = balanceOf(from);
uint256 tokenIndex = _ownedTokensIndex[tokenId];
mapping(uint256 index => uint256) storage _ownedTokensByOwner = _ownedTokens[from];
if (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokensByOwner[lastTokenIndex];
_ownedTokensByOwner[tokenIndex] = lastTokenId; _ownedTokensIndex[lastTokenId] = tokenIndex; }
delete _ownedTokensIndex[tokenId];
delete _ownedTokensByOwner[lastTokenIndex];
}
/**
* @dev Private function to remove a token from this extension's token tracking data structures.
* This has O(1) time complexity, but alters the order of the _allTokens array.
* @param tokenId uint256 ID of the token to be removed from the tokens list
*/
function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
uint256 lastTokenIndex = _allTokens.length - 1;
uint256 tokenIndex = _allTokensIndex[tokenId];
uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId; _allTokensIndex[lastTokenId] = tokenIndex;
delete _allTokensIndex[tokenId];
_allTokens.pop();
}
/**
* See {ERC721-_increaseBalance}. We need that to account tokens that were minted in batch
*/
function _increaseBalance(address account, uint128 amount) internal virtual override {
if (amount > 0) {
revert ERC721EnumerableForbiddenBatchMint();
}
super._increaseBalance(account, amount);
}
}
interface IERC4906 is IERC165, IERC721 {
event MetadataUpdate(uint256 _tokenId);
event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId);
}
/**
* @dev ERC-721 token with storage based token URI management.
*/
abstract contract ERC721URIStorage is IERC4906, ERC721 {
using Strings for uint256;
bytes4 private constant ERC4906_INTERFACE_ID = bytes4(0x49064906);
mapping(uint256 tokenId => string) private _tokenURIs;
/**
* @dev See {IERC165-supportsInterface}
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, IERC165) returns (bool) {
return interfaceId == ERC4906_INTERFACE_ID || super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
_requireOwned(tokenId);
string memory _tokenURI = _tokenURIs[tokenId];
string memory base = _baseURI();
if (bytes(base).length == 0) {
return _tokenURI;
}
if (bytes(_tokenURI).length > 0) {
return string.concat(base, _tokenURI);
}
return super.tokenURI(tokenId);
}
/**
* @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
*
* Emits {MetadataUpdate}.
*/
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
_tokenURIs[tokenId] = _tokenURI;
emit MetadataUpdate(tokenId);
}
}
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
* consider using {ReentrancyGuardTransient} instead.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https: */
abstract contract ReentrancyGuard {
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
_status = ENTERED;
}
function _nonReentrantAfter() private {
_status = NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}
/**
* @custom:security-contact [email protected]
*/
contract Runbot_NFTs is A_Base, Ownable, A_Dust, ReentrancyGuard, ERC721, ERC721Enumerable, ERC721URIStorage, I_Runbot_NFTs {
I_Runbot_Fees public feesModel;
mapping(uint256 => uint256) private _nbMinted;
mapping(uint256 => mapping(uint256 => uint256)) private _nbMintedSub;
mapping(uint256 => uint256[]) private _mintedTokenIds;
mapping(uint256 => mapping(uint256 => uint256[])) private _mintedSubTokenIds;
uint256 private _lastTokenId;
mapping(uint256 => uint256) private _nftTypes;
mapping(uint256 => uint256) private _nftSubTypes;
mapping(uint256 => MintAsk) private _mintAsks;
uint256 private _mintAsksStart;
uint256 private _mintAsksEnd;
mapping(uint256 => TransferAsk) private _transferAsks;
uint256 private _transferAsksStart;
uint256 private _transferAsksEnd;
mapping(uint256 => uint256) private _bidPrices;
mapping(uint256 => uint256) private _borrowDuration;
mapping(uint256 => uint256) private _borrowTimeout;
mapping(uint256 => bool) private _isFirstBuy;
mapping(uint256 => bool) private _withFirstBuyRebate;
mapping(uint256 => uint256) private _lockTimeout;
string private _baseURL;
bool private _initialized;
bool private _migrated;
mapping(address => uint256) private _pendingBuyTransferAmount;
constructor(string memory baseURL_, bool migrated_) ERC721("Runbot", "RUNBOT") Ownable(msg.sender) {
_baseURL = baseURL_;
_migrated = migrated_;
}
function setFeesModel(I_Runbot_Fees feesModel_) external onlyOwner nonReentrant {
feesModel = feesModel_;
_initialized = true;
}
function setBaseURI(string memory baseURI) external onlyOwner nonReentrant {
_baseURL = baseURI;
}
function askTransfer(address receiver, uint256 tokenId) external payable nonReentrant returns (uint256){
require(_initialized && _migrated, "Runbot: Not initialized");
uint256 transferFees = feesModel.getTransferFees(msg.sender);
require(msg.value >= transferFees, "Runbot: Not enough transfer fees");
require(ownerOf(tokenId) == msg.sender, "Runbot: Caller is not token owner");
require(_lockTimeout[tokenId] <= block.timestamp, "Runbot: Cannot transfer locked token");
uint256 transferAskId = _transferAsksEnd;
_transferAsks[transferAskId] = TransferAsk(msg.sender, receiver, tokenId);
_transferAsksEnd += 1;
feesModel.dispatchRoyaltyTransferFees{value:transferFees}(_nftTypes[tokenId], _nftSubTypes[tokenId], msg.sender);
emit TransferAsked(transferAskId, msg.sender, receiver, tokenId);
return transferAskId;
}
function getNbTransferAsks() external view returns (uint256){
return _transferAsksEnd - _transferAsksStart;
}
function getFirstTransferAsk() external view returns (uint256, TransferAsk memory){
require(_transferAsksStart < _transferAsksEnd, "Runbot: No transfer ask");
return (_transferAsksStart, _transferAsks[_transferAsksStart]);
}
function completeTransferAsking(uint256 transferId, bool isApproved) external onlyOwner nonReentrant{
require(transferId == _transferAsksStart, "Runbot: Transfer ask not the first one");
TransferAsk memory transferAsk = _transferAsks[transferId];
uint256 tokenId = transferAsk.tokenId;
delete _transferAsks[transferId];
_transferAsksStart += 1;
if(isApproved){
_bidPrices[tokenId] = 0;
_safeTransfer(transferAsk.asker, transferAsk.receiver, tokenId, "");
emit Move(transferAsk.asker, transferAsk.receiver, tokenId);
}
}
function migrateFromPreviousContract(I_Runbot_NFTs previousContract, uint256 nbtokens) external onlyOwner nonReentrant{
require(!_migrated, "Runbot: Already migrated");
uint256 nbMintedTokens = previousContract.getNbMintedTokens();
for (uint256 i = 0; i < nbtokens; i++){
uint256 tokenId = _lastTokenId;
if (tokenId >= nbMintedTokens){
break;
}
(uint256 nftType, uint256 nftSubType, uint256 borrowDuration, uint256 borrowTimeout, bool isFirstBuy, bool withFirstBuyRebate, uint256 lockTimeout) = previousContract.getInfos(tokenId);
uint256 bidPrice = previousContract.getBidPrice(tokenId);
address to = previousContract.ownerOf(tokenId);
_lastTokenId += 1;
_nftTypes[tokenId] = nftType;
_nftSubTypes[tokenId] = nftSubType;
_bidPrices[tokenId] = bidPrice;
_borrowDuration[tokenId] = borrowDuration;
_borrowTimeout[tokenId] = borrowTimeout;
_isFirstBuy[tokenId] = isFirstBuy;
_withFirstBuyRebate[tokenId] = withFirstBuyRebate;
_lockTimeout[tokenId] = lockTimeout;
_nbMinted[nftType] += 1;
_nbMintedSub[nftType][nftSubType] += 1;
_mintedTokenIds[nftType].push(tokenId);
_mintedSubTokenIds[nftType][nftSubType].push(tokenId);
_safeMint(to, tokenId);
_setTokenURI(tokenId, Strings.toString(tokenId));
}
if (_lastTokenId == nbMintedTokens){
_migrated = true;
}
}
function askMint(uint256 nb, uint256 nftType, uint256 nftSubType, uint256 borrowDuration, uint256 bidPrice) external payable nonReentrant returns (uint256){
require(_initialized && _migrated, "Runbot: Not initialized");
require(nb > 0, "Runbot: Cannot mint 0 token");
(uint256 groupMintNbLimit,) = feesModel.getMintFeesRebate(msg.sender);
require(nb <= groupMintNbLimit, "Runbot: Cannot mint so many NFT at once");
uint256 fees = feesModel.getBaseFees(nftType, nftSubType, borrowDuration, true, nb, msg.sender);
require(msg.value >= fees, "Runbot: Not enough mint fees");
uint256 mintAskId = _mintAsksEnd;
_mintAsks[mintAskId] = MintAsk(msg.sender, nb, nftType, nftSubType, borrowDuration, bidPrice);
_mintAsksEnd += 1;
feesModel.dispatchRoyaltyMintFees{value:fees}(nftType, nftSubType, msg.sender);
emit MintAsked(mintAskId, msg.sender, nb, nftType, nftSubType, borrowDuration, bidPrice);
return mintAskId;
}
function getNbMintAsks() external view returns (uint256){
return _mintAsksEnd - _mintAsksStart;
}
function getFirstMintAsk() external view returns (uint256, MintAsk memory){
require(_mintAsksStart < _mintAsksEnd, "Runbot: No mint ask");
return (_mintAsksStart, _mintAsks[_mintAsksStart]);
}
function completeAskMint(uint256 mintId, uint256 lockTimeout, bool withFirstBidRebate, bool isApproved) external onlyOwner nonReentrant{
require(mintId == _mintAsksStart, "Runbot: Mint ask not the first one");
MintAsk memory mintAsk = _mintAsks[mintId];
delete _mintAsks[mintId];
_mintAsksStart += 1;
if(isApproved){
uint256 bidPrice = mintAsk.bidPrice;
if (lockTimeout > block.timestamp){
bidPrice = 0;
}
_batchSafeMint(mintAsk.nb, mintAsk.asker, mintAsk.nftType, mintAsk.nftSubType, bidPrice, mintAsk.borrowDuration, lockTimeout, withFirstBidRebate);
}
}
function batchSafeMint(uint256 nb, address to, uint256 nftType, uint256 nftSubType, uint256 bidPrice, uint256 borrowDuration, uint256 lockTimeout, bool withFirstBidRebate) external onlyOwner nonReentrant{
_batchSafeMint(nb, to, nftType, nftSubType, bidPrice, borrowDuration, lockTimeout, withFirstBidRebate);
}
function batchSafeMintLinear(uint256 nb, address to, uint256 nftType, uint256 nftSubTypeStart, uint256 nftSubTypeAdd, uint256 bidPriceStart, uint256 bidPriceAdd, uint256 borrowDurationStart, uint256 borrowDurationAdd, uint256 lockTimeoutStart, uint256 lockTimeoutAdd, bool withFirstBidRebate) external onlyOwner nonReentrant{
for (uint256 i = 0; i < nb; i++){
_processSafeMint(to, nftType, nftSubTypeStart + i * nftSubTypeAdd, bidPriceStart + i * bidPriceAdd, borrowDurationStart + i * borrowDurationAdd, lockTimeoutStart + i * lockTimeoutAdd, withFirstBidRebate);
}
}
function safeMint(address to, uint256 nftType, uint256 nftSubType, uint256 bidPrice, uint256 borrowDuration, uint256 lockTimeout, bool withFirstBidRebate) external onlyOwner nonReentrant{
_processSafeMint(to, nftType, nftSubType, bidPrice, borrowDuration, lockTimeout, withFirstBidRebate);
}
function getNbMintedTokens() external view returns (uint256){
return _lastTokenId;
}
function getNbMintedTokensByType(uint256 nftType) external view returns (uint256){
return _nbMinted[nftType];
}
function getNbMintedTokensBySubType(uint256 nftType, uint256 nftSubType) external view returns (uint256){
return _nbMintedSub[nftType][nftSubType];
}
function getTokenIdByType(uint256 nfttype, uint256 index) external view returns (uint256){
return _mintedTokenIds[nfttype][index];
}
function getTokenIdBySubType(uint256 nfttype, uint256 nftSubType, uint256 index) external view returns (uint256){
return _mintedSubTokenIds[nfttype][nftSubType][index];
}
function setBidPrice(uint256 tokenId, uint256 bidPrice) external nonReentrant{
_setBidPrice(tokenId, bidPrice);
}
function batchSetBidPrice(uint256[] memory tokenIds, uint256[] memory bidPrices) external nonReentrant{
require(tokenIds.length == bidPrices.length, "Runbot: tokenIds and bidPrices must have the same length");
for (uint256 i = 0; i < tokenIds.length; i++){
_setBidPrice(tokenIds[i], bidPrices[i]);
}
}
function getBidPrice(uint256 tokenId) external view returns (uint256){
return _bidPrices[tokenId];
}
function getInfos(uint256 tokenId) public view returns(uint256, uint256, uint256, uint256, bool, bool, uint256){
return (_nftTypes[tokenId], _nftSubTypes[tokenId], _borrowDuration[tokenId], _borrowTimeout[tokenId], _isFirstBuy[tokenId], _withFirstBuyRebate[tokenId], _lockTimeout[tokenId]);
}
function getFees(uint256 tokenId) public view returns (uint256){
uint256 bidPrice = _bidPrices[tokenId];
bool isFirstBuy = _isFirstBuy[tokenId];
uint256 initialBorrowDuration = _borrowDuration[tokenId];
address seller = ownerOf(tokenId);
return feesModel.getFees(_nftTypes[tokenId], _nftSubTypes[tokenId], bidPrice, isFirstBuy && _withFirstBuyRebate[tokenId], initialBorrowDuration, _getCurrentBorrowDuration(tokenId), seller, msg.sender);
}
function buy(uint256 tokenId) external payable nonReentrant{
_buyTo(msg.sender, tokenId);
}
function buyTo(address to, uint256 tokenId) external payable nonReentrant{
_buyTo(to, tokenId);
}
function tokenURI(uint256 tokenId) public view override(ERC721, ERC721URIStorage) returns (string memory)
{
return super.tokenURI(tokenId);
}
function supportsInterface(bytes4 interfaceId) public view override(IERC165, ERC721, ERC721URIStorage, ERC721Enumerable) returns (bool)
{
return super.supportsInterface(interfaceId);
}
function getBaseURI() external view returns (string memory) {
return _baseURL;
}
function claimPendingBuyTransfer(address to) external nonReentrant{
uint256 amount = _pendingBuyTransferAmount[msg.sender];
require(amount > 0, "Runbot: No pending buy transfer");
require(amount <= address(this).balance, "Runbot: Not enough funds");
_pendingBuyTransferAmount[msg.sender] = 0;
(bool success, ) = payable(to).call{value: amount}("");
require(success, "Runbot: Transfer failed");
emit PendingBuyTransferClaimed(msg.sender, to, amount);
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory data
) public virtual override(IERC721, ERC721) {
require(false, "Runbot: NFT not directly transferable");
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override(IERC721, ERC721) {
require(false, "Runbot: NFT not directly transferable");
}
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override(IERC721, ERC721) {
require(false, "Runbot: NFT not directly transferable");
}
function _processSafeMint(address to, uint256 nftType, uint256 nftSubType, uint256 bidPrice, uint256 borrowDuration, uint256 lockTimeout, bool withFirstBuyRebate) internal{
require(_initialized && _migrated, "Runbot: Not initialized");
require(lockTimeout <= block.timestamp || bidPrice == 0, "Runbot: Cannot set bid price and lock timeout simulataneously");
uint256 tokenId = _lastTokenId;
_lastTokenId += 1;
_nftTypes[tokenId] = nftType;
_nftSubTypes[tokenId] = nftSubType;
_bidPrices[tokenId] = bidPrice;
_borrowDuration[tokenId] = borrowDuration;
_isFirstBuy[tokenId] = true;
_withFirstBuyRebate[tokenId] = withFirstBuyRebate;
_lockTimeout[tokenId] = lockTimeout;
_nbMinted[nftType] += 1;
_nbMintedSub[nftType][nftSubType] += 1;
_mintedTokenIds[nftType].push(tokenId);
_mintedSubTokenIds[nftType][nftSubType].push(tokenId);
_safeMint(to, tokenId);
_setTokenURI(tokenId, Strings.toString(tokenId));
emit Mint(to, tokenId, nftType, nftSubType, bidPrice, borrowDuration, lockTimeout, withFirstBuyRebate);
}
function _buyTo(address to, uint256 tokenId) internal{
require(_initialized && _migrated, "Runbot: Not initialized");
require(_lockTimeout[tokenId] <= block.timestamp, "Runbot: NFT locked");
uint256 bidPrice = _bidPrices[tokenId];
bool isFirstBuy = _isFirstBuy[tokenId];
uint256 initialBorrowDuration = _borrowDuration[tokenId];
address seller = ownerOf(tokenId);
require(bidPrice > 0, "Runbot: NFT not for sale");
uint256 fees = feesModel.getFees(_nftTypes[tokenId], _nftSubTypes[tokenId], bidPrice, isFirstBuy && _withFirstBuyRebate[tokenId], initialBorrowDuration, _getCurrentBorrowDuration(tokenId), seller, to);
require(msg.value >= bidPrice + fees, "Runbot: Not enough funds");
if (_isFirstBuy[tokenId]){
_borrowTimeout[tokenId] = block.timestamp + initialBorrowDuration;
_isFirstBuy[tokenId] = false;
}
_bidPrices[tokenId] = 0;
_safeTransfer(seller, to, tokenId, "");
feesModel.dispatchRoyaltySellFees{value:fees}(_nftTypes[tokenId], _nftSubTypes[tokenId], seller, to);
(bool success, ) = payable(seller).call{value: bidPrice}("");
if (!success){
_pendingBuyTransferAmount[seller] += bidPrice;
}
emit Buy(to, seller, tokenId, bidPrice, fees);
}
function _setBidPrice(uint256 tokenId, uint256 bidPrice) internal{
require(_isAuthorized(_ownerOf(tokenId), msg.sender, tokenId), "Runbot: Caller is not token owner or approved");
require(_lockTimeout[tokenId] <= block.timestamp, "Runbot: Cannot set bid price while locked");
_bidPrices[tokenId] = bidPrice;
emit SetBidPrice(ownerOf(tokenId), tokenId, bidPrice);
}
function _getCurrentBorrowDuration(uint256 tokenId) private view returns (uint256){
uint256 borrowDuration = _borrowDuration[tokenId];
if (!_isFirstBuy[tokenId]){
uint256 borrowTimeout = _borrowTimeout[tokenId];
if (borrowTimeout > block.timestamp){
borrowDuration = borrowTimeout - block.timestamp;
}else{
borrowDuration = 0;
}
}
return borrowDuration;
}
function _baseURI() internal view override returns (string memory) {
return _baseURL;
}
function _update(address to, uint256 tokenId, address auth) internal override(ERC721, ERC721Enumerable) returns (address)
{
return super._update(to, tokenId, auth);
}
function _increaseBalance(address account, uint128 value) internal virtual override(ERC721, ERC721Enumerable) {
super._increaseBalance(account, value);
}
function _batchSafeMint(uint256 nb, address to, uint256 nftType, uint256 nftSubType, uint256 bidPrice, uint256 borrowDuration, uint256 lockTimeout, bool withFirstBidRebate)internal{
for (uint256 i = 0; i < nb; i++){
_processSafeMint(to, nftType, nftSubType, bidPrice, borrowDuration, lockTimeout, withFirstBidRebate);
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"string","name":"baseURL_","type":"string"},{"internalType":"bool","name":"migrated_","type":"bool"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ERC721EnumerableForbiddenBatchMint","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721IncorrectOwner","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721InsufficientApproval","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC721InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC721InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721InvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC721InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC721InvalidSender","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721NonexistentToken","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"ERC721OutOfBoundsIndex","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","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":"uint256","name":"_fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_toTokenId","type":"uint256"}],"name":"BatchMetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bidPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fees","type":"uint256"}],"name":"Buy","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"MetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nftType","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nftSubType","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bidPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"borrowDuration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockTimeout","type":"uint256"},{"indexed":false,"internalType":"bool","name":"withFirstBidRebate","type":"bool"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"mintId","type":"uint256"},{"indexed":true,"internalType":"address","name":"asker","type":"address"},{"indexed":false,"internalType":"uint256","name":"nb","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nftType","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nftSubType","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"borrowDuration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bidPrice","type":"uint256"}],"name":"MintAsked","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":"Move","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PendingBuyTransferClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bidPrice","type":"uint256"}],"name":"SetBidPrice","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":"uint256","name":"askId","type":"uint256"},{"indexed":true,"internalType":"address","name":"asker","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"TransferAsked","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nb","type":"uint256"},{"internalType":"uint256","name":"nftType","type":"uint256"},{"internalType":"uint256","name":"nftSubType","type":"uint256"},{"internalType":"uint256","name":"borrowDuration","type":"uint256"},{"internalType":"uint256","name":"bidPrice","type":"uint256"}],"name":"askMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"askTransfer","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","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":"nb","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"nftType","type":"uint256"},{"internalType":"uint256","name":"nftSubType","type":"uint256"},{"internalType":"uint256","name":"bidPrice","type":"uint256"},{"internalType":"uint256","name":"borrowDuration","type":"uint256"},{"internalType":"uint256","name":"lockTimeout","type":"uint256"},{"internalType":"bool","name":"withFirstBidRebate","type":"bool"}],"name":"batchSafeMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nb","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"nftType","type":"uint256"},{"internalType":"uint256","name":"nftSubTypeStart","type":"uint256"},{"internalType":"uint256","name":"nftSubTypeAdd","type":"uint256"},{"internalType":"uint256","name":"bidPriceStart","type":"uint256"},{"internalType":"uint256","name":"bidPriceAdd","type":"uint256"},{"internalType":"uint256","name":"borrowDurationStart","type":"uint256"},{"internalType":"uint256","name":"borrowDurationAdd","type":"uint256"},{"internalType":"uint256","name":"lockTimeoutStart","type":"uint256"},{"internalType":"uint256","name":"lockTimeoutAdd","type":"uint256"},{"internalType":"bool","name":"withFirstBidRebate","type":"bool"}],"name":"batchSafeMintLinear","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"bidPrices","type":"uint256[]"}],"name":"batchSetBidPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"buy","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"buyTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"claimPendingBuyTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"mintId","type":"uint256"},{"internalType":"uint256","name":"lockTimeout","type":"uint256"},{"internalType":"bool","name":"withFirstBidRebate","type":"bool"},{"internalType":"bool","name":"isApproved","type":"bool"}],"name":"completeAskMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"transferId","type":"uint256"},{"internalType":"bool","name":"isApproved","type":"bool"}],"name":"completeTransferAsking","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feesModel","outputs":[{"internalType":"contract I_Runbot_Fees","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":[],"name":"getBaseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getBidPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getETHDust","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFirstMintAsk","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"components":[{"internalType":"address","name":"asker","type":"address"},{"internalType":"uint256","name":"nb","type":"uint256"},{"internalType":"uint256","name":"nftType","type":"uint256"},{"internalType":"uint256","name":"nftSubType","type":"uint256"},{"internalType":"uint256","name":"borrowDuration","type":"uint256"},{"internalType":"uint256","name":"bidPrice","type":"uint256"}],"internalType":"struct I_Runbot_NFTs.MintAsk","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFirstTransferAsk","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"components":[{"internalType":"address","name":"asker","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct I_Runbot_NFTs.TransferAsk","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getInfos","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNbMintAsks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNbMintedTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftType","type":"uint256"},{"internalType":"uint256","name":"nftSubType","type":"uint256"}],"name":"getNbMintedTokensBySubType","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftType","type":"uint256"}],"name":"getNbMintedTokensByType","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNbTransferAsks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"getTokenDust","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nfttype","type":"uint256"},{"internalType":"uint256","name":"nftSubType","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getTokenIdBySubType","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nfttype","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getTokenIdByType","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":[{"internalType":"contract I_Runbot_NFTs","name":"previousContract","type":"address"},{"internalType":"uint256","name":"nbtokens","type":"uint256"}],"name":"migrateFromPreviousContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"nftType","type":"uint256"},{"internalType":"uint256","name":"nftSubType","type":"uint256"},{"internalType":"uint256","name":"bidPrice","type":"uint256"},{"internalType":"uint256","name":"borrowDuration","type":"uint256"},{"internalType":"uint256","name":"lockTimeout","type":"uint256"},{"internalType":"bool","name":"withFirstBidRebate","type":"bool"}],"name":"safeMint","outputs":[],"stateMutability":"nonpayable","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":"baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"bidPrice","type":"uint256"}],"name":"setBidPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract I_Runbot_Fees","name":"feesModel_","type":"address"}],"name":"setFeesModel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
608060405234801561000f575f5ffd5b5060405161568338038061568383398101604081905261002e9161015c565b604080518082018252600680825265149d5b989bdd60d21b6020808401919091528351808501909452908352651495539093d560d21b9083015290338061008e57604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b610097816100e5565b506001805560026100a883826102a1565b5060036100b582826102a1565b50602191506100c6905083826102a1565b50602280549115156101000261ff00199092169190911790555061035b565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b634e487b7160e01b5f52604160045260245ffd5b80518015158114610157575f5ffd5b919050565b5f5f6040838503121561016d575f5ffd5b82516001600160401b03811115610182575f5ffd5b8301601f81018513610192575f5ffd5b80516001600160401b038111156101ab576101ab610134565b604051601f8201601f19908116603f011681016001600160401b03811182821017156101d9576101d9610134565b6040528181528282016020018710156101f0575f5ffd5b8160208401602083015e5f6020838301015280945050505061021460208401610148565b90509250929050565b600181811c9082168061023157607f821691505b60208210810361024f57634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561029c57805f5260205f20601f840160051c8101602085101561027a5750805b601f840160051c820191505b81811015610299575f8155600101610286565b50505b505050565b81516001600160401b038111156102ba576102ba610134565b6102ce816102c8845461021d565b84610255565b6020601f821160018114610300575f83156102e95750848201515b5f19600385901b1c1916600184901b178455610299565b5f84815260208120601f198516915b8281101561032f578785015182556020948501946001909201910161030f565b508482101561034c57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b61531b806103685f395ff3fe60806040526004361061032c575f3560e01c8063714c5398116101a4578063bbc7827e116100eb578063d96a094a11610094578063e985e9c51161006e578063e985e9c5146109f9578063f0ecdbaa14610a4d578063f2fde38b14610a79578063fe42998714610a985761033b565b8063d96a094a146109b3578063dcbace94146109c6578063e611f8ba146109da5761033b565b8063cdd9544c116100c5578063cdd9544c1461093f578063cfe018d71461095e578063d5a06d4c146109945761033b565b8063bbc7827e146108fa578063c87b56dd1461090d578063c8dd63871461092c5761033b565b806395d89b411161014d578063a22cb46511610127578063a22cb465146108a2578063a25e428d146108c1578063b88d4fde146108e05761033b565b806395d89b41146108445780639b013aee146108585780639beb910a146108835761033b565b80638da5cb5b1161017e5780638da5cb5b146107a75780638f4188fa146107d057806392092708146107ef5761033b565b8063714c53981461076b578063715018a61461077f57806375ea7738146107935761033b565b806323b872dd11610273578063518ebc401161021c5780635f7bbd65116101f65780635f7bbd65146106ef5780636352211e1461070e578063702185a31461072d57806370a082311461074c5761033b565b8063518ebc401461068657806355f804b3146106a55780635cdefb90146106c45761033b565b806342842e0e1161024d57806342842e0e1461056e57806346c27e8c146105c05780634f6ccce7146106675761033b565b806323b872dd1461056e5780632f745c591461058d57806338116b30146105ac5761033b565b806310537900116102d55780631f70a966116102af5780631f70a96614610511578063201995291461053057806322cebdc71461054f5761033b565b8063105379001461046957806316df0cae1461047d57806318160ddd146104f35761033b565b8063081812fc11610306578063081812fc146103f3578063095ea7b31461043757806309bd4c31146104565761033b565b806301f899971461037f57806301ffc9a71461039e57806306fdde03146103d25761033b565b3661033b57610339610ab7565b005b5f805460405173ffffffffffffffffffffffffffffffffffffffff909116913480156108fc02929091818181858888f19350505050158015610339573d5f5f3e3d5ffd5b34801561038a575f5ffd5b506103396103993660046148e2565b610afe565b3480156103a9575f5ffd5b506103bd6103b8366004614974565b610bf9565b60405190151581526020015b60405180910390f35b3480156103dd575f5ffd5b506103e6610c09565b6040516103c991906149db565b3480156103fe575f5ffd5b5061041261040d3660046149ed565b610c99565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103c9565b348015610442575f5ffd5b50610339610451366004614a25565b610ccd565b610339610464366004614a25565b610cd8565b348015610474575f5ffd5b50610339610cf3565b348015610488575f5ffd5b50610491610d3f565b60408051928352815173ffffffffffffffffffffffffffffffffffffffff166020808501919091528201518382015281015160608084019190915281015160808084019190915281015160a080840191909152015160c082015260e0016103c9565b3480156104fe575f5ffd5b50600a545b6040519081526020016103c9565b34801561051c575f5ffd5b5061050361052b366004614a4f565b610e69565b34801561053b575f5ffd5b5061033961054a366004614a7c565b610e99565b34801561055a575f5ffd5b50610339610569366004614b11565b610f2e565b348015610579575f5ffd5b50610339610588366004614b7f565b610f61565b348015610598575f5ffd5b506105036105a7366004614a25565b610fee565b3480156105b7575f5ffd5b50610503611084565b3480156105cb575f5ffd5b5061062e6105da3660046149ed565b5f908152601360209081526040808320546014835281842054601c845282852054601d855283862054601e865284872054601f8752858820549680529490962054929691959094909360ff90811693911691565b60408051978852602088019690965294860193909352606085019190915215156080840152151560a083015260c082015260e0016103c9565b348015610672575f5ffd5b506105036106813660046149ed565b61109a565b348015610691575f5ffd5b506103396106a0366004614bbd565b611108565b3480156106b0575f5ffd5b506103396106bf366004614c4f565b61131b565b3480156106cf575f5ffd5b506105036106de3660046149ed565b5f908152600e602052604090205490565b3480156106fa575f5ffd5b50610339610709366004614c94565b611341565b348015610719575f5ffd5b506104126107283660046149ed565b611510565b348015610738575f5ffd5b50610339610747366004614bbd565b61151a565b348015610757575f5ffd5b50610503610766366004614bbd565b611679565b348015610776575f5ffd5b506103e66116f1565b34801561078a575f5ffd5b50610339611700565b34801561079e575f5ffd5b50610503611713565b3480156107b2575f5ffd5b505f5473ffffffffffffffffffffffffffffffffffffffff16610412565b3480156107db575f5ffd5b506103396107ea366004614a4f565b611724565b3480156107fa575f5ffd5b50610803611736565b60408051928352815173ffffffffffffffffffffffffffffffffffffffff9081166020808601919091528301511683820152015160608201526080016103c9565b34801561084f575f5ffd5b506103e6611814565b348015610863575f5ffd5b506105036108723660046149ed565b5f908152601b602052604090205490565b34801561088e575f5ffd5b5061050361089d366004614cc2565b611823565b3480156108ad575f5ffd5b506103396108bc366004614ceb565b61185f565b3480156108cc575f5ffd5b506103396108db366004614a25565b61186a565b3480156108eb575f5ffd5b50610339610588366004614d17565b610503610908366004614d92565b611cbf565b348015610918575f5ffd5b506103e66109273660046149ed565b6121b1565b61050361093a366004614a25565b6121bc565b34801561094a575f5ffd5b50610339610959366004614dc9565b61264c565b348015610969575f5ffd5b50610503610978366004614a4f565b5f918252600f6020908152604080842092845291905290205490565b34801561099f575f5ffd5b506105036109ae3660046149ed565b6127fb565b6103396109c13660046149ed565b612956565b3480156109d1575f5ffd5b50601254610503565b3480156109e5575f5ffd5b506103396109f4366004614bbd565b612971565b348015610a04575f5ffd5b506103bd610a13366004614e10565b73ffffffffffffffffffffffffffffffffffffffff9182165f90815260076020908152604080832093909416825291909152205460ff1690565b348015610a58575f5ffd5b50600d546104129073ffffffffffffffffffffffffffffffffffffffff1681565b348015610a84575f5ffd5b50610339610a93366004614bbd565b6129f7565b348015610aa3575f5ffd5b50610339610ab2366004614e3c565b612a57565b5f805460405173ffffffffffffffffffffffffffffffffffffffff909116913480156108fc02929091818181858888f19350505050158015610afb573d5f5f3e3d5ffd5b50565b610b06612a88565b8051825114610b9c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f52756e626f743a20746f6b656e49647320616e6420626964507269636573206d60448201527f7573742068617665207468652073616d65206c656e677468000000000000000060648201526084015b60405180910390fd5b5f5b8251811015610beb57610be3838281518110610bbc57610bbc614ea0565b6020026020010151838381518110610bd657610bd6614ea0565b6020026020010151612acb565b600101610b9e565b50610bf560018055565b5050565b5f610c0382612c8f565b92915050565b606060028054610c1890614ecd565b80601f0160208091040260200160405190810160405280929190818152602001828054610c4490614ecd565b8015610c8f5780601f10610c6657610100808354040283529160200191610c8f565b820191905f5260205f20905b815481529060010190602001808311610c7257829003601f168201915b5050505050905090565b5f610ca382612ce4565b505f8281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff16610c03565b610bf5828233612d42565b610ce0612a88565b610cea8282612d4f565b610bf560018055565b610cfb6132cb565b5f805460405173ffffffffffffffffffffffffffffffffffffffff909116914780156108fc02929091818181858888f19350505050158015610afb573d5f5f3e3d5ffd5b5f610d896040518060c001604052805f73ffffffffffffffffffffffffffffffffffffffff1681526020015f81526020015f81526020015f81526020015f81526020015f81525090565b60175460165410610df6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f52756e626f743a204e6f206d696e742061736b000000000000000000000000006044820152606401610b93565b50506016545f81815260156020908152604091829020825160c081018452815473ffffffffffffffffffffffffffffffffffffffff168152600182015492810192909252600281015492820192909252600382015460608201526004820154608082015260059091015460a08201529091565b5f828152601060205260408120805483908110610e8857610e88614ea0565b905f5260205f200154905092915050565b610ea16132cb565b610ea9612a88565b5f5b8c811015610f1657610f0e8c8c610ec28c85614f4b565b610ecc908e614f62565b610ed68b86614f4b565b610ee0908d614f62565b610eea8a87614f4b565b610ef4908c614f62565b610efe8988614f4b565b610f08908b614f62565b8861331d565b600101610eab565b50610f2060018055565b505050505050505050505050565b610f366132cb565b610f3e612a88565b610f4e88888888888888886135f6565b610f5760018055565b5050505050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f52756e626f743a204e4654206e6f74206469726563746c79207472616e73666560448201527f7261626c650000000000000000000000000000000000000000000000000000006064820152608401610b93565b505050565b5f610ff883611679565b821061104f576040517fa57d13dc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260248101839052604401610b93565b5073ffffffffffffffffffffffffffffffffffffffff919091165f908152600860209081526040808320938352929052205490565b5f601954601a546110959190614f75565b905090565b5f6110a4600a5490565b82106110e5576040517fa57d13dc0000000000000000000000000000000000000000000000000000000081525f600482015260248101839052604401610b93565b600a82815481106110f8576110f8614ea0565b905f5260205f2001549050919050565b611110612a88565b335f9081526023602052604090205480611186576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f52756e626f743a204e6f2070656e64696e6720627579207472616e73666572006044820152606401610b93565b478111156111f0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f52756e626f743a204e6f7420656e6f7567682066756e647300000000000000006044820152606401610b93565b335f908152602360205260408082208290555173ffffffffffffffffffffffffffffffffffffffff84169083908381818185875af1925050503d805f8114611253576040519150601f19603f3d011682016040523d82523d5f602084013e611258565b606091505b50509050806112c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f52756e626f743a205472616e73666572206661696c65640000000000000000006044820152606401610b93565b60405182815273ffffffffffffffffffffffffffffffffffffffff84169033907f2f87fa0e21f3b080cdbc96cb371b4ed47c540d211cd43b00f3e57b98c2685d389060200160405180910390a35050610afb60018055565b6113236132cb565b61132b612a88565b60216113378282614fcc565b50610afb60018055565b6113496132cb565b611351612a88565b60195482146113e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f52756e626f743a205472616e736665722061736b206e6f74207468652066697260448201527f7374206f6e6500000000000000000000000000000000000000000000000000006064820152608401610b93565b5f8281526018602081815260408084208151606081018352815473ffffffffffffffffffffffffffffffffffffffff808216835260018085018054928316858901526002860180549786018890528c8b52989097527fffffffffffffffffffffffff0000000000000000000000000000000000000000928316909455169093559284905560198054929491939290919061147d908490614f62565b90915550508215611505575f818152601b6020908152604080832083905584518583015182519384019092529282526114b892918490613622565b60208201518251604051839273ffffffffffffffffffffffffffffffffffffffff9081169216907fdeb3a6837278f6e9914a507e4d73f08e841d8fca434fb97d4307b3b0d3d6b105905f90a45b5050610bf560018055565b5f610c0382612ce4565b6115226132cb565b8073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb61155c5f5473ffffffffffffffffffffffffffffffffffffffff1690565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8516906370a0823190602401602060405180830381865afa1580156115c4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115e891906150e3565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff909216600483015260248201526044016020604051808303815f875af1158015611655573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bf591906150fa565b5f73ffffffffffffffffffffffffffffffffffffffff82166116c9576040517f89c62b640000000000000000000000000000000000000000000000000000000081525f6004820152602401610b93565b5073ffffffffffffffffffffffffffffffffffffffff165f9081526005602052604090205490565b606060218054610c1890614ecd565b6117086132cb565b6117115f61363a565b565b5f6016546017546110959190614f75565b61172c612a88565b610cea8282612acb565b604080516060810182525f80825260208201819052918101829052601a54601954106117be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f52756e626f743a204e6f207472616e736665722061736b0000000000000000006044820152606401610b93565b50506019545f818152601860209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff90811682526001830154169281019290925260020154918101919091529091565b606060038054610c1890614ecd565b5f838152601160209081526040808320858452909152812080548390811061184d5761184d614ea0565b905f5260205f20015490509392505050565b610bf53383836136ae565b6118726132cb565b61187a612a88565b602254610100900460ff16156118ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f52756e626f743a20416c7265616479206d6967726174656400000000000000006044820152606401610b93565b5f8273ffffffffffffffffffffffffffffffffffffffff1663dcbace946040518163ffffffff1660e01b8152600401602060405180830381865afa158015611936573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061195a91906150e3565b90505f5b82811015611c79576012548281106119765750611c79565b5f5f5f5f5f5f5f8b73ffffffffffffffffffffffffffffffffffffffff166346c27e8c896040518263ffffffff1660e01b81526004016119b891815260200190565b60e060405180830381865afa1580156119d3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119f79190615115565b96509650965096509650965096505f8c73ffffffffffffffffffffffffffffffffffffffff16639b013aee8a6040518263ffffffff1660e01b8152600401611a4191815260200190565b602060405180830381865afa158015611a5c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a8091906150e3565b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018b90529091505f9073ffffffffffffffffffffffffffffffffffffffff8f1690636352211e90602401602060405180830381865afa158015611aee573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b129190615180565b9050600160125f828254611b269190614f62565b90915550505f8a81526013602090815260408083208c9055601482528083208b9055601b8252808320859055601c82528083208a9055601d8252808320899055601e825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009081168a151517909155601f835281842080549091168815151790558180528083208690558b8352600e9091528120805460019290611bd0908490614f62565b90915550505f898152600f602090815260408083208b84529091528120805460019290611bfe908490614f62565b90915550505f898152601060209081526040808320805460018181018355918552838520018e90558c8452601183528184208c855283529083208054918201815583529120018a9055611c51818b6137aa565b611c638a611c5e8c6137c3565b61387f565b50506001909801975061195e9650505050505050565b508060125403610beb57602280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010017905550610bf560018055565b50505050565b5f611cc8612a88565b60225460ff168015611ce15750602254610100900460ff165b611d47576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f52756e626f743a204e6f7420696e697469616c697a65640000000000000000006044820152606401610b93565b5f8611611db0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f52756e626f743a2043616e6e6f74206d696e74203020746f6b656e00000000006044820152606401610b93565b600d546040517f835309b70000000000000000000000000000000000000000000000000000000081523360048201525f9173ffffffffffffffffffffffffffffffffffffffff169063835309b790602401606060405180830381865afa158015611e1c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e40919061519b565b50905080871115611ed3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f52756e626f743a2043616e6e6f74206d696e7420736f206d616e79204e46542060448201527f6174206f6e6365000000000000000000000000000000000000000000000000006064820152608401610b93565b600d546040517f96c47dc500000000000000000000000000000000000000000000000000000000815260048101889052602481018790526044810186905260016064820152608481018990523360a48201525f9173ffffffffffffffffffffffffffffffffffffffff16906396c47dc59060c401602060405180830381865afa158015611f62573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f8691906150e3565b905080341015611ff2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f52756e626f743a204e6f7420656e6f756768206d696e742066656573000000006044820152606401610b93565b601780546040805160c08101825233815260208082018d81528284018d8152606084018d8152608085018d815260a086018d81525f8981526015909652968520955186547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161786559251600180870191909155915160028601555160038501559051600484015592516005909201919091558354929391926120ae908490614f62565b9091555050600d546040517f196a93d0000000000000000000000000000000000000000000000000000000008152600481018a90526024810189905233604482015273ffffffffffffffffffffffffffffffffffffffff9091169063196a93d09084906064015f604051808303818588803b15801561212b575f5ffd5b505af115801561213d573d5f5f3e3d5ffd5b505060408051858152602081018e90529081018c9052606081018b9052608081018a905260a081018990523393507f061ba009aac8cbea2f5ff78aa7e87ee8396cd094d8dcbcc911064c4142351a70925060c001905060405180910390a2925050506121a860018055565b95945050505050565b6060610c03826138ce565b5f6121c5612a88565b60225460ff1680156121de5750602254610100900460ff165b612244576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f52756e626f743a204e6f7420696e697469616c697a65640000000000000000006044820152606401610b93565b600d546040517f0a411c310000000000000000000000000000000000000000000000000000000081523360048201525f9173ffffffffffffffffffffffffffffffffffffffff1690630a411c3190602401602060405180830381865afa1580156122b0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122d491906150e3565b905080341015612340576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f52756e626f743a204e6f7420656e6f756768207472616e7366657220666565736044820152606401610b93565b3361234a84611510565b73ffffffffffffffffffffffffffffffffffffffff16146123ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f52756e626f743a2043616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72000000000000000000000000000000000000000000000000000000000000006064820152608401610b93565b5f838152602080526040902054421015612488576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f52756e626f743a2043616e6e6f74207472616e73666572206c6f636b6564207460448201527f6f6b656e000000000000000000000000000000000000000000000000000000006064820152608401610b93565b601a80546040805160608101825233815273ffffffffffffffffffffffffffffffffffffffff88811660208084019182528385018a81525f8781526018909252948120935184549084167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216178555915160018086018054929095169190931617909255925160029092019190915583549293919261252a908490614f62565b9091555050600d545f8581526013602090815260408083205460149092528083205481517f2ebceed9000000000000000000000000000000000000000000000000000000008152600481019390935260248301523360448301525173ffffffffffffffffffffffffffffffffffffffff90931692632ebceed99286926064808201939182900301818588803b1580156125c1575f5ffd5b505af11580156125d3573d5f5f3e3d5ffd5b5050505050838573ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fe8664c789f701fb7be7be3156f0fe556f9a7023f5b4604b2a60fa257251b06cf8460405161263891815260200190565b60405180910390a4915050610c0360018055565b6126546132cb565b61265c612a88565b60165484146126ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f52756e626f743a204d696e742061736b206e6f7420746865206669727374206f60448201527f6e650000000000000000000000000000000000000000000000000000000000006064820152608401610b93565b5f848152601560208181526040808420815160c081018352815473ffffffffffffffffffffffffffffffffffffffff811682526001808401805484880152600285018054968501969096526003850180546060860152600486018054608087015260058701805460a08801528f8c52999098527fffffffffffffffffffffffff0000000000000000000000000000000000000000909316909455928790559286905591859055918490559183905560168054929391929091906127b1908490614f62565b909155505081156127f15760a0810151428511156127cc57505f5b6127ef8260200151835f0151846040015185606001518587608001518b8b6135f6565b505b50611cb960018055565b5f818152601b6020908152604080832054601e835281842054601c90935290832054909160ff16908361282d86611510565b600d545f8881526013602090815260408083205460149092529091205492935073ffffffffffffffffffffffffffffffffffffffff9091169163e7deb9b991908787801561288857505f8b8152601f602052604090205460ff165b876128928d6139cd565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b16815260048101969096526024860194909452604485019290925215156064840152608483015260a482015273ffffffffffffffffffffffffffffffffffffffff841660c48201523360e482015261010401602060405180830381865afa158015612928573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061294c91906150e3565b9695505050505050565b61295e612a88565b6129683382612d4f565b610afb60018055565b6129796132cb565b612981612a88565b600d805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116179055602280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610afb60018055565b6129ff6132cb565b73ffffffffffffffffffffffffffffffffffffffff8116612a4e576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f6004820152602401610b93565b610afb8161363a565b612a5f6132cb565b612a67612a88565b612a768787878787878761331d565b612a7f60018055565b50505050505050565b600260015403612ac4576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600155565b5f82815260046020526040902054612afa9073ffffffffffffffffffffffffffffffffffffffff163384613a1f565b612b86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f52756e626f743a2043616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72206f7220617070726f766564000000000000000000000000000000000000006064820152608401610b93565b5f828152602080526040902054421015612c22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f52756e626f743a2043616e6e6f7420736574206269642070726963652077686960448201527f6c65206c6f636b656400000000000000000000000000000000000000000000006064820152608401610b93565b5f828152601b6020526040902081905581612c3c81611510565b73ffffffffffffffffffffffffffffffffffffffff167ff6883b6e03f0249ee984a32e1a41b3c807eeef7a8874cbf7f807d715632c8a9383604051612c8391815260200190565b60405180910390a35050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f49064906000000000000000000000000000000000000000000000000000000001480610c035750610c0382613ae0565b5f8181526004602052604081205473ffffffffffffffffffffffffffffffffffffffff1680610c03576040517f7e27328900000000000000000000000000000000000000000000000000000000815260048101849052602401610b93565b610fe98383836001613b35565b60225460ff168015612d685750602254610100900460ff165b612dce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f52756e626f743a204e6f7420696e697469616c697a65640000000000000000006044820152606401610b93565b5f818152602080526040902054421015612e44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f52756e626f743a204e4654206c6f636b656400000000000000000000000000006044820152606401610b93565b5f818152601b6020908152604080832054601e835281842054601c90935290832054909260ff90921691612e7785611510565b90505f8411612ee2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f52756e626f743a204e4654206e6f7420666f722073616c6500000000000000006044820152606401610b93565b600d545f868152601360209081526040808320546014909252822054919273ffffffffffffffffffffffffffffffffffffffff169163e7deb9b9919088888015612f3957505f8b8152601f602052604090205460ff165b88612f438d6139cd565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b16815260048101969096526024860194909452604485019290925215156064840152608483015260a482015273ffffffffffffffffffffffffffffffffffffffff80861660c48301528a1660e482015261010401602060405180830381865afa158015612fdb573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612fff91906150e3565b905061300b8186614f62565b341015613074576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f52756e626f743a204e6f7420656e6f7567682066756e647300000000000000006044820152606401610b93565b5f868152601e602052604090205460ff16156130d4576130948342614f62565b5f878152601d6020908152604080832093909355601e90522080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b5f868152601b602090815260408083208390558051918201905290815261310090839089908990613622565b600d545f8781526013602090815260408083205460149092528083205481517ff7a8b7490000000000000000000000000000000000000000000000000000000081526004810193909352602483015273ffffffffffffffffffffffffffffffffffffffff86811660448401528b81166064840152905193169263f7a8b7499285926084808201939182900301818588803b15801561319c575f5ffd5b505af11580156131ae573d5f5f3e3d5ffd5b50505050505f8273ffffffffffffffffffffffffffffffffffffffff16866040515f6040518083038185875af1925050503d805f8114613209576040519150601f19603f3d011682016040523d82523d5f602084013e61320e565b606091505b50509050806132515773ffffffffffffffffffffffffffffffffffffffff83165f908152602360205260408120805488929061324b908490614f62565b90915550505b868373ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff167ef93dbdb72854b6b6fb35433086556f2635fc83c37080c667496fecfa650fb489866040516132b9929190918252602082015260400190565b60405180910390a45050505050505050565b5f5473ffffffffffffffffffffffffffffffffffffffff163314611711576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610b93565b60225460ff1680156133365750602254610100900460ff165b61339c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f52756e626f743a204e6f7420696e697469616c697a65640000000000000000006044820152606401610b93565b42821115806133a9575083155b613435576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f52756e626f743a2043616e6e6f74207365742062696420707269636520616e6460448201527f206c6f636b2074696d656f75742073696d756c6174616e656f75736c790000006064820152608401610b93565b60128054906001905f6134488385614f62565b90915550505f8181526013602090815260408083208a905560148252808320899055601b8252808320889055601c8252808320879055601e8252808320805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009182168117909255601f845282852080549091168715151790558280528184208790558a8452600e90925282208054919290916134e8908490614f62565b90915550505f878152600f602090815260408083208984529091528120805460019290613516908490614f62565b90915550505f878152601060209081526040808320805460018181018355918552838520018590558a8452601183528184208a8552835290832080549182018155835291200181905561356988826137aa565b61357681611c5e836137c3565b6040805182815260208101899052908101879052606081018690526080810185905260a0810184905282151560c082015273ffffffffffffffffffffffffffffffffffffffff8916907fe3dbf380a595a9c8689ffa1f37d50b5893c82476efe9e1c209b8adf628c245a49060e00160405180910390a25050505050505050565b5f5b888110156136175761360f8888888888888861331d565b6001016135f8565b505050505050505050565b61362d848484613cfd565b611cb93385858585613e36565b5f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff8216613713576040517f5b08ba1800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610b93565b73ffffffffffffffffffffffffffffffffffffffff8381165f8181526007602090815260408083209487168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b610bf5828260405180602001604052805f81525061402c565b60605f6137cf83614043565b60010190505f8167ffffffffffffffff8111156137ee576137ee6147f0565b6040519080825280601f01601f191660200182016040528015613818576020820181803683370190505b5090508181016020015b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a850494508461382257509392505050565b5f828152600c602052604090206138968282614fcc565b506040518281527ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79060200160405180910390a15050565b60606138d982612ce4565b505f828152600c6020526040812080546138f290614ecd565b80601f016020809104026020016040519081016040528092919081815260200182805461391e90614ecd565b80156139695780601f1061394057610100808354040283529160200191613969565b820191905f5260205f20905b81548152906001019060200180831161394c57829003601f168201915b505050505090505f6139796116f1565b905080515f0361398a575092915050565b8151156139bc5780826040516020016139a4929190615239565b60405160208183030381529060405292505050919050565b6139c584614124565b949350505050565b5f818152601c6020908152604080832054601e90925282205460ff16610c03575f838152601d602052604090205442811115613a1457613a0d4282614f75565b9150613a18565b5f91505b5092915050565b5f73ffffffffffffffffffffffffffffffffffffffff8316158015906139c557508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480613aab575073ffffffffffffffffffffffffffffffffffffffff8085165f9081526007602090815260408083209387168352929052205460ff165b806139c55750505f9081526006602052604090205473ffffffffffffffffffffffffffffffffffffffff908116911614919050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f780e9d63000000000000000000000000000000000000000000000000000000001480610c035750610c0382614189565b8080613b56575073ffffffffffffffffffffffffffffffffffffffff821615155b15613ca9575f613b6584612ce4565b905073ffffffffffffffffffffffffffffffffffffffff831615801590613bb857508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b8015613bf6575073ffffffffffffffffffffffffffffffffffffffff8082165f9081526007602090815260408083209387168352929052205460ff16155b15613c45576040517fa9fbf51f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610b93565b8115613ca757838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b50505f90815260066020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff8216613d4c576040517f64a0ae920000000000000000000000000000000000000000000000000000000081525f6004820152602401610b93565b5f613d5883835f61426b565b905073ffffffffffffffffffffffffffffffffffffffff8116613daa576040517f7e27328900000000000000000000000000000000000000000000000000000000815260048101839052602401610b93565b8373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611cb9576040517f64283d7b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80861660048301526024820184905282166044820152606401610b93565b73ffffffffffffffffffffffffffffffffffffffff83163b15614025576040517f150b7a0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84169063150b7a0290613eab90889088908790879060040161524d565b6020604051808303815f875af1925050508015613f03575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252613f009181019061529d565b60015b613f90573d808015613f30576040519150601f19603f3d011682016040523d82523d5f602084013e613f35565b606091505b5080515f03613f88576040517f64a0ae9200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610b93565b805181602001fd5b7fffffffff0000000000000000000000000000000000000000000000000000000081167f150b7a020000000000000000000000000000000000000000000000000000000014614023576040517f64a0ae9200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610b93565b505b5050505050565b6140368383614277565b610fe9335f858585613e36565b5f807a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000831061408b577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef810000000083106140b7576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106140d557662386f26fc10000830492506010015b6305f5e10083106140ed576305f5e100830492506008015b612710831061410157612710830492506004015b60648310614113576064830492506002015b600a8310610c035760010192915050565b606061412f82612ce4565b505f6141396116f1565b90505f8151116141575760405180602001604052805f815250614182565b80614161846137c3565b604051602001614172929190615239565b6040516020818303038152906040525b9392505050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd00000000000000000000000000000000000000000000000000000000148061421b57507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b80610c0357507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610c03565b5f6139c5848484614324565b73ffffffffffffffffffffffffffffffffffffffff82166142c6576040517f64a0ae920000000000000000000000000000000000000000000000000000000081525f6004820152602401610b93565b5f6142d283835f61426b565b905073ffffffffffffffffffffffffffffffffffffffff811615610fe9576040517f73c6ac6e0000000000000000000000000000000000000000000000000000000081525f6004820152602401610b93565b5f5f61433185858561443d565b905073ffffffffffffffffffffffffffffffffffffffff811661439a5761439584600a80545f838152600b60205260408120829055600182018355919091527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80155565b6143d7565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146143d7576143d781856145b4565b73ffffffffffffffffffffffffffffffffffffffff8516614400576143fb8461463e565b6139c5565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146139c5576139c585856146e5565b5f8281526004602052604081205473ffffffffffffffffffffffffffffffffffffffff9081169083161561447657614476818486614740565b73ffffffffffffffffffffffffffffffffffffffff8116156144e95761449e5f855f5f613b35565b73ffffffffffffffffffffffffffffffffffffffff81165f90815260056020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b73ffffffffffffffffffffffffffffffffffffffff8516156145315773ffffffffffffffffffffffffffffffffffffffff85165f908152600560205260409020805460010190555b5f8481526004602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff89811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b5f6145be83611679565b5f8381526009602090815260408083205473ffffffffffffffffffffffffffffffffffffffff88168452600890925290912091925090818314614620575f83815260208281526040808320548584528184208190558352600990915290208290555b5f938452600960209081526040808620869055938552525081205550565b600a545f9061464f90600190614f75565b5f838152600b6020526040812054600a805493945090928490811061467657614676614ea0565b905f5260205f200154905080600a838154811061469557614695614ea0565b5f918252602080832090910192909255828152600b9091526040808220849055858252812055600a8054806146cc576146cc6152b8565b600190038181905f5260205f20015f9055905550505050565b5f60016146f184611679565b6146fb9190614f75565b73ffffffffffffffffffffffffffffffffffffffff9093165f908152600860209081526040808320868452825280832085905593825260099052919091209190915550565b61474b838383613a1f565b610fe95773ffffffffffffffffffffffffffffffffffffffff831661479f576040517f7e27328900000000000000000000000000000000000000000000000000000000815260048101829052602401610b93565b6040517f177e802f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015260248101829052604401610b93565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614864576148646147f0565b604052919050565b5f82601f83011261487b575f5ffd5b813567ffffffffffffffff811115614895576148956147f0565b8060051b6148a56020820161481d565b918252602081850181019290810190868411156148c0575f5ffd5b6020860192505b8383101561294c5782358252602092830192909101906148c7565b5f5f604083850312156148f3575f5ffd5b823567ffffffffffffffff811115614909575f5ffd5b6149158582860161486c565b925050602083013567ffffffffffffffff811115614931575f5ffd5b61493d8582860161486c565b9150509250929050565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114610afb575f5ffd5b5f60208284031215614984575f5ffd5b813561418281614947565b5f81518084528060208401602086015e5f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081525f614182602083018461498f565b5f602082840312156149fd575f5ffd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610afb575f5ffd5b5f5f60408385031215614a36575f5ffd5b8235614a4181614a04565b946020939093013593505050565b5f5f60408385031215614a60575f5ffd5b50508035926020909101359150565b8015158114610afb575f5ffd5b5f5f5f5f5f5f5f5f5f5f5f5f6101808d8f031215614a98575f5ffd5b8c359b5060208d0135614aaa81614a04565b9a5060408d0135995060608d0135985060808d0135975060a08d0135965060c08d0135955060e08d013594506101008d013593506101208d013592506101408d013591506101608d0135614afd81614a6f565b809150509295989b509295989b509295989b565b5f5f5f5f5f5f5f5f610100898b031215614b29575f5ffd5b883597506020890135614b3b81614a04565b965060408901359550606089013594506080890135935060a0890135925060c0890135915060e0890135614b6e81614a6f565b809150509295985092959890939650565b5f5f5f60608486031215614b91575f5ffd5b8335614b9c81614a04565b92506020840135614bac81614a04565b929592945050506040919091013590565b5f60208284031215614bcd575f5ffd5b813561418281614a04565b5f5f67ffffffffffffffff841115614bf257614bf26147f0565b50601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016602001614c258161481d565b915050828152838383011115614c39575f5ffd5b828260208301375f602084830101529392505050565b5f60208284031215614c5f575f5ffd5b813567ffffffffffffffff811115614c75575f5ffd5b8201601f81018413614c85575f5ffd5b6139c584823560208401614bd8565b5f5f60408385031215614ca5575f5ffd5b823591506020830135614cb781614a6f565b809150509250929050565b5f5f5f60608486031215614cd4575f5ffd5b505081359360208301359350604090920135919050565b5f5f60408385031215614cfc575f5ffd5b8235614d0781614a04565b91506020830135614cb781614a6f565b5f5f5f5f60808587031215614d2a575f5ffd5b8435614d3581614a04565b93506020850135614d4581614a04565b925060408501359150606085013567ffffffffffffffff811115614d67575f5ffd5b8501601f81018713614d77575f5ffd5b614d8687823560208401614bd8565b91505092959194509250565b5f5f5f5f5f60a08688031215614da6575f5ffd5b505083359560208501359550604085013594606081013594506080013592509050565b5f5f5f5f60808587031215614ddc575f5ffd5b84359350602085013592506040850135614df581614a6f565b91506060850135614e0581614a6f565b939692955090935050565b5f5f60408385031215614e21575f5ffd5b8235614e2c81614a04565b91506020830135614cb781614a04565b5f5f5f5f5f5f5f60e0888a031215614e52575f5ffd5b8735614e5d81614a04565b96506020880135955060408801359450606088013593506080880135925060a0880135915060c0880135614e9081614a6f565b8091505092959891949750929550565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b600181811c90821680614ee157607f821691505b602082108103614f18577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8082028115828204841417610c0357610c03614f1e565b80820180821115610c0357610c03614f1e565b81810381811115610c0357610c03614f1e565b601f821115610fe957805f5260205f20601f840160051c81016020851015614fad5750805b601f840160051c820191505b81811015614025575f8155600101614fb9565b815167ffffffffffffffff811115614fe657614fe66147f0565b614ffa81614ff48454614ecd565b84614f88565b6020601f82116001811461504b575f83156150155750848201515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600385901b1c1916600184901b178455614025565b5f848152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08516915b828110156150985787850151825560209485019460019092019101615078565b50848210156150d457868401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b60f8161c191681555b50505050600190811b01905550565b5f602082840312156150f3575f5ffd5b5051919050565b5f6020828403121561510a575f5ffd5b815161418281614a6f565b5f5f5f5f5f5f5f60e0888a03121561512b575f5ffd5b8751602089015160408a015160608b015160808c0151939a509198509650945061515481614a6f565b60a089015190935061516581614a6f565b60c09890980151969995985093969295919492935090919050565b5f60208284031215615190575f5ffd5b815161418281614a04565b5f5f82840360608112156151ad575f5ffd5b8351925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0820112156151e0575f5ffd5b506040805190810167ffffffffffffffff81118282101715615204576152046147f0565b60409081526020858101518352940151938101939093525092909150565b5f81518060208401855e5f93019283525090919050565b5f6139c56152478386615222565b84615222565b73ffffffffffffffffffffffffffffffffffffffff8516815273ffffffffffffffffffffffffffffffffffffffff84166020820152826040820152608060608201525f61294c608083018461498f565b5f602082840312156152ad575f5ffd5b815161418281614947565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffdfea26469706673582212200679d547f98b163cdc6b5983262a84c74e279d1e3b7fc7759631bdbbc9bcfb8b64736f6c634300081c003300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002368747470733a2f2f6170702e72756e626f742e696f2f6e66742d6d657461646174612f0000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x60806040526004361061032c575f3560e01c8063714c5398116101a4578063bbc7827e116100eb578063d96a094a11610094578063e985e9c51161006e578063e985e9c5146109f9578063f0ecdbaa14610a4d578063f2fde38b14610a79578063fe42998714610a985761033b565b8063d96a094a146109b3578063dcbace94146109c6578063e611f8ba146109da5761033b565b8063cdd9544c116100c5578063cdd9544c1461093f578063cfe018d71461095e578063d5a06d4c146109945761033b565b8063bbc7827e146108fa578063c87b56dd1461090d578063c8dd63871461092c5761033b565b806395d89b411161014d578063a22cb46511610127578063a22cb465146108a2578063a25e428d146108c1578063b88d4fde146108e05761033b565b806395d89b41146108445780639b013aee146108585780639beb910a146108835761033b565b80638da5cb5b1161017e5780638da5cb5b146107a75780638f4188fa146107d057806392092708146107ef5761033b565b8063714c53981461076b578063715018a61461077f57806375ea7738146107935761033b565b806323b872dd11610273578063518ebc401161021c5780635f7bbd65116101f65780635f7bbd65146106ef5780636352211e1461070e578063702185a31461072d57806370a082311461074c5761033b565b8063518ebc401461068657806355f804b3146106a55780635cdefb90146106c45761033b565b806342842e0e1161024d57806342842e0e1461056e57806346c27e8c146105c05780634f6ccce7146106675761033b565b806323b872dd1461056e5780632f745c591461058d57806338116b30146105ac5761033b565b806310537900116102d55780631f70a966116102af5780631f70a96614610511578063201995291461053057806322cebdc71461054f5761033b565b8063105379001461046957806316df0cae1461047d57806318160ddd146104f35761033b565b8063081812fc11610306578063081812fc146103f3578063095ea7b31461043757806309bd4c31146104565761033b565b806301f899971461037f57806301ffc9a71461039e57806306fdde03146103d25761033b565b3661033b57610339610ab7565b005b5f805460405173ffffffffffffffffffffffffffffffffffffffff909116913480156108fc02929091818181858888f19350505050158015610339573d5f5f3e3d5ffd5b34801561038a575f5ffd5b506103396103993660046148e2565b610afe565b3480156103a9575f5ffd5b506103bd6103b8366004614974565b610bf9565b60405190151581526020015b60405180910390f35b3480156103dd575f5ffd5b506103e6610c09565b6040516103c991906149db565b3480156103fe575f5ffd5b5061041261040d3660046149ed565b610c99565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103c9565b348015610442575f5ffd5b50610339610451366004614a25565b610ccd565b610339610464366004614a25565b610cd8565b348015610474575f5ffd5b50610339610cf3565b348015610488575f5ffd5b50610491610d3f565b60408051928352815173ffffffffffffffffffffffffffffffffffffffff166020808501919091528201518382015281015160608084019190915281015160808084019190915281015160a080840191909152015160c082015260e0016103c9565b3480156104fe575f5ffd5b50600a545b6040519081526020016103c9565b34801561051c575f5ffd5b5061050361052b366004614a4f565b610e69565b34801561053b575f5ffd5b5061033961054a366004614a7c565b610e99565b34801561055a575f5ffd5b50610339610569366004614b11565b610f2e565b348015610579575f5ffd5b50610339610588366004614b7f565b610f61565b348015610598575f5ffd5b506105036105a7366004614a25565b610fee565b3480156105b7575f5ffd5b50610503611084565b3480156105cb575f5ffd5b5061062e6105da3660046149ed565b5f908152601360209081526040808320546014835281842054601c845282852054601d855283862054601e865284872054601f8752858820549680529490962054929691959094909360ff90811693911691565b60408051978852602088019690965294860193909352606085019190915215156080840152151560a083015260c082015260e0016103c9565b348015610672575f5ffd5b506105036106813660046149ed565b61109a565b348015610691575f5ffd5b506103396106a0366004614bbd565b611108565b3480156106b0575f5ffd5b506103396106bf366004614c4f565b61131b565b3480156106cf575f5ffd5b506105036106de3660046149ed565b5f908152600e602052604090205490565b3480156106fa575f5ffd5b50610339610709366004614c94565b611341565b348015610719575f5ffd5b506104126107283660046149ed565b611510565b348015610738575f5ffd5b50610339610747366004614bbd565b61151a565b348015610757575f5ffd5b50610503610766366004614bbd565b611679565b348015610776575f5ffd5b506103e66116f1565b34801561078a575f5ffd5b50610339611700565b34801561079e575f5ffd5b50610503611713565b3480156107b2575f5ffd5b505f5473ffffffffffffffffffffffffffffffffffffffff16610412565b3480156107db575f5ffd5b506103396107ea366004614a4f565b611724565b3480156107fa575f5ffd5b50610803611736565b60408051928352815173ffffffffffffffffffffffffffffffffffffffff9081166020808601919091528301511683820152015160608201526080016103c9565b34801561084f575f5ffd5b506103e6611814565b348015610863575f5ffd5b506105036108723660046149ed565b5f908152601b602052604090205490565b34801561088e575f5ffd5b5061050361089d366004614cc2565b611823565b3480156108ad575f5ffd5b506103396108bc366004614ceb565b61185f565b3480156108cc575f5ffd5b506103396108db366004614a25565b61186a565b3480156108eb575f5ffd5b50610339610588366004614d17565b610503610908366004614d92565b611cbf565b348015610918575f5ffd5b506103e66109273660046149ed565b6121b1565b61050361093a366004614a25565b6121bc565b34801561094a575f5ffd5b50610339610959366004614dc9565b61264c565b348015610969575f5ffd5b50610503610978366004614a4f565b5f918252600f6020908152604080842092845291905290205490565b34801561099f575f5ffd5b506105036109ae3660046149ed565b6127fb565b6103396109c13660046149ed565b612956565b3480156109d1575f5ffd5b50601254610503565b3480156109e5575f5ffd5b506103396109f4366004614bbd565b612971565b348015610a04575f5ffd5b506103bd610a13366004614e10565b73ffffffffffffffffffffffffffffffffffffffff9182165f90815260076020908152604080832093909416825291909152205460ff1690565b348015610a58575f5ffd5b50600d546104129073ffffffffffffffffffffffffffffffffffffffff1681565b348015610a84575f5ffd5b50610339610a93366004614bbd565b6129f7565b348015610aa3575f5ffd5b50610339610ab2366004614e3c565b612a57565b5f805460405173ffffffffffffffffffffffffffffffffffffffff909116913480156108fc02929091818181858888f19350505050158015610afb573d5f5f3e3d5ffd5b50565b610b06612a88565b8051825114610b9c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f52756e626f743a20746f6b656e49647320616e6420626964507269636573206d60448201527f7573742068617665207468652073616d65206c656e677468000000000000000060648201526084015b60405180910390fd5b5f5b8251811015610beb57610be3838281518110610bbc57610bbc614ea0565b6020026020010151838381518110610bd657610bd6614ea0565b6020026020010151612acb565b600101610b9e565b50610bf560018055565b5050565b5f610c0382612c8f565b92915050565b606060028054610c1890614ecd565b80601f0160208091040260200160405190810160405280929190818152602001828054610c4490614ecd565b8015610c8f5780601f10610c6657610100808354040283529160200191610c8f565b820191905f5260205f20905b815481529060010190602001808311610c7257829003601f168201915b5050505050905090565b5f610ca382612ce4565b505f8281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff16610c03565b610bf5828233612d42565b610ce0612a88565b610cea8282612d4f565b610bf560018055565b610cfb6132cb565b5f805460405173ffffffffffffffffffffffffffffffffffffffff909116914780156108fc02929091818181858888f19350505050158015610afb573d5f5f3e3d5ffd5b5f610d896040518060c001604052805f73ffffffffffffffffffffffffffffffffffffffff1681526020015f81526020015f81526020015f81526020015f81526020015f81525090565b60175460165410610df6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f52756e626f743a204e6f206d696e742061736b000000000000000000000000006044820152606401610b93565b50506016545f81815260156020908152604091829020825160c081018452815473ffffffffffffffffffffffffffffffffffffffff168152600182015492810192909252600281015492820192909252600382015460608201526004820154608082015260059091015460a08201529091565b5f828152601060205260408120805483908110610e8857610e88614ea0565b905f5260205f200154905092915050565b610ea16132cb565b610ea9612a88565b5f5b8c811015610f1657610f0e8c8c610ec28c85614f4b565b610ecc908e614f62565b610ed68b86614f4b565b610ee0908d614f62565b610eea8a87614f4b565b610ef4908c614f62565b610efe8988614f4b565b610f08908b614f62565b8861331d565b600101610eab565b50610f2060018055565b505050505050505050505050565b610f366132cb565b610f3e612a88565b610f4e88888888888888886135f6565b610f5760018055565b5050505050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f52756e626f743a204e4654206e6f74206469726563746c79207472616e73666560448201527f7261626c650000000000000000000000000000000000000000000000000000006064820152608401610b93565b505050565b5f610ff883611679565b821061104f576040517fa57d13dc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260248101839052604401610b93565b5073ffffffffffffffffffffffffffffffffffffffff919091165f908152600860209081526040808320938352929052205490565b5f601954601a546110959190614f75565b905090565b5f6110a4600a5490565b82106110e5576040517fa57d13dc0000000000000000000000000000000000000000000000000000000081525f600482015260248101839052604401610b93565b600a82815481106110f8576110f8614ea0565b905f5260205f2001549050919050565b611110612a88565b335f9081526023602052604090205480611186576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f52756e626f743a204e6f2070656e64696e6720627579207472616e73666572006044820152606401610b93565b478111156111f0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f52756e626f743a204e6f7420656e6f7567682066756e647300000000000000006044820152606401610b93565b335f908152602360205260408082208290555173ffffffffffffffffffffffffffffffffffffffff84169083908381818185875af1925050503d805f8114611253576040519150601f19603f3d011682016040523d82523d5f602084013e611258565b606091505b50509050806112c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f52756e626f743a205472616e73666572206661696c65640000000000000000006044820152606401610b93565b60405182815273ffffffffffffffffffffffffffffffffffffffff84169033907f2f87fa0e21f3b080cdbc96cb371b4ed47c540d211cd43b00f3e57b98c2685d389060200160405180910390a35050610afb60018055565b6113236132cb565b61132b612a88565b60216113378282614fcc565b50610afb60018055565b6113496132cb565b611351612a88565b60195482146113e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f52756e626f743a205472616e736665722061736b206e6f74207468652066697260448201527f7374206f6e6500000000000000000000000000000000000000000000000000006064820152608401610b93565b5f8281526018602081815260408084208151606081018352815473ffffffffffffffffffffffffffffffffffffffff808216835260018085018054928316858901526002860180549786018890528c8b52989097527fffffffffffffffffffffffff0000000000000000000000000000000000000000928316909455169093559284905560198054929491939290919061147d908490614f62565b90915550508215611505575f818152601b6020908152604080832083905584518583015182519384019092529282526114b892918490613622565b60208201518251604051839273ffffffffffffffffffffffffffffffffffffffff9081169216907fdeb3a6837278f6e9914a507e4d73f08e841d8fca434fb97d4307b3b0d3d6b105905f90a45b5050610bf560018055565b5f610c0382612ce4565b6115226132cb565b8073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb61155c5f5473ffffffffffffffffffffffffffffffffffffffff1690565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8516906370a0823190602401602060405180830381865afa1580156115c4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115e891906150e3565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff909216600483015260248201526044016020604051808303815f875af1158015611655573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bf591906150fa565b5f73ffffffffffffffffffffffffffffffffffffffff82166116c9576040517f89c62b640000000000000000000000000000000000000000000000000000000081525f6004820152602401610b93565b5073ffffffffffffffffffffffffffffffffffffffff165f9081526005602052604090205490565b606060218054610c1890614ecd565b6117086132cb565b6117115f61363a565b565b5f6016546017546110959190614f75565b61172c612a88565b610cea8282612acb565b604080516060810182525f80825260208201819052918101829052601a54601954106117be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f52756e626f743a204e6f207472616e736665722061736b0000000000000000006044820152606401610b93565b50506019545f818152601860209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff90811682526001830154169281019290925260020154918101919091529091565b606060038054610c1890614ecd565b5f838152601160209081526040808320858452909152812080548390811061184d5761184d614ea0565b905f5260205f20015490509392505050565b610bf53383836136ae565b6118726132cb565b61187a612a88565b602254610100900460ff16156118ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f52756e626f743a20416c7265616479206d6967726174656400000000000000006044820152606401610b93565b5f8273ffffffffffffffffffffffffffffffffffffffff1663dcbace946040518163ffffffff1660e01b8152600401602060405180830381865afa158015611936573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061195a91906150e3565b90505f5b82811015611c79576012548281106119765750611c79565b5f5f5f5f5f5f5f8b73ffffffffffffffffffffffffffffffffffffffff166346c27e8c896040518263ffffffff1660e01b81526004016119b891815260200190565b60e060405180830381865afa1580156119d3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119f79190615115565b96509650965096509650965096505f8c73ffffffffffffffffffffffffffffffffffffffff16639b013aee8a6040518263ffffffff1660e01b8152600401611a4191815260200190565b602060405180830381865afa158015611a5c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a8091906150e3565b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018b90529091505f9073ffffffffffffffffffffffffffffffffffffffff8f1690636352211e90602401602060405180830381865afa158015611aee573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b129190615180565b9050600160125f828254611b269190614f62565b90915550505f8a81526013602090815260408083208c9055601482528083208b9055601b8252808320859055601c82528083208a9055601d8252808320899055601e825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009081168a151517909155601f835281842080549091168815151790558180528083208690558b8352600e9091528120805460019290611bd0908490614f62565b90915550505f898152600f602090815260408083208b84529091528120805460019290611bfe908490614f62565b90915550505f898152601060209081526040808320805460018181018355918552838520018e90558c8452601183528184208c855283529083208054918201815583529120018a9055611c51818b6137aa565b611c638a611c5e8c6137c3565b61387f565b50506001909801975061195e9650505050505050565b508060125403610beb57602280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010017905550610bf560018055565b50505050565b5f611cc8612a88565b60225460ff168015611ce15750602254610100900460ff165b611d47576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f52756e626f743a204e6f7420696e697469616c697a65640000000000000000006044820152606401610b93565b5f8611611db0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f52756e626f743a2043616e6e6f74206d696e74203020746f6b656e00000000006044820152606401610b93565b600d546040517f835309b70000000000000000000000000000000000000000000000000000000081523360048201525f9173ffffffffffffffffffffffffffffffffffffffff169063835309b790602401606060405180830381865afa158015611e1c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e40919061519b565b50905080871115611ed3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f52756e626f743a2043616e6e6f74206d696e7420736f206d616e79204e46542060448201527f6174206f6e6365000000000000000000000000000000000000000000000000006064820152608401610b93565b600d546040517f96c47dc500000000000000000000000000000000000000000000000000000000815260048101889052602481018790526044810186905260016064820152608481018990523360a48201525f9173ffffffffffffffffffffffffffffffffffffffff16906396c47dc59060c401602060405180830381865afa158015611f62573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f8691906150e3565b905080341015611ff2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f52756e626f743a204e6f7420656e6f756768206d696e742066656573000000006044820152606401610b93565b601780546040805160c08101825233815260208082018d81528284018d8152606084018d8152608085018d815260a086018d81525f8981526015909652968520955186547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161786559251600180870191909155915160028601555160038501559051600484015592516005909201919091558354929391926120ae908490614f62565b9091555050600d546040517f196a93d0000000000000000000000000000000000000000000000000000000008152600481018a90526024810189905233604482015273ffffffffffffffffffffffffffffffffffffffff9091169063196a93d09084906064015f604051808303818588803b15801561212b575f5ffd5b505af115801561213d573d5f5f3e3d5ffd5b505060408051858152602081018e90529081018c9052606081018b9052608081018a905260a081018990523393507f061ba009aac8cbea2f5ff78aa7e87ee8396cd094d8dcbcc911064c4142351a70925060c001905060405180910390a2925050506121a860018055565b95945050505050565b6060610c03826138ce565b5f6121c5612a88565b60225460ff1680156121de5750602254610100900460ff165b612244576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f52756e626f743a204e6f7420696e697469616c697a65640000000000000000006044820152606401610b93565b600d546040517f0a411c310000000000000000000000000000000000000000000000000000000081523360048201525f9173ffffffffffffffffffffffffffffffffffffffff1690630a411c3190602401602060405180830381865afa1580156122b0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122d491906150e3565b905080341015612340576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f52756e626f743a204e6f7420656e6f756768207472616e7366657220666565736044820152606401610b93565b3361234a84611510565b73ffffffffffffffffffffffffffffffffffffffff16146123ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f52756e626f743a2043616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72000000000000000000000000000000000000000000000000000000000000006064820152608401610b93565b5f838152602080526040902054421015612488576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f52756e626f743a2043616e6e6f74207472616e73666572206c6f636b6564207460448201527f6f6b656e000000000000000000000000000000000000000000000000000000006064820152608401610b93565b601a80546040805160608101825233815273ffffffffffffffffffffffffffffffffffffffff88811660208084019182528385018a81525f8781526018909252948120935184549084167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216178555915160018086018054929095169190931617909255925160029092019190915583549293919261252a908490614f62565b9091555050600d545f8581526013602090815260408083205460149092528083205481517f2ebceed9000000000000000000000000000000000000000000000000000000008152600481019390935260248301523360448301525173ffffffffffffffffffffffffffffffffffffffff90931692632ebceed99286926064808201939182900301818588803b1580156125c1575f5ffd5b505af11580156125d3573d5f5f3e3d5ffd5b5050505050838573ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fe8664c789f701fb7be7be3156f0fe556f9a7023f5b4604b2a60fa257251b06cf8460405161263891815260200190565b60405180910390a4915050610c0360018055565b6126546132cb565b61265c612a88565b60165484146126ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f52756e626f743a204d696e742061736b206e6f7420746865206669727374206f60448201527f6e650000000000000000000000000000000000000000000000000000000000006064820152608401610b93565b5f848152601560208181526040808420815160c081018352815473ffffffffffffffffffffffffffffffffffffffff811682526001808401805484880152600285018054968501969096526003850180546060860152600486018054608087015260058701805460a08801528f8c52999098527fffffffffffffffffffffffff0000000000000000000000000000000000000000909316909455928790559286905591859055918490559183905560168054929391929091906127b1908490614f62565b909155505081156127f15760a0810151428511156127cc57505f5b6127ef8260200151835f0151846040015185606001518587608001518b8b6135f6565b505b50611cb960018055565b5f818152601b6020908152604080832054601e835281842054601c90935290832054909160ff16908361282d86611510565b600d545f8881526013602090815260408083205460149092529091205492935073ffffffffffffffffffffffffffffffffffffffff9091169163e7deb9b991908787801561288857505f8b8152601f602052604090205460ff165b876128928d6139cd565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b16815260048101969096526024860194909452604485019290925215156064840152608483015260a482015273ffffffffffffffffffffffffffffffffffffffff841660c48201523360e482015261010401602060405180830381865afa158015612928573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061294c91906150e3565b9695505050505050565b61295e612a88565b6129683382612d4f565b610afb60018055565b6129796132cb565b612981612a88565b600d805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116179055602280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610afb60018055565b6129ff6132cb565b73ffffffffffffffffffffffffffffffffffffffff8116612a4e576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f6004820152602401610b93565b610afb8161363a565b612a5f6132cb565b612a67612a88565b612a768787878787878761331d565b612a7f60018055565b50505050505050565b600260015403612ac4576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600155565b5f82815260046020526040902054612afa9073ffffffffffffffffffffffffffffffffffffffff163384613a1f565b612b86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f52756e626f743a2043616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72206f7220617070726f766564000000000000000000000000000000000000006064820152608401610b93565b5f828152602080526040902054421015612c22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f52756e626f743a2043616e6e6f7420736574206269642070726963652077686960448201527f6c65206c6f636b656400000000000000000000000000000000000000000000006064820152608401610b93565b5f828152601b6020526040902081905581612c3c81611510565b73ffffffffffffffffffffffffffffffffffffffff167ff6883b6e03f0249ee984a32e1a41b3c807eeef7a8874cbf7f807d715632c8a9383604051612c8391815260200190565b60405180910390a35050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f49064906000000000000000000000000000000000000000000000000000000001480610c035750610c0382613ae0565b5f8181526004602052604081205473ffffffffffffffffffffffffffffffffffffffff1680610c03576040517f7e27328900000000000000000000000000000000000000000000000000000000815260048101849052602401610b93565b610fe98383836001613b35565b60225460ff168015612d685750602254610100900460ff165b612dce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f52756e626f743a204e6f7420696e697469616c697a65640000000000000000006044820152606401610b93565b5f818152602080526040902054421015612e44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f52756e626f743a204e4654206c6f636b656400000000000000000000000000006044820152606401610b93565b5f818152601b6020908152604080832054601e835281842054601c90935290832054909260ff90921691612e7785611510565b90505f8411612ee2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f52756e626f743a204e4654206e6f7420666f722073616c6500000000000000006044820152606401610b93565b600d545f868152601360209081526040808320546014909252822054919273ffffffffffffffffffffffffffffffffffffffff169163e7deb9b9919088888015612f3957505f8b8152601f602052604090205460ff165b88612f438d6139cd565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b16815260048101969096526024860194909452604485019290925215156064840152608483015260a482015273ffffffffffffffffffffffffffffffffffffffff80861660c48301528a1660e482015261010401602060405180830381865afa158015612fdb573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612fff91906150e3565b905061300b8186614f62565b341015613074576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f52756e626f743a204e6f7420656e6f7567682066756e647300000000000000006044820152606401610b93565b5f868152601e602052604090205460ff16156130d4576130948342614f62565b5f878152601d6020908152604080832093909355601e90522080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b5f868152601b602090815260408083208390558051918201905290815261310090839089908990613622565b600d545f8781526013602090815260408083205460149092528083205481517ff7a8b7490000000000000000000000000000000000000000000000000000000081526004810193909352602483015273ffffffffffffffffffffffffffffffffffffffff86811660448401528b81166064840152905193169263f7a8b7499285926084808201939182900301818588803b15801561319c575f5ffd5b505af11580156131ae573d5f5f3e3d5ffd5b50505050505f8273ffffffffffffffffffffffffffffffffffffffff16866040515f6040518083038185875af1925050503d805f8114613209576040519150601f19603f3d011682016040523d82523d5f602084013e61320e565b606091505b50509050806132515773ffffffffffffffffffffffffffffffffffffffff83165f908152602360205260408120805488929061324b908490614f62565b90915550505b868373ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff167ef93dbdb72854b6b6fb35433086556f2635fc83c37080c667496fecfa650fb489866040516132b9929190918252602082015260400190565b60405180910390a45050505050505050565b5f5473ffffffffffffffffffffffffffffffffffffffff163314611711576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610b93565b60225460ff1680156133365750602254610100900460ff165b61339c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f52756e626f743a204e6f7420696e697469616c697a65640000000000000000006044820152606401610b93565b42821115806133a9575083155b613435576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f52756e626f743a2043616e6e6f74207365742062696420707269636520616e6460448201527f206c6f636b2074696d656f75742073696d756c6174616e656f75736c790000006064820152608401610b93565b60128054906001905f6134488385614f62565b90915550505f8181526013602090815260408083208a905560148252808320899055601b8252808320889055601c8252808320879055601e8252808320805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009182168117909255601f845282852080549091168715151790558280528184208790558a8452600e90925282208054919290916134e8908490614f62565b90915550505f878152600f602090815260408083208984529091528120805460019290613516908490614f62565b90915550505f878152601060209081526040808320805460018181018355918552838520018590558a8452601183528184208a8552835290832080549182018155835291200181905561356988826137aa565b61357681611c5e836137c3565b6040805182815260208101899052908101879052606081018690526080810185905260a0810184905282151560c082015273ffffffffffffffffffffffffffffffffffffffff8916907fe3dbf380a595a9c8689ffa1f37d50b5893c82476efe9e1c209b8adf628c245a49060e00160405180910390a25050505050505050565b5f5b888110156136175761360f8888888888888861331d565b6001016135f8565b505050505050505050565b61362d848484613cfd565b611cb93385858585613e36565b5f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff8216613713576040517f5b08ba1800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610b93565b73ffffffffffffffffffffffffffffffffffffffff8381165f8181526007602090815260408083209487168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b610bf5828260405180602001604052805f81525061402c565b60605f6137cf83614043565b60010190505f8167ffffffffffffffff8111156137ee576137ee6147f0565b6040519080825280601f01601f191660200182016040528015613818576020820181803683370190505b5090508181016020015b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a850494508461382257509392505050565b5f828152600c602052604090206138968282614fcc565b506040518281527ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79060200160405180910390a15050565b60606138d982612ce4565b505f828152600c6020526040812080546138f290614ecd565b80601f016020809104026020016040519081016040528092919081815260200182805461391e90614ecd565b80156139695780601f1061394057610100808354040283529160200191613969565b820191905f5260205f20905b81548152906001019060200180831161394c57829003601f168201915b505050505090505f6139796116f1565b905080515f0361398a575092915050565b8151156139bc5780826040516020016139a4929190615239565b60405160208183030381529060405292505050919050565b6139c584614124565b949350505050565b5f818152601c6020908152604080832054601e90925282205460ff16610c03575f838152601d602052604090205442811115613a1457613a0d4282614f75565b9150613a18565b5f91505b5092915050565b5f73ffffffffffffffffffffffffffffffffffffffff8316158015906139c557508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480613aab575073ffffffffffffffffffffffffffffffffffffffff8085165f9081526007602090815260408083209387168352929052205460ff165b806139c55750505f9081526006602052604090205473ffffffffffffffffffffffffffffffffffffffff908116911614919050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f780e9d63000000000000000000000000000000000000000000000000000000001480610c035750610c0382614189565b8080613b56575073ffffffffffffffffffffffffffffffffffffffff821615155b15613ca9575f613b6584612ce4565b905073ffffffffffffffffffffffffffffffffffffffff831615801590613bb857508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b8015613bf6575073ffffffffffffffffffffffffffffffffffffffff8082165f9081526007602090815260408083209387168352929052205460ff16155b15613c45576040517fa9fbf51f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610b93565b8115613ca757838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b50505f90815260066020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff8216613d4c576040517f64a0ae920000000000000000000000000000000000000000000000000000000081525f6004820152602401610b93565b5f613d5883835f61426b565b905073ffffffffffffffffffffffffffffffffffffffff8116613daa576040517f7e27328900000000000000000000000000000000000000000000000000000000815260048101839052602401610b93565b8373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611cb9576040517f64283d7b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80861660048301526024820184905282166044820152606401610b93565b73ffffffffffffffffffffffffffffffffffffffff83163b15614025576040517f150b7a0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84169063150b7a0290613eab90889088908790879060040161524d565b6020604051808303815f875af1925050508015613f03575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252613f009181019061529d565b60015b613f90573d808015613f30576040519150601f19603f3d011682016040523d82523d5f602084013e613f35565b606091505b5080515f03613f88576040517f64a0ae9200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610b93565b805181602001fd5b7fffffffff0000000000000000000000000000000000000000000000000000000081167f150b7a020000000000000000000000000000000000000000000000000000000014614023576040517f64a0ae9200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610b93565b505b5050505050565b6140368383614277565b610fe9335f858585613e36565b5f807a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000831061408b577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef810000000083106140b7576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106140d557662386f26fc10000830492506010015b6305f5e10083106140ed576305f5e100830492506008015b612710831061410157612710830492506004015b60648310614113576064830492506002015b600a8310610c035760010192915050565b606061412f82612ce4565b505f6141396116f1565b90505f8151116141575760405180602001604052805f815250614182565b80614161846137c3565b604051602001614172929190615239565b6040516020818303038152906040525b9392505050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd00000000000000000000000000000000000000000000000000000000148061421b57507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b80610c0357507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610c03565b5f6139c5848484614324565b73ffffffffffffffffffffffffffffffffffffffff82166142c6576040517f64a0ae920000000000000000000000000000000000000000000000000000000081525f6004820152602401610b93565b5f6142d283835f61426b565b905073ffffffffffffffffffffffffffffffffffffffff811615610fe9576040517f73c6ac6e0000000000000000000000000000000000000000000000000000000081525f6004820152602401610b93565b5f5f61433185858561443d565b905073ffffffffffffffffffffffffffffffffffffffff811661439a5761439584600a80545f838152600b60205260408120829055600182018355919091527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80155565b6143d7565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146143d7576143d781856145b4565b73ffffffffffffffffffffffffffffffffffffffff8516614400576143fb8461463e565b6139c5565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146139c5576139c585856146e5565b5f8281526004602052604081205473ffffffffffffffffffffffffffffffffffffffff9081169083161561447657614476818486614740565b73ffffffffffffffffffffffffffffffffffffffff8116156144e95761449e5f855f5f613b35565b73ffffffffffffffffffffffffffffffffffffffff81165f90815260056020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b73ffffffffffffffffffffffffffffffffffffffff8516156145315773ffffffffffffffffffffffffffffffffffffffff85165f908152600560205260409020805460010190555b5f8481526004602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff89811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b5f6145be83611679565b5f8381526009602090815260408083205473ffffffffffffffffffffffffffffffffffffffff88168452600890925290912091925090818314614620575f83815260208281526040808320548584528184208190558352600990915290208290555b5f938452600960209081526040808620869055938552525081205550565b600a545f9061464f90600190614f75565b5f838152600b6020526040812054600a805493945090928490811061467657614676614ea0565b905f5260205f200154905080600a838154811061469557614695614ea0565b5f918252602080832090910192909255828152600b9091526040808220849055858252812055600a8054806146cc576146cc6152b8565b600190038181905f5260205f20015f9055905550505050565b5f60016146f184611679565b6146fb9190614f75565b73ffffffffffffffffffffffffffffffffffffffff9093165f908152600860209081526040808320868452825280832085905593825260099052919091209190915550565b61474b838383613a1f565b610fe95773ffffffffffffffffffffffffffffffffffffffff831661479f576040517f7e27328900000000000000000000000000000000000000000000000000000000815260048101829052602401610b93565b6040517f177e802f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015260248101829052604401610b93565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614864576148646147f0565b604052919050565b5f82601f83011261487b575f5ffd5b813567ffffffffffffffff811115614895576148956147f0565b8060051b6148a56020820161481d565b918252602081850181019290810190868411156148c0575f5ffd5b6020860192505b8383101561294c5782358252602092830192909101906148c7565b5f5f604083850312156148f3575f5ffd5b823567ffffffffffffffff811115614909575f5ffd5b6149158582860161486c565b925050602083013567ffffffffffffffff811115614931575f5ffd5b61493d8582860161486c565b9150509250929050565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114610afb575f5ffd5b5f60208284031215614984575f5ffd5b813561418281614947565b5f81518084528060208401602086015e5f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081525f614182602083018461498f565b5f602082840312156149fd575f5ffd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610afb575f5ffd5b5f5f60408385031215614a36575f5ffd5b8235614a4181614a04565b946020939093013593505050565b5f5f60408385031215614a60575f5ffd5b50508035926020909101359150565b8015158114610afb575f5ffd5b5f5f5f5f5f5f5f5f5f5f5f5f6101808d8f031215614a98575f5ffd5b8c359b5060208d0135614aaa81614a04565b9a5060408d0135995060608d0135985060808d0135975060a08d0135965060c08d0135955060e08d013594506101008d013593506101208d013592506101408d013591506101608d0135614afd81614a6f565b809150509295989b509295989b509295989b565b5f5f5f5f5f5f5f5f610100898b031215614b29575f5ffd5b883597506020890135614b3b81614a04565b965060408901359550606089013594506080890135935060a0890135925060c0890135915060e0890135614b6e81614a6f565b809150509295985092959890939650565b5f5f5f60608486031215614b91575f5ffd5b8335614b9c81614a04565b92506020840135614bac81614a04565b929592945050506040919091013590565b5f60208284031215614bcd575f5ffd5b813561418281614a04565b5f5f67ffffffffffffffff841115614bf257614bf26147f0565b50601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016602001614c258161481d565b915050828152838383011115614c39575f5ffd5b828260208301375f602084830101529392505050565b5f60208284031215614c5f575f5ffd5b813567ffffffffffffffff811115614c75575f5ffd5b8201601f81018413614c85575f5ffd5b6139c584823560208401614bd8565b5f5f60408385031215614ca5575f5ffd5b823591506020830135614cb781614a6f565b809150509250929050565b5f5f5f60608486031215614cd4575f5ffd5b505081359360208301359350604090920135919050565b5f5f60408385031215614cfc575f5ffd5b8235614d0781614a04565b91506020830135614cb781614a6f565b5f5f5f5f60808587031215614d2a575f5ffd5b8435614d3581614a04565b93506020850135614d4581614a04565b925060408501359150606085013567ffffffffffffffff811115614d67575f5ffd5b8501601f81018713614d77575f5ffd5b614d8687823560208401614bd8565b91505092959194509250565b5f5f5f5f5f60a08688031215614da6575f5ffd5b505083359560208501359550604085013594606081013594506080013592509050565b5f5f5f5f60808587031215614ddc575f5ffd5b84359350602085013592506040850135614df581614a6f565b91506060850135614e0581614a6f565b939692955090935050565b5f5f60408385031215614e21575f5ffd5b8235614e2c81614a04565b91506020830135614cb781614a04565b5f5f5f5f5f5f5f60e0888a031215614e52575f5ffd5b8735614e5d81614a04565b96506020880135955060408801359450606088013593506080880135925060a0880135915060c0880135614e9081614a6f565b8091505092959891949750929550565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b600181811c90821680614ee157607f821691505b602082108103614f18577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8082028115828204841417610c0357610c03614f1e565b80820180821115610c0357610c03614f1e565b81810381811115610c0357610c03614f1e565b601f821115610fe957805f5260205f20601f840160051c81016020851015614fad5750805b601f840160051c820191505b81811015614025575f8155600101614fb9565b815167ffffffffffffffff811115614fe657614fe66147f0565b614ffa81614ff48454614ecd565b84614f88565b6020601f82116001811461504b575f83156150155750848201515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600385901b1c1916600184901b178455614025565b5f848152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08516915b828110156150985787850151825560209485019460019092019101615078565b50848210156150d457868401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b60f8161c191681555b50505050600190811b01905550565b5f602082840312156150f3575f5ffd5b5051919050565b5f6020828403121561510a575f5ffd5b815161418281614a6f565b5f5f5f5f5f5f5f60e0888a03121561512b575f5ffd5b8751602089015160408a015160608b015160808c0151939a509198509650945061515481614a6f565b60a089015190935061516581614a6f565b60c09890980151969995985093969295919492935090919050565b5f60208284031215615190575f5ffd5b815161418281614a04565b5f5f82840360608112156151ad575f5ffd5b8351925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0820112156151e0575f5ffd5b506040805190810167ffffffffffffffff81118282101715615204576152046147f0565b60409081526020858101518352940151938101939093525092909150565b5f81518060208401855e5f93019283525090919050565b5f6139c56152478386615222565b84615222565b73ffffffffffffffffffffffffffffffffffffffff8516815273ffffffffffffffffffffffffffffffffffffffff84166020820152826040820152608060608201525f61294c608083018461498f565b5f602082840312156152ad575f5ffd5b815161418281614947565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffdfea26469706673582212200679d547f98b163cdc6b5983262a84c74e279d1e3b7fc7759631bdbbc9bcfb8b64736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002368747470733a2f2f6170702e72756e626f742e696f2f6e66742d6d657461646174612f0000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : baseURL_ (string): https://app.runbot.io/nft-metadata/
Arg [1] : migrated_ (bool): False
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000023
Arg [3] : 68747470733a2f2f6170702e72756e626f742e696f2f6e66742d6d6574616461
Arg [4] : 74612f0000000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
133261:15881:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7118:10;:8;:10::i;:::-;133261:15881;;5332:7;5359:6;;7259:36;;5359:6;;;;;7285:9;7259:36;;;;;7285:9;;7259:36;5332:7;7259:36;7285:9;5359:6;7259:36;;;;;;;;;;;;;;;;;;;142181:320;;;;;;;;;;-1:-1:-1;142181:320:0;;;;;:::i;:::-;;:::i;143751:191::-;;;;;;;;;;-1:-1:-1;143751:191:0;;;;;:::i;:::-;;:::i;:::-;;;2514:14:1;;2507:22;2489:41;;2477:2;2462:18;143751:191:0;;;;;;;;109016:91;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;110188:158::-;;;;;;;;;;-1:-1:-1;110188:158:0;;;;;:::i;:::-;;:::i;:::-;;;3548:42:1;3536:55;;;3518:74;;3506:2;3491:18;110188:158:0;3372:226:1;110007:115:0;;;;;;;;;;-1:-1:-1;110007:115:0;;;;;:::i;:::-;;:::i;143489:102::-;;;;;;:::i;:::-;;:::i;6855:99::-;;;;;;;;;;;;;:::i;139324:204::-;;;;;;;;;;;;;:::i;:::-;;;;4359:25:1;;;4424:13;;4439:42;4420:62;4415:2;4400:18;;;4393:90;;;;4525:15;;4519:22;4499:18;;;4492:50;4584:15;;4578:22;4573:2;4558:18;;;4551:50;;;;4644:15;;4638:22;4632:3;4617:19;;;4610:51;;;;4704:16;;4698:23;4692:3;4677:19;;;4670:52;;;;4765:16;4759:23;4753:3;4738:19;;4731:52;4346:3;4331:19;139324:204:0;4134:655:1;124822:104:0;;;;;;;;;;-1:-1:-1;124901:10:0;:17;124822:104;;;4940:25:1;;;4928:2;4913:18;124822:104:0;4794:177:1;141733:137:0;;;;;;;;;;-1:-1:-1;141733:137:0;;;;;:::i;:::-;;:::i;140468:580::-;;;;;;;;;;-1:-1:-1;140468:580:0;;;;;:::i;:::-;;:::i;140147:315::-;;;;;;;;;;-1:-1:-1;140147:315:0;;;;;:::i;:::-;;:::i;145012:213::-;;;;;;;;;;-1:-1:-1;145012:213:0;;;;;:::i;:::-;;:::i;124486:260::-;;;;;;;;;;-1:-1:-1;124486:260:0;;;;;:::i;:::-;;:::i;135901:114::-;;;;;;;;;;;;;:::i;142618:297::-;;;;;;;;;;-1:-1:-1;142618:297:0;;;;;:::i;:::-;142673:7;142742:18;;;:9;:18;;;;;;;;;142762:12;:21;;;;;;142785:15;:24;;;;;;142811:14;:23;;;;;;142836:11;:20;;;;;;142858:19;:28;;;;;;142888:21;;;;;;;;142742:18;;142762:21;;142785:24;;142811:23;;142836:20;;;;;142858:28;;;142618:297;;;;;8984:25:1;;;9040:2;9025:18;;9018:34;;;;9068:18;;;9061:34;;;;9126:2;9111:18;;9104:34;;;;9182:14;9175:22;9169:3;9154:19;;9147:51;9242:14;9235:22;9229:3;9214:19;;9207:51;9289:3;9274:19;;9267:35;8971:3;8956:19;142618:297:0;8681:627:1;125003:231:0;;;;;;;;;;-1:-1:-1;125003:231:0;;;;;:::i;:::-;;:::i;144038:482::-;;;;;;;;;;-1:-1:-1;144038:482:0;;;;;:::i;:::-;;:::i;134914:103::-;;;;;;;;;;-1:-1:-1;134914:103:0;;;;;:::i;:::-;;:::i;141451:116::-;;;;;;;;;;-1:-1:-1;141451:116:0;;;;;:::i;:::-;141524:7;141544:18;;;:9;:18;;;;;;;141451:116;136263:566;;;;;;;;;;-1:-1:-1;136263:566:0;;;;;:::i;:::-;;:::i;108829:120::-;;;;;;;;;;-1:-1:-1;108829:120:0;;;;;:::i;:::-;;:::i;6960:::-;;;;;;;;;;-1:-1:-1;6960:120:0;;;;;:::i;:::-;;:::i;108554:213::-;;;;;;;;;;-1:-1:-1;108554:213:0;;;;;:::i;:::-;;:::i;143948:85::-;;;;;;;;;;;;;:::i;5961:103::-;;;;;;;;;;;;;:::i;139216:102::-;;;;;;;;;;;;;:::i;5286:87::-;;;;;;;;;;-1:-1:-1;5332:7:0;5359:6;;;5286:87;;142057:118;;;;;;;;;;-1:-1:-1;142057:118:0;;;;;:::i;:::-;;:::i;136021:236::-;;;;;;;;;;;;;:::i;:::-;;;;11399:25:1;;;11464:13;;11479:42;11460:62;;;11455:2;11440:18;;;11433:90;;;;11569:15;;11563:22;11559:71;11539:18;;;11532:99;11673:15;11667:22;11662:2;11647:18;;11640:50;11386:3;11371:19;136021:236:0;11166:530:1;109176:95:0;;;;;;;;;;;;;:::i;142507:105::-;;;;;;;;;;-1:-1:-1;142507:105:0;;;;;:::i;:::-;142568:7;142588:19;;;:10;:19;;;;;;;142507:105;141876:175;;;;;;;;;;-1:-1:-1;141876:175:0;;;;;:::i;:::-;;:::i;110418:146::-;;;;;;;;;;-1:-1:-1;110418:146:0;;;;;:::i;:::-;;:::i;136834:1388::-;;;;;;;;;;-1:-1:-1;136834:1388:0;;;;;:::i;:::-;;:::i;144532:245::-;;;;;;;;;;-1:-1:-1;144532:245:0;;;;;:::i;138231:979::-;;;;;;:::i;:::-;;:::i;143597:148::-;;;;;;;;;;-1:-1:-1;143597:148:0;;;;;:::i;:::-;;:::i;135026:869::-;;;;;;:::i;:::-;;:::i;139534:607::-;;;;;;;;;;-1:-1:-1;139534:607:0;;;;;:::i;:::-;;:::i;141573:154::-;;;;;;;;;;-1:-1:-1;141573:154:0;;;;;:::i;:::-;141669:7;141689:21;;;:12;:21;;;;;;;;:33;;;;;;;;;;141573:154;142921:460;;;;;;;;;;-1:-1:-1;142921:460:0;;;;;:::i;:::-;;:::i;143387:96::-;;;;;;:::i;:::-;;:::i;141356:89::-;;;;;;;;;;-1:-1:-1;141428:12:0;;141356:89;;134772:136;;;;;;;;;;-1:-1:-1;134772:136:0;;;;;:::i;:::-;;:::i;110635:155::-;;;;;;;;;;-1:-1:-1;110635:155:0;;;;;:::i;:::-;110747:25;;;;110723:4;110747:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;110635:155;133396:30;;;;;;;;;;-1:-1:-1;133396:30:0;;;;;;;;6219:220;;;;;;;;;;-1:-1:-1;6219:220:0;;;;;:::i;:::-;;:::i;141054:296::-;;;;;;;;;;-1:-1:-1;141054:296:0;;;;;:::i;:::-;;:::i;7138:83::-;5332:7;5359:6;;7180:36;;5359:6;;;;;7206:9;7180:36;;;;;7206:9;;7180:36;5332:7;7180:36;7206:9;5359:6;7180:36;;;;;;;;;;;;;;;;;;;;;7138:83::o;142181:320::-;132530:21;:19;:21::i;:::-;142315:9:::1;:16;142296:8;:15;:35;142288:104;;;::::0;::::1;::::0;;17259:2:1;142288:104:0::1;::::0;::::1;17241:21:1::0;17298:2;17278:18;;;17271:30;17337:34;17317:18;;;17310:62;17408:26;17388:18;;;17381:54;17452:19;;142288:104:0::1;;;;;;;;;142406:9;142401:96;142425:8;:15;142421:1;:19;142401:96;;;142452:39;142465:8;142474:1;142465:11;;;;;;;;:::i;:::-;;;;;;;142478:9;142488:1;142478:12;;;;;;;;:::i;:::-;;;;;;;142452;:39::i;:::-;142442:3;;142401:96;;;;132574:20:::0;131865:1;132874:21;;132809:94;132574:20;142181:320;;:::o;143751:191::-;143881:4;143901:36;143925:11;143901:23;:36::i;:::-;143894:43;143751:191;-1:-1:-1;;143751:191:0:o;109016:91::-;109061:13;109094:5;109087:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;109016:91;:::o;110188:158::-;110255:7;110275:22;110289:7;110275:13;:22::i;:::-;-1:-1:-1;112603:7:0;112630:24;;;:15;:24;;;;;;;;110317:21;112533:129;110007:115;110079:35;110088:2;110092:7;3534:10;110079:8;:35::i;143489:102::-;132530:21;:19;:21::i;:::-;143567:19:::1;143574:2;143578:7;143567:6;:19::i;:::-;132574:20:::0;131865:1;132874:21;;132809:94;6855:99;5172:13;:11;:13::i;:::-;5332:7;5359:6;;6901:48:::1;::::0;5359:6;;;;;6927:21:::1;6901:48:::0;::::1;;;::::0;6927:21;;6901:48;5332:7;6901:48;6927:21;5359:6;6901:48;::::1;;;;;;;;;;;;;;;;;;139324:204:::0;139374:7;139383:14;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;139383:14:0;139428:12;;139411:14;;:29;139403:61;;;;;;;18315:2:1;139403:61:0;;;18297:21:1;18354:2;18334:18;;;18327:30;18393:21;18373:18;;;18366:49;18432:18;;139403:61:0;18113:343:1;139403:61:0;-1:-1:-1;;139481:14:0;;139497:25;;;;:9;:25;;;;;;;;;139473:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;139481:14;;139324:204::o;141733:137::-;141814:7;141834:24;;;:15;:24;;;;;:31;;141859:5;;141834:31;;;;;;:::i;:::-;;;;;;;;;141827:38;;141733:137;;;;:::o;140468:580::-;5172:13;:11;:13::i;:::-;132530:21:::1;:19;:21::i;:::-;140802:9:::2;140797:247;140821:2;140817:1;:6;140797:247;;;140835:203;140852:2:::0;140856:7;140883:17:::2;140887:13:::0;140883:1;:17:::2;:::i;:::-;140865:35;::::0;:15;:35:::2;:::i;:::-;140918:15;140922:11:::0;140918:1;:15:::2;:::i;:::-;140902:31;::::0;:13;:31:::2;:::i;:::-;140957:21;140961:17:::0;140957:1;:21:::2;:::i;:::-;140935:43;::::0;:19;:43:::2;:::i;:::-;140999:18;141003:14:::0;140999:1;:18:::2;:::i;:::-;140980:37;::::0;:16;:37:::2;:::i;:::-;141019:18;140835:16;:203::i;:::-;140825:3;;140797:247;;;;132574:20:::1;131865:1:::0;132874:21;;132809:94;132574:20:::1;140468:580:::0;;;;;;;;;;;;:::o;140147:315::-;5172:13;:11;:13::i;:::-;132530:21:::1;:19;:21::i;:::-;140355:102:::2;140370:2;140374;140378:7;140387:10;140399:8;140409:14;140425:11;140438:18;140355:14;:102::i;:::-;132574:20:::1;131865:1:::0;132874:21;;132809:94;132574:20:::1;140147:315:::0;;;;;;;;:::o;145012:213::-;145162:55;;;;;19155:2:1;145162:55:0;;;19137:21:1;19194:2;19174:18;;;19167:30;19233:34;19213:18;;;19206:62;19304:7;19284:18;;;19277:35;19329:19;;145162:55:0;18953:401:1;145162:55:0;145012:213;;;:::o;124486:260::-;124574:7;124607:16;124617:5;124607:9;:16::i;:::-;124598:5;:25;124594:101;;124647:36;;;;;19563:42:1;19551:55;;124647:36:0;;;19533:74:1;19623:18;;;19616:34;;;19506:18;;124647:36:0;19359:297:1;124594:101:0;-1:-1:-1;124712:19:0;;;;;;;;;:12;:19;;;;;;;;:26;;;;;;;;;124486:260::o;135901:114::-;135953:7;135992:18;;135973:16;;:37;;;;:::i;:::-;135966:44;;135901:114;:::o;125003:231::-;125069:7;125102:13;124901:10;:17;;124822:104;125102:13;125093:5;:22;125089:103;;125139:41;;;;;125170:1;125139:41;;;19533:74:1;19623:18;;;19616:34;;;19506:18;;125139:41:0;19359:297:1;125089:103:0;125209:10;125220:5;125209:17;;;;;;;;:::i;:::-;;;;;;;;;125202:24;;125003:231;;;:::o;144038:482::-;132530:21;:19;:21::i;:::-;144152:10:::1;144109:14;144126:37:::0;;;:25:::1;:37;::::0;;;;;144178:10;144170:54:::1;;;::::0;::::1;::::0;;19996:2:1;144170:54:0::1;::::0;::::1;19978:21:1::0;20035:2;20015:18;;;20008:30;20074:33;20054:18;;;20047:61;20125:18;;144170:54:0::1;19794:355:1::0;144170:54:0::1;144247:21;144237:6;:31;;144229:68;;;::::0;::::1;::::0;;20356:2:1;144229:68:0::1;::::0;::::1;20338:21:1::0;20395:2;20375:18;;;20368:30;20434:26;20414:18;;;20407:54;20478:18;;144229:68:0::1;20154:348:1::0;144229:68:0::1;144330:10;144344:1;144304:37:::0;;;:25:::1;:37;::::0;;;;;:41;;;144371:35;144304:37:::1;144371:16:::0;::::1;::::0;144395:6;;144344:1;144371:35;144344:1;144371:35;144395:6;144371:16;:35:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;144352:54;;;144419:7;144411:43;;;::::0;::::1;::::0;;20919:2:1;144411:43:0::1;::::0;::::1;20901:21:1::0;20958:2;20938:18;;;20931:30;20997:25;20977:18;;;20970:53;21040:18;;144411:43:0::1;20717:347:1::0;144411:43:0::1;144466:49;::::0;4940:25:1;;;144466:49:0::1;::::0;::::1;::::0;144492:10:::1;::::0;144466:49:::1;::::0;4928:2:1;4913:18;144466:49:0::1;;;;;;;144104:416;;132574:20:::0;131865:1;132874:21;;132809:94;134914:103;5172:13;:11;:13::i;:::-;132530:21:::1;:19;:21::i;:::-;134994:8:::2;:18;135005:7:::0;134994:8;:18:::2;:::i;:::-;;132574:20:::1;131865:1:::0;132874:21;;132809:94;136263:566;5172:13;:11;:13::i;:::-;132530:21:::1;:19;:21::i;:::-;136390:18:::2;;136376:10;:32;136368:83;;;::::0;::::2;::::0;;23574:2:1;136368:83:0::2;::::0;::::2;23556:21:1::0;23613:2;23593:18;;;23586:30;23652:34;23632:18;;;23625:62;23723:8;23703:18;;;23696:36;23749:19;;136368:83:0::2;23372:402:1::0;136368:83:0::2;136460:30;136493:25:::0;;;:13:::2;:25;::::0;;;;;;;136460:58;;::::2;::::0;::::2;::::0;;;;::::2;::::0;;::::2;::::0;;;;;::::2;::::0;;;;::::2;::::0;;::::2;::::0;::::2;::::0;::::2;::::0;;;;;;;;136578:25;;;;;;;136571:32;;;::::2;::::0;;;::::2;::::0;;;;;;;136608:18:::2;:23:::0;;136460:58;;;;;136608:18;;136460:30;136608:23:::2;::::0;136460:58;;136608:23:::2;:::i;:::-;::::0;;;-1:-1:-1;;136638:187:0;::::2;;;136680:1;136658:19:::0;;;:10:::2;:19;::::0;;;;;;;:23;;;136701:17;;136720:20;;::::2;::::0;136687:67;;;;::::2;::::0;;;;;;::::2;::::0;136701:17;136669:7;;136687:13:::2;:67::i;:::-;136789:20;::::0;::::2;::::0;136770:17;;136765:54:::2;::::0;136811:7;;136765:54:::2;::::0;;::::2;::::0;::::2;::::0;::::2;::::0;136770:17:::2;::::0;136765:54:::2;136638:187;136363:466;;132574:20:::1;131865:1:::0;132874:21;;132809:94;108829:120;108892:7;108919:22;108933:7;108919:13;:22::i;6960:120::-;5172:13;:11;:13::i;:::-;7020:5:::1;:14;;;7035:7;5332::::0;5359:6;;;;5286:87;7035:7:::1;7044:30;::::0;;;;7068:4:::1;7044:30;::::0;::::1;3518:74:1::0;7044:15:0::1;::::0;::::1;::::0;::::1;::::0;3491:18:1;;7044:30:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7020:55;::::0;;::::1;::::0;;;;;;19563:42:1;19551:55;;;7020::0::1;::::0;::::1;19533:74:1::0;19623:18;;;19616:34;19506:18;;7020:55:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;108554:213::-:0;108617:7;108641:19;;;108637:89;;108684:30;;;;;108711:1;108684:30;;;3518:74:1;3491:18;;108684:30:0;3372:226:1;108637:89:0;-1:-1:-1;108743:16:0;;;;;;:9;:16;;;;;;;108554:213::o;143948:85::-;143993:13;144020:8;144013:15;;;;;:::i;5961:103::-;5172:13;:11;:13::i;:::-;6026:30:::1;6053:1;6026:18;:30::i;:::-;5961:103::o:0;139216:102::-;139264:7;139299:14;;139284:12;;:29;;;;:::i;142057:118::-;132530:21;:19;:21::i;:::-;142139:31:::1;142152:7;142161:8;142139:12;:31::i;136021:236::-:0;-1:-1:-1;;;;;;;;136075:7:0;-1:-1:-1;;;;;;;;;;;;;;;136137:16:0;;136116:18;;:37;136108:73;;;;;;;24466:2:1;136108:73:0;;;24448:21:1;24505:2;24485:18;;;24478:30;24544:25;24524:18;;;24517:53;24587:18;;136108:73:0;24264:347:1;136108:73:0;-1:-1:-1;;136198:18:0;;136218:33;;;;:13;:33;;;;;;;;;136190:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;136198:18;;136021:236::o;109176:95::-;109223:13;109256:7;109249:14;;;;;:::i;141876:175::-;141980:7;142000:27;;;:18;:27;;;;;;;;:39;;;;;;;;:46;;142040:5;;142000:46;;;;;;:::i;:::-;;;;;;;;;141993:53;;141876:175;;;;;:::o;110418:146::-;110504:52;3534:10;110537:8;110547;110504:18;:52::i;136834:1388::-;5172:13;:11;:13::i;:::-;132530:21:::1;:19;:21::i;:::-;136966:9:::2;::::0;::::2;::::0;::::2;;;136965:10;136957:47;;;::::0;::::2;::::0;;24818:2:1;136957:47:0::2;::::0;::::2;24800:21:1::0;24857:2;24837:18;;;24830:30;24896:26;24876:18;;;24869:54;24940:18;;136957:47:0::2;24616:348:1::0;136957:47:0::2;137011:22;137036:16;:34;;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;137011:61:::0;-1:-1:-1;137084:9:0::2;137079:1068;137103:8;137099:1;:12;137079:1068;;;137141:12;::::0;137165:25;;::::2;137161:49;;137198:5;;;137161:49;137218:15;137235:18;137255:22;137279:21;137302:15;137319:23;137344:19;137367:16;:25;;;137393:7;137367:34;;;;;;;;;;;;;4940:25:1::0;;4928:2;4913:18;;4794:177;137367:34:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;137217:184;;;;;;;;;;;;;;137407:16;137426;:28;;;137455:7;137426:37;;;;;;;;;;;;;4940:25:1::0;;4928:2;4913:18;;4794:177;137426:37:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;137482:33;::::0;;;;::::2;::::0;::::2;4940:25:1::0;;;137407:56:0;;-1:-1:-1;137469:10:0::2;::::0;137482:24:::2;::::0;::::2;::::0;::::2;::::0;4913:18:1;;137482:33:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;137469:46;;137539:1;137523:12;;:17;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;137548:18:0::2;::::0;;;:9:::2;:18;::::0;;;;;;;:28;;;137582:12:::2;:21:::0;;;;;:34;;;137622:10:::2;:19:::0;;;;;:30;;;137658:15:::2;:24:::0;;;;;:41;;;137705:14:::2;:23:::0;;;;;:39;;;137750:11:::2;:20:::0;;;;;:33;;;;;::::2;::::0;::::2;;;::::0;;;137789:19:::2;:28:::0;;;;;:49;;;;::::2;::::0;::::2;;;::::0;;137844:21;;;;;;:35;;;137887:18;;;:9:::2;:18:::0;;;;;:23;;-1:-1:-1;;137548:18:0;137887:23:::2;::::0;-1:-1:-1;;137887:23:0::2;:::i;:::-;::::0;;;-1:-1:-1;;137916:21:0::2;::::0;;;:12:::2;:21;::::0;;;;;;;:33;;;;;;;;:38;;137953:1:::2;::::0;137916:21;:38:::2;::::0;137953:1;;137916:38:::2;:::i;:::-;::::0;;;-1:-1:-1;;137960:24:0::2;::::0;;;:15:::2;:24;::::0;;;;;;;:38;;::::2;::::0;;::::2;::::0;;;;;;;;::::2;::::0;;;138004:27;;;:18:::2;:27:::0;;;;;:39;;;;;;;;:53;;;;::::2;::::0;;;;;;::::2;::::0;;;138065:22:::2;138075:2:::0;137990:7;138065:9:::2;:22::i;:::-;138093:48;138106:7;138115:25;138132:7;138115:16;:25::i;:::-;138093:12;:48::i;:::-;-1:-1:-1::0;;137113:3:0::2;::::0;;::::2;::::0;-1:-1:-1;137079:1068:0::2;::::0;-1:-1:-1;;;;;;;137079:1068:0::2;;;138175:14;138159:12;;:30:::0;138155:63:::2;;138196:9;:16:::0;;;::::2;;;::::0;;136952:1270:::2;132574:20:::1;131865:1:::0;132874:21;;132809:94;144714:55;144532:245;;;;:::o;138231:979::-;138378:7;132530:21;:19;:21::i;:::-;138399:12:::1;::::0;::::1;;:25:::0;::::1;;;-1:-1:-1::0;138415:9:0::1;::::0;::::1;::::0;::::1;;;138399:25;138391:61;;;::::0;::::1;::::0;;26374:2:1;138391:61:0::1;::::0;::::1;26356:21:1::0;26413:2;26393:18;;;26386:30;26452:25;26432:18;;;26425:53;26495:18;;138391:61:0::1;26172:347:1::0;138391:61:0::1;138470:1;138465:2;:6;138457:46;;;::::0;::::1;::::0;;26726:2:1;138457:46:0::1;::::0;::::1;26708:21:1::0;26765:2;26745:18;;;26738:30;26804:29;26784:18;;;26777:57;26851:18;;138457:46:0::1;26524:351:1::0;138457:46:0::1;138542:9;::::0;:39:::1;::::0;;;;138570:10:::1;138542:39;::::0;::::1;3518:74:1::0;138513:24:0::1;::::0;138542:9:::1;;::::0;:27:::1;::::0;3491:18:1;;138542:39:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;138512:69;;;138604:16;138598:2;:22;;138590:74;;;::::0;::::1;::::0;;27963:2:1;138590:74:0::1;::::0;::::1;27945:21:1::0;28002:2;27982:18;;;27975:30;28041:34;28021:18;;;28014:62;28112:9;28092:18;;;28085:37;28139:19;;138590:74:0::1;27761:403:1::0;138590:74:0::1;138688:9;::::0;:80:::1;::::0;;;;::::1;::::0;::::1;28450:25:1::0;;;28491:18;;;28484:34;;;28534:18;;;28527:34;;;138688:9:0;28577:18:1;;;28570:50;28636:19;;;28629:35;;;138757:10:0::1;28680:19:1::0;;;28673:84;138673:12:0::1;::::0;138688:9:::1;;::::0;:21:::1;::::0;28422:19:1;;138688:80:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;138673:95;;138798:4;138785:9;:17;;138777:58;;;::::0;::::1;::::0;;28970:2:1;138777:58:0::1;::::0;::::1;28952:21:1::0;29009:2;28989:18;;;28982:30;29048;29028:18;;;29021:58;29096:18;;138777:58:0::1;28768:352:1::0;138777:58:0::1;138862:12;::::0;;138906:70:::1;::::0;;::::1;::::0;::::1;::::0;;138914:10:::1;138906:70:::0;;::::1;::::0;;::::1;::::0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;138883:20:0;;;:9:::1;:20:::0;;;;;;:93;;;;;::::1;138906:70;138883:93:::0;;::::1;;::::0;;;;-1:-1:-1;138883:93:0;;::::1;::::0;;;;;;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;;138981:17;;138862:12;;-1:-1:-1;;138981:17:0::1;::::0;-1:-1:-1;;138981:17:0::1;:::i;:::-;::::0;;;-1:-1:-1;;139007:9:0::1;::::0;:78:::1;::::0;;;;::::1;::::0;::::1;29327:25:1::0;;;29368:18;;;29361:34;;;139074:10:0::1;29411:18:1::0;;;29404:83;139007:9:0::1;::::0;;::::1;::::0;:33:::1;::::0;139047:4;;29300:18:1;;139007:78:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;139097:83:0::1;::::0;;29785:25:1;;;29841:2;29826:18;;29819:34;;;29869:18;;;29862:34;;;29927:2;29912:18;;29905:34;;;29970:3;29955:19;;29948:35;;;30014:3;29999:19;;29992:35;;;139118:10:0::1;::::0;-1:-1:-1;139097:83:0::1;::::0;-1:-1:-1;29772:3:1;29757:19;;-1:-1:-1;139097:83:0::1;;;;;;;139196:9:::0;-1:-1:-1;;;132574:20:0;131865:1;132874:21;;132809:94;132574:20;138231:979;;;;;;;:::o;143597:148::-;143688:13;143717:23;143732:7;143717:14;:23::i;135026:869::-;135121:7;132530:21;:19;:21::i;:::-;135142:12:::1;::::0;::::1;;:25:::0;::::1;;;-1:-1:-1::0;135158:9:0::1;::::0;::::1;::::0;::::1;;;135142:25;135134:61;;;::::0;::::1;::::0;;26374:2:1;135134:61:0::1;::::0;::::1;26356:21:1::0;26413:2;26393:18;;;26386:30;26452:25;26432:18;;;26425:53;26495:18;;135134:61:0::1;26172:347:1::0;135134:61:0::1;135225:9;::::0;:37:::1;::::0;;;;135251:10:::1;135225:37;::::0;::::1;3518:74:1::0;135202:20:0::1;::::0;135225:9:::1;;::::0;:25:::1;::::0;3491:18:1;;135225:37:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;135202:60;;135292:12;135279:9;:25;;135271:70;;;::::0;::::1;::::0;;30240:2:1;135271:70:0::1;::::0;::::1;30222:21:1::0;;;30259:18;;;30252:30;30318:34;30298:18;;;30291:62;30370:18;;135271:70:0::1;30038:356:1::0;135271:70:0::1;135374:10;135354:16;135362:7:::0;135354::::1;:16::i;:::-;:30;;;135346:76;;;::::0;::::1;::::0;;30601:2:1;135346:76:0::1;::::0;::::1;30583:21:1::0;30640:2;30620:18;;;30613:30;30679:34;30659:18;;;30652:62;30750:3;30730:18;;;30723:31;30771:19;;135346:76:0::1;30399:397:1::0;135346:76:0::1;135435:21;::::0;;;:12:::1;:21:::0;;;;;;135460:15:::1;-1:-1:-1::0;135435:40:0::1;135427:89;;;::::0;::::1;::::0;;31003:2:1;135427:89:0::1;::::0;::::1;30985:21:1::0;31042:2;31022:18;;;31015:30;31081:34;31061:18;;;31054:62;31152:6;31132:18;;;31125:34;31176:19;;135427:89:0::1;30801:400:1::0;135427:89:0::1;135547:16;::::0;;135601:42:::1;::::0;;::::1;::::0;::::1;::::0;;135613:10:::1;135601:42:::0;;::::1;::::0;;::::1;;::::0;;::::1;::::0;;;;;;;;;135523:21:::1;135570:28:::0;;;:13:::1;:28:::0;;;;;;:73;;;;;;::::1;::::0;;;::::1;;::::0;;;;;;;::::1;::::0;;;;;::::1;::::0;;;::::1;;::::0;;;;;::::1;::::0;;::::1;::::0;;;;135648:21;;135547:16;;135570:73;;135648:21:::1;::::0;135570:73;;135648:21:::1;:::i;:::-;::::0;;;-1:-1:-1;;135678:9:0::1;::::0;::::1;135736:18:::0;;;:9:::1;:18;::::0;;;;;;;;135756:12:::1;:21:::0;;;;;;;135678:112;;;;;::::1;::::0;::::1;29327:25:1::0;;;;29368:18;;;29361:34;135779:10:0::1;29411:18:1::0;;;29404:83;135678:112:0;:9:::1;::::0;;::::1;::::0;:37:::1;::::0;135722:12;;29300:18:1;;;;;135678:112:0;;;;;;135722:12;135678:9;:112;::::1;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;135853:7;135843:8;135802:59;;135831:10;135802:59;;;135816:13;135802:59;;;;4940:25:1::0;;4928:2;4913:18;;4794:177;135802:59:0::1;;;;;;;;135877:13:::0;-1:-1:-1;;132574:20:0;131865:1;132874:21;;132809:94;139534:607;5172:13;:11;:13::i;:::-;132530:21:::1;:19;:21::i;:::-;139692:14:::2;;139682:6;:24;139674:71;;;::::0;::::2;::::0;;31408:2:1;139674:71:0::2;::::0;::::2;31390:21:1::0;31447:2;31427:18;;;31420:30;31486:34;31466:18;;;31459:62;31557:4;31537:18;;;31530:32;31579:19;;139674:71:0::2;31206:398:1::0;139674:71:0::2;139754:22;139779:17:::0;;;:9:::2;:17;::::0;;;;;;;139754:42;;::::2;::::0;::::2;::::0;;;;::::2;::::0;::::2;::::0;;;;;::::2;::::0;;;;::::2;::::0;::::2;::::0;::::2;::::0;;;;;;;;;::::2;::::0;::::2;::::0;;;;;;::::2;::::0;::::2;::::0;;;;;;::::2;::::0;::::2;::::0;;;;;;139810:17;;;;;;;139803:24;;;::::2;::::0;;;;;;;;;;;;;;;;;;;;;;;139832:14:::2;:19:::0;;139754:42;;;;139832:14;;139754:22;139832:19:::2;::::0;139754:42;;139832:19:::2;:::i;:::-;::::0;;;-1:-1:-1;;139858:277:0;::::2;;;139897:16;::::0;::::2;::::0;139937:15:::2;139923:29:::0;::::2;139919:60;;;-1:-1:-1::0;139971:1:0::2;139919:60;139984:145;139999:7;:10;;;140011:7;:13;;;140026:7;:15;;;140043:7;:18;;;140063:8;140073:7;:22;;;140097:11;140110:18;139984:14;:145::i;:::-;139872:263;139858:277;139669:472;132574:20:::1;131865:1:::0;132874:21;;132809:94;142921:460;142976:7;143008:19;;;:10;:19;;;;;;;;;143050:11;:20;;;;;;143107:15;:24;;;;;;;143008:19;;143050:20;;;142976:7;143153:16;143019:7;143153;:16::i;:::-;143183:9;;;143201:18;;;:9;:18;;;;;;;;;143221:12;:21;;;;;;;143136:33;;-1:-1:-1;143183:9:0;;;;;:17;;143201:18;143244:8;143254:10;:42;;;;-1:-1:-1;143268:28:0;;;;:19;:28;;;;;;;;143254:42;143298:21;143321:34;143347:7;143321:25;:34::i;:::-;143183:193;;;;;;;;;;;;;31946:25:1;;;;31987:18;;;31980:34;;;;32030:18;;;32023:34;;;;32100:14;32093:22;32073:18;;;32066:50;32132:19;;;32125:35;32176:19;;;32169:35;32253:42;32241:55;;32220:19;;;32213:84;143365:10:0;32313:19:1;;;32306:84;31918:19;;143183:193:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;143176:200;142921:460;-1:-1:-1;;;;;;142921:460:0:o;143387:96::-;132530:21;:19;:21::i;:::-;143451:27:::1;143458:10;143470:7;143451:6;:27::i;:::-;132574:20:::0;131865:1;132874:21;;132809:94;134772:136;5172:13;:11;:13::i;:::-;132530:21:::1;:19;:21::i;:::-;134857:9:::2;:22:::0;;::::2;::::0;::::2;::::0;;;::::2;;::::0;;134884:12:::2;:19:::0;;;::::2;134857:22:::0;134884:19:::2;::::0;;132574:20:::1;131865:1:::0;132874:21;;132809:94;6219:220;5172:13;:11;:13::i;:::-;6304:22:::1;::::0;::::1;6300:93;;6350:31;::::0;::::1;::::0;;6378:1:::1;6350:31;::::0;::::1;3518:74:1::0;3491:18;;6350:31:0::1;3372:226:1::0;6300:93:0::1;6403:28;6422:8;6403:18;:28::i;141054:296::-:0;5172:13;:11;:13::i;:::-;132530:21:::1;:19;:21::i;:::-;141245:100:::2;141262:2;141266:7;141275:10;141287:8;141297:14;141313:11;141326:18;141245:16;:100::i;:::-;132574:20:::1;131865:1:::0;132874:21;;132809:94;132574:20:::1;141054:296:::0;;;;;;;:::o;132610:191::-;131908:1;132672:7;;:18;132668:88;;132714:30;;;;;;;;;;;;;;132668:88;131908:1;132776:7;:17;132610:191::o;147567:386::-;112361:7;112388:16;;;:7;:16;;;;;;147645:53;;112388:16;;147678:10;147690:7;147645:13;:53::i;:::-;147637:111;;;;;;;32603:2:1;147637:111:0;;;32585:21:1;32642:2;32622:18;;;32615:30;32681:34;32661:18;;;32654:62;32752:15;32732:18;;;32725:43;32785:19;;147637:111:0;32401:409:1;147637:111:0;147761:21;;;;:12;:21;;;;;;147786:15;-1:-1:-1;147761:40:0;147753:94;;;;;;;33017:2:1;147753:94:0;;;32999:21:1;33056:2;33036:18;;;33029:30;33095:34;33075:18;;;33068:62;33166:11;33146:18;;;33139:39;33195:19;;147753:94:0;32815:405:1;147753:94:0;147856:19;;;;:10;:19;;;;;:30;;;147867:7;147912:16;147867:7;147912;:16::i;:::-;147900:48;;;147939:8;147900:48;;;;4940:25:1;;4928:2;4913:18;;4794:177;147900:48:0;;;;;;;;147567:386;;:::o;129845:209::-;129947:4;129971:35;;;129689:18;129971:35;;:75;;;130010:36;130034:11;130010:23;:36::i;122777:247::-;122840:7;112388:16;;;:7;:16;;;;;;;;;122904:90;;122951:31;;;;;;;;4940:25:1;;;4913:18;;122951:31:0;4794:177:1;121152:122:0;121233:33;121242:2;121246:7;121255:4;121261;121233:8;:33::i;146310:1251::-;146376:12;;;;:25;;;;-1:-1:-1;146392:9:0;;;;;;;146376:25;146368:61;;;;;;;26374:2:1;146368:61:0;;;26356:21:1;26413:2;26393:18;;;26386:30;26452:25;26432:18;;;26425:53;26495:18;;146368:61:0;26172:347:1;146368:61:0;146442:21;;;;:12;:21;;;;;;146467:15;-1:-1:-1;146442:40:0;146434:71;;;;;;;33427:2:1;146434:71:0;;;33409:21:1;33466:2;33446:18;;;33439:30;33505:20;33485:18;;;33478:48;33543:18;;146434:71:0;33225:342:1;146434:71:0;146514:16;146533:19;;;:10;:19;;;;;;;;;146575:11;:20;;;;;;146632:15;:24;;;;;;;146533:19;;146575:20;;;;;146678:16;146544:7;146678;:16::i;:::-;146661:33;;146722:1;146711:8;:12;146703:49;;;;;;;33774:2:1;146703:49:0;;;33756:21:1;33813:2;33793:18;;;33786:30;33852:26;33832:18;;;33825:54;33896:18;;146703:49:0;33572:348:1;146703:49:0;146776:9;;146761:12;146794:18;;;:9;:18;;;;;;;;;146814:12;:21;;;;;;146761:12;;146776:9;;;:17;;146794:18;146837:8;146847:10;:42;;;;-1:-1:-1;146861:28:0;;;;:19;:28;;;;;;;;146847:42;146891:21;146914:34;146940:7;146914:25;:34::i;:::-;146776:185;;;;;;;;;;;;;31946:25:1;;;;31987:18;;;31980:34;;;;32030:18;;;32023:34;;;;32100:14;32093:22;32073:18;;;32066:50;32132:19;;;32125:35;32176:19;;;32169:35;32253:42;32241:55;;;32220:19;;;32213:84;32334:55;;32313:19;;;32306:84;31918:19;;146776:185:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;146761:200;-1:-1:-1;146991:15:0;146761:200;146991:8;:15;:::i;:::-;146978:9;:28;;146970:65;;;;;;;20356:2:1;146970:65:0;;;20338:21:1;20395:2;20375:18;;;20368:30;20434:26;20414:18;;;20407:54;20478:18;;146970:65:0;20154:348:1;146970:65:0;147046:20;;;;:11;:20;;;;;;;;147042:136;;;147099:39;147117:21;147099:15;:39;:::i;:::-;147073:23;;;;:14;:23;;;;;;;;:65;;;;147144:11;:20;;;:28;;;;;;147042:136;147208:1;147186:19;;;:10;:19;;;;;;;;:23;;;147216:38;;;;;;;;;;;;147230:6;;147238:2;;147197:7;;147216:13;:38::i;:::-;147261:9;;;147307:18;;;:9;:18;;;;;;;;;147327:12;:21;;;;;;;147261:100;;;;;;;;34156:25:1;;;;34197:18;;;34190:34;147261:9:0;34260:55:1;;;34240:18;;;34233:83;34352:55;;;34332:18;;;34325:83;147261:100:0;;:9;;;:33;;147301:4;;34128:19:1;;;;;147261:100:0;;;;;;147301:4;147261:9;:100;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;147369:12;147395:6;147387:20;;147415:8;147387:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;147368:60;;;147440:7;147435:70;;147454:33;;;;;;;:25;:33;;;;;:45;;147491:8;;147454:33;:45;;147491:8;;147454:45;:::i;:::-;;;;-1:-1:-1;;147435:70:0;147532:7;147524:6;147516:40;;147520:2;147516:40;;;147541:8;147551:4;147516:40;;;;;;34593:25:1;;;34649:2;34634:18;;34627:34;34581:2;34566:18;;34419:248;147516:40:0;;;;;;;;146363:1198;;;;;;146310:1251;;:::o;5451:166::-;5332:7;5359:6;5511:23;5359:6;3534:10;5511:23;5507:103;;5558:40;;;;;3534:10;5558:40;;;3518:74:1;3491:18;;5558:40:0;3372:226:1;145232:1073:0;145416:12;;;;:25;;;;-1:-1:-1;145432:9:0;;;;;;;145416:25;145408:61;;;;;;;26374:2:1;145408:61:0;;;26356:21:1;26413:2;26393:18;;;26386:30;26452:25;26432:18;;;26425:53;26495:18;;145408:61:0;26172:347:1;145408:61:0;145497:15;145482:11;:30;;:47;;;-1:-1:-1;145516:13:0;;145482:47;145474:121;;;;;;;34874:2:1;145474:121:0;;;34856:21:1;34913:2;34893:18;;;34886:30;34952:34;34932:18;;;34925:62;35023:31;35003:18;;;34996:59;35072:19;;145474:121:0;34672:425:1;145474:121:0;145620:12;;;;145653:1;;145602:15;145637:17;145653:1;145620:12;145637:17;:::i;:::-;;;;-1:-1:-1;;145661:18:0;;;;:9;:18;;;;;;;;:28;;;145694:12;:21;;;;;:34;;;145733:10;:19;;;;;:30;;;145768:15;:24;;;;;:41;;;145814:11;:20;;;;;:27;;145837:4;145814:27;;;;;;;;;145846:19;:28;;;;;:49;;;;;;;;;;;145900:21;;;;;;:35;;;145942:18;;;:9;:18;;;;;:23;;145837:4;;145942:18;;:23;;145837:4;;145942:23;:::i;:::-;;;;-1:-1:-1;;145970:21:0;;;;:12;:21;;;;;;;;:33;;;;;;;;:38;;146007:1;;145970:21;:38;;146007:1;;145970:38;:::i;:::-;;;;-1:-1:-1;;146013:24:0;;;;:15;:24;;;;;;;;:38;;;;;;;;;;;;;;;;;;146056:27;;;:18;:27;;;;;:39;;;;;;;;:53;;;;;;;;;;;;;;;146116:22;146126:2;146043:7;146116:9;:22::i;:::-;146143:48;146156:7;146165:25;146182:7;146165:16;:25::i;146143:48::-;146203:97;;;35411:25:1;;;35467:2;35452:18;;35445:34;;;35495:18;;;35488:34;;;35553:2;35538:18;;35531:34;;;35596:3;35581:19;;35574:35;;;35640:3;35625:19;;35618:35;;;35697:14;;35690:22;35684:3;35669:19;;35662:51;146203:97:0;;;;;;35398:3:1;35383:19;146203:97:0;;;;;;;145403:902;145232:1073;;;;;;;:::o;148806:333::-;148996:9;148991:144;149015:2;149011:1;:6;148991:144;;;149029:100;149046:2;149050:7;149059:10;149071:8;149081:14;149097:11;149110:18;149029:16;:100::i;:::-;149019:3;;148991:144;;;;148806:333;;;;;;;;:::o;120465:232::-;120578:28;120588:4;120594:2;120598:7;120578:9;:28::i;:::-;120617:72;3534:10;120665:4;120671:2;120675:7;120684:4;120617:33;:72::i;6599:191::-;6673:16;6692:6;;;6709:17;;;;;;;;;;6742:40;;6692:6;;;;;;;6742:40;;6673:16;6742:40;6662:128;6599:191;:::o;122216:318::-;122324:22;;;122320:93;;122370:31;;;;;3548:42:1;3536:55;;122370:31:0;;;3518:74:1;3491:18;;122370:31:0;3372:226:1;122320:93:0;122423:25;;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;;;;;;;;;;;;122485:41;;2489::1;;;122485::0;;2462:18:1;122485:41:0;;;;;;;122216:318;;;:::o;117220:102::-;117288:26;117298:2;117302:7;117288:26;;;;;;;;;;;;:9;:26::i;91218:650::-;91274:13;91325:14;91342:17;91353:5;91342:10;:17::i;:::-;91362:1;91342:21;91325:38;;91378:20;91412:6;91401:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;91401:18:0;-1:-1:-1;91378:41:0;-1:-1:-1;91511:28:0;;;91527:2;91511:28;91568:254;91600:5;;91706:10;91701:2;91690:14;;91685:32;91600:5;91672:46;91764:2;91755:11;;;-1:-1:-1;91785:21:0;91568:254;91785:21;-1:-1:-1;91843:6:0;91218:650;-1:-1:-1;;;91218:650:0:o;130730:170::-;130822:19;;;;:10;:19;;;;;:31;130844:9;130822:19;:31;:::i;:::-;-1:-1:-1;130869:23:0;;4940:25:1;;;130869:23:0;;4928:2:1;4913:18;130869:23:0;;;;;;;130730:170;;:::o;130125:479::-;130198:13;130224:22;130238:7;130224:13;:22::i;:::-;-1:-1:-1;130259:23:0;130285:19;;;:10;:19;;;;;130259:45;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;130315:18;130336:10;:8;:10::i;:::-;130315:31;;130377:4;130371:18;130393:1;130371:23;130367:72;;-1:-1:-1;130418:9:0;130125:479;-1:-1:-1;;130125:479:0:o;130367:72::-;130461:23;;:27;130457:97;;130526:4;130532:9;130512:30;;;;;;;;;:::i;:::-;;;;;;;;;;;;;130505:37;;;;130125:479;;;:::o;130457:97::-;130573:23;130588:7;130573:14;:23::i;:::-;130566:30;130125:479;-1:-1:-1;;;;130125:479:0:o;147959:403::-;148033:7;148071:24;;;:15;:24;;;;;;;;;148109:11;:20;;;;;;;;148104:224;;148136:21;148160:23;;;:14;:23;;;;;;148209:15;148193:31;;148189:134;;;148249:31;148265:15;148249:13;:31;:::i;:::-;148232:48;;148189:134;;;148315:1;148298:18;;148189:134;148130:198;148343:14;147959:403;-1:-1:-1;;147959:403:0:o;112982:276::-;113085:4;113122:21;;;;;;;:128;;;113170:7;113161:16;;:5;:16;;;:52;;;-1:-1:-1;110747:25:0;;;;110723:4;110747:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;113181:32;113161:88;;;-1:-1:-1;;112603:7:0;112630:24;;;:15;:24;;;;;;113217:32;112630:24;;;113217:32;;;;113102:148;-1:-1:-1;112982:276:0:o;124178:224::-;124280:4;124304:50;;;124319:35;124304:50;;:90;;;124358:36;124382:11;124358:23;:36::i;121462:535::-;121579:9;:31;;;-1:-1:-1;121592:18:0;;;;;121579:31;121575:373;;;121627:13;121643:22;121657:7;121643:13;:22::i;:::-;121627:38;-1:-1:-1;121698:18:0;;;;;;;:35;;;121729:4;121720:13;;:5;:13;;;;121698:35;:69;;;;-1:-1:-1;110747:25:0;;;;110723:4;110747:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;121737:30;121698:69;121694:144;;;121795:27;;;;;3548:42:1;3536:55;;121795:27:0;;;3518:74:1;3491:18;;121795:27:0;3372:226:1;121694:144:0;121858:9;121854:83;;;121913:7;121909:2;121893:28;;121902:5;121893:28;;;;;;;;;;;;121854:83;121612:336;121575:373;-1:-1:-1;;121960:24:0;;;;:15;:24;;;;;:29;;;;;;;;;;;;;;;121462:535::o;118667:470::-;118753:16;;;118749:89;;118793:33;;;;;118823:1;118793:33;;;3518:74:1;3491:18;;118793:33:0;3372:226:1;118749:89:0;118848:21;118872:32;118880:2;118884:7;118901:1;118872:7;:32::i;:::-;118848:56;-1:-1:-1;118919:27:0;;;118915:215;;118970:31;;;;;;;;4940:25:1;;;4913:18;;118970:31:0;4794:177:1;118915:215:0;119040:4;119023:21;;:13;:21;;;119019:111;;119068:50;;;;;36634:42:1;36622:55;;;119068:50:0;;;36604:74:1;36694:18;;;36687:34;;;36757:55;;36737:18;;;36730:83;36577:18;;119068:50:0;36402:417:1;30956:893:0;31143:14;;;;:18;31139:703;;31182:67;;;;;:36;;;;;;:67;;31219:8;;31229:4;;31235:7;;31244:4;;31182:67;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;31182:67:0;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;31178:653;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31526:6;:13;31543:1;31526:18;31522:294;;31596:39;;;;;3548:42:1;3536:55;;31596:39:0;;;3518:74:1;3491:18;;31596:39:0;3372:226:1;31522:294:0;31766:6;31760:13;31751:6;31747:2;31743:15;31736:38;31178:653;31297:51;;;31307:41;31297:51;31293:166;;31400:39;;;;;3548:42:1;3536:55;;31400:39:0;;;3518:74:1;3491:18;;31400:39:0;3372:226:1;31293:166:0;31250:224;31178:653;30956:893;;;;;:::o;117549:210::-;117644:18;117650:2;117654:7;117644:5;:18::i;:::-;117673:78;3534:10;117729:1;117733:2;117737:7;117746:4;117673:33;:78::i;85574:948::-;85627:7;;85714:8;85705:17;;85701:106;;85752:8;85743:17;;;-1:-1:-1;85789:2:0;85779:12;85701:106;85834:8;85825:5;:17;85821:106;;85872:8;85863:17;;;-1:-1:-1;85909:2:0;85899:12;85821:106;85954:8;85945:5;:17;85941:106;;85992:8;85983:17;;;-1:-1:-1;86029:2:0;86019:12;85941:106;86074:7;86065:5;:16;86061:103;;86111:7;86102:16;;;-1:-1:-1;86147:1:0;86137:11;86061:103;86191:7;86182:5;:16;86178:103;;86228:7;86219:16;;;-1:-1:-1;86264:1:0;86254:11;86178:103;86308:7;86299:5;:16;86295:103;;86345:7;86336:16;;;-1:-1:-1;86381:1:0;86371:11;86295:103;86425:7;86416:5;:16;86412:68;;86463:1;86453:11;86508:6;85574:948;-1:-1:-1;;85574:948:0:o;109342:260::-;109406:13;109432:22;109446:7;109432:13;:22::i;:::-;;109467:21;109491:10;:8;:10::i;:::-;109467:34;;109543:1;109525:7;109519:21;:25;:75;;;;;;;;;;;;;;;;;109561:7;109570:18;:7;:16;:18::i;:::-;109547:42;;;;;;;;;:::i;:::-;;;;;;;;;;;;;109519:75;109512:82;109342:260;-1:-1:-1;;;109342:260:0:o;108185:305::-;108287:4;108324:40;;;108339:25;108324:40;;:105;;-1:-1:-1;108381:48:0;;;108396:33;108381:48;108324:105;:158;;;-1:-1:-1;107193:25:0;107178:40;;;;108446:36;107078:148;148465:173;148578:7;148601:32;148615:2;148619:7;148628:4;148601:13;:32::i;116522:335::-;116590:16;;;116586:89;;116630:33;;;;;116660:1;116630:33;;;3518:74:1;3491:18;;116630:33:0;3372:226:1;116586:89:0;116685:21;116709:32;116717:2;116721:7;116738:1;116709:7;:32::i;:::-;116685:56;-1:-1:-1;116756:27:0;;;;116752:98;;116807:31;;;;;116835:1;116807:31;;;3518:74:1;3491:18;;116807:31:0;3372:226:1;125295:640:0;125390:7;125410:21;125434:32;125448:2;125452:7;125461:4;125434:13;:32::i;:::-;125410:56;-1:-1:-1;125483:27:0;;;125479:214;;125527:40;125559:7;126759:10;:17;;126732:24;;;;:15;:24;;;;;:44;;;126787:24;;;;;;;;;;;;126655:164;125527:40;125479:214;;;125606:2;125589:19;;:13;:19;;;125585:108;;125625:56;125658:13;125673:7;125625:32;:56::i;:::-;125707:16;;;125703:192;;125740:45;125777:7;125740:36;:45::i;:::-;125703:192;;;125824:2;125807:19;;:13;:19;;;125803:92;;125843:40;125871:2;125875:7;125843:27;:40::i;115494:692::-;115580:7;112388:16;;;:7;:16;;;;;;;;;;;115657:18;;;115653:88;;115692:37;115709:4;115715;115721:7;115692:16;:37::i;:::-;115765:18;;;;115761:192;;115812:48;115829:1;115833:7;115850:1;115854:5;115812:8;:48::i;:::-;115906:15;;;;;;;:9;:15;;;;;:20;;;;;;115761:192;115969:16;;;;115965:111;;116031:13;;;;;;;:9;:13;;;;;:18;;116048:1;116031:18;;;115965:111;116088:16;;;;:7;:16;;;;;;:21;;;;;;;;;;;;;;116127:27;;116088:16;;116127:27;;;;;;;116174:4;115494:692;-1:-1:-1;;;;115494:692:0:o;127446:674::-;127556:22;127581:15;127591:4;127581:9;:15::i;:::-;127607:18;127628:26;;;:17;:26;;;;;;;;;127731:18;;;;;:12;:18;;;;;;127556:40;;-1:-1:-1;127628:26:0;127774:28;;;127770:236;;127819:19;127841:35;;;;;;;;;;;;127893:31;;;;;;:45;;;127952:30;;:17;:30;;;;;:43;;;127770:236;128033:26;;;;:17;:26;;;;;;;;128026:33;;;128077:35;;;;-1:-1:-1;128077:35:0;;128070:42;-1:-1:-1;127446:674:0:o;128415:473::-;128540:10;:17;128515:22;;128540:21;;128560:1;;128540:21;:::i;:::-;128572:18;128593:24;;;:15;:24;;;;;;128676:10;:26;;128515:46;;-1:-1:-1;128593:24:0;;128515:46;;128676:26;;;;;;:::i;:::-;;;;;;;;;128654:48;;128740:11;128715:10;128726;128715:22;;;;;;;;:::i;:::-;;;;;;;;;;;;:36;;;;128761:28;;;:15;:28;;;;;;;:41;;;128829:24;;;;;128822:31;128864:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;128486:402;;;128415:473;:::o;126236:218::-;126321:14;126354:1;126338:13;126348:2;126338:9;:13::i;:::-;:17;;;;:::i;:::-;126366:16;;;;;;;;:12;:16;;;;;;;;:24;;;;;;;;:34;;;126411:26;;;:17;:26;;;;;;:35;;;;-1:-1:-1;126236:218:0:o;113701:376::-;113814:38;113828:5;113835:7;113844;113814:13;:38::i;:::-;113809:261;;113873:19;;;113869:190;;113920:31;;;;;;;;4940:25:1;;;4913:18;;113920:31:0;4794:177:1;113869:190:0;113999:44;;;;;19563:42:1;19551:55;;113999:44:0;;;19533:74:1;19623:18;;;19616:34;;;19506:18;;113999:44:0;19359:297:1;14:184;66:77;63:1;56:88;163:4;160:1;153:15;187:4;184:1;177:15;203:334;274:2;268:9;330:2;320:13;;335:66;316:86;304:99;;433:18;418:34;;454:22;;;415:62;412:88;;;480:18;;:::i;:::-;516:2;509:22;203:334;;-1:-1:-1;203:334:1:o;542:775::-;596:5;649:3;642:4;634:6;630:17;626:27;616:55;;667:1;664;657:12;616:55;707:6;694:20;737:18;729:6;726:30;723:56;;;759:18;;:::i;:::-;805:6;802:1;798:14;832:30;856:4;852:2;848:13;832:30;:::i;:::-;898:19;;;942:4;974:15;;;970:26;;;933:14;;;;1008:15;;;1005:35;;;1036:1;1033;1026:12;1005:35;1072:4;1064:6;1060:17;1049:28;;1086:200;1102:6;1097:3;1094:15;1086:200;;;1194:17;;1224:18;;1271:4;1119:14;;;;1262;;;;1086:200;;1322:590;1440:6;1448;1501:2;1489:9;1480:7;1476:23;1472:32;1469:52;;;1517:1;1514;1507:12;1469:52;1557:9;1544:23;1590:18;1582:6;1579:30;1576:50;;;1622:1;1619;1612:12;1576:50;1645:61;1698:7;1689:6;1678:9;1674:22;1645:61;:::i;:::-;1635:71;;;1759:2;1748:9;1744:18;1731:32;1788:18;1778:8;1775:32;1772:52;;;1820:1;1817;1810:12;1772:52;1843:63;1898:7;1887:8;1876:9;1872:24;1843:63;:::i;:::-;1833:73;;;1322:590;;;;;:::o;1917:177::-;2002:66;1995:5;1991:78;1984:5;1981:89;1971:117;;2084:1;2081;2074:12;2099:245;2157:6;2210:2;2198:9;2189:7;2185:23;2181:32;2178:52;;;2226:1;2223;2216:12;2178:52;2265:9;2252:23;2284:30;2308:5;2284:30;:::i;2541:359::-;2594:3;2632:5;2626:12;2659:6;2654:3;2647:19;2715:6;2708:4;2701:5;2697:16;2690:4;2685:3;2681:14;2675:47;2767:1;2760:4;2751:6;2746:3;2742:16;2738:27;2731:38;2889:4;2819:66;2814:2;2806:6;2802:15;2798:88;2793:3;2789:98;2785:109;2778:116;;;2541:359;;;;:::o;2905:231::-;3054:2;3043:9;3036:21;3017:4;3074:56;3126:2;3115:9;3111:18;3103:6;3074:56;:::i;3141:226::-;3200:6;3253:2;3241:9;3232:7;3228:23;3224:32;3221:52;;;3269:1;3266;3259:12;3221:52;-1:-1:-1;3314:23:1;;3141:226;-1:-1:-1;3141:226:1:o;3603:154::-;3689:42;3682:5;3678:54;3671:5;3668:65;3658:93;;3747:1;3744;3737:12;3762:367;3830:6;3838;3891:2;3879:9;3870:7;3866:23;3862:32;3859:52;;;3907:1;3904;3897:12;3859:52;3946:9;3933:23;3965:31;3990:5;3965:31;:::i;:::-;4015:5;4093:2;4078:18;;;;4065:32;;-1:-1:-1;;;3762:367:1:o;4976:346::-;5044:6;5052;5105:2;5093:9;5084:7;5080:23;5076:32;5073:52;;;5121:1;5118;5111:12;5073:52;-1:-1:-1;;5166:23:1;;;5286:2;5271:18;;;5258:32;;-1:-1:-1;4976:346:1:o;5327:118::-;5413:5;5406:13;5399:21;5392:5;5389:32;5379:60;;5435:1;5432;5425:12;5450:1601;5605:6;5613;5621;5629;5637;5645;5653;5661;5669;5677;5685:7;5694;5748:3;5736:9;5727:7;5723:23;5719:33;5716:53;;;5765:1;5762;5755:12;5716:53;5810:23;;;-1:-1:-1;5909:2:1;5894:18;;5881:32;5922:33;5881:32;5922:33;:::i;:::-;5974:7;-1:-1:-1;6054:2:1;6039:18;;6026:32;;-1:-1:-1;6157:2:1;6142:18;;6129:32;;-1:-1:-1;6260:3:1;6245:19;;6232:33;;-1:-1:-1;6364:3:1;6349:19;;6336:33;;-1:-1:-1;6468:3:1;6453:19;;6440:33;;-1:-1:-1;6572:3:1;6557:19;;6544:33;;-1:-1:-1;6676:3:1;6661:19;;6648:33;;-1:-1:-1;6780:3:1;6765:19;;6752:33;;-1:-1:-1;6886:3:1;6871:19;;6858:33;;-1:-1:-1;6972:3:1;6957:19;;6944:33;6986:31;6944:33;6986:31;:::i;:::-;7037:8;7026:19;;;5450:1601;;;;;;;;;;;;;;:::o;7056:1107::-;7175:6;7183;7191;7199;7207;7215;7223;7231;7284:3;7272:9;7263:7;7259:23;7255:33;7252:53;;;7301:1;7298;7291:12;7252:53;7346:23;;;-1:-1:-1;7445:2:1;7430:18;;7417:32;7458:33;7417:32;7458:33;:::i;:::-;7510:7;-1:-1:-1;7590:2:1;7575:18;;7562:32;;-1:-1:-1;7693:2:1;7678:18;;7665:32;;-1:-1:-1;7796:3:1;7781:19;;7768:33;;-1:-1:-1;7900:3:1;7885:19;;7872:33;;-1:-1:-1;8004:3:1;7989:19;;7976:33;;-1:-1:-1;8087:3:1;8072:19;;8059:33;8101:30;8059:33;8101:30;:::i;:::-;8150:7;8140:17;;;7056:1107;;;;;;;;;;;:::o;8168:508::-;8245:6;8253;8261;8314:2;8302:9;8293:7;8289:23;8285:32;8282:52;;;8330:1;8327;8320:12;8282:52;8369:9;8356:23;8388:31;8413:5;8388:31;:::i;:::-;8438:5;-1:-1:-1;8495:2:1;8480:18;;8467:32;8508:33;8467:32;8508:33;:::i;:::-;8168:508;;8560:7;;-1:-1:-1;;;8640:2:1;8625:18;;;;8612:32;;8168:508::o;9313:247::-;9372:6;9425:2;9413:9;9404:7;9400:23;9396:32;9393:52;;;9441:1;9438;9431:12;9393:52;9480:9;9467:23;9499:31;9524:5;9499:31;:::i;9565:509::-;9630:5;9662:1;9686:18;9678:6;9675:30;9672:56;;;9708:18;;:::i;:::-;-1:-1:-1;9765:2:1;9753:15;;9770:66;9749:88;9839:4;9745:99;9862:21;9745:99;9862:21;:::i;:::-;9853:30;;;9906:6;9899:5;9892:21;9946:3;9937:6;9932:3;9928:16;9925:25;9922:45;;;9963:1;9960;9953:12;9922:45;10012:6;10007:3;10000:4;9993:5;9989:16;9976:43;10066:1;10059:4;10050:6;10043:5;10039:18;10035:29;10028:40;9565:509;;;;;:::o;10079:451::-;10148:6;10201:2;10189:9;10180:7;10176:23;10172:32;10169:52;;;10217:1;10214;10207:12;10169:52;10257:9;10244:23;10290:18;10282:6;10279:30;10276:50;;;10322:1;10319;10312:12;10276:50;10345:22;;10398:4;10390:13;;10386:27;-1:-1:-1;10376:55:1;;10427:1;10424;10417:12;10376:55;10450:74;10516:7;10511:2;10498:16;10493:2;10489;10485:11;10450:74;:::i;10535:361::-;10600:6;10608;10661:2;10649:9;10640:7;10636:23;10632:32;10629:52;;;10677:1;10674;10667:12;10629:52;10722:23;;;-1:-1:-1;10821:2:1;10806:18;;10793:32;10834:30;10793:32;10834:30;:::i;:::-;10883:7;10873:17;;;10535:361;;;;;:::o;11701:466::-;11778:6;11786;11794;11847:2;11835:9;11826:7;11822:23;11818:32;11815:52;;;11863:1;11860;11853:12;11815:52;-1:-1:-1;;11908:23:1;;;12028:2;12013:18;;12000:32;;-1:-1:-1;12131:2:1;12116:18;;;12103:32;;11701:466;-1:-1:-1;11701:466:1:o;12172:382::-;12237:6;12245;12298:2;12286:9;12277:7;12273:23;12269:32;12266:52;;;12314:1;12311;12304:12;12266:52;12353:9;12340:23;12372:31;12397:5;12372:31;:::i;:::-;12422:5;-1:-1:-1;12479:2:1;12464:18;;12451:32;12492:30;12451:32;12492:30;:::i;12953:847::-;13048:6;13056;13064;13072;13125:3;13113:9;13104:7;13100:23;13096:33;13093:53;;;13142:1;13139;13132:12;13093:53;13181:9;13168:23;13200:31;13225:5;13200:31;:::i;:::-;13250:5;-1:-1:-1;13307:2:1;13292:18;;13279:32;13320:33;13279:32;13320:33;:::i;:::-;13372:7;-1:-1:-1;13452:2:1;13437:18;;13424:32;;-1:-1:-1;13533:2:1;13518:18;;13505:32;13560:18;13549:30;;13546:50;;;13592:1;13589;13582:12;13546:50;13615:22;;13668:4;13660:13;;13656:27;-1:-1:-1;13646:55:1;;13697:1;13694;13687:12;13646:55;13720:74;13786:7;13781:2;13768:16;13763:2;13759;13755:11;13720:74;:::i;:::-;13710:84;;;12953:847;;;;;;;:::o;13805:708::-;13900:6;13908;13916;13924;13932;13985:3;13973:9;13964:7;13960:23;13956:33;13953:53;;;14002:1;13999;13992:12;13953:53;-1:-1:-1;;14047:23:1;;;14167:2;14152:18;;14139:32;;-1:-1:-1;14270:2:1;14255:18;;14242:32;;14373:2;14358:18;;14345:32;;-1:-1:-1;14476:3:1;14461:19;14448:33;;-1:-1:-1;13805:708:1;-1:-1:-1;13805:708:1:o;14518:617::-;14598:6;14606;14614;14622;14675:3;14663:9;14654:7;14650:23;14646:33;14643:53;;;14692:1;14689;14682:12;14643:53;14737:23;;;-1:-1:-1;14857:2:1;14842:18;;14829:32;;-1:-1:-1;14939:2:1;14924:18;;14911:32;14952:30;14911:32;14952:30;:::i;:::-;15001:7;-1:-1:-1;15060:2:1;15045:18;;15032:32;15073:30;15032:32;15073:30;:::i;:::-;14518:617;;;;-1:-1:-1;14518:617:1;;-1:-1:-1;;14518:617:1:o;15413:388::-;15481:6;15489;15542:2;15530:9;15521:7;15517:23;15513:32;15510:52;;;15558:1;15555;15548:12;15510:52;15597:9;15584:23;15616:31;15641:5;15616:31;:::i;:::-;15666:5;-1:-1:-1;15723:2:1;15708:18;;15695:32;15736:33;15695:32;15736:33;:::i;16066:986::-;16176:6;16184;16192;16200;16208;16216;16224;16277:3;16265:9;16256:7;16252:23;16248:33;16245:53;;;16294:1;16291;16284:12;16245:53;16333:9;16320:23;16352:31;16377:5;16352:31;:::i;:::-;16402:5;-1:-1:-1;16480:2:1;16465:18;;16452:32;;-1:-1:-1;16583:2:1;16568:18;;16555:32;;-1:-1:-1;16686:2:1;16671:18;;16658:32;;-1:-1:-1;16789:3:1;16774:19;;16761:33;;-1:-1:-1;16893:3:1;16878:19;;16865:33;;-1:-1:-1;16976:3:1;16961:19;;16948:33;16990:30;16948:33;16990:30;:::i;:::-;17039:7;17029:17;;;16066:986;;;;;;;;;;:::o;17482:184::-;17534:77;17531:1;17524:88;17631:4;17628:1;17621:15;17655:4;17652:1;17645:15;17671:437;17750:1;17746:12;;;;17793;;;17814:61;;17868:4;17860:6;17856:17;17846:27;;17814:61;17921:2;17913:6;17910:14;17890:18;17887:38;17884:218;;17958:77;17955:1;17948:88;18059:4;18056:1;18049:15;18087:4;18084:1;18077:15;17884:218;;17671:437;;;:::o;18461:184::-;18513:77;18510:1;18503:88;18610:4;18607:1;18600:15;18634:4;18631:1;18624:15;18650:168;18723:9;;;18754;;18771:15;;;18765:22;;18751:37;18741:71;;18792:18;;:::i;18823:125::-;18888:9;;;18909:10;;;18906:36;;;18922:18;;:::i;19661:128::-;19728:9;;;19749:11;;;19746:37;;;19763:18;;:::i;21195:518::-;21297:2;21292:3;21289:11;21286:421;;;21333:5;21330:1;21323:16;21377:4;21374:1;21364:18;21447:2;21435:10;21431:19;21428:1;21424:27;21418:4;21414:38;21483:4;21471:10;21468:20;21465:47;;;-1:-1:-1;21506:4:1;21465:47;21561:2;21556:3;21552:12;21549:1;21545:20;21539:4;21535:31;21525:41;;21616:81;21634:2;21627:5;21624:13;21616:81;;;21693:1;21679:16;;21660:1;21649:13;21616:81;;21949:1418;22075:3;22069:10;22102:18;22094:6;22091:30;22088:56;;;22124:18;;:::i;:::-;22153:97;22243:6;22203:38;22235:4;22229:11;22203:38;:::i;:::-;22197:4;22153:97;:::i;:::-;22299:4;22330:2;22319:14;;22347:1;22342:768;;;;23154:1;23171:6;23168:89;;;-1:-1:-1;23223:19:1;;;23217:26;23168:89;21855:66;21846:1;21842:11;;;21838:84;21834:89;21824:100;21930:1;21926:11;;;21821:117;23270:81;;22312:1049;;22342:768;21142:1;21135:14;;;21179:4;21166:18;;22390:66;22378:79;;;22555:222;22569:7;22566:1;22563:14;22555:222;;;22651:19;;;22645:26;22630:42;;22758:4;22743:20;;;;22711:1;22699:14;;;;22585:12;22555:222;;;22559:3;22805:6;22796:7;22793:19;22790:261;;;22866:19;;;22860:26;22967:66;22949:1;22945:14;;;22961:3;22941:24;22937:97;22933:102;22918:118;22903:134;;22790:261;-1:-1:-1;;;;23097:1:1;23081:14;;;23077:22;23064:36;;-1:-1:-1;21949:1418:1:o;23779:230::-;23849:6;23902:2;23890:9;23881:7;23877:23;23873:32;23870:52;;;23918:1;23915;23908:12;23870:52;-1:-1:-1;23963:16:1;;23779:230;-1:-1:-1;23779:230:1:o;24014:245::-;24081:6;24134:2;24122:9;24113:7;24109:23;24105:32;24102:52;;;24150:1;24147;24140:12;24102:52;24182:9;24176:16;24201:28;24223:5;24201:28;:::i;24969:942::-;25087:6;25095;25103;25111;25119;25127;25135;25188:3;25176:9;25167:7;25163:23;25159:33;25156:53;;;25205:1;25202;25195:12;25156:53;25250:16;;25356:2;25341:18;;25335:25;25452:2;25437:18;;25431:25;25548:2;25533:18;;25527:25;25623:3;25608:19;;25602:26;25250:16;;-1:-1:-1;25335:25:1;;-1:-1:-1;25431:25:1;-1:-1:-1;25527:25:1;-1:-1:-1;25637:30:1;25602:26;25637:30;:::i;:::-;25738:3;25723:19;;25717:26;25686:7;;-1:-1:-1;25752:30:1;25717:26;25752:30;:::i;:::-;25874:3;25859:19;;;;25853:26;24969:942;;;;-1:-1:-1;24969:942:1;;;;;;25801:7;;-1:-1:-1;25853:26:1;;24969:942;-1:-1:-1;24969:942:1:o;25916:251::-;25986:6;26039:2;26027:9;26018:7;26014:23;26010:32;26007:52;;;26055:1;26052;26045:12;26007:52;26087:9;26081:16;26106:31;26131:5;26106:31;:::i;26880:876::-;26984:6;26992;27036:9;27027:7;27023:23;27066:2;27062;27058:11;27055:31;;;27082:1;27079;27072:12;27055:31;27127:16;;;-1:-1:-1;27260:4:1;27191:66;27183:75;;27179:86;27176:106;;;27278:1;27275;27268:12;27176:106;-1:-1:-1;27331:4:1;27325:11;;;27363:17;;27410:18;27395:34;;27431:22;;;27392:62;27389:88;;;27457:18;;:::i;:::-;27493:4;27486:24;;;27576:2;27561:18;;;27555:25;27589:23;;27663:20;;27657:27;27700:15;;;27693:32;;;;-1:-1:-1;26880:876:1;27596:6;;-1:-1:-1;26880:876:1:o;35913:212::-;35955:3;35993:5;35987:12;36037:6;36030:4;36023:5;36019:16;36014:3;36008:36;36099:1;36063:16;;36088:13;;;-1:-1:-1;36063:16:1;;35913:212;-1:-1:-1;35913:212:1:o;36130:267::-;36309:3;36334:57;36360:30;36386:3;36378:6;36360:30;:::i;:::-;36352:6;36334:57;:::i;36824:542::-;37067:42;37059:6;37055:55;37044:9;37037:74;37159:42;37151:6;37147:55;37142:2;37131:9;37127:18;37120:83;37239:6;37234:2;37223:9;37219:18;37212:34;37282:3;37277:2;37266:9;37262:18;37255:31;37018:4;37303:57;37355:3;37344:9;37340:19;37332:6;37303:57;:::i;37371:249::-;37440:6;37493:2;37481:9;37472:7;37468:23;37464:32;37461:52;;;37509:1;37506;37499:12;37461:52;37541:9;37535:16;37560:30;37584:5;37560:30;:::i;37625:184::-;37677:77;37674:1;37667:88;37774:4;37771:1;37764:15;37798:4;37795:1;37788:15
Swarm Source
ipfs://0679d547f98b163cdc6b5983262a84c74e279d1e3b7fc7759631bdbbc9bcfb8b
Net Worth in USD
Net Worth in ETH
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
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.