ETH Price: $3,336.99 (-2.59%)

Contract

0x5a9168BD70d260Ef39D9Cdd3bc76385eF260c01C
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Deposit210259462024-10-23 4:38:4734 days ago1729658327IN
0x5a9168BD...eF260c01C
0 ETH0.00232497.3838455
Deposit208376122024-09-26 21:55:2361 days ago1727387723IN
0x5a9168BD...eF260c01C
0 ETH0.0058068818.1192674
Deposit208375322024-09-26 21:38:5961 days ago1727386739IN
0x5a9168BD...eF260c01C
0 ETH0.0059315219.33806239
Withdraw208064682024-09-22 13:38:4765 days ago1727012327IN
0x5a9168BD...eF260c01C
0 ETH0.001172748.14723156
Claim208064502024-09-22 13:35:1165 days ago1727012111IN
0x5a9168BD...eF260c01C
0 ETH0.000449727.81940932
Set_protocol_fee207984072024-09-21 10:38:4766 days ago1726915127IN
0x5a9168BD...eF260c01C
0 ETH0.000400658.1271806
Deposit207764202024-09-18 8:55:2369 days ago1726649723IN
0x5a9168BD...eF260c01C
0 ETH0.004037118.98131452
Claim207202202024-09-10 12:29:2377 days ago1725971363IN
0x5a9168BD...eF260c01C
0 ETH0.001098067.94631506
Withdraw207194772024-09-10 9:59:4777 days ago1725962387IN
0x5a9168BD...eF260c01C
0 ETH0.0009332.19058897
Claim207171782024-09-10 2:17:1177 days ago1725934631IN
0x5a9168BD...eF260c01C
0 ETH0.00044995.24551359
Claim206867832024-09-05 20:29:3582 days ago1725568175IN
0x5a9168BD...eF260c01C
0 ETH0.000421967.33522274
Start_rentals206498222024-08-31 16:43:5987 days ago1725122639IN
0x5a9168BD...eF260c01C
0 ETH0.002342491.43358575
Delegate_to_wall...206461872024-08-31 4:32:5987 days ago1725078779IN
0x5a9168BD...eF260c01C
0 ETH0.000674151.24282204
Delegate_to_wall...206461632024-08-31 4:28:1187 days ago1725078491IN
0x5a9168BD...eF260c01C
0 ETH0.00065961.16481852
Claim206210402024-08-27 16:12:4791 days ago1724775167IN
0x5a9168BD...eF260c01C
0 ETH0.000404654.72057351
Start_rentals205996392024-08-24 16:25:5994 days ago1724516759IN
0x5a9168BD...eF260c01C
0 ETH0.000489752.42130659
Withdraw205988792024-08-24 13:53:1194 days ago1724507591IN
0x5a9168BD...eF260c01C
0 ETH0.000384671.29564214
Start_rentals205428392024-08-16 17:59:23102 days ago1723831163IN
0x5a9168BD...eF260c01C
0 ETH0.00064892.17842107
Start_rentals205427892024-08-16 17:49:23102 days ago1723830563IN
0x5a9168BD...eF260c01C
0 ETH0.000557521.87605645
Renter_delegate_...205387592024-08-16 4:20:35102 days ago1723782035IN
0x5a9168BD...eF260c01C
0 ETH0.000114011.19237025
Extend_rentals205387562024-08-16 4:19:59102 days ago1723781999IN
0x5a9168BD...eF260c01C
0 ETH0.000110391.15544618
Start_rentals205236422024-08-14 1:39:35104 days ago1723599575IN
0x5a9168BD...eF260c01C
0 ETH0.000314481.25887381
Claim205215782024-08-13 18:44:59105 days ago1723574699IN
0x5a9168BD...eF260c01C
0 ETH0.000111461.75372308
Claim205196272024-08-13 12:13:23105 days ago1723551203IN
0x5a9168BD...eF260c01C
0 ETH0.000113911.98070358
Claim205054452024-08-11 12:43:35107 days ago1723380215IN
0x5a9168BD...eF260c01C
0 ETH0.000191792.58998482
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
210259462024-10-23 4:38:4734 days ago1729658327
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
208376122024-09-26 21:55:2361 days ago1727387723
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
208375322024-09-26 21:38:5961 days ago1727386739
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
207764202024-09-18 8:55:2369 days ago1726649723
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
207764202024-09-18 8:55:2369 days ago1726649723
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
207764202024-09-18 8:55:2369 days ago1726649723
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
204243372024-07-31 5:06:59118 days ago1722402419
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
204243372024-07-31 5:06:59118 days ago1722402419
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
204243372024-07-31 5:06:59118 days ago1722402419
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
204243372024-07-31 5:06:59118 days ago1722402419
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
204243372024-07-31 5:06:59118 days ago1722402419
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
204243372024-07-31 5:06:59118 days ago1722402419
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
204243372024-07-31 5:06:59118 days ago1722402419
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
204243372024-07-31 5:06:59118 days ago1722402419
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
204243372024-07-31 5:06:59118 days ago1722402419
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
204243372024-07-31 5:06:59118 days ago1722402419
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
204243372024-07-31 5:06:59118 days ago1722402419
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
202838752024-07-11 14:30:35138 days ago1720708235
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
202499302024-07-06 20:43:11143 days ago1720298591
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
202437542024-07-06 0:01:23144 days ago1720224083
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
202008682024-06-30 0:17:11149 days ago1719706631
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
201859162024-06-27 22:09:35152 days ago1719526175
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
201856792024-06-27 21:22:11152 days ago1719523331
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
201856792024-06-27 21:22:11152 days ago1719523331
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
201523952024-06-23 5:44:59156 days ago1719121499
0x5a9168BD...eF260c01C
 Contract Creation0 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Zharta Renting Contract

Compiler Version
vyper:0.3.10

Optimization Enabled:
N/A

Other Settings:
None license
# @version 0.3.10

"""
@title Zharta Renting Contract
@author [Zharta](https://zharta.io/)
@notice This contract manages the renting process for NFTs in the LOTM Renting Protocol.
@dev This contract is the single user-facing contract for each Renting Market. It does not hold any NFTs, although it holds the rentals values and the protocol fees (payment tokens). It also manages the creation of vaults (as minimal proxies to the vault implementation) and implements the rental logic. The delegation and staking functionality are implemented in the vaults.
The information regarding listings and rentals was externalized in order to reduce the gas costs while using the protocol. That requires the state to be passed as an argument to each function and validated by matching its hash against the one stored in the contract. Conversly, changes to the state are hashed and stored, and the resulting state variables are either published as events or returned directly to the user.
The information that hold the state (`TokenContext`) consist of the token id, the owner of the NFT and the active rental (`Rental`), which are required to keep the integrity of the contract.
The listings (`SignedListing`) are required arguments for the relevant functions and must be signed by both the owner (EIP-712 type 3) and the protocol admin (EIP-712 type 0). The signature is validated by the contract and requires the signature timestamp to be within 2 minutes of the current timestamp
"""


# Interfaces

from vyper.interfaces import ERC20 as IERC20
from vyper.interfaces import ERC721 as IERC721

interface IVault:
    def initialise(): nonpayable
    def deposit(token_id: uint256, nft_owner: address, delegate: address): nonpayable
    def withdraw(token_id: uint256, wallet: address): nonpayable
    def delegate_to_wallet(delegate: address, expiration: uint256): nonpayable
    def staking_deposit(sender: address, amount: uint256, token_id: uint256, staking_addr: address, pool_method_id: bytes4): nonpayable
    def staking_withdraw(wallet: address, amount: uint256, token_id: uint256, staking_addr: address, pool_method_id: bytes4): nonpayable
    def staking_claim(wallet: address, token_id: uint256, staking_addr: address, pool_method_id: bytes4): nonpayable
    def staking_compound(token_id: uint256, staking_addr: address, pool_claim_method_id: bytes4, pool_deposit_method_id: bytes4): nonpayable


interface ERC721Receiver:
    def onERC721Received(_operator: address, _from: address, _tokenId: uint256, _data: Bytes[1024]) -> bytes4: view

interface RentingERC721:
    def initialise(): nonpayable
    def mint(tokens: DynArray[TokenAndWallet, 32]): nonpayable
    def burn(tokens: DynArray[TokenAndWallet, 32]): nonpayable
    def ownerOf(tokenId: uint256) -> address: view
    def owner_of(tokenId: uint256) -> address: view


# Structs

struct TokenContext:
    token_id: uint256
    nft_owner: address
    active_rental: Rental

struct Rental:
    id: bytes32 # keccak256 of the renter, token_id, start and expiration
    owner: address
    renter: address
    delegate: address
    token_id: uint256
    start: uint256
    min_expiration: uint256
    expiration: uint256
    amount: uint256
    protocol_fee: uint256

struct Listing:
    token_id: uint256
    price: uint256 # price per hour, 0 means not listed
    min_duration: uint256 # min duration in hours
    max_duration: uint256 # max duration in hours, 0 means unlimited
    timestamp: uint256

struct Signature:
    v: uint256
    r: uint256
    s: uint256

struct SignedListing:
    listing: Listing
    owner_signature: Signature
    admin_signature: Signature

struct TokenContextAndListing:
    token_context: TokenContext
    signed_listing: SignedListing
    duration: uint256

struct TokenContextAndAmount:
    token_context: TokenContext
    amount: uint256

struct RentalLog:
    id: bytes32
    vault: address
    owner: address
    token_id: uint256
    start: uint256
    min_expiration: uint256
    expiration: uint256
    amount: uint256
    protocol_fee: uint256

struct RentalExtensionLog:
    id: bytes32
    vault: address
    owner: address
    token_id: uint256
    start: uint256
    min_expiration: uint256
    expiration: uint256
    amount_settled: uint256
    extension_amount: uint256
    protocol_fee: uint256


struct RewardLog:
    token_id: uint256
    active_rental_amount: uint256

struct WithdrawalLog:
    vault: address
    token_id: uint256

struct VaultLog:
    vault: address
    token_id: uint256

struct StakingLog:
    token_id: uint256
    amount: uint256

struct TokenAndWallet:
    token_id: uint256
    wallet: address

# Events

event NftsDeposited:
    owner: address
    nft_contract: address
    vaults: DynArray[VaultLog, 32]
    delegate: address

event NftsWithdrawn:
    owner: address
    nft_contract: address
    total_rewards: uint256
    withdrawals: DynArray[WithdrawalLog, 32]

event DelegatedToWallet:
    owner: address
    delegate: address
    nft_contract: address
    vaults: DynArray[VaultLog, 32]

event RenterDelegatedToWallet:
    renter: address
    delegate: address
    nft_contract: address
    vaults: DynArray[VaultLog, 32]

event ListingsRevoked:
    owner: address
    timestamp: uint256
    token_ids: DynArray[uint256, 32]

event RentalStarted:
    renter: address
    delegate: address
    nft_contract: address
    rentals: DynArray[RentalLog, 32]

event RentalClosed:
    renter: address
    nft_contract: address
    rentals: DynArray[RentalLog, 32]

event RentalExtended:
    renter: address
    nft_contract: address
    rentals: DynArray[RentalExtensionLog, 32]

event RewardsClaimed:
    owner: address
    nft_contract: address
    amount: uint256
    protocol_fee_amount: uint256
    rewards: DynArray[RewardLog, 32]

event TokenOwnershipChanged:
    new_owner: address
    nft_contract: address
    tokens: DynArray[uint256, 32]

event ProtocolFeeSet:
    old_fee: uint256
    new_fee: uint256
    fee_wallet: address

event ProtocolWalletChanged:
    old_wallet: address
    new_wallet: address

event StakingAddressSet:
    old_value: address
    new_value: address

event AdminProposed:
    admin: address
    proposed_admin: address

event OwnershipTransferred:
    old_admin: address
    new_admin: address

event StakingDeposit:
    owner: address
    nft_contract: address
    tokens: DynArray[StakingLog, 32]

event StakingWithdraw:
    owner: address
    nft_contract: address
    recipient: address
    tokens: DynArray[StakingLog, 32]

event StakingClaim:
    owner: address
    nft_contract: address
    recipient: address
    tokens: DynArray[uint256, 32]

event StakingCompound:
    owner: address
    nft_contract: address
    tokens: DynArray[uint256, 32]

event FeesClaimed:
    fee_wallet: address
    amount: uint256


event PauseStateSet:
    old_value: bool
    new_value: bool


# Global Variables

ZHARTA_DOMAIN_NAME: constant(String[6]) = "Zharta"
ZHARTA_DOMAIN_VERSION: constant(String[1]) = "1"

DOMAIN_TYPE_HASH: constant(bytes32) = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")
LISTING_TYPE_HASH: constant(bytes32) = keccak256("Listing(uint256 token_id,uint256 price,uint256 min_duration,uint256 max_duration,uint256 timestamp)")

_COLLISION_OFFSET: constant(bytes1) = 0xFF
_DEPLOYMENT_CODE: constant(bytes9) = 0x602D3D8160093D39F3
_PRE: constant(bytes10) = 0x363d3d373d3d3d363d73
_POST: constant(bytes15) = 0x5af43d82803e903d91602b57fd5bf3

SUPPORTED_INTERFACES: constant(bytes4[2]) = [0x01ffc9a7, 0x80ac58cd] # ERC165, ERC721

LISTINGS_SIGNATURE_VALID_PERIOD: constant(uint256) = 120

listing_sig_domain_separator: immutable(bytes32)
vault_impl_addr: public(immutable(address))
payment_token: public(immutable(IERC20))
nft_contract_addr: public(immutable(address))
delegation_registry_addr: public(immutable(address))
staking_addr: public(address)
renting_erc721: public(immutable(RentingERC721))
max_protocol_fee: public(immutable(uint256))

protocol_wallet: public(address)
protocol_fee: public(uint256)
protocol_admin: public(address)
proposed_admin: public(address)

rental_states: public(HashMap[uint256, bytes32]) # token_id -> hash(token_context)
listing_revocations: public(HashMap[uint256, uint256]) # token_id -> timestamp

unclaimed_rewards: public(HashMap[address, uint256]) # wallet -> amount
protocol_fees_amount: public(uint256)
paused: public(bool)

##### EXTERNAL METHODS - WRITE #####


@external
def __init__(
    _vault_impl_addr: address,
    _payment_token_addr: address,
    _nft_contract_addr: address,
    _delegation_registry_addr: address,
    _renting_erc721: address,
    _staking_addr: address,
    _max_protocol_fee: uint256,
    _protocol_fee: uint256,
    _protocol_wallet: address,
    _protocol_admin: address
):
    """
    @notice Initialize the renting contract with necessary parameters and addresses.
    @dev Sets up the contract by initializing various addresses and fees.
    @param _vault_impl_addr The address of the vault implementation.
    @param _payment_token_addr The address of the payment token.
    @param _nft_contract_addr The address of the NFT contract.
    @param _delegation_registry_addr The address of the delegation registry.
    @param _renting_erc721 The address of the renting ERC721 contract.
    @param _max_protocol_fee The maximum protocol fee that can be set.
    @param _protocol_fee The initial protocol fee.
    @param _protocol_wallet The wallet to receive protocol fees.
    @param _protocol_admin The administrator of the protocol.
    """

    assert _vault_impl_addr != empty(address), "vault impl is the zero addr"
    assert _payment_token_addr != empty(address), "payment token is the zero addr"
    assert _nft_contract_addr != empty(address), "nft contract is the zero addr"
    assert _delegation_registry_addr != empty(address), "deleg registry is the zero addr"
    assert _renting_erc721 != empty(address), "renting_erc721 is the zero addr"
    assert _max_protocol_fee <= 10000, "max protocol fee > 100%"
    assert _protocol_fee <= _max_protocol_fee, "protocol fee > max fee"
    assert _protocol_wallet != empty(address), "protocol wallet not set"
    assert _protocol_admin != empty(address), "admin wallet not set"

    vault_impl_addr = _vault_impl_addr
    payment_token = IERC20(_payment_token_addr)
    nft_contract_addr = _nft_contract_addr
    delegation_registry_addr = _delegation_registry_addr
    max_protocol_fee = _max_protocol_fee
    renting_erc721 = RentingERC721(_renting_erc721)

    self.staking_addr = _staking_addr
    self.protocol_wallet = _protocol_wallet
    self.protocol_fee = _protocol_fee
    self.protocol_admin = _protocol_admin
    self.paused = False

    listing_sig_domain_separator = keccak256(
        _abi_encode(
            DOMAIN_TYPE_HASH,
            keccak256(ZHARTA_DOMAIN_NAME),
            keccak256(ZHARTA_DOMAIN_VERSION),
            chain.id,
            self
        )
    )

    renting_erc721.initialise()


@external
def delegate_to_wallet(token_contexts: DynArray[TokenContext, 32], delegate: address):

    """
    @notice Delegates multiple NFTs to a wallet while not rented
    @dev Iterates over token contexts to delegate NFTs to a wallet
    @param token_contexts An array of token contexts, each containing the vault state for an NFT.
    @param delegate The address to delegate the NFTs to.
    """

    vault_logs: DynArray[VaultLog, 32] = empty(DynArray[VaultLog, 32])

    for token_context in token_contexts:
        assert self._is_context_valid(token_context), "invalid context"
        assert not self._is_rental_active(token_context.active_rental), "active rental"
        assert msg.sender == token_context.nft_owner, "not owner"
        vault: IVault = self._get_vault(token_context.token_id)

        vault.delegate_to_wallet(delegate, max_value(uint256))

        vault_logs.append(VaultLog({vault: vault.address, token_id: token_context.token_id}))

    log DelegatedToWallet(msg.sender, delegate, nft_contract_addr, vault_logs)



@external
def renter_delegate_to_wallet(token_contexts: DynArray[TokenContext, 32], delegate: address):

    """
    @notice Delegates multiple NFTs to a wallet while rented
    @dev Iterates over token contexts to delegate NFTs to a wallet
    @param token_contexts An array of token contexts, each containing the vault state for an NFT.
    @param delegate The address to delegate the NFTs to.
    """

    vault_logs: DynArray[VaultLog, 32] = empty(DynArray[VaultLog, 32])

    for token_context in token_contexts:
        assert self._is_context_valid(token_context), "invalid context"
        assert self._is_rental_active(token_context.active_rental), "no active rental"
        assert msg.sender == token_context.active_rental.renter, "not renter"

        vault: IVault = self._get_vault(token_context.token_id)
        vault.delegate_to_wallet(delegate, token_context.active_rental.expiration)

        self._store_token_state(
            token_context.token_id,
            token_context.nft_owner,
            Rental({
                id: token_context.active_rental.id,
                owner: token_context.active_rental.owner,
                renter: token_context.active_rental.renter,
                delegate: delegate,
                token_id: token_context.active_rental.token_id,
                start: token_context.active_rental.start,
                min_expiration: token_context.active_rental.min_expiration,
                expiration: token_context.active_rental.expiration,
                amount: token_context.active_rental.amount,
                protocol_fee: token_context.active_rental.protocol_fee,
            })
        )

        vault_logs.append(VaultLog({vault: vault.address, token_id: token_context.token_id}))

    log RenterDelegatedToWallet(msg.sender, delegate, nft_contract_addr, vault_logs)


@external
def deposit(token_ids: DynArray[uint256, 32], delegate: address):

    """
    @notice Deposits a set of NFTs in vaults (creating them if needed) and sets up delegations
    @dev Iterates over a list of token ids, creating vaults if not needed, transfering the NFTs to the vaults and setting the delegations
    @param token_ids An array of NFT token ids to deposit.
    @param delegate Address to delegate the NFT to while listed.
    """

    self._check_not_paused()
    vault_logs: DynArray[VaultLog, 32] = empty(DynArray[VaultLog, 32])

    for token_id in token_ids:
        assert self.rental_states[token_id] == empty(bytes32), "invalid state"
        vault: IVault = self._create_vault(token_id)
        vault.deposit(token_id, msg.sender, delegate)

        self._store_token_state(token_id, msg.sender, empty(Rental))

        vault_logs.append(VaultLog({
            vault: vault.address,
            token_id: token_id
        }))

    log NftsDeposited(msg.sender, nft_contract_addr, vault_logs, delegate)


@external
def mint(token_contexts: DynArray[TokenContext, 32]):

    """
    @notice Mints ERC721 renting tokens for a set of NFTs
    @dev Iterates over a list of token contexts, creating ERC721 renting tokens with matching ids for each NFT
    @param token_contexts An array of token contexts, each containing the rental state for an NFT.
    """

    tokens: DynArray[TokenAndWallet, 32] = empty(DynArray[TokenAndWallet, 32])

    for token_context in token_contexts:
        assert self._is_context_valid(token_context), "invalid context"

        tokens.append(TokenAndWallet({
            token_id: token_context.token_id,
            wallet: token_context.nft_owner
        }))

    renting_erc721.mint(tokens)


@external
def revoke_listing(token_contexts: DynArray[TokenContext, 32]):

    """
    @notice Revokes any existing listings for a set of NFTs
    @dev Iterates over a list of token contexts, revoking listings for each NFT created before the current block timestamp
    @param token_contexts An array of token contexts, each containing the rental state for an NFT.
    """

    token_ids: DynArray[uint256, 32] = empty(DynArray[uint256, 32])
    for token_context in token_contexts:
        assert self._is_context_valid(token_context), "invalid context"
        assert token_context.nft_owner == msg.sender, "not owner"
        self.listing_revocations[token_context.token_id] = block.timestamp
        token_ids.append(token_context.token_id)
    log ListingsRevoked(msg.sender, block.timestamp, token_ids)


@external
def start_rentals(token_contexts: DynArray[TokenContextAndListing, 32], delegate: address, signature_timestamp: uint256):

    """
    @notice Start rentals for multiple NFTs for the specified duration and delegate them to a wallet
    @dev Iterates over token contexts to begin rentals for each NFT. The rental conditions are evaluated against the matching listing, signed by the owner and the protocol admin. The rental amount is computed and transferred to the protocol wallet and the delegation is created for the given wallet.
    @param token_contexts An array of token contexts, each containing the rental state and signed listing for an NFT.
    @param delegate The address to delegate the NFT to during the rental period.
    @param signature_timestamp The timestamp of the protocol admin signature.
    """

    self._check_not_paused()

    rental_logs: DynArray[RentalLog, 32] = []
    rental_amounts: uint256 = 0

    for context in token_contexts:
        rental_amounts += self._compute_rental_amount(block.timestamp, block.timestamp + context.duration * 3600, context.signed_listing.listing.price)

    self._receive_payment_token(msg.sender, rental_amounts)

    for context in token_contexts:
        vault: IVault = self._get_vault(context.token_context.token_id)
        assert self._is_context_valid(context.token_context), "invalid context"
        assert not self._is_rental_active(context.token_context.active_rental), "active rental"
        assert self._is_within_duration_range(context.signed_listing.listing, context.duration), "duration not respected"
        assert context.signed_listing.listing.price > 0, "listing not active"
        self._check_valid_listing(context.token_context.token_id, context.signed_listing, signature_timestamp, context.token_context.nft_owner)

        expiration: uint256 = block.timestamp + context.duration * 3600
        vault.delegate_to_wallet(delegate if delegate != empty(address) else msg.sender, expiration)

        # store unclaimed rewards
        self._consolidate_claims(context.token_context.token_id, context.token_context.nft_owner, context.token_context.active_rental)

        # create rental
        rental_id: bytes32 = self._compute_rental_id(msg.sender, context.token_context.token_id, block.timestamp, expiration)

        new_rental: Rental = Rental({
            id: rental_id,
            owner: context.token_context.nft_owner,
            renter: msg.sender,
            delegate: delegate,
            token_id: context.token_context.token_id,
            start: block.timestamp,
            min_expiration: block.timestamp + context.signed_listing.listing.min_duration * 3600,
            expiration: expiration,
            amount: self._compute_rental_amount(block.timestamp, expiration, context.signed_listing.listing.price),
            protocol_fee: self.protocol_fee,
        })

        self._store_token_state(context.token_context.token_id, context.token_context.nft_owner, new_rental)

        rental_logs.append(RentalLog({
            id: rental_id,
            vault: vault.address,
            owner: context.token_context.nft_owner,
            token_id: context.token_context.token_id,
            start: block.timestamp,
            min_expiration: new_rental.min_expiration,
            expiration: expiration,
            amount: new_rental.amount,
            protocol_fee: new_rental.protocol_fee,
        }))

    log RentalStarted(msg.sender, delegate, nft_contract_addr, rental_logs)


@external
def close_rentals(token_contexts: DynArray[TokenContext, 32]):

    """
    @notice Close rentals for multiple NFTs and claim rewards
    @dev Iterates over token contexts to close rentals for each NFT. The new rental amount is computed pro-rata (considering the minimum duration) and any payback amount transferred to the renter. The protocol fee is computed and accrued and the delegation is revoked.
    @param token_contexts An array of token contexts, each containing the rental state for an NFT.
    """

    rental_logs: DynArray[RentalLog, 32] = []
    protocol_fees_amount: uint256 = 0
    payback_amounts: uint256 = 0

    for token_context in token_contexts:
        vault: IVault = self._get_vault(token_context.token_id)
        assert self._is_context_valid(token_context), "invalid context"
        assert self._is_rental_active(token_context.active_rental), "active rental does not exist"
        assert msg.sender == token_context.active_rental.renter, "not renter of active rental"

        real_expiration_adjusted: uint256 = block.timestamp
        if block.timestamp < token_context.active_rental.min_expiration:
            real_expiration_adjusted = token_context.active_rental.min_expiration

        pro_rata_rental_amount: uint256 = self._compute_real_rental_amount(
            token_context.active_rental.expiration - token_context.active_rental.start,
            real_expiration_adjusted - token_context.active_rental.start,
            token_context.active_rental.amount
        )
        payback_amount: uint256 = token_context.active_rental.amount - pro_rata_rental_amount
        payback_amounts += payback_amount

        protocol_fee_amount: uint256 = pro_rata_rental_amount * token_context.active_rental.protocol_fee / 10000
        protocol_fees_amount += protocol_fee_amount

        # clear active rental
        self._store_token_state(token_context.token_id, token_context.nft_owner, empty(Rental))

        # set unclaimed rewards
        self.unclaimed_rewards[token_context.nft_owner] += pro_rata_rental_amount - protocol_fee_amount

        # revoke delegation
        vault.delegate_to_wallet(empty(address), 0)

        rental_logs.append(RentalLog({
            id: token_context.active_rental.id,
            vault: vault.address,
            owner: token_context.active_rental.owner,
            token_id: token_context.active_rental.token_id,
            start: token_context.active_rental.start,
            min_expiration: token_context.active_rental.min_expiration,
            expiration: block.timestamp,
            amount: pro_rata_rental_amount,
            protocol_fee: token_context.active_rental.protocol_fee,
        }))

    assert payment_token.transfer(msg.sender, payback_amounts), "transfer failed"

    if protocol_fees_amount > 0:
        self.protocol_fees_amount += protocol_fees_amount

    log RentalClosed(msg.sender, nft_contract_addr, rental_logs)


@external
def extend_rentals(token_contexts: DynArray[TokenContextAndListing, 32], signature_timestamp: uint256):

    """
    @notice Extend rentals for multiple NFTs for the specified duration
    @dev Iterates over token contexts to extend rentals for each NFT. The rental amount is computed pro-rata (considering the minimum duration) and the new rental amount is computed. The difference between the new rental amount and the payback amount is transferred from / to the renter and the new rental protocol fee is computed and accrued.
    @param token_contexts An array of token contexts, each containing the rental state and signed listing for an NFT.
    @param signature_timestamp The timestamp of the protocol admin signature.
    """

    rental_logs: DynArray[RentalExtensionLog, 32] = []
    protocol_fees_amount: uint256 = 0
    payback_amounts: uint256 = 0
    extension_amounts: uint256 = 0

    for context in token_contexts:
        vault: IVault = self._get_vault(context.token_context.token_id)
        assert self._is_context_valid(context.token_context), "invalid context"
        assert self._is_rental_active(context.token_context.active_rental), "no active rental"
        assert msg.sender == context.token_context.active_rental.renter, "not renter of active rental"

        assert self._is_within_duration_range(context.signed_listing.listing, context.duration), "duration not respected"
        assert context.signed_listing.listing.price > 0, "listing not active"
        self._check_valid_listing(context.token_context.token_id, context.signed_listing, signature_timestamp, context.token_context.nft_owner)

        expiration: uint256 = block.timestamp + context.duration * 3600
        real_expiration_adjusted: uint256 = block.timestamp
        if block.timestamp < context.token_context.active_rental.min_expiration:
            real_expiration_adjusted = context.token_context.active_rental.min_expiration

        pro_rata_rental_amount: uint256 = self._compute_real_rental_amount(
            context.token_context.active_rental.expiration - context.token_context.active_rental.start,
            real_expiration_adjusted - context.token_context.active_rental.start,
            context.token_context.active_rental.amount
        )
        new_rental_amount: uint256 = self._compute_rental_amount(block.timestamp, expiration, context.signed_listing.listing.price)
        extension_amounts += new_rental_amount

        payback_amount: uint256 = context.token_context.active_rental.amount - pro_rata_rental_amount
        payback_amounts += payback_amount

        protocol_fee_amount: uint256 = pro_rata_rental_amount * context.token_context.active_rental.protocol_fee / 10000
        protocol_fees_amount += protocol_fee_amount

        new_rental: Rental = Rental({
            id: context.token_context.active_rental.id,
            owner: context.token_context.nft_owner,
            renter: msg.sender,
            delegate: context.token_context.active_rental.delegate,
            token_id: context.token_context.token_id,
            start: block.timestamp,
            min_expiration: block.timestamp + context.signed_listing.listing.min_duration * 3600,
            expiration: expiration,
            amount: new_rental_amount,
            protocol_fee: self.protocol_fee,
        })
        # clear active rental
        self._store_token_state(context.token_context.token_id, context.token_context.nft_owner, new_rental)

        # set unclaimed rewards
        self.unclaimed_rewards[context.token_context.nft_owner] += pro_rata_rental_amount - protocol_fee_amount

        rental_logs.append(RentalExtensionLog({
            id: context.token_context.active_rental.id,
            vault: vault.address,
            owner: context.token_context.active_rental.owner,
            token_id: context.token_context.active_rental.token_id,
            start: block.timestamp,
            min_expiration: block.timestamp + context.signed_listing.listing.min_duration * 3600,
            expiration: expiration,
            amount_settled: pro_rata_rental_amount,
            extension_amount: new_rental_amount,
            protocol_fee: context.token_context.active_rental.protocol_fee,
        }))

    if payback_amounts > extension_amounts:
        self._transfer_payment_token(msg.sender, payback_amounts - extension_amounts)
    elif payback_amounts < extension_amounts:
        self._receive_payment_token(msg.sender, extension_amounts - payback_amounts)

    if protocol_fees_amount > 0:
        self.protocol_fees_amount += protocol_fees_amount

    log RentalExtended(msg.sender, nft_contract_addr, rental_logs)


@external
def withdraw(token_contexts: DynArray[TokenContext, 32]):

    """
    @notice Withdraw multiple NFTs and claim rewards
    @dev Iterates over token contexts to withdraw NFTs from their vaults and claim any unclaimed rewards, while also burning the matching ERC721 renting token.
    @param token_contexts An array of token contexts, each containing the vault state for an NFT.
    """


    withdrawal_log: DynArray[WithdrawalLog, 32] = empty(DynArray[WithdrawalLog, 32])
    tokens: DynArray[TokenAndWallet, 32] = empty(DynArray[TokenAndWallet, 32])
    total_rewards: uint256 = 0

    for token_context in token_contexts:
        assert self._is_context_valid(token_context), "invalid context"
        assert not self._is_rental_active(token_context.active_rental), "active rental"
        token_owner: address = renting_erc721.owner_of(token_context.token_id)
        if token_owner != empty(address):
            assert msg.sender == token_owner, "not owner"
        else:
            assert msg.sender == token_context.nft_owner, "not owner"

        vault: IVault = self._get_vault(token_context.token_id)

        self._consolidate_claims(token_context.token_id, token_context.nft_owner, token_context.active_rental, False)

        self._clear_token_state(token_context.token_id)

        tokens.append(TokenAndWallet({
            token_id: token_context.token_id,
            wallet: token_context.nft_owner
        }))

        vault.withdraw(token_context.token_id, msg.sender)
        self.listing_revocations[token_context.token_id] = block.timestamp

        withdrawal_log.append(WithdrawalLog({
            vault: vault.address,
            token_id: token_context.token_id,
        }))

    renting_erc721.burn(tokens)

    rewards_to_claim: uint256 = self.unclaimed_rewards[msg.sender]

    # transfer reward to nft owner
    if rewards_to_claim > 0:
        self.unclaimed_rewards[msg.sender] = 0
        self._transfer_payment_token(msg.sender, rewards_to_claim)

    log NftsWithdrawn(
        msg.sender,
        nft_contract_addr,
        rewards_to_claim,
        withdrawal_log
    )


@external
def stake_deposit(token_contexts: DynArray[TokenContextAndAmount, 32], pool_method_id: bytes4):

    """
    @notice Deposit the given amounts for multiple NFTs in the configured staking pool
    @dev Iterates over token contexts to deposit the given amounts for each NFT in the staking pool
    @param token_contexts An array of token contexts paired with amounts, each containing the rental state for an NFT.
    @param pool_method_id The method id to call on the staking pool to deposit the given amounts.
    """

    self._check_not_paused()
    staking_addr: address = self.staking_addr
    assert staking_addr != empty(address), "staking not supported"

    staking_log: DynArray[StakingLog, 32] = empty(DynArray[StakingLog, 32])

    for context in token_contexts:
        assert msg.sender == context.token_context.nft_owner, "not owner"
        assert self._is_context_valid(context.token_context), "invalid context"

        vault: IVault = self._get_vault(context.token_context.token_id)
        assert payment_token.transferFrom(msg.sender, vault.address, context.amount), "transferFrom failed"
        vault.staking_deposit(msg.sender, context.amount, context.token_context.token_id, staking_addr, pool_method_id)
        staking_log.append(StakingLog({
            token_id: context.token_context.token_id,
            amount: context.amount
        }))

    log StakingDeposit(msg.sender, nft_contract_addr, staking_log)


@external
def stake_withdraw(token_contexts: DynArray[TokenContextAndAmount, 32], recipient: address, pool_method_id: bytes4):

    """
    @notice Withdraw the given amounts for multiple NFTs from the configured staking pool
    @dev Iterates over token contexts to withdraw the given amounts for each NFT from the staking pool
    @param token_contexts An array of token contexts paired with amounts, each containing the rental state for an NFT.
    @param recipient The address to receive the withdrawn amounts.
    @param pool_method_id The method id to call on the staking pool to withdraw the given amounts.
    """

    staking_addr: address = self.staking_addr
    assert staking_addr != empty(address), "staking not supported"

    staking_log: DynArray[StakingLog, 32] = empty(DynArray[StakingLog, 32])

    for context in token_contexts:
        assert msg.sender == context.token_context.nft_owner, "not owner"
        assert self._is_context_valid(context.token_context), "invalid context"

        self._get_vault(context.token_context.token_id).staking_withdraw(recipient, context.amount, context.token_context.token_id, staking_addr, pool_method_id)
        staking_log.append(StakingLog({
            token_id: context.token_context.token_id,
            amount: context.amount
        }))

    log StakingWithdraw(msg.sender, nft_contract_addr, recipient, staking_log)


@external
def stake_claim(token_contexts: DynArray[TokenContextAndAmount, 32], recipient: address, pool_method_id: bytes4):

    """
    @notice Claim the rewards for multiple NFTs from the configured staking pool
    @dev Iterates over token contexts to claim the rewards for each NFT from the staking pool
    @param token_contexts An array of token contexts paired with amounts, each containing the rental state for an NFT.
    @param recipient The address to receive the claimed rewards.
    @param pool_method_id The method id to call on the staking pool to claim the rewards.
    """

    staking_addr: address = self.staking_addr
    assert staking_addr != empty(address), "staking not supported"
    tokens: DynArray[uint256, 32] = empty(DynArray[uint256, 32])

    for context in token_contexts:
        assert msg.sender == context.token_context.nft_owner, "not owner"
        assert self._is_context_valid(context.token_context), "invalid context"
        self._get_vault(context.token_context.token_id).staking_claim(recipient, context.token_context.token_id, staking_addr, pool_method_id)
        tokens.append(context.token_context.token_id)

    log StakingClaim(msg.sender, nft_contract_addr, recipient, tokens)


@external
def stake_compound(token_contexts: DynArray[TokenContextAndAmount, 32], pool_claim_method_id: bytes4, pool_deposit_method_id: bytes4):

    """
    @notice Compound the rewards for multiple NFTs in the configured staking pool
    @dev Iterates over token contexts to compound the rewards for each NFT in the staking pool
    @param token_contexts An array of token contexts paired with amounts, each containing the rental state for an NFT.
    @param pool_claim_method_id The method id to call on the staking pool to claim the rewards.
    @param pool_deposit_method_id The method id to call on the staking pool to deposit the rewards.
    """

    self._check_not_paused()
    staking_addr: address = self.staking_addr
    assert staking_addr != empty(address), "staking not supported"
    tokens: DynArray[uint256, 32] = empty(DynArray[uint256, 32])

    for context in token_contexts:
        assert msg.sender == context.token_context.nft_owner, "not owner"
        assert self._is_context_valid(context.token_context), "invalid context"

        self._get_vault(context.token_context.token_id).staking_compound(context.token_context.token_id, staking_addr, pool_claim_method_id, pool_deposit_method_id)
        tokens.append(context.token_context.token_id)

    log StakingCompound(msg.sender, nft_contract_addr, tokens)


@external
def claim(token_contexts: DynArray[TokenContext, 32]):

    """
    @notice Claim the rental rewards for multiple NFTs
    @dev Iterates over token contexts to claim rewards for each expired rental. The rental rewards and any previous unclaimed rewards are transferred to the NFT owner and the protocol fees are accrued.
    @param token_contexts An array of token contexts, each containing the rental state for an NFT.
    """

    reward_logs: DynArray[RewardLog, 32] = []

    for token_context in token_contexts:
        assert self._is_context_valid(token_context), "invalid context"
        assert token_context.nft_owner == msg.sender, "not owner"

        result_active_rental: Rental = self._consolidate_claims(token_context.token_id, token_context.nft_owner, token_context.active_rental)

        reward_logs.append(RewardLog({
            token_id: token_context.token_id,
            active_rental_amount: result_active_rental.amount
        }))

    rewards_to_claim: uint256 = self.unclaimed_rewards[msg.sender]

    # transfer reward to nft owner
    assert rewards_to_claim > 0, "no rewards to claim"
    assert payment_token.transfer(msg.sender, rewards_to_claim), "transfer failed"
    self.unclaimed_rewards[msg.sender] = 0

    log RewardsClaimed(msg.sender, nft_contract_addr, rewards_to_claim, self.protocol_fees_amount, reward_logs)


@view
@external
def claimable_rewards(nft_owner: address, token_contexts: DynArray[TokenContext, 32]) -> uint256:

    """
    @notice Compute the claimable rewards for a given NFT owner
    @dev Iterates over token contexts to compute the claimable rewards for each expired rental, wich are then summed up to any previous unclaimed rewards.
    @param nft_owner The address of the NFT owner.
    @param token_contexts An array of token contexts, each containing the rental state for an NFT.
    @return The claimable rewards for the given NFT owner.
    """

    rewards: uint256 = self.unclaimed_rewards[nft_owner]
    for context in token_contexts:
        assert self._is_context_valid(context), "invalid context"
        assert context.nft_owner == nft_owner, "not owner"
        if context.active_rental.expiration < block.timestamp:
            rewards += context.active_rental.amount * (10000 - context.active_rental.protocol_fee) / 10000
    return rewards


@external
def claim_token_ownership(token_contexts: DynArray[TokenContext, 32]):

    """
    @notice Allow the owner of rental ERC721 tokens to claim the ownership of the underlying NFTs
    @dev Iterates over token contexts to claim the ownership of each NFT. The ownership is transferred to the NFT owner.
    @param token_contexts An array of token contexts, each containing the rental state for an NFT.
    """

    tokens: DynArray[uint256, 32] = empty(DynArray[uint256, 32])

    for token_context in token_contexts:
        assert self._is_context_valid(token_context), "invalid context"
        assert renting_erc721.ownerOf(token_context.token_id) == msg.sender, "not owner"
        self._store_token_state(token_context.token_id, msg.sender, token_context.active_rental)
        tokens.append(token_context.token_id)

    log TokenOwnershipChanged(msg.sender, nft_contract_addr, tokens)


@external
def claim_fees():

    """
    @notice Claim the accrued protocol fees
    @dev Transfers the accrued protocol fees to the protocol wallet and logs the event.
    """

    assert msg.sender == self.protocol_admin, "not admin"
    protocol_fees_amount: uint256 = self.protocol_fees_amount
    self.protocol_fees_amount = 0
    self._transfer_payment_token(self.protocol_wallet, protocol_fees_amount)
    log FeesClaimed(self.protocol_wallet, protocol_fees_amount)


@external
def set_protocol_fee(protocol_fee: uint256):

    """
    @notice Set the protocol fee
    @dev Sets the protocol fee to the given value and logs the event. Admin function.
    @param protocol_fee The new protocol fee.
    """

    assert msg.sender == self.protocol_admin, "not protocol admin"
    assert protocol_fee <= max_protocol_fee, "protocol fee > max fee"

    log ProtocolFeeSet(self.protocol_fee, protocol_fee, self.protocol_wallet)
    self.protocol_fee = protocol_fee


@external
def change_protocol_wallet(new_protocol_wallet: address):

    """
    @notice Change the protocol wallet
    @dev Changes the protocol wallet to the given address and logs the event. Admin function.
    @param new_protocol_wallet The new protocol wallet.
    """

    assert msg.sender == self.protocol_admin, "not protocol admin"
    assert new_protocol_wallet != empty(address), "wallet is the zero address"

    log ProtocolWalletChanged(self.protocol_wallet, new_protocol_wallet)
    self.protocol_wallet = new_protocol_wallet


@external
def set_paused(paused: bool):

    """
    @notice Pause or unpause the contract
    @dev Pauses or unpauses the contract and logs the event. Admin function.
    @param paused The new paused state.
    """

    assert msg.sender == self.protocol_admin, "not protocol admin"

    log PauseStateSet(self.paused, paused)

    self.paused = paused


@external
def set_staking_addr(staking_addr: address):

    """
    @notice Set the staking pool address
    @dev Sets the staking pool address to the given value and logs the event. Admin function.
    @param staking_addr The new staking pool address.
    """

    assert msg.sender == self.protocol_admin, "not protocol admin"
    log StakingAddressSet(self.staking_addr, staking_addr)
    self.staking_addr = staking_addr


@external
def propose_admin(_address: address):

    """
    @notice Propose a new admin
    @dev Proposes a new admin and logs the event. Admin function.
    @param _address The address of the proposed admin.
    """

    assert msg.sender == self.protocol_admin, "not the admin"
    assert _address != empty(address), "_address is the zero address"

    log AdminProposed(self.protocol_admin, _address)
    self.proposed_admin = _address


@external
def claim_ownership():

    """
    @notice Claim the ownership of the contract
    @dev Claims the ownership of the contract and logs the event. Requires the caller to be the proposed admin.
    """

    assert msg.sender == self.proposed_admin, "not the proposed"

    log OwnershipTransferred(self.protocol_admin, self.proposed_admin)
    self.protocol_admin = self.proposed_admin
    self.proposed_admin = empty(address)


@view
@external
def tokenid_to_vault(token_id: uint256) -> address:

    """
    @notice Get the vault address for a given token id
    @dev Computes the vault address for the given token id and returns it.
    @param token_id The token id.
    @return The vault address for the given token id.
    """

    return self._tokenid_to_vault(token_id)


@pure
@external
def supportsInterface(interface_id: bytes4) -> bool:
    """
    @notice Check if the contract supports the given interface, as defined in ERC-165
    @dev Checks if the contract supports the given interface and returns true if it does.
    @param interface_id The interface id.
    @return True if the contract supports the given interface.
    """
    return interface_id in SUPPORTED_INTERFACES


@view
@internal
def _tokenid_to_vault(token_id: uint256) -> address:
    return self._compute_address(
        convert(token_id, bytes32),
        keccak256(concat(
            _DEPLOYMENT_CODE,
            _PRE,
            convert(vault_impl_addr, bytes20),
            _POST
        )),
        self
    )


@pure
@internal
def _state_hash(token_id: uint256, nft_owner: address, rental: Rental) -> bytes32:
    return keccak256(
        concat(
            convert(token_id, bytes32),
            convert(nft_owner, bytes32),
            rental.id,
            convert(rental.owner, bytes32),
            convert(rental.renter, bytes32),
            convert(rental.delegate, bytes32),  #should this be part of state?
            convert(rental.token_id, bytes32),
            convert(rental.start, bytes32),
            convert(rental.min_expiration, bytes32),
            convert(rental.expiration, bytes32),
            convert(rental.amount, bytes32),
            convert(rental.protocol_fee, bytes32),
        )
    )


@pure
@internal
def _compute_address(salt: bytes32, bytecode_hash: bytes32, deployer: address) -> address:
    data: bytes32 = keccak256(concat(_COLLISION_OFFSET, convert(deployer, bytes20), salt, bytecode_hash))
    return self._convert_keccak256_2_address(data)


@pure
@internal
def _convert_keccak256_2_address(digest: bytes32) -> address:
    return convert(convert(digest, uint256) & convert(max_value(uint160), uint256), address)


@view
@internal
def _is_rental_active(rental: Rental) -> bool:
    return rental.expiration > block.timestamp


@view
@internal
def _is_context_valid(context: TokenContext) -> bool:
    """ Check if the context is valid, also meaning that the token is deposited """
    return self.rental_states[context.token_id] == self._state_hash(context.token_id, context.nft_owner, context.active_rental)


@internal
def _store_token_state(token_id: uint256, nft_owner: address, rental: Rental):
    self.rental_states[token_id] = self._state_hash(token_id, nft_owner, rental)


@internal
def _clear_token_state(token_id: uint256):
    self.rental_states[token_id] = empty(bytes32)


@internal
def _get_vault(token_id: uint256) -> IVault:
    vault: address = self._tokenid_to_vault(token_id)
    assert vault.is_contract, "no vault exists for token_id"
    return IVault(vault)


@internal
def _create_vault(token_id: uint256) -> IVault:
    # only creates a vault if needed
    vault: address = self._tokenid_to_vault(token_id)
    if not vault.is_contract:
        vault = create_minimal_proxy_to(vault_impl_addr, salt=convert(token_id, bytes32))
        IVault(vault).initialise()

    return IVault(vault)


@internal
def _transfer_payment_token(_to: address, _amount: uint256):
    assert payment_token.transfer(_to, _amount), "transferFrom failed"


@internal
def _receive_payment_token(_from: address, _amount: uint256):
    assert payment_token.transferFrom(_from, self, _amount), "transferFrom failed"


@pure
@internal
def _compute_rental_id(renter: address, token_id: uint256, start: uint256, expiration: uint256) -> bytes32:
    return keccak256(concat(convert(renter, bytes32), convert(token_id, bytes32), convert(start, bytes32), convert(expiration, bytes32)))

@pure
@internal
def _compute_rental_amount(start: uint256, expiration: uint256, price: uint256) -> uint256:
    return (expiration - start) * price / 3600


@pure
@internal
def _compute_real_rental_amount(duration: uint256, real_duration: uint256, rental_amount: uint256) -> uint256:
    return rental_amount * real_duration / duration


@internal
def _check_not_paused():
    assert not self.paused, "paused"


@internal
def _consolidate_claims(token_id: uint256, nft_owner: address, active_rental: Rental, store_state: bool = True) -> Rental:
    if active_rental.amount == 0 or active_rental.expiration >= block.timestamp:
        return active_rental
    else:
        protocol_fee_amount: uint256 = active_rental.amount * active_rental.protocol_fee / 10000

        self.unclaimed_rewards[active_rental.owner] += active_rental.amount - protocol_fee_amount
        self.protocol_fees_amount += protocol_fee_amount

        new_rental: Rental = Rental({
            id: active_rental.id,
            owner: active_rental.owner,
            renter: active_rental.renter,
            delegate: active_rental.delegate,
            token_id: token_id,
            start: active_rental.start,
            min_expiration: active_rental.min_expiration,
            expiration: active_rental.expiration,
            amount: 0,
            protocol_fee: active_rental.protocol_fee,
        })

        if store_state:
            self._store_token_state(token_id, nft_owner, new_rental)

        return new_rental


@internal
def _check_valid_listing(token_id: uint256, signed_listing: SignedListing, signature_timestamp:uint256, nft_owner: address):
    assert token_id == signed_listing.listing.token_id, "invalid token_id"
    assert self._is_listing_signed_by_owner(signed_listing, nft_owner), "invalid owner signature"
    assert self._is_listing_signed_by_admin(signed_listing, signature_timestamp), "invalid admin signature"
    assert signature_timestamp + LISTINGS_SIGNATURE_VALID_PERIOD > block.timestamp, "listing expired"
    assert self.listing_revocations[signed_listing.listing.token_id] < signed_listing.listing.timestamp, "listing revoked"


@internal
def _is_within_duration_range(listing: Listing, duration: uint256) -> bool:
    return duration >= listing.min_duration and (listing.max_duration == 0 or duration <= listing.max_duration)


@internal
def _is_listing_signed_by_owner(signed_listing: SignedListing, owner: address) -> bool:
    return ecrecover(
        keccak256(
            concat(
                convert("\x19\x01", Bytes[2]),
                _abi_encode(
                    listing_sig_domain_separator,
                    keccak256(_abi_encode(LISTING_TYPE_HASH, signed_listing.listing))
                )
            )
        ),
        signed_listing.owner_signature.v,
        signed_listing.owner_signature.r,
        signed_listing.owner_signature.s
    ) == owner


@internal
def _is_listing_signed_by_admin(signed_listing: SignedListing, signature_timestamp: uint256) -> bool:
    return ecrecover(
        keccak256(
            concat(
                convert("\x19\x00", Bytes[2]),
                convert(self, bytes20),
                keccak256(_abi_encode(signed_listing.owner_signature)),
                convert(signature_timestamp, bytes32)
            )
        ),
        signed_listing.admin_signature.v,
        signed_listing.admin_signature.r,
        signed_listing.admin_signature.s
    ) == self.protocol_admin

Contract Security Audit

Contract ABI

[{"name":"NftsDeposited","inputs":[{"name":"owner","type":"address","indexed":false},{"name":"nft_contract","type":"address","indexed":false},{"name":"vaults","type":"tuple[]","components":[{"name":"vault","type":"address"},{"name":"token_id","type":"uint256"}],"indexed":false},{"name":"delegate","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"NftsWithdrawn","inputs":[{"name":"owner","type":"address","indexed":false},{"name":"nft_contract","type":"address","indexed":false},{"name":"total_rewards","type":"uint256","indexed":false},{"name":"withdrawals","type":"tuple[]","components":[{"name":"vault","type":"address"},{"name":"token_id","type":"uint256"}],"indexed":false}],"anonymous":false,"type":"event"},{"name":"DelegatedToWallet","inputs":[{"name":"owner","type":"address","indexed":false},{"name":"delegate","type":"address","indexed":false},{"name":"nft_contract","type":"address","indexed":false},{"name":"vaults","type":"tuple[]","components":[{"name":"vault","type":"address"},{"name":"token_id","type":"uint256"}],"indexed":false}],"anonymous":false,"type":"event"},{"name":"RenterDelegatedToWallet","inputs":[{"name":"renter","type":"address","indexed":false},{"name":"delegate","type":"address","indexed":false},{"name":"nft_contract","type":"address","indexed":false},{"name":"vaults","type":"tuple[]","components":[{"name":"vault","type":"address"},{"name":"token_id","type":"uint256"}],"indexed":false}],"anonymous":false,"type":"event"},{"name":"ListingsRevoked","inputs":[{"name":"owner","type":"address","indexed":false},{"name":"timestamp","type":"uint256","indexed":false},{"name":"token_ids","type":"uint256[]","indexed":false}],"anonymous":false,"type":"event"},{"name":"RentalStarted","inputs":[{"name":"renter","type":"address","indexed":false},{"name":"delegate","type":"address","indexed":false},{"name":"nft_contract","type":"address","indexed":false},{"name":"rentals","type":"tuple[]","components":[{"name":"id","type":"bytes32"},{"name":"vault","type":"address"},{"name":"owner","type":"address"},{"name":"token_id","type":"uint256"},{"name":"start","type":"uint256"},{"name":"min_expiration","type":"uint256"},{"name":"expiration","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"protocol_fee","type":"uint256"}],"indexed":false}],"anonymous":false,"type":"event"},{"name":"RentalClosed","inputs":[{"name":"renter","type":"address","indexed":false},{"name":"nft_contract","type":"address","indexed":false},{"name":"rentals","type":"tuple[]","components":[{"name":"id","type":"bytes32"},{"name":"vault","type":"address"},{"name":"owner","type":"address"},{"name":"token_id","type":"uint256"},{"name":"start","type":"uint256"},{"name":"min_expiration","type":"uint256"},{"name":"expiration","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"protocol_fee","type":"uint256"}],"indexed":false}],"anonymous":false,"type":"event"},{"name":"RentalExtended","inputs":[{"name":"renter","type":"address","indexed":false},{"name":"nft_contract","type":"address","indexed":false},{"name":"rentals","type":"tuple[]","components":[{"name":"id","type":"bytes32"},{"name":"vault","type":"address"},{"name":"owner","type":"address"},{"name":"token_id","type":"uint256"},{"name":"start","type":"uint256"},{"name":"min_expiration","type":"uint256"},{"name":"expiration","type":"uint256"},{"name":"amount_settled","type":"uint256"},{"name":"extension_amount","type":"uint256"},{"name":"protocol_fee","type":"uint256"}],"indexed":false}],"anonymous":false,"type":"event"},{"name":"RewardsClaimed","inputs":[{"name":"owner","type":"address","indexed":false},{"name":"nft_contract","type":"address","indexed":false},{"name":"amount","type":"uint256","indexed":false},{"name":"protocol_fee_amount","type":"uint256","indexed":false},{"name":"rewards","type":"tuple[]","components":[{"name":"token_id","type":"uint256"},{"name":"active_rental_amount","type":"uint256"}],"indexed":false}],"anonymous":false,"type":"event"},{"name":"TokenOwnershipChanged","inputs":[{"name":"new_owner","type":"address","indexed":false},{"name":"nft_contract","type":"address","indexed":false},{"name":"tokens","type":"uint256[]","indexed":false}],"anonymous":false,"type":"event"},{"name":"ProtocolFeeSet","inputs":[{"name":"old_fee","type":"uint256","indexed":false},{"name":"new_fee","type":"uint256","indexed":false},{"name":"fee_wallet","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"ProtocolWalletChanged","inputs":[{"name":"old_wallet","type":"address","indexed":false},{"name":"new_wallet","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"StakingAddressSet","inputs":[{"name":"old_value","type":"address","indexed":false},{"name":"new_value","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"AdminProposed","inputs":[{"name":"admin","type":"address","indexed":false},{"name":"proposed_admin","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"OwnershipTransferred","inputs":[{"name":"old_admin","type":"address","indexed":false},{"name":"new_admin","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"StakingDeposit","inputs":[{"name":"owner","type":"address","indexed":false},{"name":"nft_contract","type":"address","indexed":false},{"name":"tokens","type":"tuple[]","components":[{"name":"token_id","type":"uint256"},{"name":"amount","type":"uint256"}],"indexed":false}],"anonymous":false,"type":"event"},{"name":"StakingWithdraw","inputs":[{"name":"owner","type":"address","indexed":false},{"name":"nft_contract","type":"address","indexed":false},{"name":"recipient","type":"address","indexed":false},{"name":"tokens","type":"tuple[]","components":[{"name":"token_id","type":"uint256"},{"name":"amount","type":"uint256"}],"indexed":false}],"anonymous":false,"type":"event"},{"name":"StakingClaim","inputs":[{"name":"owner","type":"address","indexed":false},{"name":"nft_contract","type":"address","indexed":false},{"name":"recipient","type":"address","indexed":false},{"name":"tokens","type":"uint256[]","indexed":false}],"anonymous":false,"type":"event"},{"name":"StakingCompound","inputs":[{"name":"owner","type":"address","indexed":false},{"name":"nft_contract","type":"address","indexed":false},{"name":"tokens","type":"uint256[]","indexed":false}],"anonymous":false,"type":"event"},{"name":"FeesClaimed","inputs":[{"name":"fee_wallet","type":"address","indexed":false},{"name":"amount","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"PauseStateSet","inputs":[{"name":"old_value","type":"bool","indexed":false},{"name":"new_value","type":"bool","indexed":false}],"anonymous":false,"type":"event"},{"stateMutability":"nonpayable","type":"constructor","inputs":[{"name":"_vault_impl_addr","type":"address"},{"name":"_payment_token_addr","type":"address"},{"name":"_nft_contract_addr","type":"address"},{"name":"_delegation_registry_addr","type":"address"},{"name":"_renting_erc721","type":"address"},{"name":"_staking_addr","type":"address"},{"name":"_max_protocol_fee","type":"uint256"},{"name":"_protocol_fee","type":"uint256"},{"name":"_protocol_wallet","type":"address"},{"name":"_protocol_admin","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"delegate_to_wallet","inputs":[{"name":"token_contexts","type":"tuple[]","components":[{"name":"token_id","type":"uint256"},{"name":"nft_owner","type":"address"},{"name":"active_rental","type":"tuple","components":[{"name":"id","type":"bytes32"},{"name":"owner","type":"address"},{"name":"renter","type":"address"},{"name":"delegate","type":"address"},{"name":"token_id","type":"uint256"},{"name":"start","type":"uint256"},{"name":"min_expiration","type":"uint256"},{"name":"expiration","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"protocol_fee","type":"uint256"}]}]},{"name":"delegate","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"renter_delegate_to_wallet","inputs":[{"name":"token_contexts","type":"tuple[]","components":[{"name":"token_id","type":"uint256"},{"name":"nft_owner","type":"address"},{"name":"active_rental","type":"tuple","components":[{"name":"id","type":"bytes32"},{"name":"owner","type":"address"},{"name":"renter","type":"address"},{"name":"delegate","type":"address"},{"name":"token_id","type":"uint256"},{"name":"start","type":"uint256"},{"name":"min_expiration","type":"uint256"},{"name":"expiration","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"protocol_fee","type":"uint256"}]}]},{"name":"delegate","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"deposit","inputs":[{"name":"token_ids","type":"uint256[]"},{"name":"delegate","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"mint","inputs":[{"name":"token_contexts","type":"tuple[]","components":[{"name":"token_id","type":"uint256"},{"name":"nft_owner","type":"address"},{"name":"active_rental","type":"tuple","components":[{"name":"id","type":"bytes32"},{"name":"owner","type":"address"},{"name":"renter","type":"address"},{"name":"delegate","type":"address"},{"name":"token_id","type":"uint256"},{"name":"start","type":"uint256"},{"name":"min_expiration","type":"uint256"},{"name":"expiration","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"protocol_fee","type":"uint256"}]}]}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"revoke_listing","inputs":[{"name":"token_contexts","type":"tuple[]","components":[{"name":"token_id","type":"uint256"},{"name":"nft_owner","type":"address"},{"name":"active_rental","type":"tuple","components":[{"name":"id","type":"bytes32"},{"name":"owner","type":"address"},{"name":"renter","type":"address"},{"name":"delegate","type":"address"},{"name":"token_id","type":"uint256"},{"name":"start","type":"uint256"},{"name":"min_expiration","type":"uint256"},{"name":"expiration","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"protocol_fee","type":"uint256"}]}]}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"start_rentals","inputs":[{"name":"token_contexts","type":"tuple[]","components":[{"name":"token_context","type":"tuple","components":[{"name":"token_id","type":"uint256"},{"name":"nft_owner","type":"address"},{"name":"active_rental","type":"tuple","components":[{"name":"id","type":"bytes32"},{"name":"owner","type":"address"},{"name":"renter","type":"address"},{"name":"delegate","type":"address"},{"name":"token_id","type":"uint256"},{"name":"start","type":"uint256"},{"name":"min_expiration","type":"uint256"},{"name":"expiration","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"protocol_fee","type":"uint256"}]}]},{"name":"signed_listing","type":"tuple","components":[{"name":"listing","type":"tuple","components":[{"name":"token_id","type":"uint256"},{"name":"price","type":"uint256"},{"name":"min_duration","type":"uint256"},{"name":"max_duration","type":"uint256"},{"name":"timestamp","type":"uint256"}]},{"name":"owner_signature","type":"tuple","components":[{"name":"v","type":"uint256"},{"name":"r","type":"uint256"},{"name":"s","type":"uint256"}]},{"name":"admin_signature","type":"tuple","components":[{"name":"v","type":"uint256"},{"name":"r","type":"uint256"},{"name":"s","type":"uint256"}]}]},{"name":"duration","type":"uint256"}]},{"name":"delegate","type":"address"},{"name":"signature_timestamp","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"close_rentals","inputs":[{"name":"token_contexts","type":"tuple[]","components":[{"name":"token_id","type":"uint256"},{"name":"nft_owner","type":"address"},{"name":"active_rental","type":"tuple","components":[{"name":"id","type":"bytes32"},{"name":"owner","type":"address"},{"name":"renter","type":"address"},{"name":"delegate","type":"address"},{"name":"token_id","type":"uint256"},{"name":"start","type":"uint256"},{"name":"min_expiration","type":"uint256"},{"name":"expiration","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"protocol_fee","type":"uint256"}]}]}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"extend_rentals","inputs":[{"name":"token_contexts","type":"tuple[]","components":[{"name":"token_context","type":"tuple","components":[{"name":"token_id","type":"uint256"},{"name":"nft_owner","type":"address"},{"name":"active_rental","type":"tuple","components":[{"name":"id","type":"bytes32"},{"name":"owner","type":"address"},{"name":"renter","type":"address"},{"name":"delegate","type":"address"},{"name":"token_id","type":"uint256"},{"name":"start","type":"uint256"},{"name":"min_expiration","type":"uint256"},{"name":"expiration","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"protocol_fee","type":"uint256"}]}]},{"name":"signed_listing","type":"tuple","components":[{"name":"listing","type":"tuple","components":[{"name":"token_id","type":"uint256"},{"name":"price","type":"uint256"},{"name":"min_duration","type":"uint256"},{"name":"max_duration","type":"uint256"},{"name":"timestamp","type":"uint256"}]},{"name":"owner_signature","type":"tuple","components":[{"name":"v","type":"uint256"},{"name":"r","type":"uint256"},{"name":"s","type":"uint256"}]},{"name":"admin_signature","type":"tuple","components":[{"name":"v","type":"uint256"},{"name":"r","type":"uint256"},{"name":"s","type":"uint256"}]}]},{"name":"duration","type":"uint256"}]},{"name":"signature_timestamp","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"withdraw","inputs":[{"name":"token_contexts","type":"tuple[]","components":[{"name":"token_id","type":"uint256"},{"name":"nft_owner","type":"address"},{"name":"active_rental","type":"tuple","components":[{"name":"id","type":"bytes32"},{"name":"owner","type":"address"},{"name":"renter","type":"address"},{"name":"delegate","type":"address"},{"name":"token_id","type":"uint256"},{"name":"start","type":"uint256"},{"name":"min_expiration","type":"uint256"},{"name":"expiration","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"protocol_fee","type":"uint256"}]}]}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"stake_deposit","inputs":[{"name":"token_contexts","type":"tuple[]","components":[{"name":"token_context","type":"tuple","components":[{"name":"token_id","type":"uint256"},{"name":"nft_owner","type":"address"},{"name":"active_rental","type":"tuple","components":[{"name":"id","type":"bytes32"},{"name":"owner","type":"address"},{"name":"renter","type":"address"},{"name":"delegate","type":"address"},{"name":"token_id","type":"uint256"},{"name":"start","type":"uint256"},{"name":"min_expiration","type":"uint256"},{"name":"expiration","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"protocol_fee","type":"uint256"}]}]},{"name":"amount","type":"uint256"}]},{"name":"pool_method_id","type":"bytes4"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"stake_withdraw","inputs":[{"name":"token_contexts","type":"tuple[]","components":[{"name":"token_context","type":"tuple","components":[{"name":"token_id","type":"uint256"},{"name":"nft_owner","type":"address"},{"name":"active_rental","type":"tuple","components":[{"name":"id","type":"bytes32"},{"name":"owner","type":"address"},{"name":"renter","type":"address"},{"name":"delegate","type":"address"},{"name":"token_id","type":"uint256"},{"name":"start","type":"uint256"},{"name":"min_expiration","type":"uint256"},{"name":"expiration","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"protocol_fee","type":"uint256"}]}]},{"name":"amount","type":"uint256"}]},{"name":"recipient","type":"address"},{"name":"pool_method_id","type":"bytes4"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"stake_claim","inputs":[{"name":"token_contexts","type":"tuple[]","components":[{"name":"token_context","type":"tuple","components":[{"name":"token_id","type":"uint256"},{"name":"nft_owner","type":"address"},{"name":"active_rental","type":"tuple","components":[{"name":"id","type":"bytes32"},{"name":"owner","type":"address"},{"name":"renter","type":"address"},{"name":"delegate","type":"address"},{"name":"token_id","type":"uint256"},{"name":"start","type":"uint256"},{"name":"min_expiration","type":"uint256"},{"name":"expiration","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"protocol_fee","type":"uint256"}]}]},{"name":"amount","type":"uint256"}]},{"name":"recipient","type":"address"},{"name":"pool_method_id","type":"bytes4"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"stake_compound","inputs":[{"name":"token_contexts","type":"tuple[]","components":[{"name":"token_context","type":"tuple","components":[{"name":"token_id","type":"uint256"},{"name":"nft_owner","type":"address"},{"name":"active_rental","type":"tuple","components":[{"name":"id","type":"bytes32"},{"name":"owner","type":"address"},{"name":"renter","type":"address"},{"name":"delegate","type":"address"},{"name":"token_id","type":"uint256"},{"name":"start","type":"uint256"},{"name":"min_expiration","type":"uint256"},{"name":"expiration","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"protocol_fee","type":"uint256"}]}]},{"name":"amount","type":"uint256"}]},{"name":"pool_claim_method_id","type":"bytes4"},{"name":"pool_deposit_method_id","type":"bytes4"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"claim","inputs":[{"name":"token_contexts","type":"tuple[]","components":[{"name":"token_id","type":"uint256"},{"name":"nft_owner","type":"address"},{"name":"active_rental","type":"tuple","components":[{"name":"id","type":"bytes32"},{"name":"owner","type":"address"},{"name":"renter","type":"address"},{"name":"delegate","type":"address"},{"name":"token_id","type":"uint256"},{"name":"start","type":"uint256"},{"name":"min_expiration","type":"uint256"},{"name":"expiration","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"protocol_fee","type":"uint256"}]}]}],"outputs":[]},{"stateMutability":"view","type":"function","name":"claimable_rewards","inputs":[{"name":"nft_owner","type":"address"},{"name":"token_contexts","type":"tuple[]","components":[{"name":"token_id","type":"uint256"},{"name":"nft_owner","type":"address"},{"name":"active_rental","type":"tuple","components":[{"name":"id","type":"bytes32"},{"name":"owner","type":"address"},{"name":"renter","type":"address"},{"name":"delegate","type":"address"},{"name":"token_id","type":"uint256"},{"name":"start","type":"uint256"},{"name":"min_expiration","type":"uint256"},{"name":"expiration","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"protocol_fee","type":"uint256"}]}]}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"claim_token_ownership","inputs":[{"name":"token_contexts","type":"tuple[]","components":[{"name":"token_id","type":"uint256"},{"name":"nft_owner","type":"address"},{"name":"active_rental","type":"tuple","components":[{"name":"id","type":"bytes32"},{"name":"owner","type":"address"},{"name":"renter","type":"address"},{"name":"delegate","type":"address"},{"name":"token_id","type":"uint256"},{"name":"start","type":"uint256"},{"name":"min_expiration","type":"uint256"},{"name":"expiration","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"protocol_fee","type":"uint256"}]}]}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"claim_fees","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"set_protocol_fee","inputs":[{"name":"protocol_fee","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"change_protocol_wallet","inputs":[{"name":"new_protocol_wallet","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"set_paused","inputs":[{"name":"paused","type":"bool"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"set_staking_addr","inputs":[{"name":"staking_addr","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"propose_admin","inputs":[{"name":"_address","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"claim_ownership","inputs":[],"outputs":[]},{"stateMutability":"view","type":"function","name":"tokenid_to_vault","inputs":[{"name":"token_id","type":"uint256"}],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"pure","type":"function","name":"supportsInterface","inputs":[{"name":"interface_id","type":"bytes4"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"vault_impl_addr","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"payment_token","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"nft_contract_addr","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"delegation_registry_addr","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"staking_addr","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"renting_erc721","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"max_protocol_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"protocol_wallet","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"protocol_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"protocol_admin","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"proposed_admin","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"rental_states","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"bytes32"}]},{"stateMutability":"view","type":"function","name":"listing_revocations","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"unclaimed_rewards","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"protocol_fees_amount","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"paused","inputs":[],"outputs":[{"name":"","type":"bool"}]}]

615f815150346105b75760206164925f395f518060a01c6105b75760405260206164b25f395f518060a01c6105b75760605260206164d25f395f518060a01c6105b75760805260206164f25f395f518060a01c6105b75760a05260206165125f395f518060a01c6105b75760c05260206165325f395f518060a01c6105b75760e05260206165925f395f518060a01c6105b7576101005260206165b25f395f518060a01c6105b7576101205260405161011757601b610140527f7661756c7420696d706c20697320746865207a65726f206164647200000000006101605261014050610140518061016001601f825f031636823750506308c379a061010052602061012052601f19601f61014051011660440161011cfd5b60605161018357601e610140527f7061796d656e7420746f6b656e20697320746865207a65726f206164647200006101605261014050610140518061016001601f825f031636823750506308c379a061010052602061012052601f19601f61014051011660440161011cfd5b6080516101ef57601d610140527f6e667420636f6e747261637420697320746865207a65726f20616464720000006101605261014050610140518061016001601f825f031636823750506308c379a061010052602061012052601f19601f61014051011660440161011cfd5b60a05161025b57601f610140527f64656c656720726567697374727920697320746865207a65726f2061646472006101605261014050610140518061016001601f825f031636823750506308c379a061010052602061012052601f19601f61014051011660440161011cfd5b60c0516102c757601f610140527f72656e74696e675f65726337323120697320746865207a65726f2061646472006101605261014050610140518061016001601f825f031636823750506308c379a061010052602061012052601f19601f61014051011660440161011cfd5b61271060206165525f395f51111561033e576017610140527f6d61782070726f746f636f6c20666565203e20313030250000000000000000006101605261014050610140518061016001601f825f031636823750506308c379a061010052602061012052601f19601f61014051011660440161011cfd5b60206165525f395f5160206165725f395f5111156103bb576016610140527f70726f746f636f6c20666565203e206d617820666565000000000000000000006101605261014050610140518061016001601f825f031636823750506308c379a061010052602061012052601f19601f61014051011660440161011cfd5b61010051610428576017610140527f70726f746f636f6c2077616c6c6574206e6f74207365740000000000000000006101605261014050610140518061016001601f825f031636823750506308c379a061010052602061012052601f19601f61014051011660440161011cfd5b61012051610495576014610140527f61646d696e2077616c6c6574206e6f74207365740000000000000000000000006101605261014050610140518061016001601f825f031636823750506308c379a061010052602061012052601f19601f61014051011660440161011cfd5b604051615ee152606051615f0152608051615f215260a051615f415260206165525f395f51615f815260c051615f615260e0515f556101005160015560206165725f395f51600255610120516003555f6009557f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f610160527f8cfe527f02f4c08ff029d82debdef92d77938d41c05f0919d733c8091bf9b8d8610180527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66101a052466101c052306101e05260a061014052610140805160208201209050615ec152615f615163592e6f5961014052803b156105b7575f610140600461015c5f855af16105a4573d5f5f3e3d5ffd5b50615ec16105bb61000039615fa1610000f35b5f80fd5f3560e01c60026022820660011b615e7d01601e395f51565b63fe80cbc081186100365734615e79576020615ee160403960206040f35b638afbd8ce811861517d5734615e79576020615f4160403960206040f361517d565b63331c6587811861517d5734615e79576020615f0160403960206040f361517d565b6304cca53b81186100985734615e79576020615f2160403960206040f35b633ffd45b7811861015957602436103417615e79576004358060a01c615e79576040526003543318156101215760126060527f6e6f742070726f746f636f6c2061646d696e000000000000000000000000000060805260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b7f705cd0c010fe71835c798c37a9b8ba0340aa60d9dcd5e8981ea2dfd4880368685f5460605260405160805260406060a16040515f55005b635f11b0a1811861517d57602436103417615e79576004358060a01c615e79576040526003543318156101e257600d6060527f6e6f74207468652061646d696e0000000000000000000000000000000000000060805260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b60405161024557601c6060527f5f6164647265737320697320746865207a65726f20616464726573730000000060805260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b7ffd22260ca7b3d2a5f6332770491ab546b6235bc73909c334f5e304d2fae455b160035460605260405160805260406060a16040516004550061517d565b63f728b1d8811861029e5734615e79575f5460405260206040f35b63baa24c12811861517d5734615e795760035433181561031d576009610140527f6e6f742061646d696e00000000000000000000000000000000000000000000006101605261014050610140518061016001601f825f031636823750506308c379a061010052602061012052601f19601f61014051011660440161011cfd5b600854610140525f6008556001546040526101405160605261033d615daf565b7f9493e5bbe4e8e0ac67284469a2d677403d0378a85a59e341d3abc433d0d9a2096001546101605261014051610180526040610160a10061517d565b630bfab6bb81186103975734615e79576020615f6160403960206040f35b63abf61417811861517d5734615e795760045460405260206040f361517d565b635fb83221811861517d5734615e79576020615f8160403960206040f361517d565b6367db7499811861517d5734615e795760015460405260206040f361517d565b631655273281186104155734615e795760025460405260206040f35b63c9c0b69481186106c657606436103417615e79576004358060a01c615e7957610500526024356004016020813511615e795780355f8160208111615e7957801561051657905b610180810261054001610180820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e08301526101008101356101008301526101208101356101208301525050505060010181811861045c575b5050806105205250506007610500516020525f5260405f2054613540525f6105205160208111615e795780156106bd57905b6101808102610540016101806135606101808360045afa505061018061036061018061356060045afa5061057d6136e0615254565b6136e0516105ea57600f613700527f696e76616c696420636f6e7465787400000000000000000000000000000000006137205261370050613700518061372001601f825f031636823750506308c379a06136c05260206136e052601f19601f6137005101166044016136dcfd5b6105005161358051181561065d5760096136e0527f6e6f74206f776e65720000000000000000000000000000000000000000000000613700526136e0506136e0518061370001601f825f031636823750506308c379a06136a05260206136c052601f19601f6136e05101166044016136bcfd5b426136805110156106b257613540516136a0516136c05180612710036127108111615e79579050808202811583838304141715615e79579050905061271081049050808201828110615e795790509050613540525b600101818118610548575b50506020613540f35b63f7a79a02811861517d5734615e795760045433181561073b5760106040527f6e6f74207468652070726f706f7365640000000000000000000000000000000060605260405060405180606001601f825f031636823750506308c379a05f526020602052601f19601f6040510116604401601cfd5b7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060035460405260045460605260406040a16004546003555f6004550061517d565b63d9aa6924811861517d5734615e795760035460405260206040f361517d565b634931bd2981186107ca57602436103417615e795760056004356020525f5260405f205460405260206040f35b6301ffc9a7811861517d57602436103417615e79576004358060201b615e79576040526040517f01ffc9a700000000000000000000000000000000000000000000000000000000811861081e576001610843565b7f80ac58cd000000000000000000000000000000000000000000000000000000008118155b905060805260206080f361517d565b63b2815bcb811861087f57602436103417615e795760066004356020525f5260405f205460405260206040f35b63dce9d9ed8118610eb157604436103417615e79576004356004016020813511615e795780355f8160208111615e7957801561097157905b610180810261052001610180820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e0830152610100810135610100830152610120810135610120830152505050506001018181186108b7575b5050806105005250505f613520525f615940525f615960525f6105005160208111615e79578015610d3057905b6101808102610520016101806159806101808360045afa505061598051610200526109ca615b2061542d565b615b2051615b005261018061036061018061598060045afa506109ee615b20615254565b615b2051610a5b57600f615b40527f696e76616c696420636f6e746578740000000000000000000000000000000000615b6052615b4050615b405180615b6001601f825f031636823750506308c379a0615b00526020615b2052601f19601f615b40510116604401615b1cfd5b61014060406101406159c060045afa50610a76615b20615297565b615b2051610ae357601c615b40527f6163746976652072656e74616c20646f6573206e6f7420657869737400000000615b6052615b4050615b405180615b6001601f825f031636823750506308c379a0615b00526020615b2052601f19601f615b40510116604401615b1cfd5b615a0051331815610b5357601b615b20527f6e6f742072656e746572206f66206163746976652072656e74616c0000000000615b4052615b2050615b205180615b4001601f825f031636823750506308c379a0615ae0526020615b0052601f19601f615b20510116604401615afcfd5b42615b2052615a8051421015610b6c57615a8051615b20525b615aa051615a6051808203828111615e795790509050604052615b2051615a6051808203828111615e795790509050606052615ac051608052610bb0615b60615d80565b615b6051615b4052615ac051615b4051808203828111615e795790509050615b605261596051615b6051808201828110615e79579050905061596052615b4051615ae051808202811583838304141715615e79579050905061271081049050615b805261594051615b8051808201828110615e7957905090506159405261598051610360526159a05161038052610140366103a037610c4d6154bf565b60076159a0516020525f5260405f208054615b4051615b8051808203828111615e795790509050808201828110615e795790509050815550615b00516395941b73615ba052604036615bc037803b15615e79575f615ba06044615bbc5f855af1610cb9573d5f5f3e3d5ffd5b5061352051601f8111615e79576101208102613540016159c0518152615b005160208201526159e0516040820152615a40516060820152615a60516080820152615a805160a08201524260c0820152615b405160e0820152615ae0516101008201525060018101613520525060010181811861099e575b50506020615f015f395f5163a9059cbb61598052336159a052615960516159c0526020615980604461599c5f855af1610d6b573d5f5f3e3d5ffd5b60203d10615e7957615980518060011c615e79576159e0526159e0905051610df257600f615a00527f7472616e73666572206661696c65640000000000000000000000000000000000615a2052615a0050615a005180615a2001601f825f031636823750506308c379a06159c05260206159e052601f19601f615a005101166044016159dcfd5b6159405115610e145760085461594051808201828110615e7957905090506008555b7f73ff4b2da3afbf85c00543bcb289f888bb1a6a72dd3511fe075808a97ca20ecd606033615980526020615f216159a039806159c05280615980015f6135205180835261012081025f8260208111615e79578015610e9b57905b61012081026135400161012082026020880101610120816101208460045afa505050600101818118610e6e575b50508201602001915050905081019050615980a1005b63e4fbd50b811861517d57608436103417615e79576004356004016020813511615e795780355f8160208111615e79578015610faf57905b6101a08102610520016101a0820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e083015261010081013561010083015261012081013561012083015250506101808101356101808301525050600101818118610ee9575b5050806105005250506024358060a01c615e7957613920526044358060201b615e7957613940525f546139605261396051611049576015613980527f7374616b696e67206e6f7420737570706f7274656400000000000000000000006139a0526139805061398051806139a001601f825f031636823750506308c379a061394052602061396052601f19601f61398051011660440161395cfd5b5f613980525f6105005160208111615e7957801561120357905b6101a08102610520016101a0613da06101a08360045afa5050613dc0513318156110ec576009613f40527f6e6f74206f776e65720000000000000000000000000000000000000000000000613f6052613f4050613f405180613f6001601f825f031636823750506308c379a0613f00526020613f2052601f19601f613f40510116604401613f1cfd5b610180610360610180613da060045afa50611108613f40615254565b613f405161117557600f613f60527f696e76616c696420636f6e746578740000000000000000000000000000000000613f8052613f6050613f605180613f8001601f825f031636823750506308c379a0613f20526020613f4052601f19601f613f60510116604401613f3cfd5b613da05161020052611188613f4061542d565b613f40516386ac890e613f605261392051613f8052613da051613fa05261396051613fc05261394051613fe052803b15615e79575f613f606084613f7c5f855af16111d5573d5f5f3e3d5ffd5b5061398051601f8111615e7957613da0518160051b6139a00152600181016139805250600101818118611063575b50507fd1036436febefb47614e14b42527d085cdfac0b0818a538acd3b1c941db19a3c608033613da0526020615f21613dc03961392051613de05280613e005280613da0015f613980518083528060051b5f8260208111615e7957801561128457905b8060051b6139a001518160051b602088010152600101818118611266575b50508201602001915050905081019050613da0a10061517d565b630b4b74e481186112d957602436103417615e79576004358060a01c615e795760405260076040516020525f5260405f205460605260206060f35b63c2b82de4811861517d57602436103417615e79576003543318156113535760126040527f6e6f742070726f746f636f6c2061646d696e000000000000000000000000000060605260405060405180606001601f825f031636823750506308c379a05f526020602052601f19601f6040510116604401601cfd5b6020615f815f395f5160043511156113c05760166040527f70726f746f636f6c20666565203e206d6178206665650000000000000000000060605260405060405180606001601f825f031636823750506308c379a05f526020602052601f19601f6040510116604401601cfd5b7faf7807c71b0e34bca82bd3067b4b5a4c760067c32fd82f2a714ef2624a33ce4360025460405260043560605260015460805260606040a16004356002550061517d565b6354139928811861517d5734615e795760085460405260206040f361517d565b635c975abb811861517d5734615e795760095460405260206040f361517d565b6378b848eb811861185657606436103417615e79576004356004016020813511615e795780355f8160208111615e7957801561153657905b610180810261052001610180820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e08301526101008101356101008301526101208101356101208301525050505060010181811861147c575b5050806105005250506024358060a01c615e7957613520525f613540525f6105005160208111615e795780156117b157905b610180810261052001610180613d606101808360045afa5050610180610360610180613d6060045afa5061159d613ee0615254565b613ee05161160a57600f613f00527f696e76616c696420636f6e746578740000000000000000000000000000000000613f2052613f0050613f005180613f2001601f825f031636823750506308c379a0613ec0526020613ee052601f19601f613f00510116604401613edcfd5b6101406040610140613da060045afa50611625613ee0615297565b613ee0511561169357600d613f00527f6163746976652072656e74616c00000000000000000000000000000000000000613f2052613f0050613f005180613f2001601f825f031636823750506308c379a0613ec0526020613ee052601f19601f613f00510116604401613edcfd5b613d8051331815611703576009613ee0527f6e6f74206f776e65720000000000000000000000000000000000000000000000613f0052613ee050613ee05180613f0001601f825f031636823750506308c379a0613ea0526020613ec052601f19601f613ee0510116604401613ebcfd5b613d605161020052611716613f0061542d565b613f0051613ee052613ee0516395941b73613f005261352051613f20527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff613f4052803b15615e79575f613f006044613f1c5f855af1611778573d5f5f3e3d5ffd5b5061354051601f8111615e79578060061b61356001613ee0518152613d6051602082015250600181016135405250600101818118611568575b50507f7fcaf5307ea3e5c35bd915f8a03c59f2a94386a469ebd9833192f0dcb8af92ae608033613d605261352051613d80526020615f21613da03980613dc05280613d60015f613540518083528060061b5f8260208111615e7957801561184057905b8060061b60208701018160061b6135600180518252602081015160208301525050600101818118611814575b50508201602001915050905081019050613d60a1005b6372e76f13811861517d57602436103417615e79576004358060a01c615e79576040526003543318156118df5760126060527f6e6f742070726f746f636f6c2061646d696e000000000000000000000000000060805260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b60405161194257601a6060527f77616c6c657420697320746865207a65726f206164647265737300000000000060805260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b7f6defa6e1a7dcc97f459fb552cf25427ab19cd60692b94e4f38660850a6e917e860015460605260405160805260406060a16040516001550061517d565b63338f5ad38118611ddc57606436103417615e79576004356004016020813511615e795780355f8160208111615e79578015611a7257905b610180810261052001610180820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e0830152610100810135610100830152610120810135610120830152505050506001018181186119b8575b5050806105005250506024358060a01c615e7957613520525f613540525f6105005160208111615e79578015611d3757905b610180810261052001610180613d606101808360045afa5050610180610360610180613d6060045afa50611ad9613ee0615254565b613ee051611b4657600f613f00527f696e76616c696420636f6e746578740000000000000000000000000000000000613f2052613f0050613f005180613f2001601f825f031636823750506308c379a0613ec0526020613ee052601f19601f613f00510116604401613edcfd5b6101406040610140613da060045afa50611b61613ee0615297565b613ee051611bce576010613f00527f6e6f206163746976652072656e74616c00000000000000000000000000000000613f2052613f0050613f005180613f2001601f825f031636823750506308c379a0613ec0526020613ee052601f19601f613f00510116604401613edcfd5b613de051331815611c3e57600a613ee0527f6e6f742072656e74657200000000000000000000000000000000000000000000613f0052613ee050613ee05180613f0001601f825f031636823750506308c379a0613ea0526020613ec052601f19601f613ee0510116604401613ebcfd5b613d605161020052611c51613f0061542d565b613f0051613ee052613ee0516395941b73613f005261352051613f2052613e8051613f4052803b15615e79575f613f006044613f1c5f855af1611c96573d5f5f3e3d5ffd5b50613d605161036052613d805161038052613da0516103a052613dc0516103c052613de0516103e0526135205161040052613e205161042052613e405161044052613e605161046052613e805161048052613ea0516104a052613ec0516104c052611cff6154bf565b61354051601f8111615e79578060061b61356001613ee0518152613d6051602082015250600181016135405250600101818118611aa4575b50507f28d724adcdae826aa56f4985e8b0d99476f3a9226f3a9f3c75a64fa61931852a608033613d605261352051613d80526020615f21613da03980613dc05280613d60015f613540518083528060061b5f8260208111615e79578015611dc657905b8060061b60208701018160061b6135600180518252602081015160208301525050600101818118611d9a575b50508201602001915050905081019050613d60a1005b63023c67b1811861517d57608436103417615e79576004356004016020813511615e795780355f8160208111615e79578015611f5857905b610300810261082001610300820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e0830152610100810135610100830152610120810135610120830152505061018082016101808201803582526020810135602083015260408101356040830152606081013560608301526080810135608083015260a0820160a08201803582526020810135602083015260408101356040830152505061010082016101008201803582526020810135602083015260408101356040830152505050506102e08101356102e08301525050600101818118611e14575b5050806108005250506024358060a01c615e795761682052611f786154fe565b5f616840525f618c60525f6108005160208111615e7957801561201357905b610300810261082001610300618c806103008360045afa5050618c60514260405242618f6051610e10810281610e10820418615e79579050808201828110615e795790509050606052618e2051608052611ff2618f8061562e565b618f8051808201828110615e795790509050618c6052600101818118611f97575b505033604052618c6051606052612028615665565b5f6108005160208111615e795780156124c557905b610300810261082001610300618c806103008360045afa5050618c805161020052612069618fa061542d565b618fa051618f8052610180610360610180618c8060045afa5061208d618fa0615254565b618fa0516120fa57600f618fc0527f696e76616c696420636f6e746578740000000000000000000000000000000000618fe052618fc050618fc05180618fe001601f825f031636823750506308c379a0618f80526020618fa052601f19601f618fc0510116604401618f9cfd5b6101406040610140618cc060045afa50612115618fa0615297565b618fa0511561218357600d618fc0527f6163746976652072656e74616c00000000000000000000000000000000000000618fe052618fc050618fc05180618fe001601f825f031636823750506308c379a0618f80526020618fa052601f19601f618fc0510116604401618f9cfd5b618e0051604052618e2051606052618e4051608052618e605160a052618e805160c052618f605160e0526121b8618fa0615724565b618fa051612225576016618fc0527f6475726174696f6e206e6f742072657370656374656400000000000000000000618fe052618fc050618fc05180618fe001601f825f031636823750506308c379a0618f80526020618fa052601f19601f618fc0510116604401618f9cfd5b618e2051612292576012618fa0527f6c697374696e67206e6f74206163746976650000000000000000000000000000618fc052618fa050618fa05180618fc001601f825f031636823750506308c379a0618f60526020618f8052601f19601f618fa0510116604401618f7cfd5b618c805161046052610160610480610160618e0060045afa506044356105e052618ca051610600526122c2615965565b42618f6051610e10810281610e10820418615e79579050808201828110615e795790509050618fa052618f80516395941b73618fe052616820511561230957616820612312565b33618fc052618fc05b5161900052618fa05161902052803b15615e79575f618fe06044618ffc5f855af161233f573d5f5f3e3d5ffd5b50618c805161050052618ca05161052052610140610540610140618cc060045afa50600161068052612372618fc0615bf4565b618fc05033604052618c805160605242608052618fa05160a052612397618fe0615d31565b618fe051618fc052618fc051618fe052618ca0516190005233619020526168205161904052618c805161906052426190805242618e4051610e10810281610e10820418615e79579050808201828110615e7957905090506190a052618fa0516190c05242604052618fa051606052618e205160805261241761912061562e565b619120516190e05260025461910052618c805161036052618ca051610380526101406103a0610140618fe060045afa5061244f6154bf565b61684051601f8111615e7957610120810261686001618fc0518152618f80516020820152618ca0516040820152618c805160608201524260808201526190a05160a0820152618fa05160c08201526190e05160e0820152619100516101008201525060018101616840525060010181811861203d575b50507f8c4674b6dd5bb42474e86779169da5cbdc1c1e541e8e576f629dc865bf702e32608033618c805261682051618ca0526020615f21618cc03980618ce05280618c80015f6168405180835261012081025f8260208111615e7957801561255657905b61012081026168600161012082026020880101610120816101208460045afa505050600101818118612529575b50508201602001915050905081019050618c80a10061517d565b63f2cac92081186127b657606436103417615e79576004356004016020813511615e7957803560208160051b018083610500375050506024358060a01c615e7957610920526125bd6154fe565b5f610940525f6105005160208111615e7957801561271157905b8060051b6105200151611160526005611160516020525f5260405f20541561265e57600d611180527f696e76616c6964207374617465000000000000000000000000000000000000006111a0526111805061118051806111a001601f825f031636823750506308c379a061114052602061116052601f19601f61118051011660440161115cfd5b61116051610200526126716111a0615563565b6111a0516111805261118051632e2d29846111a052611160516111c052336111e0526109205161120052803b15615e79575f6111a060646111bc5f855af16126bb573d5f5f3e3d5ffd5b5061116051610360523361038052610140366103a0376126d96154bf565b61094051601f8111615e79578060061b61096001611180518152611160516020820152506001810161094052506001018181186125d7575b50507f14f25625ebd0b44e2a92d47d22a3eeff9b38c448dea84f07be367c8ebdadf88f608033611160526020615f2161118039806111a05280611160015f610940518083528060061b5f8260208111615e7957801561279857905b8060061b60208701018160061b610960018051825260208101516020830152505060010181811861276c575b50508201602001915050905081019050610920516111c052611160a1005b635622a776811861517d57608436103417615e79576004356004016020813511615e795780355f8160208111615e795780156128b457905b6101a08102610520016101a0820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e0830152610100810135610100830152610120810135610120830152505061018081013561018083015250506001018181186127ee575b5050806105005250506024358060201b615e7957613920526044358060201b615e7957613940526128e36154fe565b5f546139605261396051612956576015613980527f7374616b696e67206e6f7420737570706f7274656400000000000000000000006139a0526139805061398051806139a001601f825f031636823750506308c379a061394052602061396052601f19601f61398051011660440161395cfd5b5f613980525f6105005160208111615e79578015612b1057905b6101a08102610520016101a0613da06101a08360045afa5050613dc0513318156129f9576009613f40527f6e6f74206f776e65720000000000000000000000000000000000000000000000613f6052613f4050613f405180613f6001601f825f031636823750506308c379a0613f00526020613f2052601f19601f613f40510116604401613f1cfd5b610180610360610180613da060045afa50612a15613f40615254565b613f4051612a8257600f613f60527f696e76616c696420636f6e746578740000000000000000000000000000000000613f8052613f6050613f605180613f8001601f825f031636823750506308c379a0613f20526020613f4052601f19601f613f60510116604401613f3cfd5b613da05161020052612a95613f4061542d565b613f40516394ca6999613f6052613da051613f805261396051613fa05261392051613fc05261394051613fe052803b15615e79575f613f606084613f7c5f855af1612ae2573d5f5f3e3d5ffd5b5061398051601f8111615e7957613da0518160051b6139a00152600181016139805250600101818118612970575b50507f59dd9897d3d45fb2ad9a6c6675e80d6b5f2883c511744d68331e38fdd4dfcfe2606033613da0526020615f21613dc03980613de05280613da0015f613980518083528060051b5f8260208111615e79578015612b8957905b8060051b6139a001518160051b602088010152600101818118612b6b575b50508201602001915050905081019050613da0a10061517d565b6368bbb5598118612e3057604436103417615e79576004356004016020813511615e795780355f8160208111615e79578015612c9557905b610180810261052001610180820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e083015261010081013561010083015261012081013561012083015250505050600101818118612bdb575b5050806105005250505f613520525f6105005160208111615e79578015612d9257905b610180810261052001610180613d406101808360045afa5050610180610360610180613d4060045afa50612ced613ec0615254565b613ec051612d5a57600f613ee0527f696e76616c696420636f6e746578740000000000000000000000000000000000613f0052613ee050613ee05180613f0001601f825f031636823750506308c379a0613ea0526020613ec052601f19601f613ee0510116604401613ebcfd5b61352051601f8111615e79578060061b61354001613d40518152613d6051602082015250600181016135205250600101818118612cb8575b50506020615f615f395f51638fd404c7613d4052602080613d605280613d60015f613520518083528060061b5f8260208111615e79578015612dfc57905b8060061b60208701018160061b6135400180518252602081015160208301525050600101818118612dd0575b50508201602001915050905081015050803b15615e79575f613d40610844613d5c5f855af1612e2d573d5f5f3e3d5ffd5b50005b631e81a8b7811861517d57604436103417615e79576004356004016020813511615e795780355f8160208111615e79578015612f2257905b610180810261052001610180820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e083015261010081013561010083015261012081013561012083015250505050600101818118612e68575b5050806105005250505f613520525f6105005160208111615e795780156130f757905b6101808102610520016101806139406101808360045afa505061018061036061018061394060045afa50612f7a613ac0615254565b613ac051612fe757600f613ae0527f696e76616c696420636f6e746578740000000000000000000000000000000000613b0052613ae050613ae05180613b0001601f825f031636823750506308c379a0613aa0526020613ac052601f19601f613ae0510116604401613abcfd5b336020615f615f395f51636352211e613ac05261394051613ae0526020613ac06024613adc845afa61301b573d5f5f3e3d5ffd5b60203d10615e7957613ac0518060a01c615e7957613b0052613b0090505118156130a4576009613b20527f6e6f74206f776e65720000000000000000000000000000000000000000000000613b4052613b2050613b205180613b4001601f825f031636823750506308c379a0613ae0526020613b0052601f19601f613b20510116604401613afcfd5b613940516103605233610380526101406103a061014061398060045afa506130ca6154bf565b61352051601f8111615e7957613940518160051b6135400152600181016135205250600101818118612f45575b50507f5f1d5777673eb2dacd3b07f793491178b16d931e7241b2bdbc9c3620f62083a2606033613940526020615f2161396039806139805280613940015f613520518083528060051b5f8260208111615e7957801561317057905b8060051b61354001518160051b602088010152600101818118613152575b50508201602001915050905081019050613940a10061517d565b63b137c422811861517d57604436103417615e79576004356004016020813511615e795780355f8160208111615e7957801561327c57905b610180810261052001610180820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e0830152610100810135610100830152610120810135610120830152505050506001018181186131c2575b5050806105005250505f613520525f6105005160208111615e795780156133ef57905b6101808102610520016101806139406101808360045afa505061018061036061018061394060045afa506132d4613ac0615254565b613ac05161334157600f613ae0527f696e76616c696420636f6e746578740000000000000000000000000000000000613b0052613ae050613ae05180613b0001601f825f031636823750506308c379a0613aa0526020613ac052601f19601f613ae0510116604401613abcfd5b336139605118156133b1576009613ac0527f6e6f74206f776e65720000000000000000000000000000000000000000000000613ae052613ac050613ac05180613ae001601f825f031636823750506308c379a0613a80526020613aa052601f19601f613ac0510116604401613a9cfd5b426006613940516020525f5260405f205561352051601f8111615e7957613940518160051b613540015260018101613520525060010181811861329f575b50507f61cf4a9dff83a5d31c96658f0e9e1c1f5fde0405271ebe5e76a7347209a0b0fb606033613940524261396052806139805280613940015f613520518083528060051b5f8260208111615e7957801561346457905b8060051b61354001518160051b602088010152600101818118613446575b50508201602001915050905081019050613940a10061517d565b631a93aa93811861517d57606436103417615e79576004356004016020813511615e795780355f8160208111615e795780156135fa57905b61030081026106a001610300820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e0830152610100810135610100830152610120810135610120830152505061018082016101808201803582526020810135602083015260408101356040830152606081013560608301526080810135608083015260a0820160a08201803582526020810135602083015260408101356040830152505061010082016101008201803582526020810135602083015260408101356040830152505050506102e08101356102e083015250506001018181186134b6575b5050806106805250505f6166a0525f618ec052604036618ee0375f6106805160208111615e79578015613bcb57905b61030081026106a001610300618f206103008360045afa5050618f20516102005261365561924061542d565b6192405161922052610180610360610180618f2060045afa50613679619240615254565b619240516136e657600f619260527f696e76616c696420636f6e7465787400000000000000000000000000000000006192805261926050619260518061928001601f825f031636823750506308c379a061922052602061924052601f19601f61926051011660440161923cfd5b6101406040610140618f6060045afa50613701619240615297565b6192405161376e576010619260527f6e6f206163746976652072656e74616c000000000000000000000000000000006192805261926050619260518061928001601f825f031636823750506308c379a061922052602061924052601f19601f61926051011660440161923cfd5b618fa0513318156137de57601b619240527f6e6f742072656e746572206f66206163746976652072656e74616c00000000006192605261924050619240518061926001601f825f031636823750506308c379a061920052602061922052601f19601f61924051011660440161921cfd5b6190a0516040526190c0516060526190e0516080526191005160a0526191205160c0526192005160e052613813619240615724565b61924051613880576016619260527f6475726174696f6e206e6f7420726573706563746564000000000000000000006192805261926050619260518061928001601f825f031636823750506308c379a061922052602061924052601f19601f61926051011660440161923cfd5b6190c0516138ed576012619240527f6c697374696e67206e6f742061637469766500000000000000000000000000006192605261924050619240518061926001601f825f031636823750506308c379a061920052602061922052601f19601f61924051011660440161921cfd5b618f2051610460526101606104806101606190a060045afa506024356105e052618f40516106005261391d615965565b4261920051610e10810281610e10820418615e79579050808201828110615e7957905090506192405242619260526190205142101561395f5761902051619260525b6190405161900051808203828111615e7957905090506040526192605161900051808203828111615e795790509050606052619060516080526139a36192a0615d80565b6192a0516192805242604052619240516060526190c0516080526139c86192c061562e565b6192c0516192a052618f00516192a051808201828110615e795790509050618f00526190605161928051808203828111615e7957905090506192c052618ee0516192c051808201828110615e795790509050618ee0526192805161908051808202811583838304141715615e795790509050612710810490506192e052618ec0516192e051808201828110615e795790509050618ec052618f605161930052618f4051619320523361934052618fc05161936052618f205161938052426193a052426190e051610e10810281610e10820418615e79579050808201828110615e7957905090506193c052619240516193e0526192a0516194005260025461942052618f205161036052618f4051610380526101406103a061014061930060045afa50613af26154bf565b6007618f40516020525f5260405f208054619280516192e051808203828111615e795790509050808201828110615e7957905090508155506166a051601f8111615e795761014081026166c001618f60518152619220516020820152618f80516040820152618fe0516060820152426080820152426190e051610e10810281610e10820418615e79579050808201828110615e79579050905060a08201526192405160c08201526192805160e08201526192a0516101008201526190805161012082015250600181016166a05250600101818118613629575b5050618f0051618ee05111613c1157618f0051618ee0511015613c365733604052618f0051618ee051808203828111615e795790509050606052613c3661566556613c36565b33604052618ee051618f0051808203828111615e795790509050606052613c36615daf565b618ec05115613c5857600854618ec051808201828110615e7957905090506008555b7fa811dbbf231ee171f33b26c54ff3d080f0987b0a772f38f9fea9ce837f068063606033618f20526020615f21618f403980618f605280618f20015f6166a05180835261014081025f8260208111615e79578015613cdf57905b61014081026166c00161014082026020880101610140816101408460045afa505050600101818118613cb2575b50508201602001915050905081019050618f20a10061517d565b63368eaf5b811861517d57604436103417615e79576004356004016020813511615e795780355f8160208111615e79578015613deb57905b610180810261082001610180820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e083015261010081013561010083015261012081013561012083015250505050600101818118613d31575b5050806108005250505f613820525f614040525f614860525f6108005160208111615e7957801561419457905b6101808102610820016101806148806101808360045afa505061018061036061018061488060045afa50613e4d614a00615254565b614a0051613eba57600f614a20527f696e76616c696420636f6e746578740000000000000000000000000000000000614a4052614a2050614a205180614a4001601f825f031636823750506308c379a06149e0526020614a0052601f19601f614a205101166044016149fcfd5b61014060406101406148c060045afa50613ed5614a00615297565b614a005115613f4357600d614a20527f6163746976652072656e74616c00000000000000000000000000000000000000614a4052614a2050614a205180614a4001601f825f031636823750506308c379a06149e0526020614a0052601f19601f614a205101166044016149fcfd5b6020615f615f395f516342a0106b614a205261488051614a40526020614a206024614a3c845afa613f76573d5f5f3e3d5ffd5b60203d10615e7957614a20518060a01c615e7957614a6052614a60905051614a0052614a00511561401557614a0051331815614085576009614a20527f6e6f74206f776e65720000000000000000000000000000000000000000000000614a4052614a2050614a205180614a4001601f825f031636823750506308c379a06149e0526020614a0052601f19601f614a205101166044016149fcfd614085565b6148a051331815614085576009614a20527f6e6f74206f776e65720000000000000000000000000000000000000000000000614a4052614a2050614a205180614a4001601f825f031636823750506308c379a06149e0526020614a0052601f19601f614a205101166044016149fcfd5b6148805161020052614098614a4061542d565b614a4051614a205261488051610500526148a051610520526101406105406101406148c060045afa505f610680526140d1614a40615bf4565b614a4050614880516040526140e4615e67565b61404051601f8111615e79578060061b614060016148805181526148a051602082015250600181016140405250614a205162f714ce614a405261488051614a605233614a8052803b15615e79575f614a406044614a5c5f855af161414a573d5f5f3e3d5ffd5b50426006614880516020525f5260405f205561382051601f8111615e79578060061b61384001614a2051815261488051602082015250600181016138205250600101818118613e18575b50506020615f615f395f5163ebc803d0614880526020806148a052806148a0015f614040518083528060061b5f8260208111615e795780156141fe57905b8060061b60208701018160061b61406001805182526020810151602083015250506001018181186141d2575b50508201602001915050905081015050803b15615e79575f61488061084461489c5f855af161422f573d5f5f3e3d5ffd5b506007336020525f5260405f205461488052614880511561426b575f6007336020525f5260405f2055336040526148805160605261426b615daf565b7f66e25f0f38428dc92a79bde4219b9209156f468e2360faa803c0798298b411526080336148a0526020615f216148c039614880516148e0528061490052806148a0015f613820518083528060061b5f8260208111615e795780156142f857905b8060061b60208701018160061b61384001805182526020810151602083015250506001018181186142cc575b505082016020019150509050810190506148a0a10061517d565b63295f385a811861517d57606436103417615e79576004356004016020813511615e795780355f8160208111615e7957801561441057905b6101a08102610520016101a0820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e08301526101008101356101008301526101208101356101208301525050610180810135610180830152505060010181811861434a575b5050806105005250506024358060201b615e7957613920526144306154fe565b5f5461394052613940516144a3576015613960527f7374616b696e67206e6f7420737570706f7274656400000000000000000000006139805261396050613960518061398001601f825f031636823750506308c379a061392052602061394052601f19601f61396051011660440161393cfd5b5f613960525f6105005160208111615e7957801561473d57905b6101a08102610520016101a06141806101a08360045afa50506141a051331815614546576009614320527f6e6f74206f776e657200000000000000000000000000000000000000000000006143405261432050614320518061434001601f825f031636823750506308c379a06142e052602061430052601f19601f6143205101166044016142fcfd5b61018061036061018061418060045afa50614562614320615254565b614320516145cf57600f614340527f696e76616c696420636f6e7465787400000000000000000000000000000000006143605261434050614340518061436001601f825f031636823750506308c379a061430052602061432052601f19601f61434051011660440161431cfd5b61418051610200526145e261434061542d565b61434051614320526020615f015f395f516323b872dd6143405233614360526143205161438052614300516143a0526020614340606461435c5f855af161462b573d5f5f3e3d5ffd5b60203d10615e7957614340518060011c615e79576143c0526143c09050516146b25760136143e0527f7472616e7366657246726f6d206661696c656400000000000000000000000000614400526143e0506143e0518061440001601f825f031636823750506308c379a06143a05260206143c052601f19601f6143e05101166044016143bcfd5b61432051637cfb8a756143405233614360526143005161438052614180516143a052613940516143c052613920516143e052803b15615e79575f61434060a461435c5f855af1614704573d5f5f3e3d5ffd5b5061396051601f8111615e79578060061b61398001614180518152614300516020820152506001810161396052506001018181186144bd575b50507fda7e91c665c767ab0ceda28c5f7a59924da2e798ddc67088394339700c8a983c606033614180526020615f216141a039806141c05280614180015f613960518083528060061b5f8260208111615e795780156147c457905b8060061b60208701018160061b6139800180518252602081015160208301525050600101818118614798575b50508201602001915050905081019050614180a10061517d565b632995627c8118614be857608436103417615e79576004356004016020813511615e795780355f8160208111615e795780156148dc57905b6101a08102610520016101a0820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e083015261010081013561010083015261012081013561012083015250506101808101356101808301525050600101818118614816575b5050806105005250506024358060a01c615e7957613920526044358060201b615e7957613940525f546139605261396051614976576015613980527f7374616b696e67206e6f7420737570706f7274656400000000000000000000006139a0526139805061398051806139a001601f825f031636823750506308c379a061394052602061396052601f19601f61398051011660440161395cfd5b5f613980525f6105005160208111615e79578015614b4357905b6101a08102610520016101a06141a06101a08360045afa50506141c051331815614a19576009614340527f6e6f74206f776e657200000000000000000000000000000000000000000000006143605261434050614340518061436001601f825f031636823750506308c379a061430052602061432052601f19601f61434051011660440161431cfd5b6101806103606101806141a060045afa50614a35614340615254565b61434051614aa257600f614360527f696e76616c696420636f6e7465787400000000000000000000000000000000006143805261436050614360518061438001601f825f031636823750506308c379a061432052602061434052601f19601f61436051011660440161433cfd5b6141a05161020052614ab561434061542d565b61434051639babe7bd614360526139205161438052614320516143a0526141a0516143c052613960516143e0526139405161440052803b15615e79575f61436060a461437c5f855af1614b0a573d5f5f3e3d5ffd5b5061398051601f8111615e79578060061b6139a0016141a051815261432051602082015250600181016139805250600101818118614990575b50507fc0145443abe0348e5fbb3cddc9f89bbef6cc14377065302899fa2fe479a750366080336141a0526020615f216141c039613920516141e0528061420052806141a0015f613980518083528060061b5f8260208111615e79578015614bd257905b8060061b60208701018160061b6139a00180518252602081015160208301525050600101818118614ba6575b505082016020019150509050810190506141a0a1005b636696eac6811861517d57604436103417615e79576004356004016020813511615e795780355f8160208111615e79578015614cda57905b610180810261082001610180820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e083015261010081013561010083015261012081013561012083015250505050600101818118614c20575b5050806108005250505f613820525f6108005160208111615e79578015614e8c57905b6101808102610820016101806140406101808360045afa505061018061036061018061404060045afa50614d326141c0615254565b6141c051614d9f57600f6141e0527f696e76616c696420636f6e746578740000000000000000000000000000000000614200526141e0506141e0518061420001601f825f031636823750506308c379a06141a05260206141c052601f19601f6141e05101166044016141bcfd5b33614060511815614e0f5760096141c0527f6e6f74206f776e657200000000000000000000000000000000000000000000006141e0526141c0506141c051806141e001601f825f031636823750506308c379a06141805260206141a052601f19601f6141c051011660440161419cfd5b6140405161050052614060516105205261014061054061014061408060045afa50600161068052614e41614300615bf4565b6143006101406141c06101408360045afa505061382051601f8111615e79578060061b613840016140405181526142c051602082015250600181016138205250600101818118614cfd575b50506007336020525f5260405f20546140405261404051614f0c576013614060527f6e6f207265776172647320746f20636c61696d000000000000000000000000006140805261406050614060518061408001601f825f031636823750506308c379a061402052602061404052601f19601f61406051011660440161403cfd5b6020615f015f395f5163a9059cbb614060523361408052614040516140a0526020614060604461407c5f855af1614f45573d5f5f3e3d5ffd5b60203d10615e7957614060518060011c615e79576140c0526140c0905051614fcc57600f6140e0527f7472616e73666572206661696c65640000000000000000000000000000000000614100526140e0506140e0518061410001601f825f031636823750506308c379a06140a05260206140c052601f19601f6140e05101166044016140bcfd5b5f6007336020525f5260405f20557f75d9fb02b6811f542f9236825a4f8c3698e023691c1fd76b15ece3d40264b41160a033614060526020615f2161408039614040516140a0526008546140c052806140e05280614060015f613820518083528060061b5f8260208111615e7957801561506e57905b8060061b60208701018160061b6138400180518252602081015160208301525050600101818118615042575b50508201602001915050905081019050614060a10061517d565b630ff5ce72811861517d57602436103417615e79576004358060011c615e79576040526003543318156151115760126060527f6e6f742070726f746f636f6c2061646d696e000000000000000000000000000060805260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b7f61546262c46330c86d6db302369d59188947245ae9c631d9c48155bcd8ffaebe60095460605260405160805260406060a16040516009550061517d565b63b6b92522811861517d57602436103417615e7957602060043561016052615178610200615355565b610200f35b5f5ffd5b5f604051816101e00152602081019050606051816101e00152602081019050608051816101e0015260208101905060a051816101e0015260208101905060c051816101e0015260208101905060e051816101e0015260208101905061010051816101e0015260208101905061012051816101e0015260208101905061014051816101e0015260208101905061016051816101e0015260208101905061018051816101e001526020810190506101a051816101e00152602081019050806101c0526101c09050805160208201209050815250565b610360516040526103805160605261014060806101406103a060045afa5061527d6104e0615181565b6104e0516005610360516020525f5260405f205414815250565b426101205111815250565b73ffffffffffffffffffffffffffffffffffffffff604051168060a01c615e7957815250565b5f7fff0000000000000000000000000000000000000000000000000000000000000081610100015260018101905060a0518060601b90508161010001526014810190506060518161010001526020810190506080518161010001526020810190508060e05260e0905080516020820120905060c05260c05160405261534d60e06152a2565b60e051815250565b610160516060525f7f602d3d8160093d39f30000000000000000000000000000000000000000000000816101a001526009810190507f363d3d373d3d3d363d7300000000000000000000000000000000000000000000816101a00152600a810190506020615ee15f395f518060601b9050816101a001526014810190507f5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000816101a00152600f81019050806101805261018090508051602082012090506080523060a0526154246101e06152c8565b6101e051815250565b6102005161016052615440610240615355565b6102405161022052610220513b6154b657601c610240527f6e6f207661756c742065786973747320666f7220746f6b656e5f6964000000006102605261024050610240518061026001601f825f031636823750506308c379a061020052602061022052601f19601f61024051011660440161021cfd5b61022051815250565b610360516040526103805160605261014060806101406103a060045afa506154e86104e0615181565b6104e0516005610360516020525f5260405f2055565b600954156155615760066040527f706175736564000000000000000000000000000000000000000000000000000060605260405060405180606001601f825f031636823750506308c379a05f526020602052601f19601f6040510116604401601cfd5b565b6102005161016052615576610240615355565b6102405161022052610220513b615625577f602d3d8160093d39f3363d3d373d3d3d363d7300000000000000000000000000610240526020615ee15f395f5160601b610253527f5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000610267526102005160366102405ff58015615e7957610220526102205163592e6f5961024052803b15615e79575f610240600461025c5f855af1615623573d5f5f3e3d5ffd5b505b61022051815250565b606051604051808203828111615e795790509050608051808202811583838304141715615e795790509050610e1081049050815250565b6020615f015f395f516323b872dd60805260405160a0523060c05260605160e052602060806064609c5f855af161569e573d5f5f3e3d5ffd5b60203d10615e79576080518060011c615e795761010052610100905051615722576013610120527f7472616e7366657246726f6d206661696c6564000000000000000000000000006101405261012050610120518061014001601f825f031636823750506308c379a060e052602061010052601f19601f61012051011660440160fcfd5b565b60805160e0511015615736575f61574d565b60a05161574457600161574d565b60a05160e05111155b815250565b6101a0515f610440525f60026101c0527f19010000000000000000000000000000000000000000000000000000000000006101e0526101c08051602082018361036001815181525050808301925050506020615ec1610300397f8bfe2af4290476395b89e8859d048827bdabb82447fa4a7943209a078a3030ff6102205260405161024052606051610260526080516102805260a0516102a05260c0516102c05260c0610200526102008051602082012090506103205260406102e0526102e080516020820183610360018281848460045afa50505080830192505050806103405261034090508051602082012090506103c05260e0516103e05261010051610400526101205161042052602061044060806103c060015afa506104405114815250565b6003545f610380525f60026101c0527f19000000000000000000000000000000000000000000000000000000000000006101e0526101c0805160208201836102a00181518152505080830192505050308060601b9050816102a0015260148101905060e0516102205261010051610240526101205161026052606061020052610200805160208201209050816102a001526020810190506101a051816102a0015260208101905080610280526102809050805160208201209050610300526101405161032052610160516103405261018051610360526020610380608061030060015afa506103805114815250565b610480516104605118156159d8576010610620527f696e76616c696420746f6b656e5f6964000000000000000000000000000000006106405261062050610620518061064001601f825f031636823750506308c379a06105e052602061060052601f19601f6106205101166044016105fcfd5b610160604061016061048060045afa50610600516101a0526159fb610620615752565b61062051615a68576017610640527f696e76616c6964206f776e6572207369676e61747572650000000000000000006106605261064050610640518061066001601f825f031636823750506308c379a061060052602061062052601f19601f61064051011660440161061cfd5b610160604061016061048060045afa506105e0516101a052615a8b610620615876565b61062051615af8576017610640527f696e76616c69642061646d696e207369676e61747572650000000000000000006106605261064050610640518061066001601f825f031636823750506308c379a061060052602061062052601f19601f61064051011660440161061cfd5b426105e05160788101818110615e7957905011615b7457600f610620527f6c697374696e67206578706972656400000000000000000000000000000000006106405261062050610620518061064001601f825f031636823750506308c379a06105e052602061060052601f19601f6106205101166044016105fcfd5b610500516006610480516020525f5260405f205410615bf257600f610620527f6c697374696e67207265766f6b656400000000000000000000000000000000006106405261062050610620518061064001601f825f031636823750506308c379a06105e052602061060052601f19601f6106205101166044016105fcfd5b565b61064051615c03576001615c0b565b426106205110155b615d1e576106405161066051808202811583838304141715615e795790509050612710810490506106a0526007610560516020525f5260405f208054610640516106a051808203828111615e795790509050808201828110615e7957905090508155506008546106a051808201828110615e795790509050600855610540516106c052610560516106e05261058051610700526105a0516107205261050051610740526105e051610760526106005161078052610620516107a0525f6107c052610660516107e0526106805115615d0557610500516103605261052051610380526101406103a06101406106c060045afa50615d056154bf565b610140816101406106c060045afa5050615d2f56615d2f565b6101408161014061054060045afa50505b565b5f6040518160e001526020810190506060518160e001526020810190506080518160e0015260208101905060a0518160e001526020810190508060c05260c09050805160208201209050815250565b608051606051808202811583838304141715615e7957905090506040518015615e795780820490509050815250565b6020615f015f395f5163a9059cbb60805260405160a05260605160c052602060806044609c5f855af1615de4573d5f5f3e3d5ffd5b60203d10615e79576080518060011c615e795760e05260e0905051615e65576013610100527f7472616e7366657246726f6d206661696c6564000000000000000000000000006101205261010050610100518061012001601f825f031636823750506308c379a060c052602060e052601f19601f61010051011660440160dcfd5b565b5f60056040516020525f5260405f2055565b5f80fd0283037950883cf947de03b7517d007a517d00584312517d001803d92570517d517d2ba3077d1980318a517d129e08521404517d03f91424517d079d514f347e517d144484195ec181184418e0a16576797065728300030a001600000000000000000000000094fa19545e51ea6f2c12d2c8480af5657f8a30b20000000000000000000000004d224452801aced8b2f0aebe155379bb5d5943810000000000000000000000003bdca51226202fc2a64211aa35a8d95d61c6ca99000000000000000000000000c3aa9bc72bd623168860a1e5c6a4530d3d80456c000000000000000000000000cbe9b03415175d1d410801bad7783f8ac8aba89f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007d96cc26566bfca358c61fbe7be3ca771da7ea6000000000000000000000000314ba3811129ae06fc35894a3bb62157028a9fd9

Deployed Bytecode

0x5f3560e01c60026022820660011b615e7d01601e395f51565b63fe80cbc081186100365734615e79576020615ee160403960206040f35b638afbd8ce811861517d5734615e79576020615f4160403960206040f361517d565b63331c6587811861517d5734615e79576020615f0160403960206040f361517d565b6304cca53b81186100985734615e79576020615f2160403960206040f35b633ffd45b7811861015957602436103417615e79576004358060a01c615e79576040526003543318156101215760126060527f6e6f742070726f746f636f6c2061646d696e000000000000000000000000000060805260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b7f705cd0c010fe71835c798c37a9b8ba0340aa60d9dcd5e8981ea2dfd4880368685f5460605260405160805260406060a16040515f55005b635f11b0a1811861517d57602436103417615e79576004358060a01c615e79576040526003543318156101e257600d6060527f6e6f74207468652061646d696e0000000000000000000000000000000000000060805260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b60405161024557601c6060527f5f6164647265737320697320746865207a65726f20616464726573730000000060805260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b7ffd22260ca7b3d2a5f6332770491ab546b6235bc73909c334f5e304d2fae455b160035460605260405160805260406060a16040516004550061517d565b63f728b1d8811861029e5734615e79575f5460405260206040f35b63baa24c12811861517d5734615e795760035433181561031d576009610140527f6e6f742061646d696e00000000000000000000000000000000000000000000006101605261014050610140518061016001601f825f031636823750506308c379a061010052602061012052601f19601f61014051011660440161011cfd5b600854610140525f6008556001546040526101405160605261033d615daf565b7f9493e5bbe4e8e0ac67284469a2d677403d0378a85a59e341d3abc433d0d9a2096001546101605261014051610180526040610160a10061517d565b630bfab6bb81186103975734615e79576020615f6160403960206040f35b63abf61417811861517d5734615e795760045460405260206040f361517d565b635fb83221811861517d5734615e79576020615f8160403960206040f361517d565b6367db7499811861517d5734615e795760015460405260206040f361517d565b631655273281186104155734615e795760025460405260206040f35b63c9c0b69481186106c657606436103417615e79576004358060a01c615e7957610500526024356004016020813511615e795780355f8160208111615e7957801561051657905b610180810261054001610180820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e08301526101008101356101008301526101208101356101208301525050505060010181811861045c575b5050806105205250506007610500516020525f5260405f2054613540525f6105205160208111615e795780156106bd57905b6101808102610540016101806135606101808360045afa505061018061036061018061356060045afa5061057d6136e0615254565b6136e0516105ea57600f613700527f696e76616c696420636f6e7465787400000000000000000000000000000000006137205261370050613700518061372001601f825f031636823750506308c379a06136c05260206136e052601f19601f6137005101166044016136dcfd5b6105005161358051181561065d5760096136e0527f6e6f74206f776e65720000000000000000000000000000000000000000000000613700526136e0506136e0518061370001601f825f031636823750506308c379a06136a05260206136c052601f19601f6136e05101166044016136bcfd5b426136805110156106b257613540516136a0516136c05180612710036127108111615e79579050808202811583838304141715615e79579050905061271081049050808201828110615e795790509050613540525b600101818118610548575b50506020613540f35b63f7a79a02811861517d5734615e795760045433181561073b5760106040527f6e6f74207468652070726f706f7365640000000000000000000000000000000060605260405060405180606001601f825f031636823750506308c379a05f526020602052601f19601f6040510116604401601cfd5b7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060035460405260045460605260406040a16004546003555f6004550061517d565b63d9aa6924811861517d5734615e795760035460405260206040f361517d565b634931bd2981186107ca57602436103417615e795760056004356020525f5260405f205460405260206040f35b6301ffc9a7811861517d57602436103417615e79576004358060201b615e79576040526040517f01ffc9a700000000000000000000000000000000000000000000000000000000811861081e576001610843565b7f80ac58cd000000000000000000000000000000000000000000000000000000008118155b905060805260206080f361517d565b63b2815bcb811861087f57602436103417615e795760066004356020525f5260405f205460405260206040f35b63dce9d9ed8118610eb157604436103417615e79576004356004016020813511615e795780355f8160208111615e7957801561097157905b610180810261052001610180820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e0830152610100810135610100830152610120810135610120830152505050506001018181186108b7575b5050806105005250505f613520525f615940525f615960525f6105005160208111615e79578015610d3057905b6101808102610520016101806159806101808360045afa505061598051610200526109ca615b2061542d565b615b2051615b005261018061036061018061598060045afa506109ee615b20615254565b615b2051610a5b57600f615b40527f696e76616c696420636f6e746578740000000000000000000000000000000000615b6052615b4050615b405180615b6001601f825f031636823750506308c379a0615b00526020615b2052601f19601f615b40510116604401615b1cfd5b61014060406101406159c060045afa50610a76615b20615297565b615b2051610ae357601c615b40527f6163746976652072656e74616c20646f6573206e6f7420657869737400000000615b6052615b4050615b405180615b6001601f825f031636823750506308c379a0615b00526020615b2052601f19601f615b40510116604401615b1cfd5b615a0051331815610b5357601b615b20527f6e6f742072656e746572206f66206163746976652072656e74616c0000000000615b4052615b2050615b205180615b4001601f825f031636823750506308c379a0615ae0526020615b0052601f19601f615b20510116604401615afcfd5b42615b2052615a8051421015610b6c57615a8051615b20525b615aa051615a6051808203828111615e795790509050604052615b2051615a6051808203828111615e795790509050606052615ac051608052610bb0615b60615d80565b615b6051615b4052615ac051615b4051808203828111615e795790509050615b605261596051615b6051808201828110615e79579050905061596052615b4051615ae051808202811583838304141715615e79579050905061271081049050615b805261594051615b8051808201828110615e7957905090506159405261598051610360526159a05161038052610140366103a037610c4d6154bf565b60076159a0516020525f5260405f208054615b4051615b8051808203828111615e795790509050808201828110615e795790509050815550615b00516395941b73615ba052604036615bc037803b15615e79575f615ba06044615bbc5f855af1610cb9573d5f5f3e3d5ffd5b5061352051601f8111615e79576101208102613540016159c0518152615b005160208201526159e0516040820152615a40516060820152615a60516080820152615a805160a08201524260c0820152615b405160e0820152615ae0516101008201525060018101613520525060010181811861099e575b50506020615f015f395f5163a9059cbb61598052336159a052615960516159c0526020615980604461599c5f855af1610d6b573d5f5f3e3d5ffd5b60203d10615e7957615980518060011c615e79576159e0526159e0905051610df257600f615a00527f7472616e73666572206661696c65640000000000000000000000000000000000615a2052615a0050615a005180615a2001601f825f031636823750506308c379a06159c05260206159e052601f19601f615a005101166044016159dcfd5b6159405115610e145760085461594051808201828110615e7957905090506008555b7f73ff4b2da3afbf85c00543bcb289f888bb1a6a72dd3511fe075808a97ca20ecd606033615980526020615f216159a039806159c05280615980015f6135205180835261012081025f8260208111615e79578015610e9b57905b61012081026135400161012082026020880101610120816101208460045afa505050600101818118610e6e575b50508201602001915050905081019050615980a1005b63e4fbd50b811861517d57608436103417615e79576004356004016020813511615e795780355f8160208111615e79578015610faf57905b6101a08102610520016101a0820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e083015261010081013561010083015261012081013561012083015250506101808101356101808301525050600101818118610ee9575b5050806105005250506024358060a01c615e7957613920526044358060201b615e7957613940525f546139605261396051611049576015613980527f7374616b696e67206e6f7420737570706f7274656400000000000000000000006139a0526139805061398051806139a001601f825f031636823750506308c379a061394052602061396052601f19601f61398051011660440161395cfd5b5f613980525f6105005160208111615e7957801561120357905b6101a08102610520016101a0613da06101a08360045afa5050613dc0513318156110ec576009613f40527f6e6f74206f776e65720000000000000000000000000000000000000000000000613f6052613f4050613f405180613f6001601f825f031636823750506308c379a0613f00526020613f2052601f19601f613f40510116604401613f1cfd5b610180610360610180613da060045afa50611108613f40615254565b613f405161117557600f613f60527f696e76616c696420636f6e746578740000000000000000000000000000000000613f8052613f6050613f605180613f8001601f825f031636823750506308c379a0613f20526020613f4052601f19601f613f60510116604401613f3cfd5b613da05161020052611188613f4061542d565b613f40516386ac890e613f605261392051613f8052613da051613fa05261396051613fc05261394051613fe052803b15615e79575f613f606084613f7c5f855af16111d5573d5f5f3e3d5ffd5b5061398051601f8111615e7957613da0518160051b6139a00152600181016139805250600101818118611063575b50507fd1036436febefb47614e14b42527d085cdfac0b0818a538acd3b1c941db19a3c608033613da0526020615f21613dc03961392051613de05280613e005280613da0015f613980518083528060051b5f8260208111615e7957801561128457905b8060051b6139a001518160051b602088010152600101818118611266575b50508201602001915050905081019050613da0a10061517d565b630b4b74e481186112d957602436103417615e79576004358060a01c615e795760405260076040516020525f5260405f205460605260206060f35b63c2b82de4811861517d57602436103417615e79576003543318156113535760126040527f6e6f742070726f746f636f6c2061646d696e000000000000000000000000000060605260405060405180606001601f825f031636823750506308c379a05f526020602052601f19601f6040510116604401601cfd5b6020615f815f395f5160043511156113c05760166040527f70726f746f636f6c20666565203e206d6178206665650000000000000000000060605260405060405180606001601f825f031636823750506308c379a05f526020602052601f19601f6040510116604401601cfd5b7faf7807c71b0e34bca82bd3067b4b5a4c760067c32fd82f2a714ef2624a33ce4360025460405260043560605260015460805260606040a16004356002550061517d565b6354139928811861517d5734615e795760085460405260206040f361517d565b635c975abb811861517d5734615e795760095460405260206040f361517d565b6378b848eb811861185657606436103417615e79576004356004016020813511615e795780355f8160208111615e7957801561153657905b610180810261052001610180820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e08301526101008101356101008301526101208101356101208301525050505060010181811861147c575b5050806105005250506024358060a01c615e7957613520525f613540525f6105005160208111615e795780156117b157905b610180810261052001610180613d606101808360045afa5050610180610360610180613d6060045afa5061159d613ee0615254565b613ee05161160a57600f613f00527f696e76616c696420636f6e746578740000000000000000000000000000000000613f2052613f0050613f005180613f2001601f825f031636823750506308c379a0613ec0526020613ee052601f19601f613f00510116604401613edcfd5b6101406040610140613da060045afa50611625613ee0615297565b613ee0511561169357600d613f00527f6163746976652072656e74616c00000000000000000000000000000000000000613f2052613f0050613f005180613f2001601f825f031636823750506308c379a0613ec0526020613ee052601f19601f613f00510116604401613edcfd5b613d8051331815611703576009613ee0527f6e6f74206f776e65720000000000000000000000000000000000000000000000613f0052613ee050613ee05180613f0001601f825f031636823750506308c379a0613ea0526020613ec052601f19601f613ee0510116604401613ebcfd5b613d605161020052611716613f0061542d565b613f0051613ee052613ee0516395941b73613f005261352051613f20527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff613f4052803b15615e79575f613f006044613f1c5f855af1611778573d5f5f3e3d5ffd5b5061354051601f8111615e79578060061b61356001613ee0518152613d6051602082015250600181016135405250600101818118611568575b50507f7fcaf5307ea3e5c35bd915f8a03c59f2a94386a469ebd9833192f0dcb8af92ae608033613d605261352051613d80526020615f21613da03980613dc05280613d60015f613540518083528060061b5f8260208111615e7957801561184057905b8060061b60208701018160061b6135600180518252602081015160208301525050600101818118611814575b50508201602001915050905081019050613d60a1005b6372e76f13811861517d57602436103417615e79576004358060a01c615e79576040526003543318156118df5760126060527f6e6f742070726f746f636f6c2061646d696e000000000000000000000000000060805260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b60405161194257601a6060527f77616c6c657420697320746865207a65726f206164647265737300000000000060805260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b7f6defa6e1a7dcc97f459fb552cf25427ab19cd60692b94e4f38660850a6e917e860015460605260405160805260406060a16040516001550061517d565b63338f5ad38118611ddc57606436103417615e79576004356004016020813511615e795780355f8160208111615e79578015611a7257905b610180810261052001610180820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e0830152610100810135610100830152610120810135610120830152505050506001018181186119b8575b5050806105005250506024358060a01c615e7957613520525f613540525f6105005160208111615e79578015611d3757905b610180810261052001610180613d606101808360045afa5050610180610360610180613d6060045afa50611ad9613ee0615254565b613ee051611b4657600f613f00527f696e76616c696420636f6e746578740000000000000000000000000000000000613f2052613f0050613f005180613f2001601f825f031636823750506308c379a0613ec0526020613ee052601f19601f613f00510116604401613edcfd5b6101406040610140613da060045afa50611b61613ee0615297565b613ee051611bce576010613f00527f6e6f206163746976652072656e74616c00000000000000000000000000000000613f2052613f0050613f005180613f2001601f825f031636823750506308c379a0613ec0526020613ee052601f19601f613f00510116604401613edcfd5b613de051331815611c3e57600a613ee0527f6e6f742072656e74657200000000000000000000000000000000000000000000613f0052613ee050613ee05180613f0001601f825f031636823750506308c379a0613ea0526020613ec052601f19601f613ee0510116604401613ebcfd5b613d605161020052611c51613f0061542d565b613f0051613ee052613ee0516395941b73613f005261352051613f2052613e8051613f4052803b15615e79575f613f006044613f1c5f855af1611c96573d5f5f3e3d5ffd5b50613d605161036052613d805161038052613da0516103a052613dc0516103c052613de0516103e0526135205161040052613e205161042052613e405161044052613e605161046052613e805161048052613ea0516104a052613ec0516104c052611cff6154bf565b61354051601f8111615e79578060061b61356001613ee0518152613d6051602082015250600181016135405250600101818118611aa4575b50507f28d724adcdae826aa56f4985e8b0d99476f3a9226f3a9f3c75a64fa61931852a608033613d605261352051613d80526020615f21613da03980613dc05280613d60015f613540518083528060061b5f8260208111615e79578015611dc657905b8060061b60208701018160061b6135600180518252602081015160208301525050600101818118611d9a575b50508201602001915050905081019050613d60a1005b63023c67b1811861517d57608436103417615e79576004356004016020813511615e795780355f8160208111615e79578015611f5857905b610300810261082001610300820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e0830152610100810135610100830152610120810135610120830152505061018082016101808201803582526020810135602083015260408101356040830152606081013560608301526080810135608083015260a0820160a08201803582526020810135602083015260408101356040830152505061010082016101008201803582526020810135602083015260408101356040830152505050506102e08101356102e08301525050600101818118611e14575b5050806108005250506024358060a01c615e795761682052611f786154fe565b5f616840525f618c60525f6108005160208111615e7957801561201357905b610300810261082001610300618c806103008360045afa5050618c60514260405242618f6051610e10810281610e10820418615e79579050808201828110615e795790509050606052618e2051608052611ff2618f8061562e565b618f8051808201828110615e795790509050618c6052600101818118611f97575b505033604052618c6051606052612028615665565b5f6108005160208111615e795780156124c557905b610300810261082001610300618c806103008360045afa5050618c805161020052612069618fa061542d565b618fa051618f8052610180610360610180618c8060045afa5061208d618fa0615254565b618fa0516120fa57600f618fc0527f696e76616c696420636f6e746578740000000000000000000000000000000000618fe052618fc050618fc05180618fe001601f825f031636823750506308c379a0618f80526020618fa052601f19601f618fc0510116604401618f9cfd5b6101406040610140618cc060045afa50612115618fa0615297565b618fa0511561218357600d618fc0527f6163746976652072656e74616c00000000000000000000000000000000000000618fe052618fc050618fc05180618fe001601f825f031636823750506308c379a0618f80526020618fa052601f19601f618fc0510116604401618f9cfd5b618e0051604052618e2051606052618e4051608052618e605160a052618e805160c052618f605160e0526121b8618fa0615724565b618fa051612225576016618fc0527f6475726174696f6e206e6f742072657370656374656400000000000000000000618fe052618fc050618fc05180618fe001601f825f031636823750506308c379a0618f80526020618fa052601f19601f618fc0510116604401618f9cfd5b618e2051612292576012618fa0527f6c697374696e67206e6f74206163746976650000000000000000000000000000618fc052618fa050618fa05180618fc001601f825f031636823750506308c379a0618f60526020618f8052601f19601f618fa0510116604401618f7cfd5b618c805161046052610160610480610160618e0060045afa506044356105e052618ca051610600526122c2615965565b42618f6051610e10810281610e10820418615e79579050808201828110615e795790509050618fa052618f80516395941b73618fe052616820511561230957616820612312565b33618fc052618fc05b5161900052618fa05161902052803b15615e79575f618fe06044618ffc5f855af161233f573d5f5f3e3d5ffd5b50618c805161050052618ca05161052052610140610540610140618cc060045afa50600161068052612372618fc0615bf4565b618fc05033604052618c805160605242608052618fa05160a052612397618fe0615d31565b618fe051618fc052618fc051618fe052618ca0516190005233619020526168205161904052618c805161906052426190805242618e4051610e10810281610e10820418615e79579050808201828110615e7957905090506190a052618fa0516190c05242604052618fa051606052618e205160805261241761912061562e565b619120516190e05260025461910052618c805161036052618ca051610380526101406103a0610140618fe060045afa5061244f6154bf565b61684051601f8111615e7957610120810261686001618fc0518152618f80516020820152618ca0516040820152618c805160608201524260808201526190a05160a0820152618fa05160c08201526190e05160e0820152619100516101008201525060018101616840525060010181811861203d575b50507f8c4674b6dd5bb42474e86779169da5cbdc1c1e541e8e576f629dc865bf702e32608033618c805261682051618ca0526020615f21618cc03980618ce05280618c80015f6168405180835261012081025f8260208111615e7957801561255657905b61012081026168600161012082026020880101610120816101208460045afa505050600101818118612529575b50508201602001915050905081019050618c80a10061517d565b63f2cac92081186127b657606436103417615e79576004356004016020813511615e7957803560208160051b018083610500375050506024358060a01c615e7957610920526125bd6154fe565b5f610940525f6105005160208111615e7957801561271157905b8060051b6105200151611160526005611160516020525f5260405f20541561265e57600d611180527f696e76616c6964207374617465000000000000000000000000000000000000006111a0526111805061118051806111a001601f825f031636823750506308c379a061114052602061116052601f19601f61118051011660440161115cfd5b61116051610200526126716111a0615563565b6111a0516111805261118051632e2d29846111a052611160516111c052336111e0526109205161120052803b15615e79575f6111a060646111bc5f855af16126bb573d5f5f3e3d5ffd5b5061116051610360523361038052610140366103a0376126d96154bf565b61094051601f8111615e79578060061b61096001611180518152611160516020820152506001810161094052506001018181186125d7575b50507f14f25625ebd0b44e2a92d47d22a3eeff9b38c448dea84f07be367c8ebdadf88f608033611160526020615f2161118039806111a05280611160015f610940518083528060061b5f8260208111615e7957801561279857905b8060061b60208701018160061b610960018051825260208101516020830152505060010181811861276c575b50508201602001915050905081019050610920516111c052611160a1005b635622a776811861517d57608436103417615e79576004356004016020813511615e795780355f8160208111615e795780156128b457905b6101a08102610520016101a0820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e0830152610100810135610100830152610120810135610120830152505061018081013561018083015250506001018181186127ee575b5050806105005250506024358060201b615e7957613920526044358060201b615e7957613940526128e36154fe565b5f546139605261396051612956576015613980527f7374616b696e67206e6f7420737570706f7274656400000000000000000000006139a0526139805061398051806139a001601f825f031636823750506308c379a061394052602061396052601f19601f61398051011660440161395cfd5b5f613980525f6105005160208111615e79578015612b1057905b6101a08102610520016101a0613da06101a08360045afa5050613dc0513318156129f9576009613f40527f6e6f74206f776e65720000000000000000000000000000000000000000000000613f6052613f4050613f405180613f6001601f825f031636823750506308c379a0613f00526020613f2052601f19601f613f40510116604401613f1cfd5b610180610360610180613da060045afa50612a15613f40615254565b613f4051612a8257600f613f60527f696e76616c696420636f6e746578740000000000000000000000000000000000613f8052613f6050613f605180613f8001601f825f031636823750506308c379a0613f20526020613f4052601f19601f613f60510116604401613f3cfd5b613da05161020052612a95613f4061542d565b613f40516394ca6999613f6052613da051613f805261396051613fa05261392051613fc05261394051613fe052803b15615e79575f613f606084613f7c5f855af1612ae2573d5f5f3e3d5ffd5b5061398051601f8111615e7957613da0518160051b6139a00152600181016139805250600101818118612970575b50507f59dd9897d3d45fb2ad9a6c6675e80d6b5f2883c511744d68331e38fdd4dfcfe2606033613da0526020615f21613dc03980613de05280613da0015f613980518083528060051b5f8260208111615e79578015612b8957905b8060051b6139a001518160051b602088010152600101818118612b6b575b50508201602001915050905081019050613da0a10061517d565b6368bbb5598118612e3057604436103417615e79576004356004016020813511615e795780355f8160208111615e79578015612c9557905b610180810261052001610180820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e083015261010081013561010083015261012081013561012083015250505050600101818118612bdb575b5050806105005250505f613520525f6105005160208111615e79578015612d9257905b610180810261052001610180613d406101808360045afa5050610180610360610180613d4060045afa50612ced613ec0615254565b613ec051612d5a57600f613ee0527f696e76616c696420636f6e746578740000000000000000000000000000000000613f0052613ee050613ee05180613f0001601f825f031636823750506308c379a0613ea0526020613ec052601f19601f613ee0510116604401613ebcfd5b61352051601f8111615e79578060061b61354001613d40518152613d6051602082015250600181016135205250600101818118612cb8575b50506020615f615f395f51638fd404c7613d4052602080613d605280613d60015f613520518083528060061b5f8260208111615e79578015612dfc57905b8060061b60208701018160061b6135400180518252602081015160208301525050600101818118612dd0575b50508201602001915050905081015050803b15615e79575f613d40610844613d5c5f855af1612e2d573d5f5f3e3d5ffd5b50005b631e81a8b7811861517d57604436103417615e79576004356004016020813511615e795780355f8160208111615e79578015612f2257905b610180810261052001610180820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e083015261010081013561010083015261012081013561012083015250505050600101818118612e68575b5050806105005250505f613520525f6105005160208111615e795780156130f757905b6101808102610520016101806139406101808360045afa505061018061036061018061394060045afa50612f7a613ac0615254565b613ac051612fe757600f613ae0527f696e76616c696420636f6e746578740000000000000000000000000000000000613b0052613ae050613ae05180613b0001601f825f031636823750506308c379a0613aa0526020613ac052601f19601f613ae0510116604401613abcfd5b336020615f615f395f51636352211e613ac05261394051613ae0526020613ac06024613adc845afa61301b573d5f5f3e3d5ffd5b60203d10615e7957613ac0518060a01c615e7957613b0052613b0090505118156130a4576009613b20527f6e6f74206f776e65720000000000000000000000000000000000000000000000613b4052613b2050613b205180613b4001601f825f031636823750506308c379a0613ae0526020613b0052601f19601f613b20510116604401613afcfd5b613940516103605233610380526101406103a061014061398060045afa506130ca6154bf565b61352051601f8111615e7957613940518160051b6135400152600181016135205250600101818118612f45575b50507f5f1d5777673eb2dacd3b07f793491178b16d931e7241b2bdbc9c3620f62083a2606033613940526020615f2161396039806139805280613940015f613520518083528060051b5f8260208111615e7957801561317057905b8060051b61354001518160051b602088010152600101818118613152575b50508201602001915050905081019050613940a10061517d565b63b137c422811861517d57604436103417615e79576004356004016020813511615e795780355f8160208111615e7957801561327c57905b610180810261052001610180820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e0830152610100810135610100830152610120810135610120830152505050506001018181186131c2575b5050806105005250505f613520525f6105005160208111615e795780156133ef57905b6101808102610520016101806139406101808360045afa505061018061036061018061394060045afa506132d4613ac0615254565b613ac05161334157600f613ae0527f696e76616c696420636f6e746578740000000000000000000000000000000000613b0052613ae050613ae05180613b0001601f825f031636823750506308c379a0613aa0526020613ac052601f19601f613ae0510116604401613abcfd5b336139605118156133b1576009613ac0527f6e6f74206f776e65720000000000000000000000000000000000000000000000613ae052613ac050613ac05180613ae001601f825f031636823750506308c379a0613a80526020613aa052601f19601f613ac0510116604401613a9cfd5b426006613940516020525f5260405f205561352051601f8111615e7957613940518160051b613540015260018101613520525060010181811861329f575b50507f61cf4a9dff83a5d31c96658f0e9e1c1f5fde0405271ebe5e76a7347209a0b0fb606033613940524261396052806139805280613940015f613520518083528060051b5f8260208111615e7957801561346457905b8060051b61354001518160051b602088010152600101818118613446575b50508201602001915050905081019050613940a10061517d565b631a93aa93811861517d57606436103417615e79576004356004016020813511615e795780355f8160208111615e795780156135fa57905b61030081026106a001610300820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e0830152610100810135610100830152610120810135610120830152505061018082016101808201803582526020810135602083015260408101356040830152606081013560608301526080810135608083015260a0820160a08201803582526020810135602083015260408101356040830152505061010082016101008201803582526020810135602083015260408101356040830152505050506102e08101356102e083015250506001018181186134b6575b5050806106805250505f6166a0525f618ec052604036618ee0375f6106805160208111615e79578015613bcb57905b61030081026106a001610300618f206103008360045afa5050618f20516102005261365561924061542d565b6192405161922052610180610360610180618f2060045afa50613679619240615254565b619240516136e657600f619260527f696e76616c696420636f6e7465787400000000000000000000000000000000006192805261926050619260518061928001601f825f031636823750506308c379a061922052602061924052601f19601f61926051011660440161923cfd5b6101406040610140618f6060045afa50613701619240615297565b6192405161376e576010619260527f6e6f206163746976652072656e74616c000000000000000000000000000000006192805261926050619260518061928001601f825f031636823750506308c379a061922052602061924052601f19601f61926051011660440161923cfd5b618fa0513318156137de57601b619240527f6e6f742072656e746572206f66206163746976652072656e74616c00000000006192605261924050619240518061926001601f825f031636823750506308c379a061920052602061922052601f19601f61924051011660440161921cfd5b6190a0516040526190c0516060526190e0516080526191005160a0526191205160c0526192005160e052613813619240615724565b61924051613880576016619260527f6475726174696f6e206e6f7420726573706563746564000000000000000000006192805261926050619260518061928001601f825f031636823750506308c379a061922052602061924052601f19601f61926051011660440161923cfd5b6190c0516138ed576012619240527f6c697374696e67206e6f742061637469766500000000000000000000000000006192605261924050619240518061926001601f825f031636823750506308c379a061920052602061922052601f19601f61924051011660440161921cfd5b618f2051610460526101606104806101606190a060045afa506024356105e052618f40516106005261391d615965565b4261920051610e10810281610e10820418615e79579050808201828110615e7957905090506192405242619260526190205142101561395f5761902051619260525b6190405161900051808203828111615e7957905090506040526192605161900051808203828111615e795790509050606052619060516080526139a36192a0615d80565b6192a0516192805242604052619240516060526190c0516080526139c86192c061562e565b6192c0516192a052618f00516192a051808201828110615e795790509050618f00526190605161928051808203828111615e7957905090506192c052618ee0516192c051808201828110615e795790509050618ee0526192805161908051808202811583838304141715615e795790509050612710810490506192e052618ec0516192e051808201828110615e795790509050618ec052618f605161930052618f4051619320523361934052618fc05161936052618f205161938052426193a052426190e051610e10810281610e10820418615e79579050808201828110615e7957905090506193c052619240516193e0526192a0516194005260025461942052618f205161036052618f4051610380526101406103a061014061930060045afa50613af26154bf565b6007618f40516020525f5260405f208054619280516192e051808203828111615e795790509050808201828110615e7957905090508155506166a051601f8111615e795761014081026166c001618f60518152619220516020820152618f80516040820152618fe0516060820152426080820152426190e051610e10810281610e10820418615e79579050808201828110615e79579050905060a08201526192405160c08201526192805160e08201526192a0516101008201526190805161012082015250600181016166a05250600101818118613629575b5050618f0051618ee05111613c1157618f0051618ee0511015613c365733604052618f0051618ee051808203828111615e795790509050606052613c3661566556613c36565b33604052618ee051618f0051808203828111615e795790509050606052613c36615daf565b618ec05115613c5857600854618ec051808201828110615e7957905090506008555b7fa811dbbf231ee171f33b26c54ff3d080f0987b0a772f38f9fea9ce837f068063606033618f20526020615f21618f403980618f605280618f20015f6166a05180835261014081025f8260208111615e79578015613cdf57905b61014081026166c00161014082026020880101610140816101408460045afa505050600101818118613cb2575b50508201602001915050905081019050618f20a10061517d565b63368eaf5b811861517d57604436103417615e79576004356004016020813511615e795780355f8160208111615e79578015613deb57905b610180810261082001610180820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e083015261010081013561010083015261012081013561012083015250505050600101818118613d31575b5050806108005250505f613820525f614040525f614860525f6108005160208111615e7957801561419457905b6101808102610820016101806148806101808360045afa505061018061036061018061488060045afa50613e4d614a00615254565b614a0051613eba57600f614a20527f696e76616c696420636f6e746578740000000000000000000000000000000000614a4052614a2050614a205180614a4001601f825f031636823750506308c379a06149e0526020614a0052601f19601f614a205101166044016149fcfd5b61014060406101406148c060045afa50613ed5614a00615297565b614a005115613f4357600d614a20527f6163746976652072656e74616c00000000000000000000000000000000000000614a4052614a2050614a205180614a4001601f825f031636823750506308c379a06149e0526020614a0052601f19601f614a205101166044016149fcfd5b6020615f615f395f516342a0106b614a205261488051614a40526020614a206024614a3c845afa613f76573d5f5f3e3d5ffd5b60203d10615e7957614a20518060a01c615e7957614a6052614a60905051614a0052614a00511561401557614a0051331815614085576009614a20527f6e6f74206f776e65720000000000000000000000000000000000000000000000614a4052614a2050614a205180614a4001601f825f031636823750506308c379a06149e0526020614a0052601f19601f614a205101166044016149fcfd614085565b6148a051331815614085576009614a20527f6e6f74206f776e65720000000000000000000000000000000000000000000000614a4052614a2050614a205180614a4001601f825f031636823750506308c379a06149e0526020614a0052601f19601f614a205101166044016149fcfd5b6148805161020052614098614a4061542d565b614a4051614a205261488051610500526148a051610520526101406105406101406148c060045afa505f610680526140d1614a40615bf4565b614a4050614880516040526140e4615e67565b61404051601f8111615e79578060061b614060016148805181526148a051602082015250600181016140405250614a205162f714ce614a405261488051614a605233614a8052803b15615e79575f614a406044614a5c5f855af161414a573d5f5f3e3d5ffd5b50426006614880516020525f5260405f205561382051601f8111615e79578060061b61384001614a2051815261488051602082015250600181016138205250600101818118613e18575b50506020615f615f395f5163ebc803d0614880526020806148a052806148a0015f614040518083528060061b5f8260208111615e795780156141fe57905b8060061b60208701018160061b61406001805182526020810151602083015250506001018181186141d2575b50508201602001915050905081015050803b15615e79575f61488061084461489c5f855af161422f573d5f5f3e3d5ffd5b506007336020525f5260405f205461488052614880511561426b575f6007336020525f5260405f2055336040526148805160605261426b615daf565b7f66e25f0f38428dc92a79bde4219b9209156f468e2360faa803c0798298b411526080336148a0526020615f216148c039614880516148e0528061490052806148a0015f613820518083528060061b5f8260208111615e795780156142f857905b8060061b60208701018160061b61384001805182526020810151602083015250506001018181186142cc575b505082016020019150509050810190506148a0a10061517d565b63295f385a811861517d57606436103417615e79576004356004016020813511615e795780355f8160208111615e7957801561441057905b6101a08102610520016101a0820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e08301526101008101356101008301526101208101356101208301525050610180810135610180830152505060010181811861434a575b5050806105005250506024358060201b615e7957613920526144306154fe565b5f5461394052613940516144a3576015613960527f7374616b696e67206e6f7420737570706f7274656400000000000000000000006139805261396050613960518061398001601f825f031636823750506308c379a061392052602061394052601f19601f61396051011660440161393cfd5b5f613960525f6105005160208111615e7957801561473d57905b6101a08102610520016101a06141806101a08360045afa50506141a051331815614546576009614320527f6e6f74206f776e657200000000000000000000000000000000000000000000006143405261432050614320518061434001601f825f031636823750506308c379a06142e052602061430052601f19601f6143205101166044016142fcfd5b61018061036061018061418060045afa50614562614320615254565b614320516145cf57600f614340527f696e76616c696420636f6e7465787400000000000000000000000000000000006143605261434050614340518061436001601f825f031636823750506308c379a061430052602061432052601f19601f61434051011660440161431cfd5b61418051610200526145e261434061542d565b61434051614320526020615f015f395f516323b872dd6143405233614360526143205161438052614300516143a0526020614340606461435c5f855af161462b573d5f5f3e3d5ffd5b60203d10615e7957614340518060011c615e79576143c0526143c09050516146b25760136143e0527f7472616e7366657246726f6d206661696c656400000000000000000000000000614400526143e0506143e0518061440001601f825f031636823750506308c379a06143a05260206143c052601f19601f6143e05101166044016143bcfd5b61432051637cfb8a756143405233614360526143005161438052614180516143a052613940516143c052613920516143e052803b15615e79575f61434060a461435c5f855af1614704573d5f5f3e3d5ffd5b5061396051601f8111615e79578060061b61398001614180518152614300516020820152506001810161396052506001018181186144bd575b50507fda7e91c665c767ab0ceda28c5f7a59924da2e798ddc67088394339700c8a983c606033614180526020615f216141a039806141c05280614180015f613960518083528060061b5f8260208111615e795780156147c457905b8060061b60208701018160061b6139800180518252602081015160208301525050600101818118614798575b50508201602001915050905081019050614180a10061517d565b632995627c8118614be857608436103417615e79576004356004016020813511615e795780355f8160208111615e795780156148dc57905b6101a08102610520016101a0820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e083015261010081013561010083015261012081013561012083015250506101808101356101808301525050600101818118614816575b5050806105005250506024358060a01c615e7957613920526044358060201b615e7957613940525f546139605261396051614976576015613980527f7374616b696e67206e6f7420737570706f7274656400000000000000000000006139a0526139805061398051806139a001601f825f031636823750506308c379a061394052602061396052601f19601f61398051011660440161395cfd5b5f613980525f6105005160208111615e79578015614b4357905b6101a08102610520016101a06141a06101a08360045afa50506141c051331815614a19576009614340527f6e6f74206f776e657200000000000000000000000000000000000000000000006143605261434050614340518061436001601f825f031636823750506308c379a061430052602061432052601f19601f61434051011660440161431cfd5b6101806103606101806141a060045afa50614a35614340615254565b61434051614aa257600f614360527f696e76616c696420636f6e7465787400000000000000000000000000000000006143805261436050614360518061438001601f825f031636823750506308c379a061432052602061434052601f19601f61436051011660440161433cfd5b6141a05161020052614ab561434061542d565b61434051639babe7bd614360526139205161438052614320516143a0526141a0516143c052613960516143e0526139405161440052803b15615e79575f61436060a461437c5f855af1614b0a573d5f5f3e3d5ffd5b5061398051601f8111615e79578060061b6139a0016141a051815261432051602082015250600181016139805250600101818118614990575b50507fc0145443abe0348e5fbb3cddc9f89bbef6cc14377065302899fa2fe479a750366080336141a0526020615f216141c039613920516141e0528061420052806141a0015f613980518083528060061b5f8260208111615e79578015614bd257905b8060061b60208701018160061b6139a00180518252602081015160208301525050600101818118614ba6575b505082016020019150509050810190506141a0a1005b636696eac6811861517d57604436103417615e79576004356004016020813511615e795780355f8160208111615e79578015614cda57905b610180810261082001610180820260208601018035825260208101358060a01c615e7957602083015260408201604082018035825260208101358060a01c615e7957602083015260408101358060a01c615e7957604083015260608101358060a01c615e795760608301526080810135608083015260a081013560a083015260c081013560c083015260e081013560e083015261010081013561010083015261012081013561012083015250505050600101818118614c20575b5050806108005250505f613820525f6108005160208111615e79578015614e8c57905b6101808102610820016101806140406101808360045afa505061018061036061018061404060045afa50614d326141c0615254565b6141c051614d9f57600f6141e0527f696e76616c696420636f6e746578740000000000000000000000000000000000614200526141e0506141e0518061420001601f825f031636823750506308c379a06141a05260206141c052601f19601f6141e05101166044016141bcfd5b33614060511815614e0f5760096141c0527f6e6f74206f776e657200000000000000000000000000000000000000000000006141e0526141c0506141c051806141e001601f825f031636823750506308c379a06141805260206141a052601f19601f6141c051011660440161419cfd5b6140405161050052614060516105205261014061054061014061408060045afa50600161068052614e41614300615bf4565b6143006101406141c06101408360045afa505061382051601f8111615e79578060061b613840016140405181526142c051602082015250600181016138205250600101818118614cfd575b50506007336020525f5260405f20546140405261404051614f0c576013614060527f6e6f207265776172647320746f20636c61696d000000000000000000000000006140805261406050614060518061408001601f825f031636823750506308c379a061402052602061404052601f19601f61406051011660440161403cfd5b6020615f015f395f5163a9059cbb614060523361408052614040516140a0526020614060604461407c5f855af1614f45573d5f5f3e3d5ffd5b60203d10615e7957614060518060011c615e79576140c0526140c0905051614fcc57600f6140e0527f7472616e73666572206661696c65640000000000000000000000000000000000614100526140e0506140e0518061410001601f825f031636823750506308c379a06140a05260206140c052601f19601f6140e05101166044016140bcfd5b5f6007336020525f5260405f20557f75d9fb02b6811f542f9236825a4f8c3698e023691c1fd76b15ece3d40264b41160a033614060526020615f2161408039614040516140a0526008546140c052806140e05280614060015f613820518083528060061b5f8260208111615e7957801561506e57905b8060061b60208701018160061b6138400180518252602081015160208301525050600101818118615042575b50508201602001915050905081019050614060a10061517d565b630ff5ce72811861517d57602436103417615e79576004358060011c615e79576040526003543318156151115760126060527f6e6f742070726f746f636f6c2061646d696e000000000000000000000000000060805260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b7f61546262c46330c86d6db302369d59188947245ae9c631d9c48155bcd8ffaebe60095460605260405160805260406060a16040516009550061517d565b63b6b92522811861517d57602436103417615e7957602060043561016052615178610200615355565b610200f35b5f5ffd5b5f604051816101e00152602081019050606051816101e00152602081019050608051816101e0015260208101905060a051816101e0015260208101905060c051816101e0015260208101905060e051816101e0015260208101905061010051816101e0015260208101905061012051816101e0015260208101905061014051816101e0015260208101905061016051816101e0015260208101905061018051816101e001526020810190506101a051816101e00152602081019050806101c0526101c09050805160208201209050815250565b610360516040526103805160605261014060806101406103a060045afa5061527d6104e0615181565b6104e0516005610360516020525f5260405f205414815250565b426101205111815250565b73ffffffffffffffffffffffffffffffffffffffff604051168060a01c615e7957815250565b5f7fff0000000000000000000000000000000000000000000000000000000000000081610100015260018101905060a0518060601b90508161010001526014810190506060518161010001526020810190506080518161010001526020810190508060e05260e0905080516020820120905060c05260c05160405261534d60e06152a2565b60e051815250565b610160516060525f7f602d3d8160093d39f30000000000000000000000000000000000000000000000816101a001526009810190507f363d3d373d3d3d363d7300000000000000000000000000000000000000000000816101a00152600a810190506020615ee15f395f518060601b9050816101a001526014810190507f5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000816101a00152600f81019050806101805261018090508051602082012090506080523060a0526154246101e06152c8565b6101e051815250565b6102005161016052615440610240615355565b6102405161022052610220513b6154b657601c610240527f6e6f207661756c742065786973747320666f7220746f6b656e5f6964000000006102605261024050610240518061026001601f825f031636823750506308c379a061020052602061022052601f19601f61024051011660440161021cfd5b61022051815250565b610360516040526103805160605261014060806101406103a060045afa506154e86104e0615181565b6104e0516005610360516020525f5260405f2055565b600954156155615760066040527f706175736564000000000000000000000000000000000000000000000000000060605260405060405180606001601f825f031636823750506308c379a05f526020602052601f19601f6040510116604401601cfd5b565b6102005161016052615576610240615355565b6102405161022052610220513b615625577f602d3d8160093d39f3363d3d373d3d3d363d7300000000000000000000000000610240526020615ee15f395f5160601b610253527f5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000610267526102005160366102405ff58015615e7957610220526102205163592e6f5961024052803b15615e79575f610240600461025c5f855af1615623573d5f5f3e3d5ffd5b505b61022051815250565b606051604051808203828111615e795790509050608051808202811583838304141715615e795790509050610e1081049050815250565b6020615f015f395f516323b872dd60805260405160a0523060c05260605160e052602060806064609c5f855af161569e573d5f5f3e3d5ffd5b60203d10615e79576080518060011c615e795761010052610100905051615722576013610120527f7472616e7366657246726f6d206661696c6564000000000000000000000000006101405261012050610120518061014001601f825f031636823750506308c379a060e052602061010052601f19601f61012051011660440160fcfd5b565b60805160e0511015615736575f61574d565b60a05161574457600161574d565b60a05160e05111155b815250565b6101a0515f610440525f60026101c0527f19010000000000000000000000000000000000000000000000000000000000006101e0526101c08051602082018361036001815181525050808301925050506020615ec1610300397f8bfe2af4290476395b89e8859d048827bdabb82447fa4a7943209a078a3030ff6102205260405161024052606051610260526080516102805260a0516102a05260c0516102c05260c0610200526102008051602082012090506103205260406102e0526102e080516020820183610360018281848460045afa50505080830192505050806103405261034090508051602082012090506103c05260e0516103e05261010051610400526101205161042052602061044060806103c060015afa506104405114815250565b6003545f610380525f60026101c0527f19000000000000000000000000000000000000000000000000000000000000006101e0526101c0805160208201836102a00181518152505080830192505050308060601b9050816102a0015260148101905060e0516102205261010051610240526101205161026052606061020052610200805160208201209050816102a001526020810190506101a051816102a0015260208101905080610280526102809050805160208201209050610300526101405161032052610160516103405261018051610360526020610380608061030060015afa506103805114815250565b610480516104605118156159d8576010610620527f696e76616c696420746f6b656e5f6964000000000000000000000000000000006106405261062050610620518061064001601f825f031636823750506308c379a06105e052602061060052601f19601f6106205101166044016105fcfd5b610160604061016061048060045afa50610600516101a0526159fb610620615752565b61062051615a68576017610640527f696e76616c6964206f776e6572207369676e61747572650000000000000000006106605261064050610640518061066001601f825f031636823750506308c379a061060052602061062052601f19601f61064051011660440161061cfd5b610160604061016061048060045afa506105e0516101a052615a8b610620615876565b61062051615af8576017610640527f696e76616c69642061646d696e207369676e61747572650000000000000000006106605261064050610640518061066001601f825f031636823750506308c379a061060052602061062052601f19601f61064051011660440161061cfd5b426105e05160788101818110615e7957905011615b7457600f610620527f6c697374696e67206578706972656400000000000000000000000000000000006106405261062050610620518061064001601f825f031636823750506308c379a06105e052602061060052601f19601f6106205101166044016105fcfd5b610500516006610480516020525f5260405f205410615bf257600f610620527f6c697374696e67207265766f6b656400000000000000000000000000000000006106405261062050610620518061064001601f825f031636823750506308c379a06105e052602061060052601f19601f6106205101166044016105fcfd5b565b61064051615c03576001615c0b565b426106205110155b615d1e576106405161066051808202811583838304141715615e795790509050612710810490506106a0526007610560516020525f5260405f208054610640516106a051808203828111615e795790509050808201828110615e7957905090508155506008546106a051808201828110615e795790509050600855610540516106c052610560516106e05261058051610700526105a0516107205261050051610740526105e051610760526106005161078052610620516107a0525f6107c052610660516107e0526106805115615d0557610500516103605261052051610380526101406103a06101406106c060045afa50615d056154bf565b610140816101406106c060045afa5050615d2f56615d2f565b6101408161014061054060045afa50505b565b5f6040518160e001526020810190506060518160e001526020810190506080518160e0015260208101905060a0518160e001526020810190508060c05260c09050805160208201209050815250565b608051606051808202811583838304141715615e7957905090506040518015615e795780820490509050815250565b6020615f015f395f5163a9059cbb60805260405160a05260605160c052602060806044609c5f855af1615de4573d5f5f3e3d5ffd5b60203d10615e79576080518060011c615e795760e05260e0905051615e65576013610100527f7472616e7366657246726f6d206661696c6564000000000000000000000000006101205261010050610100518061012001601f825f031636823750506308c379a060c052602060e052601f19601f61010051011660440160dcfd5b565b5f60056040516020525f5260405f2055565b5f80fd0283037950883cf947de03b7517d007a517d00584312517d001803d92570517d517d2ba3077d1980318a517d129e08521404517d03f91424517d079d514f347e517d1444a4b6fe9c639623601061ef4f9669fae3add32ee1111573ccc1371fa56f57e15700000000000000000000000094fa19545e51ea6f2c12d2c8480af5657f8a30b20000000000000000000000004d224452801aced8b2f0aebe155379bb5d5943810000000000000000000000003bdca51226202fc2a64211aa35a8d95d61c6ca99000000000000000000000000c3aa9bc72bd623168860a1e5c6a4530d3d80456c000000000000000000000000cbe9b03415175d1d410801bad7783f8ac8aba89f00000000000000000000000000000000000000000000000000000000000003e8

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000094fa19545e51ea6f2c12d2c8480af5657f8a30b20000000000000000000000004d224452801aced8b2f0aebe155379bb5d5943810000000000000000000000003bdca51226202fc2a64211aa35a8d95d61c6ca99000000000000000000000000c3aa9bc72bd623168860a1e5c6a4530d3d80456c000000000000000000000000cbe9b03415175d1d410801bad7783f8ac8aba89f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007d96cc26566bfca358c61fbe7be3ca771da7ea6000000000000000000000000314ba3811129ae06fc35894a3bb62157028a9fd9

-----Decoded View---------------
Arg [0] : _vault_impl_addr (address): 0x94fA19545e51eA6f2C12d2C8480aF5657F8A30B2
Arg [1] : _payment_token_addr (address): 0x4d224452801ACEd8B2F0aebE155379bb5D594381
Arg [2] : _nft_contract_addr (address): 0x3Bdca51226202Fc2a64211Aa35A8d95D61C6ca99
Arg [3] : _delegation_registry_addr (address): 0xC3AA9bc72Bd623168860a1e5c6a4530d3D80456c
Arg [4] : _renting_erc721 (address): 0xcBe9b03415175d1D410801bAD7783F8ac8aBa89F
Arg [5] : _staking_addr (address): 0x0000000000000000000000000000000000000000
Arg [6] : _max_protocol_fee (uint256): 1000
Arg [7] : _protocol_fee (uint256): 0
Arg [8] : _protocol_wallet (address): 0x07d96cC26566BFCA358C61fBe7be3Ca771Da7EA6
Arg [9] : _protocol_admin (address): 0x314BA3811129AE06Fc35894a3Bb62157028A9Fd9

-----Encoded View---------------
10 Constructor Arguments found :
Arg [0] : 00000000000000000000000094fa19545e51ea6f2c12d2c8480af5657f8a30b2
Arg [1] : 0000000000000000000000004d224452801aced8b2f0aebe155379bb5d594381
Arg [2] : 0000000000000000000000003bdca51226202fc2a64211aa35a8d95d61c6ca99
Arg [3] : 000000000000000000000000c3aa9bc72bd623168860a1e5c6a4530d3d80456c
Arg [4] : 000000000000000000000000cbe9b03415175d1d410801bad7783f8ac8aba89f
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [6] : 00000000000000000000000000000000000000000000000000000000000003e8
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [8] : 00000000000000000000000007d96cc26566bfca358c61fbe7be3ca771da7ea6
Arg [9] : 000000000000000000000000314ba3811129ae06fc35894a3bb62157028a9fd9


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.