ETH Price: $1,983.11 (-4.84%)

Contract

0x5F19431BC8A3eb21222771c6C867a63a119DeDA7
 

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Create_loan246019882026-03-07 0:26:232 hrs ago1772843183IN
0x5F19431B...a119DeDA7
0 ETH0.000379992.04607397
Create_loan246019842026-03-07 0:25:352 hrs ago1772843135IN
0x5F19431B...a119DeDA7
0 ETH0.000388972.0416793
Create_loan246019822026-03-07 0:25:112 hrs ago1772843111IN
0x5F19431B...a119DeDA7
0 ETH0.000388952.04169449
Create_loan246019802026-03-07 0:24:472 hrs ago1772843087IN
0x5F19431B...a119DeDA7
0 ETH0.000494152.04361873
Settle_loan245855622026-03-04 17:22:592 days ago1772644979IN
0x5F19431B...a119DeDA7
0 ETH0.000350782.41992856
Replace_loan245731132026-03-02 23:41:474 days ago1772494907IN
0x5F19431B...a119DeDA7
0 ETH0.000299092.04959341
Replace_loan245731112026-03-02 23:41:234 days ago1772494883IN
0x5F19431B...a119DeDA7
0 ETH0.000298882.0449719
Replace_loan245731082026-03-02 23:40:474 days ago1772494847IN
0x5F19431B...a119DeDA7
0 ETH0.000299222.05053123
Settle_loan245731022026-03-02 23:39:354 days ago1772494775IN
0x5F19431B...a119DeDA7
0 ETH0.000316592.05280996
Replace_loan245659812026-03-01 23:47:355 days ago1772408855IN
0x5F19431B...a119DeDA7
0 ETH0.000415212.040079
Create_loan245621482026-03-01 10:59:115 days ago1772362751IN
0x5F19431B...a119DeDA7
0 ETH0.000457432.03292441
Settle_loan245612462026-03-01 7:57:475 days ago1772351867IN
0x5F19431B...a119DeDA7
0 ETH0.000334812.03312491
Settle_loan245612122026-03-01 7:50:595 days ago1772351459IN
0x5F19431B...a119DeDA7
0 ETH0.000260812.03365844
Settle_loan245459972026-02-27 4:52:357 days ago1772167955IN
0x5F19431B...a119DeDA7
0 ETH0.000305372.04480898
Settle_loan245357612026-02-25 18:37:119 days ago1772044631IN
0x5F19431B...a119DeDA7
0 ETH0.000330382.20051383
Replace_loan245353052026-02-25 17:05:239 days ago1772039123IN
0x5F19431B...a119DeDA7
0 ETH0.000154840.94871693
Create_loan245325492026-02-25 7:51:359 days ago1772005895IN
0x5F19431B...a119DeDA7
0 ETH0.00040362.03539362
Create_loan245288152026-02-24 19:20:4710 days ago1771960847IN
0x5F19431B...a119DeDA7
0 ETH0.000464292.06340996
Create_loan245283972026-02-24 17:56:5910 days ago1771955819IN
0x5F19431B...a119DeDA7
0 ETH0.000400472.07796505
Replace_loan245226092026-02-23 22:35:2311 days ago1771886123IN
0x5F19431B...a119DeDA7
0 ETH0.000013420.09187285
Claim_defaulted_...245206252026-02-23 15:56:5911 days ago1771862219IN
0x5F19431B...a119DeDA7
0 ETH0.000225612.09076193
Settle_loan245086002026-02-21 23:43:4713 days ago1771717427IN
0x5F19431B...a119DeDA7
0 ETH0.000263842.03467675
Settle_loan245085972026-02-21 23:43:1113 days ago1771717391IN
0x5F19431B...a119DeDA7
0 ETH0.000273392.03322668
Settle_loan245085942026-02-21 23:42:3513 days ago1771717355IN
0x5F19431B...a119DeDA7
0 ETH0.000273222.03233162
Settle_loan245085902026-02-21 23:41:4713 days ago1771717307IN
0x5F19431B...a119DeDA7
0 ETH0.000273412.03342609
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
P2PLendingNfts

Compiler Version
vyper:0.3.10

Optimization Enabled:
N/A

Other Settings:
default evmVersion, None license

Contract Source Code (Vyper language format)

# @version 0.3.10

"""
@title P2PLendingNfts
@author [Zharta](https://zharta.io/)
@notice This contract facilitates peer-to-peer lending using NFTs as collateral.
@dev It facilitates peer-to-peer lending using NFTs as collateral.
      The contract allows lenders to offer loans and borrowers to accept them by providing NFTs as collateral.
      Key functionalities include:
      - Creating and managing loan offers
      - Accepting loan offers and locking NFTs as collateral
      - Accepts ERC721 and CryptoPunks NFTs as collateral
      - Delegating the collateral using [Delegate](https://delegate.xyz/) DelegateRegistry v2
      - Settling loans by repaying the principal and interest
      - Claiming collateral in case of loan default
      - Replacing existing loans with new terms
      - Four types of fees are supported: protocol fee, origination fee, lender broker fee, and borrower broker fee
      - Managing protocol fees and authorized proxies
      - Handling ownership transfer of the contract
      - Loan state is kept hashed in the contract to save gas
      The contract ensures secure and transparent lending operations within the Zharta ecosystem.
"""

# Interfaces

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


interface CryptoPunksMarket:
    def transferPunk(to: address, punkIndex: uint256): nonpayable
    def buyPunk(punkIndex: uint256): payable
    def punksOfferedForSale(punkIndex: uint256) -> PunkOffer: view
    def punkIndexToAddress(punkIndex: uint256) -> address: view
    def offerPunkForSaleToAddress(punkIndex: uint256, minSalePriceInWei: uint256, toAddress: address): nonpayable

interface DelegationRegistry:
    def delegateERC721(delegate: address, contract: address, token_id: uint256, rights: bytes32, _value: bool) -> bytes32: nonpayable

interface P2PLendingControl:
    def get_collection_status(collection_key_hash: bytes32) -> CollectionStatus: nonpayable

# Structs

PROOF_MAX_SIZE: constant(uint256) = 32
MAX_FEES: constant(uint256) = 4
BPS: constant(uint256) = 10000

enum FeeType:
    PROTOCOL_FEE
    ORIGINATION_FEE
    LENDER_BROKER_FEE
    BORROWER_BROKER_FEE

enum OfferType:
    TOKEN
    COLLECTION
    TRAIT

struct Fee:
    type: FeeType
    upfront_amount: uint256
    interest_bps: uint256
    wallet: address

struct FeeAmount:
    type: FeeType
    amount: uint256
    wallet: address

struct Offer:
    principal: uint256
    interest: uint256
    payment_token: address
    duration: uint256
    origination_fee_amount: uint256
    broker_upfront_fee_amount: uint256
    broker_settlement_fee_bps: uint256
    broker_address: address
    offer_type: OfferType
    token_id: uint256
    token_range_min: uint256
    token_range_max: uint256
    collection_key_hash: bytes32
    trait_hash: bytes32
    expiration: uint256
    lender: address
    pro_rata: bool
    size: uint256
    tracing_id: bytes32


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

struct SignedOffer:
    offer: Offer
    signature: Signature

struct Loan:
    id: bytes32
    offer_id: bytes32
    offer_tracing_id: bytes32
    amount: uint256  # principal - origination_fee_amount
    interest: uint256
    payment_token: address
    maturity: uint256
    start_time: uint256
    borrower: address
    lender: address
    collateral_contract: address
    collateral_token_id: uint256
    fees: DynArray[Fee, MAX_FEES]
    pro_rata: bool
    delegate: address


struct CollectionStatus:
    contract: address
    trait_root: bytes32

struct PunkOffer:
    isForSale: bool
    punkIndex: uint256
    seller: address
    minValue: uint256
    onlySellTo: address

event LoanCreated:
    id: bytes32
    amount: uint256
    interest: uint256
    payment_token: address
    maturity: uint256
    start_time: uint256
    borrower: address
    lender: address
    collateral_contract: address
    collateral_token_id: uint256
    fees: DynArray[Fee, MAX_FEES]
    pro_rata: bool
    offer_id: bytes32
    offer_tracing_id: bytes32
    delegate: address

event LoanReplaced:
    id: bytes32
    amount: uint256
    interest: uint256
    payment_token: address
    maturity: uint256
    start_time: uint256
    collateral_contract: address
    collateral_token_id: uint256
    borrower: address
    lender: address
    fees: DynArray[Fee, MAX_FEES]
    pro_rata: bool
    original_loan_id: bytes32
    paid_principal: uint256
    paid_interest: uint256
    paid_settlement_fees: DynArray[FeeAmount, MAX_FEES]
    offer_id: bytes32
    offer_tracing_id: bytes32

event LoanReplacedByLender:
    id: bytes32
    amount: uint256
    interest: uint256
    payment_token: address
    maturity: uint256
    start_time: uint256
    collateral_contract: address
    collateral_token_id: uint256
    borrower: address
    lender: address
    fees: DynArray[Fee, MAX_FEES]
    pro_rata: bool
    original_loan_id: bytes32
    paid_principal: uint256
    paid_interest: uint256
    paid_settlement_fees: DynArray[FeeAmount, MAX_FEES]
    borrower_compensation: uint256
    offer_id: bytes32
    offer_tracing_id: bytes32

event LoanPaid:
    id: bytes32
    borrower: address
    lender: address
    payment_token: address
    paid_principal: uint256
    paid_interest: uint256
    paid_settlement_fees: DynArray[FeeAmount, MAX_FEES]

event LoanCollateralClaimed:
    id: bytes32
    borrower: address
    lender: address
    collateral_contract: address
    collateral_token_id: uint256

event OfferRevoked:
    offer_id: bytes32
    lender: address
    collection_key_hash: bytes32
    offer_type: OfferType

event OwnerProposed:
    owner: address
    proposed_owner: address

event OwnershipTransferred:
    old_owner: address
    new_owner: address

event ProtocolFeeSet:
    old_upfront_fee: uint256
    old_settlement_fee: uint256
    new_upfront_fee: uint256
    new_settlement_fee: uint256

event ProtocolWalletChanged:
    old_wallet: address
    new_wallet: address

event ProxyAuthorizationChanged:
    proxy: address
    value: bool

event TransferFailed:
    _to: address
    amount: uint256

event PendingTransfersClaimed:
    _to: address
    amount: uint256


# Global variables

owner: public(address)
proposed_owner: public(address)

payment_token: public(immutable(address))
loans: public(HashMap[bytes32, bytes32])
delegation_registry: public(immutable(DelegationRegistry))
cryptopunks: public(immutable(CryptoPunksMarket))
p2p_control: public(immutable(P2PLendingControl))

protocol_wallet: public(address)
protocol_upfront_fee: public(uint256)
protocol_settlement_fee: public(uint256)
max_protocol_upfront_fee: public(immutable(uint256))
max_protocol_settlement_fee: public(immutable(uint256))
max_lender_broker_settlement_fee: public(immutable(uint256))
max_borrower_broker_settlement_fee: public(immutable(uint256))

offer_count: public(HashMap[bytes32, uint256])
revoked_offers: public(HashMap[bytes32, bool])

authorized_proxies: public(HashMap[address, bool])
pending_transfers: public(HashMap[address, uint256])

VERSION: public(constant(String[30])) = "P2PLendingNfts.20241002"

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)")
OFFER_TYPE_DEF: constant(String[413]) = "Offer(uint256 principal,uint256 interest,address payment_token,uint256 duration,uint256 origination_fee_amount," \
                                        "uint256 broker_upfront_fee_amount,uint256 broker_settlement_fee_bps,address broker_address," \
                                        "uint256 offer_type,uint256 token_id,uint256 token_range_min,uint256 token_range_max,bytes32 collection_key_hash," \
                                        "bytes32 trait_hash,uint256 expiration,address lender,bool pro_rata,uint256 size,bytes32 tracing_id)"
OFFER_TYPE_HASH: constant(bytes32) = keccak256(OFFER_TYPE_DEF)

offer_sig_domain_separator: immutable(bytes32)


@external
def __init__(
    _payment_token: address,
    _p2p_control: address,
    _delegation_registry: address,
    _cryptopunks: address,
    _protocol_upfront_fee: uint256,
    _protocol_settlement_fee: uint256,
    _protocol_wallet: address,
    _max_protocol_upfront_fee: uint256,
    _max_protocol_settlement_fee: uint256,
    _max_lender_broker_settlement_fee: uint256,
    _max_borrower_broker_settlement_fee: uint256,
):

    """
    @notice Initialize the contract with the given parameters.
    @param _payment_token The address of the payment token.
    @param _delegation_registry The address of the delegation registry.
    @param _cryptopunks The address of the CryptoPunksMarket contract.
    @param _protocol_upfront_fee The percentage (bps) of the principal paid to the protocol at origination.
    @param _protocol_settlement_fee The percentage (bps) of the interest paid to the protocol at settlement.
    @param _protocol_wallet The address where the protocol fees are accrued.
    """

    assert _protocol_wallet != empty(address), "wallet is the zero address"
    assert _payment_token != empty(address), "payment token is zero"
    assert _p2p_control != empty(address), "p2p control is zero"
    assert _delegation_registry != empty(address), "delegation registry is zero"

    assert _protocol_upfront_fee <= _max_protocol_upfront_fee, "upfront fee exceeds max"
    assert _protocol_settlement_fee <= _max_protocol_settlement_fee, "settlement fee exceeds max"

    self.owner = msg.sender
    payment_token = _payment_token
    p2p_control = P2PLendingControl(_p2p_control)
    delegation_registry = DelegationRegistry(_delegation_registry)
    cryptopunks = CryptoPunksMarket(_cryptopunks)
    max_protocol_upfront_fee = _max_protocol_upfront_fee
    max_protocol_settlement_fee = _max_protocol_settlement_fee
    max_lender_broker_settlement_fee = _max_lender_broker_settlement_fee
    max_borrower_broker_settlement_fee = _max_borrower_broker_settlement_fee
    self.protocol_upfront_fee = _protocol_upfront_fee
    self.protocol_settlement_fee = _protocol_settlement_fee
    self.protocol_wallet = _protocol_wallet

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



# Config functions


@external
def set_protocol_fee(protocol_upfront_fee: uint256, protocol_settlement_fee: uint256):

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

    assert msg.sender == self.owner, "not owner"
    assert protocol_upfront_fee <= max_protocol_upfront_fee, "upfront fee exceeds max"
    assert protocol_settlement_fee <= max_protocol_settlement_fee, "settlement fee exceeds max"

    log ProtocolFeeSet(self.protocol_upfront_fee, self.protocol_settlement_fee, protocol_upfront_fee, protocol_settlement_fee)
    self.protocol_upfront_fee = protocol_upfront_fee
    self.protocol_settlement_fee = protocol_settlement_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.owner, "not owner"
    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_proxy_authorization(_proxy: address, _value: bool):

    """
    @notice Set authorization
    @dev Sets the authorization for the given proxy and logs the event. Admin function.
    @param _proxy The address of the proxy.
    @param _value The value of the authorization.
    """

    assert msg.sender == self.owner, "not owner"

    self.authorized_proxies[_proxy] = _value

    log ProxyAuthorizationChanged(_proxy, _value)


@external
def propose_owner(_address: address):

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

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

    log OwnerProposed(self.owner, _address)
    self.proposed_owner = _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 owner.
    """

    assert msg.sender == self.proposed_owner, "not the proposed owner"

    log OwnershipTransferred(self.owner, self.proposed_owner)
    self.owner = msg.sender
    self.proposed_owner = empty(address)


# Core functions

@external
def create_loan(
    offer: SignedOffer,
    collateral_token_id: uint256,
    collateral_proof: DynArray[bytes32, PROOF_MAX_SIZE],
    delegate: address,
    borrower_broker_upfront_fee_amount: uint256,
    borrower_broker_settlement_fee_bps: uint256,
    borrower_broker: address
) -> bytes32:

    """
    @notice Create a loan.
    @param offer The signed offer.
    @param collateral_token_id The ID of the collateral token.
    @param delegate The address of the delegate. If empty, no delegation is set.
    @param borrower_broker_upfront_fee_amount The upfront fee amount for the borrower broker.
    @param borrower_broker_settlement_fee_bps The settlement fee basis points relative to the interest for the borrower broker.
    @param borrower_broker The address of the borrower broker.
    @return The ID of the created loan.
    """


    assert self._is_offer_signed_by_lender(offer, offer.offer.lender), "offer not signed by lender"
    assert offer.offer.expiration > block.timestamp, "offer expired"
    assert offer.offer.payment_token == payment_token, "invalid payment token"
    assert offer.offer.origination_fee_amount <= offer.offer.principal, "origination fee gt principal"

    collection_status: CollectionStatus = p2p_control.get_collection_status(offer.offer.collection_key_hash)
    self._validate_token_ids(offer.offer, collateral_token_id, collection_status, collateral_proof)

    fees: DynArray[Fee, MAX_FEES] = self._get_loan_fees(offer.offer, borrower_broker_upfront_fee_amount, borrower_broker_settlement_fee_bps, borrower_broker)
    total_upfront_fees: uint256 = 0
    for fee in fees:
        total_upfront_fees += fee.upfront_amount

    offer_id: bytes32 = self._compute_signed_offer_id(offer)
    loan: Loan = Loan({
        id: empty(bytes32),
        offer_id: offer_id,
        offer_tracing_id: offer.offer.tracing_id,
        amount: offer.offer.principal,
        interest: offer.offer.interest,
        payment_token: offer.offer.payment_token,
        maturity: block.timestamp + offer.offer.duration,
        start_time: block.timestamp,
        borrower: msg.sender if not self.authorized_proxies[msg.sender] else tx.origin,
        lender: offer.offer.lender,
        collateral_contract: collection_status.contract,
        collateral_token_id: collateral_token_id,
        fees: fees,
        pro_rata: offer.offer.pro_rata,
        delegate: delegate
    })
    loan.id = self._compute_loan_id(loan)

    assert self.loans[loan.id] == empty(bytes32), "loan already exists"
    self._check_and_update_offer_state(offer)
    self.loans[loan.id] = self._loan_state_hash(loan)

    self._store_collateral(loan.borrower, loan.collateral_contract, loan.collateral_token_id)
    self._transfer_funds(loan.lender, loan.borrower, loan.amount - total_upfront_fees + offer.offer.broker_upfront_fee_amount)

    for fee in fees:
        if fee.type != FeeType.ORIGINATION_FEE and fee.upfront_amount > 0:
            self._transfer_funds(loan.lender, fee.wallet, fee.upfront_amount)

    if delegate != empty(address):
        self._set_delegation(delegate, loan.collateral_contract, loan.collateral_token_id, True)

    log LoanCreated(
        loan.id,
        loan.amount,
        loan.interest,
        loan.payment_token,
        loan.maturity,
        loan.start_time,
        loan.borrower,
        loan.lender,
        loan.collateral_contract,
        loan.collateral_token_id,
        loan.fees,
        loan.pro_rata,
        offer_id,
        offer.offer.tracing_id,
        delegate
    )
    return loan.id


@external
def settle_loan(loan: Loan):

    """
    @notice Settle a loan.
    @param loan The loan to be settled.
    """

    assert self._is_loan_valid(loan), "invalid loan"
    assert block.timestamp <= loan.maturity, "loan defaulted"
    assert self._check_user(loan.borrower), "not borrower"

    interest: uint256 = self._compute_settlement_interest(loan)
    settlement_fees_total: uint256 = 0
    settlement_fees: DynArray[FeeAmount, MAX_FEES] = []
    borrower_broker_fee_amount: uint256 = 0
    settlement_fees, settlement_fees_total, borrower_broker_fee_amount = self._get_settlement_fees(loan, interest)

    self.loans[loan.id] = empty(bytes32)
    self._reduce_offer_count(loan.offer_tracing_id)

    self._receive_funds(loan.borrower, loan.amount + interest + borrower_broker_fee_amount)

    self._send_funds(loan.lender, loan.amount + interest - settlement_fees_total + borrower_broker_fee_amount)
    for fee in settlement_fees:
        self._send_funds(fee.wallet, fee.amount)

    self._transfer_collateral(loan.borrower, loan.collateral_contract, loan.collateral_token_id)

    if loan.delegate != empty(address):
        self._set_delegation(loan.delegate, loan.collateral_contract, loan.collateral_token_id, False)

    log LoanPaid(
        loan.id,
        loan.borrower,
        loan.lender,
        loan.payment_token,
        loan.amount,
        interest,
        settlement_fees
    )


@external
def claim_defaulted_loan_collateral(loan: Loan):

    """
    @notice Claim defaulted loan collateral.
    @param loan The loan whose collateral is to be claimed. The loan maturity must have been passed.
    """

    assert self._is_loan_valid(loan), "invalid loan"
    assert block.timestamp > loan.maturity, "loan not defaulted"
    assert self._check_user(loan.lender), "not lender"

    self.loans[loan.id] = empty(bytes32)

    self._transfer_collateral(loan.lender, loan.collateral_contract, loan.collateral_token_id)

    if loan.delegate != empty(address):
        self._set_delegation(loan.delegate, loan.collateral_contract, loan.collateral_token_id, False)

    log LoanCollateralClaimed(
        loan.id,
        loan.borrower,
        loan.lender,
        loan.collateral_contract,
        loan.collateral_token_id
    )


@external
def replace_loan(
    loan: Loan,
    offer: SignedOffer,
    collateral_proof: DynArray[bytes32, PROOF_MAX_SIZE],
    borrower_broker_upfront_fee_amount: uint256,
    borrower_broker_settlement_fee_bps: uint256,
    borrower_broker: address
) -> bytes32:

    """
    @notice Replace an existing loan by accepting a new offer over the same collateral. The current loan is settled and the new loan is created. Must be called by the borrower.
    @dev No collateral transfer is required and the delegation is not changed. The borrower must be the same as the borrower of the current loan.
    @param loan The loan to be replaced.
    @param offer The new signed offer.
    @param borrower_broker_upfront_fee_amount The upfront fee amount for the borrower broker.
    @param borrower_broker_settlement_fee_bps The settlement fee basis points relative to the interest for the borrower broker.
    @param borrower_broker The address of the borrower broker, if any.
    @return The ID of the new loan.
    """

    assert self._is_loan_valid(loan), "invalid loan"
    assert self._check_user(loan.borrower), "not borrower"
    assert block.timestamp <= loan.maturity, "loan defaulted"

    assert self._is_offer_signed_by_lender(offer, offer.offer.lender), "offer not signed by lender"
    assert offer.offer.expiration > block.timestamp, "offer expired"
    assert offer.offer.payment_token == payment_token, "invalid payment token"
    assert offer.offer.origination_fee_amount <= offer.offer.principal, "origination fee gt principal"

    collection_status: CollectionStatus = p2p_control.get_collection_status(offer.offer.collection_key_hash)
    self._validate_token_ids(offer.offer, loan.collateral_token_id, collection_status, collateral_proof)
    assert collection_status.contract == loan.collateral_contract, "collateral contract mismatch"

    self._check_and_update_offer_state(offer)
    self._reduce_offer_count(loan.offer_tracing_id)

    principal_delta: int256 = convert(offer.offer.principal, int256) - convert(loan.amount, int256)
    interest: uint256 = self._compute_settlement_interest(loan)

    settlement_fees_total: uint256 = 0
    settlement_fees: DynArray[FeeAmount, MAX_FEES] = []
    borrower_broker_fee_amount: uint256 = 0
    settlement_fees, settlement_fees_total, borrower_broker_fee_amount = self._get_settlement_fees(loan, interest)

    new_loan_fees: DynArray[Fee, MAX_FEES] = self._get_loan_fees(offer.offer, borrower_broker_upfront_fee_amount, borrower_broker_settlement_fee_bps, borrower_broker)
    total_upfront_fees: uint256 = 0
    for fee in new_loan_fees:
        total_upfront_fees += fee.upfront_amount

    self.loans[loan.id] = empty(bytes32)

    borrower_delta: int256 = principal_delta - convert(total_upfront_fees + interest + borrower_broker_fee_amount, int256) + convert(offer.offer.broker_upfront_fee_amount, int256)
    current_lender_delta: uint256 = loan.amount + interest - settlement_fees_total + borrower_broker_fee_amount
    new_lender_delta_abs: uint256 = offer.offer.principal - offer.offer.origination_fee_amount + offer.offer.broker_upfront_fee_amount

    if borrower_delta < 0:
        self._receive_funds(loan.borrower, convert(-1 * borrower_delta, uint256))

    if loan.lender != offer.offer.lender:
        self._receive_funds(offer.offer.lender, new_lender_delta_abs)
        self._send_funds(loan.lender, current_lender_delta)
    elif current_lender_delta > new_lender_delta_abs:
        self._send_funds(loan.lender, current_lender_delta - new_lender_delta_abs)
    elif current_lender_delta < new_lender_delta_abs:
        self._receive_funds(loan.lender, new_lender_delta_abs - current_lender_delta)

    if borrower_delta > 0:
        self._send_funds(loan.borrower, convert(borrower_delta, uint256))

    for fee in settlement_fees:
        self._send_funds(fee.wallet, fee.amount)

    for fee in new_loan_fees:
        if fee.type != FeeType.ORIGINATION_FEE and fee.upfront_amount > 0:
            self._send_funds(fee.wallet, fee.upfront_amount)

    offer_id: bytes32 = self._compute_signed_offer_id(offer)
    new_loan: Loan = Loan({
        id: empty(bytes32),
        offer_id: offer_id,
        offer_tracing_id: offer.offer.tracing_id,
        amount: offer.offer.principal,
        interest: offer.offer.interest,
        payment_token: offer.offer.payment_token,
        maturity: block.timestamp + offer.offer.duration,
        start_time: block.timestamp,
        borrower: loan.borrower,
        lender: offer.offer.lender,
        collateral_contract: collection_status.contract,
        collateral_token_id: loan.collateral_token_id,
        fees: new_loan_fees,
        pro_rata: offer.offer.pro_rata,
        delegate: loan.delegate
    })
    new_loan.id = self._compute_loan_id(new_loan)

    assert self.loans[new_loan.id] == empty(bytes32), "loan already exists"
    self.loans[new_loan.id] = self._loan_state_hash(new_loan)

    log LoanReplaced(
        new_loan.id,
        new_loan.amount,
        new_loan.interest,
        new_loan.payment_token,
        new_loan.maturity,
        new_loan.start_time,
        new_loan.collateral_contract,
        new_loan.collateral_token_id,
        new_loan.borrower,
        new_loan.lender,
        new_loan.fees,
        new_loan.pro_rata,
        loan.id,
        loan.amount,
        interest,
        settlement_fees,
        offer_id,
        offer.offer.tracing_id
    )

    return new_loan.id


@external
def replace_loan_lender(loan: Loan, offer: SignedOffer, collateral_proof: DynArray[bytes32, PROOF_MAX_SIZE]) -> bytes32:

    """
    @notice Replace a loan by the lender. The current loan is settled and the new loan is created. Must be called by the lender.
    @dev No collateral transfer is required and the delegation is not changed. The borrower must be the same as the borrower of the current loan. No funds are required from the borrower. Also no funds are required from the lender, except when the current and new lender are the same.
    @param loan The loan to be replaced.
    @param offer The new signed offer.
    @return The ID of the new loan.
    """

    assert self._is_loan_valid(loan), "invalid loan"
    assert self._check_user(loan.lender), "not lender"
    assert block.timestamp <= loan.maturity, "loan defaulted"

    assert self._is_offer_signed_by_lender(offer, offer.offer.lender), "offer not signed by lender"
    assert offer.offer.expiration > block.timestamp, "offer expired"
    assert offer.offer.payment_token == payment_token, "invalid payment token"
    assert offer.offer.origination_fee_amount <= offer.offer.principal, "origination fee gt principal"
    assert block.timestamp + offer.offer.duration >= loan.maturity, "maturity before loan maturity"

    collection_status: CollectionStatus = p2p_control.get_collection_status(offer.offer.collection_key_hash)
    self._validate_token_ids(offer.offer, loan.collateral_token_id, collection_status, collateral_proof)
    assert collection_status.contract == loan.collateral_contract, "collateral contract mismatch"

    self._check_and_update_offer_state(offer)
    self._reduce_offer_count(loan.offer_tracing_id)

    principal_delta: int256 = convert(offer.offer.principal, int256) - convert(loan.amount, int256)
    interest: uint256 = self._compute_settlement_interest(loan)

    settlement_fees_total: uint256 = 0
    settlement_fees: DynArray[FeeAmount, MAX_FEES] = []
    borrower_broker_fee_amount: uint256 = 0
    settlement_fees, settlement_fees_total, borrower_broker_fee_amount = self._get_settlement_fees(loan, interest)

    new_loan_fees: DynArray[Fee, MAX_FEES] = self._get_loan_fees(offer.offer, 0, 0, empty(address))
    total_upfront_fees: uint256 = 0
    for fee in new_loan_fees:
        total_upfront_fees += fee.upfront_amount

    self.loans[loan.id] = empty(bytes32)

    max_interest_delta: uint256 = self._compute_max_interest_delta(loan, offer.offer, interest, borrower_broker_fee_amount)
    borrower_compensation: uint256 = convert(max(convert(max_interest_delta, int256), convert(interest + borrower_broker_fee_amount, int256) - principal_delta), uint256)

    borrower_delta: int256 = principal_delta - convert(interest, int256) - convert(borrower_broker_fee_amount, int256) + convert(borrower_compensation, int256)
    current_lender_delta: int256 = convert(loan.amount + interest + borrower_broker_fee_amount + offer.offer.broker_upfront_fee_amount, int256) - convert(total_upfront_fees + settlement_fees_total + borrower_compensation, int256)
    new_lender_delta_abs: uint256 = offer.offer.principal - offer.offer.origination_fee_amount + offer.offer.broker_upfront_fee_amount

    assert borrower_delta >= 0, "borrower delta < 0"

    if loan.lender != offer.offer.lender:
        assert current_lender_delta >= 0, "lender delta < 0"
        self._receive_funds(offer.offer.lender, new_lender_delta_abs)
        if current_lender_delta > 0:
            self._send_funds(loan.lender, convert(current_lender_delta, uint256))
    else:
        lender_delta: int256 = current_lender_delta - convert(new_lender_delta_abs, int256)

        # cant have lender delta > 0 and borrower delta >= 0
        assert lender_delta <= 0, "lender delta > 0"

        if lender_delta < 0:
            self._receive_funds(loan.lender, convert(-1 * lender_delta, uint256))

    if borrower_delta > 0:
        self._send_funds(loan.borrower, convert(borrower_delta, uint256))

    for fee in settlement_fees:
        self._send_funds(fee.wallet, fee.amount)

    for fee in new_loan_fees:
        if fee.type != FeeType.ORIGINATION_FEE and fee.upfront_amount > 0:
            self._send_funds(fee.wallet, fee.upfront_amount)

    offer_id: bytes32 = self._compute_signed_offer_id(offer)
    new_loan: Loan = Loan({
        id: empty(bytes32),
        offer_id: offer_id,
        offer_tracing_id: offer.offer.tracing_id,
        amount: offer.offer.principal,
        interest: offer.offer.interest,
        payment_token: offer.offer.payment_token,
        maturity: block.timestamp + offer.offer.duration,
        start_time: block.timestamp,
        borrower: loan.borrower,
        lender: offer.offer.lender,
        collateral_contract: collection_status.contract,
        collateral_token_id: loan.collateral_token_id,
        fees: new_loan_fees,
        pro_rata: offer.offer.pro_rata,
        delegate: loan.delegate
    })
    new_loan.id = self._compute_loan_id(new_loan)

    assert self.loans[new_loan.id] == empty(bytes32), "loan already exists"
    self.loans[new_loan.id] = self._loan_state_hash(new_loan)

    log LoanReplacedByLender(
        new_loan.id,
        new_loan.amount,
        new_loan.interest,
        new_loan.payment_token,
        new_loan.maturity,
        new_loan.start_time,
        new_loan.collateral_contract,
        new_loan.collateral_token_id,
        new_loan.borrower,
        new_loan.lender,
        new_loan.fees,
        new_loan.pro_rata,
        loan.id,
        loan.amount,
        interest,
        settlement_fees,
        borrower_compensation,
        offer_id,
        offer.offer.tracing_id
    )

    return new_loan.id


@external
def revoke_offer(offer: SignedOffer):

    """
    @notice Revoke an offer.
    @param offer The signed offer to be revoked.
    """

    assert self._check_user(offer.offer.lender), "not lender"
    assert offer.offer.expiration > block.timestamp, "offer expired"
    assert self._is_offer_signed_by_lender(offer, offer.offer.lender), "offer not signed by lender"

    offer_id: bytes32 = self._compute_signed_offer_id(offer)
    assert not self.revoked_offers[offer_id], "offer already revoked"

    self._revoke_offer(offer_id, offer)


@external
def claim_pending_transfers():
    assert self.pending_transfers[msg.sender] > 0, "no pending transfers"
    _amount: uint256 = self.pending_transfers[msg.sender]
    self.pending_transfers[msg.sender] = 0

    assert IERC20(payment_token).transfer(msg.sender, _amount), "error sending funds"
    log PendingTransfersClaimed(msg.sender, _amount)



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

    """
    @notice ERC721 token receiver callback.
    @dev Returns the ERC721 receiver callback selector.
    @param _operator The address which called `safeTransferFrom` function.
    @param _from The address which previously owned the token.
    @param _tokenId The NFT identifier which is being transferred.
    @param _data Additional data with no specified format.
    @return The ERC721 receiver callback selector.
    """

    return method_id("onERC721Received(address,address,uint256,bytes)", output_type=bytes4)



# Internal functions

@pure
@internal
def _compute_loan_id(loan: Loan) -> bytes32:
    return keccak256(concat(
        convert(loan.borrower, bytes32),
        convert(loan.lender, bytes32),
        convert(loan.start_time, bytes32),
        convert(loan.collateral_contract, bytes32),
        convert(loan.collateral_token_id, bytes32),
    ))

@pure
@internal
def _compute_signed_offer_id(offer: SignedOffer) -> bytes32:
    return keccak256(concat(
        convert(offer.signature.v, bytes32),
        convert(offer.signature.r, bytes32),
        convert(offer.signature.s, bytes32),
    ))

@internal
def _check_and_update_offer_state(offer: SignedOffer):
    offer_id: bytes32 = self._compute_signed_offer_id(offer)
    assert not self.revoked_offers[offer_id], "offer revoked"

    count: uint256 = self.offer_count[offer.offer.tracing_id]
    assert count < offer.offer.size, "offer fully utilized"
    self.offer_count[offer.offer.tracing_id] = count + 1

    if offer.offer.offer_type == OfferType.TOKEN:
        self._revoke_offer(offer_id, offer)


@internal
def _revoke_offer(offer_id: bytes32, offer: SignedOffer):

    self.revoked_offers[offer_id] = True

    log OfferRevoked(
        offer_id,
        offer.offer.lender,
        offer.offer.collection_key_hash,
        offer.offer.offer_type,
    )


@internal
def _reduce_offer_count(tracing_id: bytes32):
    self.offer_count[tracing_id] -= 1

@view
@internal
def _is_loan_valid(loan: Loan) -> bool:
    return self.loans[loan.id] == self._loan_state_hash(loan)

@pure
@internal
def _loan_state_hash(loan: Loan) -> bytes32:
    return keccak256(_abi_encode(loan))


@internal
def _is_offer_signed_by_lender(signed_offer: SignedOffer, lender: address) -> bool:
    return ecrecover(
        keccak256(
            concat(
                convert("\x19\x01", Bytes[2]),
                _abi_encode(
                    offer_sig_domain_separator,
                    keccak256(_abi_encode(OFFER_TYPE_HASH, signed_offer.offer))
                )
            )
        ),
        signed_offer.signature.v,
        signed_offer.signature.r,
        signed_offer.signature.s
    ) == lender


@internal
def _get_loan_fees(offer: Offer, borrower_broker_upfront_fee_amount: uint256, borrower_broker_settlement_fee_bps: uint256, borrower_broker: address) -> DynArray[Fee, MAX_FEES]:
    fees: DynArray[Fee, MAX_FEES] = []
    if offer.origination_fee_amount > 0:
        assert offer.origination_fee_amount <= offer.principal, "origination fee gt principal"
    if offer.broker_settlement_fee_bps > 0 or offer.broker_upfront_fee_amount > 0:
        assert offer.broker_address != empty(address), "broker fee without address"
    if borrower_broker_upfront_fee_amount > 0 or borrower_broker_settlement_fee_bps > 0:
        assert borrower_broker != empty(address), "broker fee without address"
    assert offer.broker_settlement_fee_bps <= max_lender_broker_settlement_fee, "lender broker fee exceeds max"
    assert borrower_broker_settlement_fee_bps <= max_borrower_broker_settlement_fee, "borrower broker fee exceeds max"
    assert self.protocol_settlement_fee + offer.broker_settlement_fee_bps <= BPS, "settlement fees gt principal"

    fees.append(Fee({
        type: FeeType.PROTOCOL_FEE,
        upfront_amount: self.protocol_upfront_fee * offer.principal / BPS,
        interest_bps: self.protocol_settlement_fee,
        wallet: self.protocol_wallet
    }))
    fees.append(Fee({
        type: FeeType.ORIGINATION_FEE,
        upfront_amount: offer.origination_fee_amount,
        interest_bps: 0,
        wallet: offer.lender
    }))
    fees.append(Fee({
        type: FeeType.LENDER_BROKER_FEE,
        upfront_amount: offer.broker_upfront_fee_amount,
        interest_bps: offer.broker_settlement_fee_bps,
        wallet: offer.broker_address
    }))
    fees.append(Fee({
        type: FeeType.BORROWER_BROKER_FEE,
        upfront_amount: borrower_broker_upfront_fee_amount,
        interest_bps: borrower_broker_settlement_fee_bps,
        wallet: borrower_broker
    }))
    return fees

@internal
def _get_settlement_fees(loan: Loan, settlement_interest: uint256) -> (DynArray[FeeAmount, MAX_FEES], uint256, uint256):
    total: uint256 = 0
    settlement_fees: DynArray[FeeAmount, MAX_FEES] = []
    borrower_broker_fee_amount: uint256 = 0
    for fee in loan.fees:
        if fee.interest_bps > 0:
            fee_amount: uint256 = settlement_interest * fee.interest_bps / BPS
            settlement_fees.append(FeeAmount({type: fee.type, amount: fee_amount, wallet: fee.wallet}))
            total += fee_amount
            if fee.type == FeeType.BORROWER_BROKER_FEE:
                borrower_broker_fee_amount = fee_amount

    return (settlement_fees, total, borrower_broker_fee_amount)


@internal
def _compute_settlement_interest(loan: Loan) -> uint256:
    if loan.pro_rata:
        return loan.interest * (block.timestamp - loan.start_time) / (loan.maturity - loan.start_time)
    else:
        return loan.interest


@internal
def _compute_max_interest_delta(loan: Loan, offer: Offer, interest: uint256, borrower_broker_fee_amount: uint256) -> uint256:
    """
    Computes the maximum interest difference between the new offer and the current loan.
    That max difference can be reached either at the refinance timestamp or at the original loan maturity.
    The difference can never be negative because at the refinance timestamp the delta is just the offer interest.
    """

    borrower_broker_fee_bps: uint256 = 0
    for fee in loan.fees:
        if fee.type == FeeType.BORROWER_BROKER_FEE:
            borrower_broker_fee_bps = fee.interest_bps
    delta_at_refinance: uint256 = 0 if offer.pro_rata else offer.interest
    borrower_broker_fee_delta_at_maturity: uint256 = (loan.interest - interest) * borrower_broker_fee_bps / BPS if offer.pro_rata else 0
    loan_interest_delta_at_maturity: uint256 = loan.interest - interest
    offer_interest_at_loan_maturity: uint256 = offer.interest * (loan.maturity - block.timestamp) / offer.duration if offer.pro_rata else offer.interest

    return convert(max(
        convert(delta_at_refinance, int256),
        convert(offer_interest_at_loan_maturity, int256) - convert(loan_interest_delta_at_maturity, int256) - convert(borrower_broker_fee_delta_at_maturity, int256)
    ), uint256)


@internal
def _set_delegation(_wallet: address, _collateral_address: address, _token_id: uint256, _value: bool):
    delegation_registry.delegateERC721(_wallet, _collateral_address, _token_id, empty(bytes32), _value)


@internal
def _store_punk(_wallet: address, _collateralAddress: address, _tokenId: uint256):
    offer: PunkOffer = CryptoPunksMarket(_collateralAddress).punksOfferedForSale(_tokenId)

    assert offer.isForSale, "collateral not for sale"
    assert offer.punkIndex == _tokenId, "collateral with wrong punkIndex"
    assert offer.seller == _wallet, "collateral now owned by wallet"
    assert offer.minValue == 0, "collateral offer is not zero"
    assert offer.onlySellTo == empty(address) or offer.onlySellTo == self, "collateral buying not authorized"

    CryptoPunksMarket(_collateralAddress).buyPunk(_tokenId)


@internal
def _store_erc721(_wallet: address, _collateralAddress: address, _tokenId: uint256):
    IERC721(_collateralAddress).safeTransferFrom(_wallet, self, _tokenId, b"")


@internal
def _transfer_punk(_wallet: address, _collateralAddress: address, _tokenId: uint256):
    assert self._punk_owner(_collateralAddress, _tokenId) == self, "collateral not owned by vault"
    CryptoPunksMarket(_collateralAddress).transferPunk(_wallet, _tokenId)


@internal
def _transfer_erc721(_wallet: address, _collateralAddress: address, _tokenId: uint256):
    assert self._erc721_owner(_collateralAddress, _tokenId) == self, "collateral not owned by vault"
    IERC721(_collateralAddress).safeTransferFrom(self, _wallet, _tokenId, b"")


@internal
def _transfer_collateral(wallet: address, collateral_contract: address, token_id: uint256):
    if self._is_punk(collateral_contract):
        self._transfer_punk(wallet, collateral_contract, token_id)
    else:
        self._transfer_erc721(wallet, collateral_contract, token_id)


@internal
def _send_funds(_to: address, _amount: uint256):
    success: bool = False
    response: Bytes[32] = b""

    success, response = raw_call(
        payment_token,
        _abi_encode(_to, _amount, method_id=method_id("transfer(address,uint256)")),
        max_outsize=32,
        revert_on_failure=False
    )

    if not success or not convert(response, bool):
        log TransferFailed(_to, _amount)
        self.pending_transfers[_to] += _amount


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


@internal
def _transfer_funds(_from: address, _to: address, _amount: uint256):
    assert IERC20(payment_token).transferFrom(_from, _to, _amount), "transferFrom failed"

@pure
@internal
def _is_punk(_collateralAddress: address) -> bool:
    return _collateralAddress == cryptopunks.address


@view
@internal
def _punk_owner(_collateralAddress: address, _tokenId: uint256) -> address:
    return CryptoPunksMarket(_collateralAddress).punkIndexToAddress(_tokenId)


@view
@internal
def _erc721_owner(_collateralAddress: address, _tokenId: uint256) -> address:
    return IERC721(_collateralAddress).ownerOf(_tokenId)


@view
@internal
def _is_punk_approved_for_vault(_borrower: address, _collateralAddress: address, _tokenId: uint256) -> bool:
    offer: PunkOffer = cryptopunks.punksOfferedForSale(_tokenId)
    return (
        offer.isForSale and
        offer.punkIndex == _tokenId and
        offer.minValue == 0 and
        (offer.onlySellTo == empty(address) or offer.onlySellTo == self)
    )


@view
@internal
def _is_erc721_approved_for_vault(_borrower: address, _collateralAddress: address, _tokenId: uint256) -> bool:
    return IERC721(_collateralAddress).isApprovedForAll(_borrower, self) or IERC721(_collateralAddress).getApproved(_tokenId) == self


@internal
def _store_collateral(wallet: address, collateral_contract: address, token_id: uint256):

    assert wallet != empty(address), "addr is the zero addr"
    assert collateral_contract != empty(address), "collat addr is the zero addr"

    if self._is_punk(collateral_contract):
        assert self._punk_owner(collateral_contract, token_id) == wallet, "collateral not owned by wallet"
        assert self._is_punk_approved_for_vault(wallet, collateral_contract, token_id), "transfer is not approved"
        self._store_punk(wallet, collateral_contract, token_id)

    else:
        assert self._erc721_owner(collateral_contract, token_id) == wallet, "collateral not owned by wallet"
        assert self._is_erc721_approved_for_vault(wallet, collateral_contract, token_id), "transfer is not approved"
        self._store_erc721(wallet, collateral_contract, token_id)


@internal
def _check_user(user: address) -> bool:
    return msg.sender == user or (self.authorized_proxies[msg.sender] and user == tx.origin)

@internal
def _validate_token_ids(
    offer: Offer,
    collateral_token_id: uint256,
    collection_status: CollectionStatus,
    collateral_proof: DynArray[bytes32, PROOF_MAX_SIZE]
):
    assert collection_status.contract != empty(address), "collateral not whitelisted"
    if offer.offer_type == OfferType.TOKEN:
        assert offer.token_id == collateral_token_id, "token id not in offer"
    elif offer.offer_type == OfferType.COLLECTION:
        assert collateral_token_id >= offer.token_range_min, "tokenid below offer range"
        assert collateral_token_id <= offer.token_range_max, "tokenid above offer range"
    else:
        _hash: bytes32 = keccak256(_abi_encode(collection_status.contract, offer.trait_hash, collateral_token_id))
        for p in collateral_proof:
            _hash = keccak256(_abi_encode(convert(keccak256(_hash), uint256) ^ convert(keccak256(p), uint256)))
        assert collection_status.trait_root == _hash, "proof invalid"

Contract Security Audit

Contract ABI

API
[{"name":"LoanCreated","inputs":[{"name":"id","type":"bytes32","indexed":false},{"name":"amount","type":"uint256","indexed":false},{"name":"interest","type":"uint256","indexed":false},{"name":"payment_token","type":"address","indexed":false},{"name":"maturity","type":"uint256","indexed":false},{"name":"start_time","type":"uint256","indexed":false},{"name":"borrower","type":"address","indexed":false},{"name":"lender","type":"address","indexed":false},{"name":"collateral_contract","type":"address","indexed":false},{"name":"collateral_token_id","type":"uint256","indexed":false},{"name":"fees","type":"tuple[]","components":[{"name":"type","type":"uint256"},{"name":"upfront_amount","type":"uint256"},{"name":"interest_bps","type":"uint256"},{"name":"wallet","type":"address"}],"indexed":false},{"name":"pro_rata","type":"bool","indexed":false},{"name":"offer_id","type":"bytes32","indexed":false},{"name":"offer_tracing_id","type":"bytes32","indexed":false},{"name":"delegate","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"LoanReplaced","inputs":[{"name":"id","type":"bytes32","indexed":false},{"name":"amount","type":"uint256","indexed":false},{"name":"interest","type":"uint256","indexed":false},{"name":"payment_token","type":"address","indexed":false},{"name":"maturity","type":"uint256","indexed":false},{"name":"start_time","type":"uint256","indexed":false},{"name":"collateral_contract","type":"address","indexed":false},{"name":"collateral_token_id","type":"uint256","indexed":false},{"name":"borrower","type":"address","indexed":false},{"name":"lender","type":"address","indexed":false},{"name":"fees","type":"tuple[]","components":[{"name":"type","type":"uint256"},{"name":"upfront_amount","type":"uint256"},{"name":"interest_bps","type":"uint256"},{"name":"wallet","type":"address"}],"indexed":false},{"name":"pro_rata","type":"bool","indexed":false},{"name":"original_loan_id","type":"bytes32","indexed":false},{"name":"paid_principal","type":"uint256","indexed":false},{"name":"paid_interest","type":"uint256","indexed":false},{"name":"paid_settlement_fees","type":"tuple[]","components":[{"name":"type","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"wallet","type":"address"}],"indexed":false},{"name":"offer_id","type":"bytes32","indexed":false},{"name":"offer_tracing_id","type":"bytes32","indexed":false}],"anonymous":false,"type":"event"},{"name":"LoanReplacedByLender","inputs":[{"name":"id","type":"bytes32","indexed":false},{"name":"amount","type":"uint256","indexed":false},{"name":"interest","type":"uint256","indexed":false},{"name":"payment_token","type":"address","indexed":false},{"name":"maturity","type":"uint256","indexed":false},{"name":"start_time","type":"uint256","indexed":false},{"name":"collateral_contract","type":"address","indexed":false},{"name":"collateral_token_id","type":"uint256","indexed":false},{"name":"borrower","type":"address","indexed":false},{"name":"lender","type":"address","indexed":false},{"name":"fees","type":"tuple[]","components":[{"name":"type","type":"uint256"},{"name":"upfront_amount","type":"uint256"},{"name":"interest_bps","type":"uint256"},{"name":"wallet","type":"address"}],"indexed":false},{"name":"pro_rata","type":"bool","indexed":false},{"name":"original_loan_id","type":"bytes32","indexed":false},{"name":"paid_principal","type":"uint256","indexed":false},{"name":"paid_interest","type":"uint256","indexed":false},{"name":"paid_settlement_fees","type":"tuple[]","components":[{"name":"type","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"wallet","type":"address"}],"indexed":false},{"name":"borrower_compensation","type":"uint256","indexed":false},{"name":"offer_id","type":"bytes32","indexed":false},{"name":"offer_tracing_id","type":"bytes32","indexed":false}],"anonymous":false,"type":"event"},{"name":"LoanPaid","inputs":[{"name":"id","type":"bytes32","indexed":false},{"name":"borrower","type":"address","indexed":false},{"name":"lender","type":"address","indexed":false},{"name":"payment_token","type":"address","indexed":false},{"name":"paid_principal","type":"uint256","indexed":false},{"name":"paid_interest","type":"uint256","indexed":false},{"name":"paid_settlement_fees","type":"tuple[]","components":[{"name":"type","type":"uint256"},{"name":"amount","type":"uint256"},{"name":"wallet","type":"address"}],"indexed":false}],"anonymous":false,"type":"event"},{"name":"LoanCollateralClaimed","inputs":[{"name":"id","type":"bytes32","indexed":false},{"name":"borrower","type":"address","indexed":false},{"name":"lender","type":"address","indexed":false},{"name":"collateral_contract","type":"address","indexed":false},{"name":"collateral_token_id","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"OfferRevoked","inputs":[{"name":"offer_id","type":"bytes32","indexed":false},{"name":"lender","type":"address","indexed":false},{"name":"collection_key_hash","type":"bytes32","indexed":false},{"name":"offer_type","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"OwnerProposed","inputs":[{"name":"owner","type":"address","indexed":false},{"name":"proposed_owner","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"OwnershipTransferred","inputs":[{"name":"old_owner","type":"address","indexed":false},{"name":"new_owner","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"ProtocolFeeSet","inputs":[{"name":"old_upfront_fee","type":"uint256","indexed":false},{"name":"old_settlement_fee","type":"uint256","indexed":false},{"name":"new_upfront_fee","type":"uint256","indexed":false},{"name":"new_settlement_fee","type":"uint256","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":"ProxyAuthorizationChanged","inputs":[{"name":"proxy","type":"address","indexed":false},{"name":"value","type":"bool","indexed":false}],"anonymous":false,"type":"event"},{"name":"TransferFailed","inputs":[{"name":"_to","type":"address","indexed":false},{"name":"amount","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"PendingTransfersClaimed","inputs":[{"name":"_to","type":"address","indexed":false},{"name":"amount","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"stateMutability":"nonpayable","type":"constructor","inputs":[{"name":"_payment_token","type":"address"},{"name":"_p2p_control","type":"address"},{"name":"_delegation_registry","type":"address"},{"name":"_cryptopunks","type":"address"},{"name":"_protocol_upfront_fee","type":"uint256"},{"name":"_protocol_settlement_fee","type":"uint256"},{"name":"_protocol_wallet","type":"address"},{"name":"_max_protocol_upfront_fee","type":"uint256"},{"name":"_max_protocol_settlement_fee","type":"uint256"},{"name":"_max_lender_broker_settlement_fee","type":"uint256"},{"name":"_max_borrower_broker_settlement_fee","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"set_protocol_fee","inputs":[{"name":"protocol_upfront_fee","type":"uint256"},{"name":"protocol_settlement_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_proxy_authorization","inputs":[{"name":"_proxy","type":"address"},{"name":"_value","type":"bool"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"propose_owner","inputs":[{"name":"_address","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"claim_ownership","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"create_loan","inputs":[{"name":"offer","type":"tuple","components":[{"name":"offer","type":"tuple","components":[{"name":"principal","type":"uint256"},{"name":"interest","type":"uint256"},{"name":"payment_token","type":"address"},{"name":"duration","type":"uint256"},{"name":"origination_fee_amount","type":"uint256"},{"name":"broker_upfront_fee_amount","type":"uint256"},{"name":"broker_settlement_fee_bps","type":"uint256"},{"name":"broker_address","type":"address"},{"name":"offer_type","type":"uint256"},{"name":"token_id","type":"uint256"},{"name":"token_range_min","type":"uint256"},{"name":"token_range_max","type":"uint256"},{"name":"collection_key_hash","type":"bytes32"},{"name":"trait_hash","type":"bytes32"},{"name":"expiration","type":"uint256"},{"name":"lender","type":"address"},{"name":"pro_rata","type":"bool"},{"name":"size","type":"uint256"},{"name":"tracing_id","type":"bytes32"}]},{"name":"signature","type":"tuple","components":[{"name":"v","type":"uint256"},{"name":"r","type":"uint256"},{"name":"s","type":"uint256"}]}]},{"name":"collateral_token_id","type":"uint256"},{"name":"collateral_proof","type":"bytes32[]"},{"name":"delegate","type":"address"},{"name":"borrower_broker_upfront_fee_amount","type":"uint256"},{"name":"borrower_broker_settlement_fee_bps","type":"uint256"},{"name":"borrower_broker","type":"address"}],"outputs":[{"name":"","type":"bytes32"}]},{"stateMutability":"nonpayable","type":"function","name":"settle_loan","inputs":[{"name":"loan","type":"tuple","components":[{"name":"id","type":"bytes32"},{"name":"offer_id","type":"bytes32"},{"name":"offer_tracing_id","type":"bytes32"},{"name":"amount","type":"uint256"},{"name":"interest","type":"uint256"},{"name":"payment_token","type":"address"},{"name":"maturity","type":"uint256"},{"name":"start_time","type":"uint256"},{"name":"borrower","type":"address"},{"name":"lender","type":"address"},{"name":"collateral_contract","type":"address"},{"name":"collateral_token_id","type":"uint256"},{"name":"fees","type":"tuple[]","components":[{"name":"type","type":"uint256"},{"name":"upfront_amount","type":"uint256"},{"name":"interest_bps","type":"uint256"},{"name":"wallet","type":"address"}]},{"name":"pro_rata","type":"bool"},{"name":"delegate","type":"address"}]}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"claim_defaulted_loan_collateral","inputs":[{"name":"loan","type":"tuple","components":[{"name":"id","type":"bytes32"},{"name":"offer_id","type":"bytes32"},{"name":"offer_tracing_id","type":"bytes32"},{"name":"amount","type":"uint256"},{"name":"interest","type":"uint256"},{"name":"payment_token","type":"address"},{"name":"maturity","type":"uint256"},{"name":"start_time","type":"uint256"},{"name":"borrower","type":"address"},{"name":"lender","type":"address"},{"name":"collateral_contract","type":"address"},{"name":"collateral_token_id","type":"uint256"},{"name":"fees","type":"tuple[]","components":[{"name":"type","type":"uint256"},{"name":"upfront_amount","type":"uint256"},{"name":"interest_bps","type":"uint256"},{"name":"wallet","type":"address"}]},{"name":"pro_rata","type":"bool"},{"name":"delegate","type":"address"}]}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"replace_loan","inputs":[{"name":"loan","type":"tuple","components":[{"name":"id","type":"bytes32"},{"name":"offer_id","type":"bytes32"},{"name":"offer_tracing_id","type":"bytes32"},{"name":"amount","type":"uint256"},{"name":"interest","type":"uint256"},{"name":"payment_token","type":"address"},{"name":"maturity","type":"uint256"},{"name":"start_time","type":"uint256"},{"name":"borrower","type":"address"},{"name":"lender","type":"address"},{"name":"collateral_contract","type":"address"},{"name":"collateral_token_id","type":"uint256"},{"name":"fees","type":"tuple[]","components":[{"name":"type","type":"uint256"},{"name":"upfront_amount","type":"uint256"},{"name":"interest_bps","type":"uint256"},{"name":"wallet","type":"address"}]},{"name":"pro_rata","type":"bool"},{"name":"delegate","type":"address"}]},{"name":"offer","type":"tuple","components":[{"name":"offer","type":"tuple","components":[{"name":"principal","type":"uint256"},{"name":"interest","type":"uint256"},{"name":"payment_token","type":"address"},{"name":"duration","type":"uint256"},{"name":"origination_fee_amount","type":"uint256"},{"name":"broker_upfront_fee_amount","type":"uint256"},{"name":"broker_settlement_fee_bps","type":"uint256"},{"name":"broker_address","type":"address"},{"name":"offer_type","type":"uint256"},{"name":"token_id","type":"uint256"},{"name":"token_range_min","type":"uint256"},{"name":"token_range_max","type":"uint256"},{"name":"collection_key_hash","type":"bytes32"},{"name":"trait_hash","type":"bytes32"},{"name":"expiration","type":"uint256"},{"name":"lender","type":"address"},{"name":"pro_rata","type":"bool"},{"name":"size","type":"uint256"},{"name":"tracing_id","type":"bytes32"}]},{"name":"signature","type":"tuple","components":[{"name":"v","type":"uint256"},{"name":"r","type":"uint256"},{"name":"s","type":"uint256"}]}]},{"name":"collateral_proof","type":"bytes32[]"},{"name":"borrower_broker_upfront_fee_amount","type":"uint256"},{"name":"borrower_broker_settlement_fee_bps","type":"uint256"},{"name":"borrower_broker","type":"address"}],"outputs":[{"name":"","type":"bytes32"}]},{"stateMutability":"nonpayable","type":"function","name":"replace_loan_lender","inputs":[{"name":"loan","type":"tuple","components":[{"name":"id","type":"bytes32"},{"name":"offer_id","type":"bytes32"},{"name":"offer_tracing_id","type":"bytes32"},{"name":"amount","type":"uint256"},{"name":"interest","type":"uint256"},{"name":"payment_token","type":"address"},{"name":"maturity","type":"uint256"},{"name":"start_time","type":"uint256"},{"name":"borrower","type":"address"},{"name":"lender","type":"address"},{"name":"collateral_contract","type":"address"},{"name":"collateral_token_id","type":"uint256"},{"name":"fees","type":"tuple[]","components":[{"name":"type","type":"uint256"},{"name":"upfront_amount","type":"uint256"},{"name":"interest_bps","type":"uint256"},{"name":"wallet","type":"address"}]},{"name":"pro_rata","type":"bool"},{"name":"delegate","type":"address"}]},{"name":"offer","type":"tuple","components":[{"name":"offer","type":"tuple","components":[{"name":"principal","type":"uint256"},{"name":"interest","type":"uint256"},{"name":"payment_token","type":"address"},{"name":"duration","type":"uint256"},{"name":"origination_fee_amount","type":"uint256"},{"name":"broker_upfront_fee_amount","type":"uint256"},{"name":"broker_settlement_fee_bps","type":"uint256"},{"name":"broker_address","type":"address"},{"name":"offer_type","type":"uint256"},{"name":"token_id","type":"uint256"},{"name":"token_range_min","type":"uint256"},{"name":"token_range_max","type":"uint256"},{"name":"collection_key_hash","type":"bytes32"},{"name":"trait_hash","type":"bytes32"},{"name":"expiration","type":"uint256"},{"name":"lender","type":"address"},{"name":"pro_rata","type":"bool"},{"name":"size","type":"uint256"},{"name":"tracing_id","type":"bytes32"}]},{"name":"signature","type":"tuple","components":[{"name":"v","type":"uint256"},{"name":"r","type":"uint256"},{"name":"s","type":"uint256"}]}]},{"name":"collateral_proof","type":"bytes32[]"}],"outputs":[{"name":"","type":"bytes32"}]},{"stateMutability":"nonpayable","type":"function","name":"revoke_offer","inputs":[{"name":"offer","type":"tuple","components":[{"name":"offer","type":"tuple","components":[{"name":"principal","type":"uint256"},{"name":"interest","type":"uint256"},{"name":"payment_token","type":"address"},{"name":"duration","type":"uint256"},{"name":"origination_fee_amount","type":"uint256"},{"name":"broker_upfront_fee_amount","type":"uint256"},{"name":"broker_settlement_fee_bps","type":"uint256"},{"name":"broker_address","type":"address"},{"name":"offer_type","type":"uint256"},{"name":"token_id","type":"uint256"},{"name":"token_range_min","type":"uint256"},{"name":"token_range_max","type":"uint256"},{"name":"collection_key_hash","type":"bytes32"},{"name":"trait_hash","type":"bytes32"},{"name":"expiration","type":"uint256"},{"name":"lender","type":"address"},{"name":"pro_rata","type":"bool"},{"name":"size","type":"uint256"},{"name":"tracing_id","type":"bytes32"}]},{"name":"signature","type":"tuple","components":[{"name":"v","type":"uint256"},{"name":"r","type":"uint256"},{"name":"s","type":"uint256"}]}]}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"claim_pending_transfers","inputs":[],"outputs":[]},{"stateMutability":"view","type":"function","name":"onERC721Received","inputs":[{"name":"_operator","type":"address"},{"name":"_from","type":"address"},{"name":"_tokenId","type":"uint256"},{"name":"_data","type":"bytes"}],"outputs":[{"name":"","type":"bytes4"}]},{"stateMutability":"view","type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"proposed_owner","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"payment_token","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"loans","inputs":[{"name":"arg0","type":"bytes32"}],"outputs":[{"name":"","type":"bytes32"}]},{"stateMutability":"view","type":"function","name":"delegation_registry","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"cryptopunks","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"p2p_control","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"protocol_wallet","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"protocol_upfront_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"protocol_settlement_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"max_protocol_upfront_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"max_protocol_settlement_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"max_lender_broker_settlement_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"max_borrower_broker_settlement_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"offer_count","inputs":[{"name":"arg0","type":"bytes32"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"revoked_offers","inputs":[{"name":"arg0","type":"bytes32"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"authorized_proxies","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"pending_transfers","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"VERSION","inputs":[],"outputs":[{"name":"","type":"string"}]}]

615bd55150346103fd576020615eed5f395f518060a01c6103fd576040526020615f0d5f395f518060a01c6103fd576060526020615f2d5f395f518060a01c6103fd576080526020615f4d5f395f518060a01c6103fd5760a0526020615fad5f395f518060a01c6103fd5760c05260c0516100d257601a60e0527f77616c6c657420697320746865207a65726f20616464726573730000000000006101005260e05060e0518061010001601f825f031636823750506308c379a060a052602060c052601f19601f60e051011660440160bcfd5b60405161013757601560e0527f7061796d656e7420746f6b656e206973207a65726f00000000000000000000006101005260e05060e0518061010001601f825f031636823750506308c379a060a052602060c052601f19601f60e051011660440160bcfd5b60605161019c57601360e0527f70327020636f6e74726f6c206973207a65726f000000000000000000000000006101005260e05060e0518061010001601f825f031636823750506308c379a060a052602060c052601f19601f60e051011660440160bcfd5b60805161020157601b60e0527f64656c65676174696f6e207265676973747279206973207a65726f00000000006101005260e05060e0518061010001601f825f031636823750506308c379a060a052602060c052601f19601f60e051011660440160bcfd5b6020615fcd5f395f516020615f6d5f395f51111561027757601760e0527f757066726f6e74206665652065786365656473206d61780000000000000000006101005260e05060e0518061010001601f825f031636823750506308c379a060a052602060c052601f19601f60e051011660440160bcfd5b6020615fed5f395f516020615f8d5f395f5111156102ed57601a60e0527f736574746c656d656e74206665652065786365656473206d61780000000000006101005260e05060e0518061010001601f825f031636823750506308c379a060a052602060c052601f19601f60e051011660440160bcfd5b335f55604051615ad552606051615b3552608051615af55260a051615b15526020615fcd5f395f51615b55526020615fed5f395f51615b7552602061600d5f395f51615b9552602061602d5f395f51615bb5526020615f6d5f395f516004556020615f8d5f395f5160055560c0516003557f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f610100527f8cfe527f02f4c08ff029d82debdef92d77938d41c05f0919d733c8091bf9b8d8610120527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6610140524661016052306101805260a060e05260e0805160208201209050615bd552615ad561040161000039615bf5610000f35b5f80fd5f3560e01c6002601f820660011b615a9701601e395f51565b638da5cb5b81186100335734615a93575f5460405260206040f35b6361acb5598118613d0857602436103417615a935760076004356020525f5260405f205460405260206040f3613d08565b63885753de81186100805734615a935760015460405260206040f35b63ffa1ad748118613d085734615a935760208060805260176040527f5032504c656e64696e674e6674732e323032343130303200000000000000000060605260408160800181518152602082015160208201528051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506080f3613d08565b63331c658781186101205734615a93576020615ad560403960206040f35b6305107f058118613d085761022436103417615a93576004356004018035610c60526020810135610c80526040810135610ca0526060810135610cc0526080810135610ce05260a08101358060a01c615a9357610d005260c0810135610d205260e0810135610d40526101008101358060a01c615a9357610d60526101208101358060a01c615a9357610d80526101408101358060a01c615a9357610da052610160810135610dc05261018081013581016004813511615a935780355f8160048111615a9357801561023e57905b8060071b610e00018160071b602086010180358060041c615a93578252602081013560208301526040810135604083015260608101358060a01c615a9357606083015250506001018181186101ee575b505080610de05250506101a08101358060011c615a9357611000526101c08101358060a01c615a935761102052506103e06108606103e0610c6060045afa50610288611040615308565b611040516102f557600c611060527f696e76616c6964206c6f616e00000000000000000000000000000000000000006110805261106050611060518061108001601f825f031636823750506308c379a061102052602061104052601f19601f61106051011660440161103cfd5b610d20514211610364576012611040527f6c6f616e206e6f742064656661756c74656400000000000000000000000000006110605261104050611040518061106001601f825f031636823750506308c379a061100052602061102052601f19601f61104051011660440161101cfd5b610d805160405261037661104061533d565b611040516103e357600a611060527f6e6f74206c656e646572000000000000000000000000000000000000000000006110805261106050611060518061108001601f825f031636823750506308c379a061102052602061104052601f19601f61106051011660440161103cfd5b5f6002610c60516020525f5260405f2055610d805161022052610da05161024052610dc0516102605261041461588c565b611020511561043e5761102051604052610da051606052610dc0516080525f60a05261043e6152b1565b7f4a55c2facef4f87dd498aace39997457e1fc66968956bfe3ac7f20f736e77e74610c605161104052610d605161106052610d805161108052610da0516110a052610dc0516110c05260a0611040a100613d08565b63c4a9081581186104c057602436103417615a935760026004356020525f5260405f205460405260206040f35b639544fa7c8118613d0857604436103417615a93576004358060a01c615a93576040526024358060011c615a93576060525f543318156105565760096080527f6e6f74206f776e6572000000000000000000000000000000000000000000000060a0526080506080518060a001601f825f031636823750506308c379a06040526020606052601f19601f6080510116604401605cfd5b60605160086040516020525f5260405f20557f5e09e79221e29a6d762b708b6fa399e730dfc027f946b2e81a31d849b2fb1fa960405160805260605160a05260406080a100613d08565b63e5107ed781186105be5734615a93576020615af560403960206040f35b63c2a5022b8118613d0857604436103417615a93575f543318156106375760096040527f6e6f74206f776e6572000000000000000000000000000000000000000000000060605260405060405180606001601f825f031636823750506308c379a05f526020602052601f19601f6040510116604401601cfd5b6020615b555f395f5160043511156106a45760176040527f757066726f6e74206665652065786365656473206d617800000000000000000060605260405060405180606001601f825f031636823750506308c379a05f526020602052601f19601f6040510116604401601cfd5b6020615b755f395f51602435111561071157601a6040527f736574746c656d656e74206665652065786365656473206d617800000000000060605260405060405180606001601f825f031636823750506308c379a05f526020602052601f19601f6040510116604401601cfd5b7f4bfb2e8697c06dccd3777bdd9b4dab854905ca53b2a56bb47882c744729729d46004546040526005546060526040600460803760806040a160043560045560243560055500613d08565b635556eda98118613d085734615a93576020615b1560403960206040f3613d08565b637719e9ea811861079c5734615a93576020615b3560403960206040f35b639274bbcd8118613d0857602436103417615a93576004358060a01c615a935760405260096040516020525f5260405f205460605260206060f3613d08565b6367db749981186107f75734615a935760035460405260206040f35b63f8c266298118613d085734615a93576020615b9560403960206040f3613d08565b6358e7783781186108355734615a935760045460405260206040f35b63f7a79a028118613d085734615a93576001543318156108aa5760166040527f6e6f74207468652070726f706f736564206f776e65720000000000000000000060605260405060405180606001601f825f031636823750506308c379a05f526020602052601f19601f6040510116604401601cfd5b7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f5460405260015460605260406040a1335f555f60015500613d08565b6361dd0b8b8118613d085734615a935760055460405260206040f3613d08565b6350d0d5ad8118613d085734615a93576020615b5560403960206040f3613d08565b6387c8f69481186109485734615a93576020615b7560403960206040f35b63a1c7a5678118613d08576103a436103417615a935760406004610860376044358060a01c615a93576108a0526064356108c052606060846108e03760e4358060a01c615a935761094052610104358060031c615a935761096052610124356109805260a06101446109a0376101e4358060a01c615a9357610a4052610204358060011c615a9357610a60526040610224610a80376060610264610ac0376102e4356004016020813511615a9357803560208160051b018083610b2037505050610304358060a01c615a9357610f4052610364358060a01c615a9357610f60526102c060406102c061086060045afa50610a405161030052610a4b610f80613d0c565b610f8051610ab857601a610fa0527f6f66666572206e6f74207369676e6564206279206c656e646572000000000000610fc052610fa050610fa05180610fc001601f825f031636823750506308c379a0610f60526020610f8052601f19601f610fa0510116604401610f7cfd5b42610a205111610b2757600d610f80527f6f66666572206578706972656400000000000000000000000000000000000000610fa052610f8050610f805180610fa001601f825f031636823750506308c379a0610f40526020610f6052601f19601f610f80510116604401610f5cfd5b6020615ad55f395f516108a0511815610b9f576015610f80527f696e76616c6964207061796d656e7420746f6b656e0000000000000000000000610fa052610f8050610f805180610fa001601f825f031636823750506308c379a0610f40526020610f6052601f19601f610f80510116604401610f5cfd5b610860516108e0511115610c1257601c610f80527f6f726967696e6174696f6e20666565206774207072696e636970616c00000000610fa052610f8050610f805180610fa001601f825f031636823750506308c379a0610f40526020610f6052601f19601f610f80510116604401610f5cfd5b6020615b355f395f516356108f8a610fc0526109e051610fe0526040610fc06024610fdc5f855af1610c46573d5f5f3e3d5ffd5b60403d10615a9357610fc0518060a01c615a935761102052610fe0516110405261102090508051610f80526020810151610fa05250610260604061026061086060045afa506102c4356102a052610f80516102c052610fa0516102e052610b205160208160051b018061030082610b2060045afa505050610cc5613e1f565b610260604061026061086060045afa5060406103246102a037610f60516102e052610cf16111e0614104565b6111e0805160208160071b0180610fc0828560045afa505050505f6111e0525f610fc05160048111615a93578015610d7457905b8060071b610fe001805161120052602081015161122052604081015161124052606081015161126052506111e05161122051808201828110615a9357905090506111e052600101818118610d25575b50506102c060406102c061086060045afa50610d9161122061452b565b61122051611200525f611220526112005161124052610aa051611260526108605161128052610880516112a0526108a0516112c052426108c051808201828110615a9357905090506112e05242611300526008336020525f5260405f2054610df95733610dfb565b325b61132052610a405161134052610f8051611360526102c43561138052610fc05160208160071b01806113a082610fc060045afa505050610a60516115c052610f40516115e0526103e060406103e061122060045afa50610e5c611600614574565b61160051611220526002611220516020525f5260405f205415610ede576013611600527f6c6f616e20616c726561647920657869737473000000000000000000000000006116205261160050611600518061162001601f825f031636823750506308c379a06115c05260206115e052601f19601f6116005101166044016115dcfd5b6102c06103a06102c061086060045afa50610ef7614636565b6103e060406103e061122060045afa50610f126116006147a6565b611600516002611220516020525f5260405f2055611320516102a052611360516102c052611380516102e052610f46614e87565b6113405160405261132051606052611280516111e051808203828111615a93579050905061090051808201828110615a935790509050608052610f876151ed565b5f610fc05160048111615a9357801561100b57905b8060071b610fe0018051611600526020810151611620526040810151611640526060810151611660525060026116005114610fdc57611620511515610fde565b5f5b15611000576113405160405261166051606052611620516080526110006151ed565b600101818118610f9c575b5050610f40511561103857610f40516040526113605160605261138051608052600160a0526110386152b1565b7f6827a33d0a24e36314681156d8d9a7d20d6a0548c169735fe25e00c9d38ac5a96101e0611220516116005261128051611620526112a051611640526112c051611660526112e05161168052611300516116a052611320516116c052611340516116e05261136051611700526113805161172052806117405280611600015f6113a0518083528060071b5f8260048111615a9357801561111457905b8060071b60208701018160071b6113c0018051825260208101516020830152604081015160408301526060810151606083015250506001018181186110d4575b505082016020019150509050810190506115c051611760526112005161178052610aa0516117a052610f40516117c052611600a16020611220f3613d08565b631b0b0c638118613d085734615a93576020615bb560403960206040f3613d08565b63225daa0f8118613d0857602436103417615a935760066004356020525f5260405f205460405260206040f3613d08565b6396069a5f8118613d0857602436103417615a93576004358060a01c615a935760405260086040516020525f5260405f205460605260206060f3613d08565b6372e76f13811861130a57602436103417615a93576004358060a01c615a93576040525f5433181561126d5760096060527f6e6f74206f776e6572000000000000000000000000000000000000000000000060805260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b6040516112d057601a6060527f77616c6c657420697320746865207a65726f206164647265737300000000000060805260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b7f6defa6e1a7dcc97f459fb552cf25427ab19cd60692b94e4f38660850a6e917e860035460605260405160805260406060a1604051600355005b63c75b6e5e8118613d08576102c436103417615a935760406004610780376044358060a01c615a93576107c0526064356107e052606060846108003760e4358060a01c615a935761086052610104358060031c615a935761088052610124356108a05260a06101446108c0376101e4358060a01c615a935761096052610204358060011c615a93576109805260406102246109a03760606102646109e037610960516040526113ba610a4061533d565b610a405161142757600a610a60527f6e6f74206c656e64657200000000000000000000000000000000000000000000610a8052610a6050610a605180610a8001601f825f031636823750506308c379a0610a20526020610a4052601f19601f610a60510116604401610a3cfd5b42610940511161149657600d610a40527f6f66666572206578706972656400000000000000000000000000000000000000610a6052610a4050610a405180610a6001601f825f031636823750506308c379a0610a00526020610a2052601f19601f610a40510116604401610a1cfd5b6102c060406102c061078060045afa5061096051610300526114b9610a40613d0c565b610a405161152657601a610a60527f6f66666572206e6f74207369676e6564206279206c656e646572000000000000610a8052610a6050610a605180610a8001601f825f031636823750506308c379a0610a20526020610a4052601f19601f610a60510116604401610a3cfd5b6102c060406102c061078060045afa50611541610a6061452b565b610a6051610a40526007610a40516020525f5260405f2054156115c3576015610a60527f6f6666657220616c7265616479207265766f6b65640000000000000000000000610a8052610a6050610a605180610a8001601f825f031636823750506308c379a0610a20526020610a4052601f19601f610a60510116604401610a3cfd5b610a40516040526102c060606102c061078060045afa506115e26145dd565b00613d08565b63bc71771d8118613d0857602436103417615a93576004358060a01c615a93576040525f543318156116705760096060527f6e6f74206f776e6572000000000000000000000000000000000000000000000060805260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b6040516116d35760106060527f5f61646472657373206973207a65726f0000000000000000000000000000000060805260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b7f722cace8a9cbcb7713f3f71015c8c6b59ed317672489140eb6b3fa7f4a139d845f5460605260405160805260406060a160405160015500613d08565b63802d67998118613d085761022436103417615a93576004356004018035610c60526020810135610c80526040810135610ca0526060810135610cc0526080810135610ce05260a08101358060a01c615a9357610d005260c0810135610d205260e0810135610d40526101008101358060a01c615a9357610d60526101208101358060a01c615a9357610d80526101408101358060a01c615a9357610da052610160810135610dc05261018081013581016004813511615a935780355f8160048111615a9357801561182e57905b8060071b610e00018160071b602086010180358060041c615a93578252602081013560208301526040810135604083015260608101358060a01c615a9357606083015250506001018181186117de575b505080610de05250506101a08101358060011c615a9357611000526101c08101358060a01c615a935761102052506103e06108606103e0610c6060045afa50611878611040615308565b611040516118e557600c611060527f696e76616c6964206c6f616e00000000000000000000000000000000000000006110805261106050611060518061108001601f825f031636823750506308c379a061102052602061104052601f19601f61106051011660440161103cfd5b610d205142111561195557600e611040527f6c6f616e2064656661756c7465640000000000000000000000000000000000006110605261104050611040518061106001601f825f031636823750506308c379a061100052602061102052601f19601f61104051011660440161101cfd5b610d605160405261196761104061533d565b611040516119d457600c611060527f6e6f7420626f72726f77657200000000000000000000000000000000000000006110805261106050611060518061108001601f825f031636823750506308c379a061102052602061104052601f19601f61106051011660440161103cfd5b6103e060406103e0610c6060045afa506119ef611060615370565b6110605161104052604036611060375f611220526103e060406103e0610c6060045afa506110405161042052611a266112406153da565b61124080516020606082020180611080828560045afa5050506101a0810151611060526101c081015161122052505f6002610c60516020525f5260405f2055610ca051604052611a746154f5565b610d6051604052610cc05161104051808201828110615a93579050905061122051808201828110615a935790509050606052611aae615517565b610d8051604052610cc05161104051808201828110615a93579050905061106051808203828111615a93579050905061122051808201828110615a935790509050606052611afa6155d6565b5f6110805160048111615a93578015611b5157905b606081026110a001805161124052602081015161126052604081015161128052506112805160405261126051606052611b466155d6565b600101818118611b0f575b5050610d605161022052610da05161024052610dc05161026052611b7361588c565b6110205115611b9d5761102051604052610da051606052610dc0516080525f60a052611b9d6152b1565b7f2aa6f229bb00348f1aa98ab5ab1636a2618696536f698200d76b66a87906eafa60e0610c605161124052610d605161126052610d805161128052610d00516112a052610cc0516112c052611040516112e052806113005280611240015f61108051808352606081025f8260048111615a93578015611c4e57905b606081026020870101606082026110a0018051825260208101516020830152604081015160408301525050600101818118611c18575b50508201602001915050905081019050611240a100613d08565b6313c072ee8118613d085761058436103417615a93576004356004018035610c60526020810135610c80526040810135610ca0526060810135610cc0526080810135610ce05260a08101358060a01c615a9357610d005260c0810135610d205260e0810135610d40526101008101358060a01c615a9357610d60526101208101358060a01c615a9357610d80526101408101358060a01c615a9357610da052610160810135610dc05261018081013581016004813511615a935780355f8160048111615a93578015611d8657905b8060071b610e00018160071b602086010180358060041c615a93578252602081013560208301526040810135604083015260608101358060a01c615a935760608301525050600101818118611d36575b505080610de05250506101a08101358060011c615a9357611000526101c08101358060a01c615a9357611020525060406024611040376064358060a01c615a9357611080526084356110a052606060a46110c037610104358060a01c615a935761112052610124358060031c615a935761114052610144356111605260a061016461118037610204358060a01c615a935761122052610224358060011c615a93576112405260406102446112603760606102846112a0376102e4356004016020813511615a9357803560208160051b01808361130037505050610344358060a01c615a9357611720526103e06108606103e0610c6060045afa50611e8b611740615308565b61174051611ef857600c611760527f696e76616c6964206c6f616e00000000000000000000000000000000000000006117805261176050611760518061178001601f825f031636823750506308c379a061172052602061174052601f19601f61176051011660440161173cfd5b610d6051604052611f0a61174061533d565b61174051611f7757600c611760527f6e6f7420626f72726f77657200000000000000000000000000000000000000006117805261176050611760518061178001601f825f031636823750506308c379a061172052602061174052601f19601f61176051011660440161173cfd5b610d2051421115611fe757600e611740527f6c6f616e2064656661756c7465640000000000000000000000000000000000006117605261174050611740518061176001601f825f031636823750506308c379a061170052602061172052601f19601f61174051011660440161171cfd5b6102c060406102c061104060045afa50611220516103005261200a611740613d0c565b6117405161207757601a611760527f6f66666572206e6f74207369676e6564206279206c656e6465720000000000006117805261176050611760518061178001601f825f031636823750506308c379a061172052602061174052601f19601f61176051011660440161173cfd5b4261120051116120e657600d611740527f6f666665722065787069726564000000000000000000000000000000000000006117605261174050611740518061176001601f825f031636823750506308c379a061170052602061172052601f19601f61174051011660440161171cfd5b6020615ad55f395f5161108051181561215e576015611740527f696e76616c6964207061796d656e7420746f6b656e00000000000000000000006117605261174050611740518061176001601f825f031636823750506308c379a061170052602061172052601f19601f61174051011660440161171cfd5b611040516110c05111156121d157601c611740527f6f726967696e6174696f6e20666565206774207072696e636970616c000000006117605261174050611740518061176001601f825f031636823750506308c379a061170052602061172052601f19601f61174051011660440161171cfd5b6020615b355f395f516356108f8a611780526111c0516117a0526040611780602461179c5f855af1612205573d5f5f3e3d5ffd5b60403d10615a9357611780518060a01c615a93576117e0526117a051611800526117e0905080516117405260208101516117605250610260604061026061104060045afa50610dc0516102a052611740516102c052611760516102e0526113005160208160051b01806103008261130060045afa505050612284613e1f565b610da0516117405118156122f757601c611780527f636f6c6c61746572616c20636f6e7472616374206d69736d61746368000000006117a0526117805061178051806117a001601f825f031636823750506308c379a061174052602061176052601f19601f61178051011660440161175cfd5b6102c06103a06102c061104060045afa50612310614636565b610ca05160405261231f6154f5565b611040518060ff1c615a9357610cc0518060ff1c615a93578082038281135f831218615a935790509050611780526103e060406103e0610c6060045afa506123686117c0615370565b6117c0516117a0526040366117c0375f611980526103e060406103e0610c6060045afa506117a0516104205261239f6119a06153da565b6119a0805160206060820201806117e0828560045afa5050506101a08101516117c0526101c08101516119805250610260604061026061104060045afa5060406103046102a037611720516102e0526123f9611bc0614104565b611bc0805160208160071b01806119a0828560045afa505050505f611bc0525f6119a05160048111615a9357801561247c57905b8060071b6119c0018051611be0526020810151611c00526040810151611c20526060810151611c405250611bc051611c0051808201828110615a935790509050611bc05260010181811861242d575b50505f6002610c60516020525f5260405f205561178051611bc0516117a051808201828110615a93579050905061198051808201828110615a9357905090508060ff1c615a93578082038281135f831218615a9357905090506110e0518060ff1c615a93578082018281125f831218615a935790509050611be052610cc0516117a051808201828110615a9357905090506117c051808203828111615a93579050905061198051808201828110615a935790509050611c0052611040516110c051808203828111615a9357905090506110e051808201828110615a935790509050611c20527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff611be051136125c057610d6051604052611be051805f03600160ff1b82141582825f03141615615a935790505f8112615a93576060526125c0615517565b61122051610d8051146125fd5761122051604052611c20516060526125e3615517565b610d8051604052611c005160605261266c6155d65661266c565b611c2051611c00511161264457611c2051611c0051101561266c57610d8051604052611c2051611c0051808203828111615a93579050905060605261266c6155175661266c565b610d8051604052611c0051611c2051808203828111615a93579050905060605261266c6155d6565b6001611be0511261269457610d6051604052611be0515f8112615a93576060526126946155d6565b5f6117e05160048111615a935780156126eb57905b60608102611800018051611c40526020810151611c60526040810151611c805250611c8051604052611c60516060526126e06155d6565b6001018181186126a9575b50505f6119a05160048111615a9357801561276a57905b8060071b6119c0018051611c40526020810151611c60526040810151611c80526060810151611ca052506002611c40511461274257611c60511515612744565b5f5b1561275f57611ca051604052611c605160605261275f6155d6565b600101818118612702575b50506102c060406102c061104060045afa50612787611c6061452b565b611c6051611c40525f611c6052611c4051611c805261128051611ca05261104051611cc05261106051611ce05261108051611d0052426110a051808201828110615a935790509050611d205242611d4052610d6051611d605261122051611d805261174051611da052610dc051611dc0526119a05160208160071b0180611de0826119a060045afa505050611240516120005261102051612020526103e060406103e0611c6060045afa5061283d612040614574565b61204051611c60526002611c60516020525f5260405f2054156128bf576013612040527f6c6f616e20616c726561647920657869737473000000000000000000000000006120605261204050612040518061206001601f825f031636823750506308c379a061200052602061202052601f19601f61204051011660440161201cfd5b6103e060406103e0611c6060045afa506128da6120406147a6565b612040516002611c60516020525f5260405f20557fadf0e5d2eb7098352961e41ff94c8d5bd1e0d24910d7c8e7ae147610146fef21610240611c605161204052611cc05161206052611ce05161208052611d00516120a052611d20516120c052611d40516120e052611da05161210052611dc05161212052611d605161214052611d805161216052806121805280612040015f611de0518083528060071b5f8260048111615a935780156129ca57905b8060071b60208701018160071b611e000180518252602081015160208301526040810151604083015260608101516060830152505060010181811861298a575b50508201602001915050905081019050612000516121a052610c60516121c052610cc0516121e0526117a05161220052806122205280612040015f6117e051808352606081025f8260048111615a93578015612a5857905b60608102602087010160608202611800018051825260208101516020830152604081015160408301525050600101818118612a22575b50508201602001915050905081019050611c4051612240526112805161226052612040a16020611c60f3613d08565b63304b74ed8118613d085761052436103417615a93576004356004018035610c60526020810135610c80526040810135610ca0526060810135610cc0526080810135610ce05260a08101358060a01c615a9357610d005260c0810135610d205260e0810135610d40526101008101358060a01c615a9357610d60526101208101358060a01c615a9357610d80526101408101358060a01c615a9357610da052610160810135610dc05261018081013581016004813511615a935780355f8160048111615a93578015612ba557905b8060071b610e00018160071b602086010180358060041c615a93578252602081013560208301526040810135604083015260608101358060a01c615a935760608301525050600101818118612b55575b505080610de05250506101a08101358060011c615a9357611000526101c08101358060a01c615a9357611020525060406024611040376064358060a01c615a9357611080526084356110a052606060a46110c037610104358060a01c615a935761112052610124358060031c615a935761114052610144356111605260a061016461118037610204358060a01c615a935761122052610224358060011c615a93576112405260406102446112603760606102846112a0376102e4356004016020813511615a9357803560208160051b018083611300375050506103e06108606103e0610c6060045afa50612c9a611720615308565b61172051612d0757600c611740527f696e76616c6964206c6f616e00000000000000000000000000000000000000006117605261174050611740518061176001601f825f031636823750506308c379a061170052602061172052601f19601f61174051011660440161171cfd5b610d8051604052612d1961172061533d565b61172051612d8657600a611740527f6e6f74206c656e646572000000000000000000000000000000000000000000006117605261174050611740518061176001601f825f031636823750506308c379a061170052602061172052601f19601f61174051011660440161171cfd5b610d2051421115612df657600e611720527f6c6f616e2064656661756c7465640000000000000000000000000000000000006117405261172050611720518061174001601f825f031636823750506308c379a06116e052602061170052601f19601f6117205101166044016116fcfd5b6102c060406102c061104060045afa506112205161030052612e19611720613d0c565b61172051612e8657601a611740527f6f66666572206e6f74207369676e6564206279206c656e6465720000000000006117605261174050611740518061176001601f825f031636823750506308c379a061170052602061172052601f19601f61174051011660440161171cfd5b426112005111612ef557600d611720527f6f666665722065787069726564000000000000000000000000000000000000006117405261172050611720518061174001601f825f031636823750506308c379a06116e052602061170052601f19601f6117205101166044016116fcfd5b6020615ad55f395f51611080511815612f6d576015611720527f696e76616c6964207061796d656e7420746f6b656e00000000000000000000006117405261172050611720518061174001601f825f031636823750506308c379a06116e052602061170052601f19601f6117205101166044016116fcfd5b611040516110c0511115612fe057601c611720527f6f726967696e6174696f6e20666565206774207072696e636970616c000000006117405261172050611720518061174001601f825f031636823750506308c379a06116e052602061170052601f19601f6117205101166044016116fcfd5b610d2051426110a051808201828110615a935790509050101561306257601d611720527f6d61747572697479206265666f7265206c6f616e206d617475726974790000006117405261172050611720518061174001601f825f031636823750506308c379a06116e052602061170052601f19601f6117205101166044016116fcfd5b6020615b355f395f516356108f8a611760526111c051611780526040611760602461177c5f855af1613096573d5f5f3e3d5ffd5b60403d10615a9357611760518060a01c615a93576117c052611780516117e0526117c0905080516117205260208101516117405250610260604061026061104060045afa50610dc0516102a052611720516102c052611740516102e0526113005160208160051b01806103008261130060045afa505050613115613e1f565b610da05161172051181561318857601c611760527f636f6c6c61746572616c20636f6e7472616374206d69736d61746368000000006117805261176050611760518061178001601f825f031636823750506308c379a061172052602061174052601f19601f61176051011660440161173cfd5b6102c06103a06102c061104060045afa506131a1614636565b610ca0516040526131b06154f5565b611040518060ff1c615a9357610cc0518060ff1c615a93578082038281135f831218615a935790509050611760526103e060406103e0610c6060045afa506131f96117a0615370565b6117a051611780526040366117a0375f611960526103e060406103e0610c6060045afa5061178051610420526132306119806153da565b611980805160206060820201806117c0828560045afa5050506101a08101516117a0526101c08101516119605250610260604061026061104060045afa506060366102a037613280611ba0614104565b611ba0805160208160071b0180611980828560045afa505050505f611ba0525f6119805160048111615a9357801561330357905b8060071b6119a0018051611bc0526020810151611be0526040810151611c00526060810151611c205250611ba051611be051808201828110615a935790509050611ba0526001018181186132b4575b50505f6002610c60516020525f5260405f20556103e060406103e0610c6060045afa5061026061042061026061104060045afa506117805161068052611960516106a052613352611be06158ea565b611be051611bc052611bc0518060ff1c615a93576117805161196051808201828110615a9357905090508060ff1c615a9357611760518082038281135f831218615a935790509050808281188284130218905090505f8112615a9357611be05261176051611780518060ff1c615a93578082038281135f831218615a935790509050611960518060ff1c615a93578082038281135f831218615a935790509050611be0518060ff1c615a93578082018281125f831218615a935790509050611c0052610cc05161178051808201828110615a93579050905061196051808201828110615a9357905090506110e051808201828110615a9357905090508060ff1c615a9357611ba0516117a051808201828110615a935790509050611be051808201828110615a9357905090508060ff1c615a93578082038281135f831218615a935790509050611c2052611040516110c051808203828111615a9357905090506110e051808201828110615a935790509050611c40525f611c00511215613538576012611c60527f626f72726f7765722064656c7461203c20300000000000000000000000000000611c8052611c6050611c605180611c8001601f825f031636823750506308c379a0611c20526020611c4052601f19601f611c60510116604401611c3cfd5b61122051610d8051146135f7575f611c205112156135b5576010611c60527f6c656e6465722064656c7461203c203000000000000000000000000000000000611c8052611c6050611c605180611c8001601f825f031636823750506308c379a0611c20526020611c4052601f19601f611c60510116604401611c3cfd5b61122051604052611c40516060526135cb615517565b6001611c2051126136ec57610d8051604052611c20515f8112615a93576060526136ec6155d6566136ec565b611c2051611c40518060ff1c615a93578082038281135f831218615a935790509050611c60525f611c6051131561368d576010611c80527f6c656e6465722064656c7461203e203000000000000000000000000000000000611ca052611c8050611c805180611ca001601f825f031636823750506308c379a0611c40526020611c6052601f19601f611c80510116604401611c5cfd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff611c6051136136ec57610d8051604052611c6051805f03600160ff1b82141582825f03141615615a935790505f8112615a93576060526136ec615517565b6001611c00511261371457610d6051604052611c00515f8112615a93576060526137146155d6565b5f6117c05160048111615a9357801561376b57905b606081026117e0018051611c60526020810151611c80526040810151611ca05250611ca051604052611c80516060526137606155d6565b600101818118613729575b50505f6119805160048111615a935780156137ea57905b8060071b6119a0018051611c60526020810151611c80526040810151611ca0526060810151611cc052506002611c6051146137c257611c805115156137c4565b5f5b156137df57611cc051604052611c80516060526137df6155d6565b600101818118613782575b50506102c060406102c061104060045afa50613807611c8061452b565b611c8051611c60525f611c8052611c6051611ca05261128051611cc05261104051611ce05261106051611d005261108051611d2052426110a051808201828110615a935790509050611d405242611d6052610d6051611d805261122051611da05261172051611dc052610dc051611de0526119805160208160071b0180611e008261198060045afa505050611240516120205261102051612040526103e060406103e0611c8060045afa506138bd612060614574565b61206051611c80526002611c80516020525f5260405f20541561393f576013612060527f6c6f616e20616c726561647920657869737473000000000000000000000000006120805261206050612060518061208001601f825f031636823750506308c379a061202052602061204052601f19601f61206051011660440161203cfd5b6103e060406103e0611c8060045afa5061395a6120606147a6565b612060516002611c80516020525f5260405f20557f3104dd99ab576a709e2bea4bedb076e17210d16fdbc54a86b7db45e9f3be8284610260611c805161206052611ce05161208052611d00516120a052611d20516120c052611d40516120e052611d605161210052611dc05161212052611de05161214052611d805161216052611da05161218052806121a05280612060015f611e00518083528060071b5f8260048111615a93578015613a4a57905b8060071b60208701018160071b611e2001805182526020810151602083015260408101516040830152606081015160608301525050600101818118613a0a575b50508201602001915050905081019050612020516121c052610c60516121e052610cc051612200526117805161222052806122405280612060015f6117c051808352606081025f8260048111615a93578015613ad857905b606081026020870101606082026117e0018051825260208101516020830152604081015160408301525050600101818118613aa2575b50508201602001915050905081019050611be05161226052611c605161228052611280516122a052612060a16020611c80f3613d08565b638199abaf8118613d085734615a93576009336020525f5260405f2054613b8b5760146040527f6e6f2070656e64696e67207472616e736665727300000000000000000000000060605260405060405180606001601f825f031636823750506308c379a05f526020602052601f19601f6040510116604401601cfd5b6009336020525f5260405f20546040525f6009336020525f5260405f20556020615ad55f395f5163a9059cbb6060523360805260405160a052602060606044607c5f855af1613bdc573d5f5f3e3d5ffd5b60203d10615a93576060518060011c615a935760c05260c0905051613c5957601360e0527f6572726f722073656e64696e672066756e6473000000000000000000000000006101005260e05060e0518061010001601f825f031636823750506308c379a060a052602060c052601f19601f60e051011660440160bcfd5b7fb533bf65f7139533fed34316e420b8cefd0c9fb1730ceaf49fa4d0cd42341dd93360605260405160805260406060a100613d08565b63150b7a028118613d085760a436103417615a93576004358060a01c615a93576040526024358060a01c615a9357606052606435600401610400813511615a93576020813501808260803750507f150b7a02000000000000000000000000000000000000000000000000000000006104a05260206104a0f35b5f5ffd5b610300515f610760525f6002610320527f1901000000000000000000000000000000000000000000000000000000000000610340526103208051602082018361068001815181525050808301925050506020615bd5610620397fb54af15efd4078a08fa64b2ca6923174f13b55e91014d675bcae943a355f4335610380526102606103a0610260604060045afa50610280610360526103608051602082012090506106405260406106005261060080516020820183610680018281848460045afa50505080830192505050806106605261066090508051602082012090506106e0526102a051610700526102c051610720526102e05161074052602061076060806106e060015afa506107605114815250565b6102c051613e8c57601a610720527f636f6c6c61746572616c206e6f742077686974656c69737465640000000000006107405261072050610720518061074001601f825f031636823750506308c379a06106e052602061070052601f19601f6107205101166044016106fcfd5b60016101405118613f0e576102a051610160511815614102576015610720527f746f6b656e206964206e6f7420696e206f6666657200000000000000000000006107405261072050610720518061074001601f825f031636823750506308c379a06106e052602061070052601f19601f6107205101166044016106fcfd614102565b6002610140511861400357610180516102a0511015613f8c576019610720527f746f6b656e69642062656c6f77206f666665722072616e6765000000000000006107405261072050610720518061074001601f825f031636823750506308c379a06106e052602061070052601f19601f6107205101166044016106fcfd5b6101a0516102a0511115614102576019610720527f746f6b656e69642061626f7665206f666665722072616e6765000000000000006107405261072050610720518061074001601f825f031636823750506308c379a06106e052602061070052601f19601f6107205101166044016106fcfd614102565b6102c051610760526101e051610780526102a0516107a052606061074052610740805160208201209050610720525f6103005160208111615a9357801561408d57905b8060051b610320015161074052610740515f5260205f20610720515f5260205f20186107805260206107605261076080516020820120905061072052600101818118614046575b5050610720516102e051181561410257600d610740527f70726f6f6620696e76616c6964000000000000000000000000000000000000006107605261074050610740518061076001601f825f031636823750506308c379a061070052602061072052601f19601f61074051011660440161071cfd5b565b5f6103005260c051156141825760405160c051111561418257601c610520527f6f726967696e6174696f6e20666565206774207072696e636970616c000000006105405261052050610520518061054001601f825f031636823750506308c379a06104e052602061050052601f19601f6105205101166044016104fcfd5b6101005115614192576001614198565b60e05115155b1561420a576101205161420a57601a610520527f62726f6b65722066656520776974686f757420616464726573730000000000006105405261052050610520518061054001601f825f031636823750506308c379a06104e052602061050052601f19601f6105205101166044016104fcfd5b6102a0511561421a576001614221565b6102c05115155b15614293576102e05161429357601a610520527f62726f6b65722066656520776974686f757420616464726573730000000000006105405261052050610520518061054001601f825f031636823750506308c379a06104e052602061050052601f19601f6105205101166044016104fcfd5b6020615b955f395f5161010051111561430b57601d610520527f6c656e6465722062726f6b6572206665652065786365656473206d61780000006105405261052050610520518061054001601f825f031636823750506308c379a06104e052602061050052601f19601f6105205101166044016104fcfd5b6020615bb55f395f516102c051111561438357601f610520527f626f72726f7765722062726f6b6572206665652065786365656473206d6178006105405261052050610520518061054001601f825f031636823750506308c379a06104e052602061050052601f19601f6105205101166044016104fcfd5b61271060055461010051808201828110615a935790509050111561440657601c610520527f736574746c656d656e742066656573206774207072696e636970616c000000006105405261052050610520518061054001601f825f031636823750506308c379a06104e052602061050052601f19601f6105205101166044016104fcfd5b6103005160038111615a93578060071b6103200160018152600454604051808202811583838304141715615a93579050905061271081049050602082015260055460408201526003546060820152506001810161030052506103005160038111615a93578060071b610320016002815260c05160208201525f6040820152610220516060820152506001810161030052506103005160038111615a93578060071b610320016004815260e0516020820152610100516040820152610120516060820152506001810161030052506103005160038111615a93578060071b61032001600881526102a05160208201526102c05160408201526102e0516060820152506001810161030052506103005160208160071b0180838261030060045afa50505050565b5f6102a0518161032001526020810190506102c0518161032001526020810190506102e05181610320015260208101905080610300526103009050805160208201209050815250565b5f610140518161044001526020810190506101605181610440015260208101905061012051816104400152602081019050610180518161044001526020810190506101a05181610440015260208101905080610420526104209050805160208201209050815250565b600160076040516020525f5260405f20557f08f7f4fedc8c9bd3165579676da5b715f2babe388ed555519fcae0e56c2e507d6040516103205261024051610340526101e0516103605261016051610380526080610320a1565b6102c060406102c06103a060045afa5061465161068061452b565b61068051610660526007610660516020525f5260405f2054156146d357600d610680527f6f66666572207265766f6b6564000000000000000000000000000000000000006106a0526106805061068051806106a001601f825f031636823750506308c379a061064052602061066052601f19601f61068051011660440161065cfd5b60066105e0516020525f5260405f2054610680526105c05161068051106147595760146106a0527f6f666665722066756c6c79207574696c697a65640000000000000000000000006106c0526106a0506106a051806106c001601f825f031636823750506308c379a061066052602061068052601f19601f6106a051011660440161067cfd5b6106805160018101818110615a9357905060066105e0516020525f5260405f205560016104a051186147a457610660516040526102c060606102c06103a060045afa506147a46145dd565b565b6020806104405280610440016101e060405182526060516020830152608051604083015260a051606083015260c051608083015260e05160a08301526101005160c08301526101205160e08301526101405161010083015261016051610120830152610180516101408301526101a051610160830152806101808301528082015f6101c0518083528060071b5f8260048111615a9357801561488457905b8060071b60208701018160071b6101e001805182526020810151602083015260408101516040830152606081015160608301525050600101818118614844575b505082016020019150509050810190506103e0516101a0830152610400516101c083015290508101905061042052610420805160208201209050815250565b604051635817816860805260605160a052602060806024609c845afa6148eb573d5f5f3e3d5ffd5b60203d10615a93576080518060a01c615a935760c05260c0905051815250565b6020615b155f395f5163088f11f3610140526080516101605260a0610140602461015c845afa61493d573d5f5f3e3d5ffd5b60a03d10615a9357610140518060011c615a9357610200526101605161022052610180518060a01c615a9357610240526101a051610260526101c0518060a01c615a9357610280526102009050805160a052602081015160c052604081015160e0526060810151610100526080810151610120525060a0516149bf575f6149f5565b60805160c051186149f357610100516149ed57610120516149e15760016149f5565b306101205118156149f5565b5f6149f5565b5f5b815250565b60605163088f11f3610140526080516101605260a0610140602461015c845afa614a26573d5f5f3e3d5ffd5b60a03d10615a9357610140518060011c615a9357610200526101605161022052610180518060a01c615a9357610240526101a051610260526101c0518060a01c615a9357610280526102009050805160a052602081015160c052604081015160e0526060810151610100526080810151610120525060a051614b07576017610140527f636f6c6c61746572616c206e6f7420666f722073616c650000000000000000006101605261014050610140518061016001601f825f031636823750506308c379a061010052602061012052601f19601f61014051011660440161011cfd5b60805160c0511815614b7857601f610140527f636f6c6c61746572616c20776974682077726f6e672070756e6b496e646578006101605261014050610140518061016001601f825f031636823750506308c379a061010052602061012052601f19601f61014051011660440161011cfd5b60405160e0511815614be957601e610140527f636f6c6c61746572616c206e6f77206f776e65642062792077616c6c657400006101605261014050610140518061016001601f825f031636823750506308c379a061010052602061012052601f19601f61014051011660440161011cfd5b6101005115614c5757601c610140527f636f6c6c61746572616c206f66666572206973206e6f74207a65726f000000006101605261014050610140518061016001601f825f031636823750506308c379a061010052602061012052601f19601f61014051011660440161011cfd5b61012051614c66576001614c6e565b306101205118155b614cd7576020610140527f636f6c6c61746572616c20627579696e67206e6f7420617574686f72697a65646101605261014050610140518061016001601f825f031636823750506308c379a061010052602061012052601f19601f61014051011660440161011cfd5b606051638264fe986101405260805161016052803b15615a93575f610140602461015c5f855af1614d0a573d5f5f3e3d5ffd5b50565b604051636352211e60805260605160a052602060806024609c845afa614d35573d5f5f3e3d5ffd5b60203d10615a93576080518060a01c615a935760c05260c0905051815250565b60605163e985e9c560a05260405160c0523060e052602060a0604460bc845afa614d81573d5f5f3e3d5ffd5b60203d10615a935760a0518060011c615a935761010052610100905051614df4573060605163081812fc61012052608051610140526020610120602461013c845afa614dcf573d5f5f3e3d5ffd5b60203d10615a9357610120518060a01c615a9357610160526101609050511815614df7565b60015b815250565b60605163b88d4fde60c052608060405160e05230610100526080516101205280610140525f60a05260a08160e0015f81528051806020830101601f825f03163682375050601f19601f825160200101169050905081015050803b15615a93575f60c060a460dc5f855af1614e72573d5f5f3e3d5ffd5b50565b6020615b155f395f5160405114815250565b6102a051614ef4576015610300527f6164647220697320746865207a65726f206164647200000000000000000000006103205261030050610300518061032001601f825f031636823750506308c379a06102c05260206102e052601f19601f6103005101166044016102dcfd5b6102c051614f6157601c610300527f636f6c6c6174206164647220697320746865207a65726f2061646472000000006103205261030050610300518061032001601f825f031636823750506308c379a06102c05260206102e052601f19601f6103005101166044016102dcfd5b6102c051604052614f73610300614e75565b610300516150b5576102a0516102c0516040526102e051606052614f98610300614d0d565b61030051181561500757601e610320527f636f6c6c61746572616c206e6f74206f776e65642062792077616c6c657400006103405261032050610320518061034001601f825f031636823750506308c379a06102e052602061030052601f19601f6103205101166044016102fcfd5b6102a0516040526102c0516060526102e051608052615027610300614d55565b61030051615094576018610320527f7472616e73666572206973206e6f7420617070726f76656400000000000000006103405261032050610320518061034001601f825f031636823750506308c379a06102e052602061030052601f19601f6103205101166044016102fcfd5b6102a0516040526102c0516060526102e0516080526151eb614dfc566151eb565b6102a0516102c0516040526102e0516060526150d26103206148c3565b61032051181561514157601e610340527f636f6c6c61746572616c206e6f74206f776e65642062792077616c6c657400006103605261034050610340518061036001601f825f031636823750506308c379a061030052602061032052601f19601f61034051011660440161031cfd5b6102a0516040526102c0516060526102e05160805261516161032061490b565b610320516151ce576018610340527f7472616e73666572206973206e6f7420617070726f76656400000000000000006103605261034050610340518061036001601f825f031636823750506308c379a061030052602061032052601f19601f61034051011660440161031cfd5b6102a0516040526102c0516060526102e0516080526151eb6149fa565b565b6020615ad55f395f516323b872dd60a05260405160c05260605160e05260805161010052602060a0606460bc5f855af1615229573d5f5f3e3d5ffd5b60203d10615a935760a0518060011c615a9357610120526101209050516152af576013610140527f7472616e7366657246726f6d206661696c6564000000000000000000000000006101605261014050610140518061016001601f825f031636823750506308c379a061010052602061012052601f19601f61014051011660440161011cfd5b565b6020615af55f395f5163b18e2bbb60c05260405160e05260605161010052608051610120525f6101405260a05161016052602060c060a460dc5f855af16152fa573d5f5f3e3d5ffd5b60203d10615a935760c05050565b6103e060406103e061086060045afa50615323610c406147a6565b610c40516002610860516020525f5260405f205414815250565b604051331861534d57600161536b565b6008336020525f5260405f2054615364575f61536b565b3260405118155b815250565b6103e0516153875760c0518152506153d8566153d8565b60c0514261012051808203828111615a935790509050808202811583838304141715615a9357905090506101005161012051808203828111615a9357905090508015615a9357808204905090508152505b565b604036610440375f610600525f6101c05160048111615a935780156154c457905b8060071b6101e0018051610620526020810151610640526040810151610660526060810151610680525061066051156154b9576104205161066051808202811583838304141715615a935790509050612710810490506106a0526104605160038111615a935760608102610480016106205181526106a051602082015261068051604082015250600181016104605250610440516106a051808201828110615a93579050905061044052600861062051186154b9576106a051610600525b6001018181186153fb575b5050610460516020606082020180838261046060045afa505050610440516101a0820152610600516101c082015250565b60066040516020525f5260405f20805460018103818111615a93579050815550565b6020615ad55f395f516323b872dd60805260405160a0523060c05260605160e052602060806064609c5f855af1615550573d5f5f3e3d5ffd5b60203d10615a93576080518060011c615a9357610100526101009050516155d4576013610120527f7472616e7366657246726f6d206661696c6564000000000000000000000000006101405261012050610120518061014001601f825f031636823750506308c379a060e052602061010052601f19601f61012051011660440160fcfd5b565b6040366080376020615ad55f395f515a63a9059cbb60e4526004604051610104526060516101245260400160e05260e050602061018060e0516101005f8686f1905090506080523d602081183d602010021861016052610160805160a052602081015160c0525060805161564b57600161565a565b60c05160a05160200360031b1c155b156156b7577f1c43b9761b3fba5321ca8212bfc231945f668ccc0c446f333999eea9ce8fda8160405160e05260605161010052604060e0a160096040516020525f5260405f208054606051808201828110615a9357905090508155505b565b3061010051604052610120516060526156d36101406148c3565b61014051181561574257601d610160527f636f6c6c61746572616c206e6f74206f776e6564206279207661756c740000006101805261016050610160518061018001601f825f031636823750506308c379a061012052602061014052601f19601f61016051011660440161013cfd5b61010051638b72a2ec6101405260e051610160526101205161018052803b15615a93575f610140604461015c5f855af161577e573d5f5f3e3d5ffd5b50565b30610100516040526101205160605261579b610140614d0d565b61014051181561580a57601d610160527f636f6c6c61746572616c206e6f74206f776e6564206279207661756c740000006101805261016050610160518061018001601f825f031636823750506308c379a061012052602061014052601f19601f61016051011660440161013cfd5b6101005163b88d4fde610160526080306101805260e0516101a052610120516101c052806101e0525f6101405261014081610180015f81528051806020830101601f825f03163682375050601f19601f825160200101169050905081015050803b15615a93575f61016060a461017c5f855af1615889573d5f5f3e3d5ffd5b50565b6102405160405261589e610280614e75565b610280516158c9576102205160e052610240516101005261026051610120526158e8615781566158e8565b6102205160e052610240516101005261026051610120526158e86156b9565b565b5f6106c0525f6101c05160048111615a9357801561594d57905b8060071b6101e00180516106e0526020810151610700526040810151610720526060810151610740525060086106e0511861594257610720516106c0525b600101818118615904575b50506106205161595f57610440615968565b5f610700526107005b516106e0526106205161597b575f6159b0565b60c05161068051808203828111615a9357905090506106c051808202811583838304141715615a935790509050612710810490505b6107005260c05161068051808203828111615a93579050905061072052610620516159dd57610440615a21565b610440516101005142808203828111615a935790509050808202811583838304141715615a935790509050610480518015615a935780820490509050610760526107605b51610740526106e0518060ff1c615a9357610740518060ff1c615a9357610720518060ff1c615a93578082038281135f831218615a935790509050610700518060ff1c615a93578082038281135f831218615a935790509050808281188284130218905090505f8112615a9357815250565b5f80fd11e5075c08193c8f3d0807db2a873b0f09081c683d083d0800643d083d0817103d0801023d0811a608e805a0077e00183d080493092a3d081175115315e884195ad581183e190120a16576797065728300030a0017000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a11704b3dd545dc0771d9a9c5572064db2a5c06200000000000000000000000000000000000000447e69651d841bd8d104bed493000000000000000000000000b47e3cd837ddf8e4c57f05d70ab865de6e193bbb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007d96cc26566bfca358c61fbe7be3ca771da7ea60000000000000000000000000000000000000000000000000000000000001388000000000000000000000000000000000000000000000000000000000000138800000000000000000000000000000000000000000000000000000000000013880000000000000000000000000000000000000000000000000000000000001388

Deployed Bytecode

0x5f3560e01c6002601f820660011b615a9701601e395f51565b638da5cb5b81186100335734615a93575f5460405260206040f35b6361acb5598118613d0857602436103417615a935760076004356020525f5260405f205460405260206040f3613d08565b63885753de81186100805734615a935760015460405260206040f35b63ffa1ad748118613d085734615a935760208060805260176040527f5032504c656e64696e674e6674732e323032343130303200000000000000000060605260408160800181518152602082015160208201528051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506080f3613d08565b63331c658781186101205734615a93576020615ad560403960206040f35b6305107f058118613d085761022436103417615a93576004356004018035610c60526020810135610c80526040810135610ca0526060810135610cc0526080810135610ce05260a08101358060a01c615a9357610d005260c0810135610d205260e0810135610d40526101008101358060a01c615a9357610d60526101208101358060a01c615a9357610d80526101408101358060a01c615a9357610da052610160810135610dc05261018081013581016004813511615a935780355f8160048111615a9357801561023e57905b8060071b610e00018160071b602086010180358060041c615a93578252602081013560208301526040810135604083015260608101358060a01c615a9357606083015250506001018181186101ee575b505080610de05250506101a08101358060011c615a9357611000526101c08101358060a01c615a935761102052506103e06108606103e0610c6060045afa50610288611040615308565b611040516102f557600c611060527f696e76616c6964206c6f616e00000000000000000000000000000000000000006110805261106050611060518061108001601f825f031636823750506308c379a061102052602061104052601f19601f61106051011660440161103cfd5b610d20514211610364576012611040527f6c6f616e206e6f742064656661756c74656400000000000000000000000000006110605261104050611040518061106001601f825f031636823750506308c379a061100052602061102052601f19601f61104051011660440161101cfd5b610d805160405261037661104061533d565b611040516103e357600a611060527f6e6f74206c656e646572000000000000000000000000000000000000000000006110805261106050611060518061108001601f825f031636823750506308c379a061102052602061104052601f19601f61106051011660440161103cfd5b5f6002610c60516020525f5260405f2055610d805161022052610da05161024052610dc0516102605261041461588c565b611020511561043e5761102051604052610da051606052610dc0516080525f60a05261043e6152b1565b7f4a55c2facef4f87dd498aace39997457e1fc66968956bfe3ac7f20f736e77e74610c605161104052610d605161106052610d805161108052610da0516110a052610dc0516110c05260a0611040a100613d08565b63c4a9081581186104c057602436103417615a935760026004356020525f5260405f205460405260206040f35b639544fa7c8118613d0857604436103417615a93576004358060a01c615a93576040526024358060011c615a93576060525f543318156105565760096080527f6e6f74206f776e6572000000000000000000000000000000000000000000000060a0526080506080518060a001601f825f031636823750506308c379a06040526020606052601f19601f6080510116604401605cfd5b60605160086040516020525f5260405f20557f5e09e79221e29a6d762b708b6fa399e730dfc027f946b2e81a31d849b2fb1fa960405160805260605160a05260406080a100613d08565b63e5107ed781186105be5734615a93576020615af560403960206040f35b63c2a5022b8118613d0857604436103417615a93575f543318156106375760096040527f6e6f74206f776e6572000000000000000000000000000000000000000000000060605260405060405180606001601f825f031636823750506308c379a05f526020602052601f19601f6040510116604401601cfd5b6020615b555f395f5160043511156106a45760176040527f757066726f6e74206665652065786365656473206d617800000000000000000060605260405060405180606001601f825f031636823750506308c379a05f526020602052601f19601f6040510116604401601cfd5b6020615b755f395f51602435111561071157601a6040527f736574746c656d656e74206665652065786365656473206d617800000000000060605260405060405180606001601f825f031636823750506308c379a05f526020602052601f19601f6040510116604401601cfd5b7f4bfb2e8697c06dccd3777bdd9b4dab854905ca53b2a56bb47882c744729729d46004546040526005546060526040600460803760806040a160043560045560243560055500613d08565b635556eda98118613d085734615a93576020615b1560403960206040f3613d08565b637719e9ea811861079c5734615a93576020615b3560403960206040f35b639274bbcd8118613d0857602436103417615a93576004358060a01c615a935760405260096040516020525f5260405f205460605260206060f3613d08565b6367db749981186107f75734615a935760035460405260206040f35b63f8c266298118613d085734615a93576020615b9560403960206040f3613d08565b6358e7783781186108355734615a935760045460405260206040f35b63f7a79a028118613d085734615a93576001543318156108aa5760166040527f6e6f74207468652070726f706f736564206f776e65720000000000000000000060605260405060405180606001601f825f031636823750506308c379a05f526020602052601f19601f6040510116604401601cfd5b7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f5460405260015460605260406040a1335f555f60015500613d08565b6361dd0b8b8118613d085734615a935760055460405260206040f3613d08565b6350d0d5ad8118613d085734615a93576020615b5560403960206040f3613d08565b6387c8f69481186109485734615a93576020615b7560403960206040f35b63a1c7a5678118613d08576103a436103417615a935760406004610860376044358060a01c615a93576108a0526064356108c052606060846108e03760e4358060a01c615a935761094052610104358060031c615a935761096052610124356109805260a06101446109a0376101e4358060a01c615a9357610a4052610204358060011c615a9357610a60526040610224610a80376060610264610ac0376102e4356004016020813511615a9357803560208160051b018083610b2037505050610304358060a01c615a9357610f4052610364358060a01c615a9357610f60526102c060406102c061086060045afa50610a405161030052610a4b610f80613d0c565b610f8051610ab857601a610fa0527f6f66666572206e6f74207369676e6564206279206c656e646572000000000000610fc052610fa050610fa05180610fc001601f825f031636823750506308c379a0610f60526020610f8052601f19601f610fa0510116604401610f7cfd5b42610a205111610b2757600d610f80527f6f66666572206578706972656400000000000000000000000000000000000000610fa052610f8050610f805180610fa001601f825f031636823750506308c379a0610f40526020610f6052601f19601f610f80510116604401610f5cfd5b6020615ad55f395f516108a0511815610b9f576015610f80527f696e76616c6964207061796d656e7420746f6b656e0000000000000000000000610fa052610f8050610f805180610fa001601f825f031636823750506308c379a0610f40526020610f6052601f19601f610f80510116604401610f5cfd5b610860516108e0511115610c1257601c610f80527f6f726967696e6174696f6e20666565206774207072696e636970616c00000000610fa052610f8050610f805180610fa001601f825f031636823750506308c379a0610f40526020610f6052601f19601f610f80510116604401610f5cfd5b6020615b355f395f516356108f8a610fc0526109e051610fe0526040610fc06024610fdc5f855af1610c46573d5f5f3e3d5ffd5b60403d10615a9357610fc0518060a01c615a935761102052610fe0516110405261102090508051610f80526020810151610fa05250610260604061026061086060045afa506102c4356102a052610f80516102c052610fa0516102e052610b205160208160051b018061030082610b2060045afa505050610cc5613e1f565b610260604061026061086060045afa5060406103246102a037610f60516102e052610cf16111e0614104565b6111e0805160208160071b0180610fc0828560045afa505050505f6111e0525f610fc05160048111615a93578015610d7457905b8060071b610fe001805161120052602081015161122052604081015161124052606081015161126052506111e05161122051808201828110615a9357905090506111e052600101818118610d25575b50506102c060406102c061086060045afa50610d9161122061452b565b61122051611200525f611220526112005161124052610aa051611260526108605161128052610880516112a0526108a0516112c052426108c051808201828110615a9357905090506112e05242611300526008336020525f5260405f2054610df95733610dfb565b325b61132052610a405161134052610f8051611360526102c43561138052610fc05160208160071b01806113a082610fc060045afa505050610a60516115c052610f40516115e0526103e060406103e061122060045afa50610e5c611600614574565b61160051611220526002611220516020525f5260405f205415610ede576013611600527f6c6f616e20616c726561647920657869737473000000000000000000000000006116205261160050611600518061162001601f825f031636823750506308c379a06115c05260206115e052601f19601f6116005101166044016115dcfd5b6102c06103a06102c061086060045afa50610ef7614636565b6103e060406103e061122060045afa50610f126116006147a6565b611600516002611220516020525f5260405f2055611320516102a052611360516102c052611380516102e052610f46614e87565b6113405160405261132051606052611280516111e051808203828111615a93579050905061090051808201828110615a935790509050608052610f876151ed565b5f610fc05160048111615a9357801561100b57905b8060071b610fe0018051611600526020810151611620526040810151611640526060810151611660525060026116005114610fdc57611620511515610fde565b5f5b15611000576113405160405261166051606052611620516080526110006151ed565b600101818118610f9c575b5050610f40511561103857610f40516040526113605160605261138051608052600160a0526110386152b1565b7f6827a33d0a24e36314681156d8d9a7d20d6a0548c169735fe25e00c9d38ac5a96101e0611220516116005261128051611620526112a051611640526112c051611660526112e05161168052611300516116a052611320516116c052611340516116e05261136051611700526113805161172052806117405280611600015f6113a0518083528060071b5f8260048111615a9357801561111457905b8060071b60208701018160071b6113c0018051825260208101516020830152604081015160408301526060810151606083015250506001018181186110d4575b505082016020019150509050810190506115c051611760526112005161178052610aa0516117a052610f40516117c052611600a16020611220f3613d08565b631b0b0c638118613d085734615a93576020615bb560403960206040f3613d08565b63225daa0f8118613d0857602436103417615a935760066004356020525f5260405f205460405260206040f3613d08565b6396069a5f8118613d0857602436103417615a93576004358060a01c615a935760405260086040516020525f5260405f205460605260206060f3613d08565b6372e76f13811861130a57602436103417615a93576004358060a01c615a93576040525f5433181561126d5760096060527f6e6f74206f776e6572000000000000000000000000000000000000000000000060805260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b6040516112d057601a6060527f77616c6c657420697320746865207a65726f206164647265737300000000000060805260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b7f6defa6e1a7dcc97f459fb552cf25427ab19cd60692b94e4f38660850a6e917e860035460605260405160805260406060a1604051600355005b63c75b6e5e8118613d08576102c436103417615a935760406004610780376044358060a01c615a93576107c0526064356107e052606060846108003760e4358060a01c615a935761086052610104358060031c615a935761088052610124356108a05260a06101446108c0376101e4358060a01c615a935761096052610204358060011c615a93576109805260406102246109a03760606102646109e037610960516040526113ba610a4061533d565b610a405161142757600a610a60527f6e6f74206c656e64657200000000000000000000000000000000000000000000610a8052610a6050610a605180610a8001601f825f031636823750506308c379a0610a20526020610a4052601f19601f610a60510116604401610a3cfd5b42610940511161149657600d610a40527f6f66666572206578706972656400000000000000000000000000000000000000610a6052610a4050610a405180610a6001601f825f031636823750506308c379a0610a00526020610a2052601f19601f610a40510116604401610a1cfd5b6102c060406102c061078060045afa5061096051610300526114b9610a40613d0c565b610a405161152657601a610a60527f6f66666572206e6f74207369676e6564206279206c656e646572000000000000610a8052610a6050610a605180610a8001601f825f031636823750506308c379a0610a20526020610a4052601f19601f610a60510116604401610a3cfd5b6102c060406102c061078060045afa50611541610a6061452b565b610a6051610a40526007610a40516020525f5260405f2054156115c3576015610a60527f6f6666657220616c7265616479207265766f6b65640000000000000000000000610a8052610a6050610a605180610a8001601f825f031636823750506308c379a0610a20526020610a4052601f19601f610a60510116604401610a3cfd5b610a40516040526102c060606102c061078060045afa506115e26145dd565b00613d08565b63bc71771d8118613d0857602436103417615a93576004358060a01c615a93576040525f543318156116705760096060527f6e6f74206f776e6572000000000000000000000000000000000000000000000060805260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b6040516116d35760106060527f5f61646472657373206973207a65726f0000000000000000000000000000000060805260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b7f722cace8a9cbcb7713f3f71015c8c6b59ed317672489140eb6b3fa7f4a139d845f5460605260405160805260406060a160405160015500613d08565b63802d67998118613d085761022436103417615a93576004356004018035610c60526020810135610c80526040810135610ca0526060810135610cc0526080810135610ce05260a08101358060a01c615a9357610d005260c0810135610d205260e0810135610d40526101008101358060a01c615a9357610d60526101208101358060a01c615a9357610d80526101408101358060a01c615a9357610da052610160810135610dc05261018081013581016004813511615a935780355f8160048111615a9357801561182e57905b8060071b610e00018160071b602086010180358060041c615a93578252602081013560208301526040810135604083015260608101358060a01c615a9357606083015250506001018181186117de575b505080610de05250506101a08101358060011c615a9357611000526101c08101358060a01c615a935761102052506103e06108606103e0610c6060045afa50611878611040615308565b611040516118e557600c611060527f696e76616c6964206c6f616e00000000000000000000000000000000000000006110805261106050611060518061108001601f825f031636823750506308c379a061102052602061104052601f19601f61106051011660440161103cfd5b610d205142111561195557600e611040527f6c6f616e2064656661756c7465640000000000000000000000000000000000006110605261104050611040518061106001601f825f031636823750506308c379a061100052602061102052601f19601f61104051011660440161101cfd5b610d605160405261196761104061533d565b611040516119d457600c611060527f6e6f7420626f72726f77657200000000000000000000000000000000000000006110805261106050611060518061108001601f825f031636823750506308c379a061102052602061104052601f19601f61106051011660440161103cfd5b6103e060406103e0610c6060045afa506119ef611060615370565b6110605161104052604036611060375f611220526103e060406103e0610c6060045afa506110405161042052611a266112406153da565b61124080516020606082020180611080828560045afa5050506101a0810151611060526101c081015161122052505f6002610c60516020525f5260405f2055610ca051604052611a746154f5565b610d6051604052610cc05161104051808201828110615a93579050905061122051808201828110615a935790509050606052611aae615517565b610d8051604052610cc05161104051808201828110615a93579050905061106051808203828111615a93579050905061122051808201828110615a935790509050606052611afa6155d6565b5f6110805160048111615a93578015611b5157905b606081026110a001805161124052602081015161126052604081015161128052506112805160405261126051606052611b466155d6565b600101818118611b0f575b5050610d605161022052610da05161024052610dc05161026052611b7361588c565b6110205115611b9d5761102051604052610da051606052610dc0516080525f60a052611b9d6152b1565b7f2aa6f229bb00348f1aa98ab5ab1636a2618696536f698200d76b66a87906eafa60e0610c605161124052610d605161126052610d805161128052610d00516112a052610cc0516112c052611040516112e052806113005280611240015f61108051808352606081025f8260048111615a93578015611c4e57905b606081026020870101606082026110a0018051825260208101516020830152604081015160408301525050600101818118611c18575b50508201602001915050905081019050611240a100613d08565b6313c072ee8118613d085761058436103417615a93576004356004018035610c60526020810135610c80526040810135610ca0526060810135610cc0526080810135610ce05260a08101358060a01c615a9357610d005260c0810135610d205260e0810135610d40526101008101358060a01c615a9357610d60526101208101358060a01c615a9357610d80526101408101358060a01c615a9357610da052610160810135610dc05261018081013581016004813511615a935780355f8160048111615a93578015611d8657905b8060071b610e00018160071b602086010180358060041c615a93578252602081013560208301526040810135604083015260608101358060a01c615a935760608301525050600101818118611d36575b505080610de05250506101a08101358060011c615a9357611000526101c08101358060a01c615a9357611020525060406024611040376064358060a01c615a9357611080526084356110a052606060a46110c037610104358060a01c615a935761112052610124358060031c615a935761114052610144356111605260a061016461118037610204358060a01c615a935761122052610224358060011c615a93576112405260406102446112603760606102846112a0376102e4356004016020813511615a9357803560208160051b01808361130037505050610344358060a01c615a9357611720526103e06108606103e0610c6060045afa50611e8b611740615308565b61174051611ef857600c611760527f696e76616c6964206c6f616e00000000000000000000000000000000000000006117805261176050611760518061178001601f825f031636823750506308c379a061172052602061174052601f19601f61176051011660440161173cfd5b610d6051604052611f0a61174061533d565b61174051611f7757600c611760527f6e6f7420626f72726f77657200000000000000000000000000000000000000006117805261176050611760518061178001601f825f031636823750506308c379a061172052602061174052601f19601f61176051011660440161173cfd5b610d2051421115611fe757600e611740527f6c6f616e2064656661756c7465640000000000000000000000000000000000006117605261174050611740518061176001601f825f031636823750506308c379a061170052602061172052601f19601f61174051011660440161171cfd5b6102c060406102c061104060045afa50611220516103005261200a611740613d0c565b6117405161207757601a611760527f6f66666572206e6f74207369676e6564206279206c656e6465720000000000006117805261176050611760518061178001601f825f031636823750506308c379a061172052602061174052601f19601f61176051011660440161173cfd5b4261120051116120e657600d611740527f6f666665722065787069726564000000000000000000000000000000000000006117605261174050611740518061176001601f825f031636823750506308c379a061170052602061172052601f19601f61174051011660440161171cfd5b6020615ad55f395f5161108051181561215e576015611740527f696e76616c6964207061796d656e7420746f6b656e00000000000000000000006117605261174050611740518061176001601f825f031636823750506308c379a061170052602061172052601f19601f61174051011660440161171cfd5b611040516110c05111156121d157601c611740527f6f726967696e6174696f6e20666565206774207072696e636970616c000000006117605261174050611740518061176001601f825f031636823750506308c379a061170052602061172052601f19601f61174051011660440161171cfd5b6020615b355f395f516356108f8a611780526111c0516117a0526040611780602461179c5f855af1612205573d5f5f3e3d5ffd5b60403d10615a9357611780518060a01c615a93576117e0526117a051611800526117e0905080516117405260208101516117605250610260604061026061104060045afa50610dc0516102a052611740516102c052611760516102e0526113005160208160051b01806103008261130060045afa505050612284613e1f565b610da0516117405118156122f757601c611780527f636f6c6c61746572616c20636f6e7472616374206d69736d61746368000000006117a0526117805061178051806117a001601f825f031636823750506308c379a061174052602061176052601f19601f61178051011660440161175cfd5b6102c06103a06102c061104060045afa50612310614636565b610ca05160405261231f6154f5565b611040518060ff1c615a9357610cc0518060ff1c615a93578082038281135f831218615a935790509050611780526103e060406103e0610c6060045afa506123686117c0615370565b6117c0516117a0526040366117c0375f611980526103e060406103e0610c6060045afa506117a0516104205261239f6119a06153da565b6119a0805160206060820201806117e0828560045afa5050506101a08101516117c0526101c08101516119805250610260604061026061104060045afa5060406103046102a037611720516102e0526123f9611bc0614104565b611bc0805160208160071b01806119a0828560045afa505050505f611bc0525f6119a05160048111615a9357801561247c57905b8060071b6119c0018051611be0526020810151611c00526040810151611c20526060810151611c405250611bc051611c0051808201828110615a935790509050611bc05260010181811861242d575b50505f6002610c60516020525f5260405f205561178051611bc0516117a051808201828110615a93579050905061198051808201828110615a9357905090508060ff1c615a93578082038281135f831218615a9357905090506110e0518060ff1c615a93578082018281125f831218615a935790509050611be052610cc0516117a051808201828110615a9357905090506117c051808203828111615a93579050905061198051808201828110615a935790509050611c0052611040516110c051808203828111615a9357905090506110e051808201828110615a935790509050611c20527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff611be051136125c057610d6051604052611be051805f03600160ff1b82141582825f03141615615a935790505f8112615a93576060526125c0615517565b61122051610d8051146125fd5761122051604052611c20516060526125e3615517565b610d8051604052611c005160605261266c6155d65661266c565b611c2051611c00511161264457611c2051611c0051101561266c57610d8051604052611c2051611c0051808203828111615a93579050905060605261266c6155175661266c565b610d8051604052611c0051611c2051808203828111615a93579050905060605261266c6155d6565b6001611be0511261269457610d6051604052611be0515f8112615a93576060526126946155d6565b5f6117e05160048111615a935780156126eb57905b60608102611800018051611c40526020810151611c60526040810151611c805250611c8051604052611c60516060526126e06155d6565b6001018181186126a9575b50505f6119a05160048111615a9357801561276a57905b8060071b6119c0018051611c40526020810151611c60526040810151611c80526060810151611ca052506002611c40511461274257611c60511515612744565b5f5b1561275f57611ca051604052611c605160605261275f6155d6565b600101818118612702575b50506102c060406102c061104060045afa50612787611c6061452b565b611c6051611c40525f611c6052611c4051611c805261128051611ca05261104051611cc05261106051611ce05261108051611d0052426110a051808201828110615a935790509050611d205242611d4052610d6051611d605261122051611d805261174051611da052610dc051611dc0526119a05160208160071b0180611de0826119a060045afa505050611240516120005261102051612020526103e060406103e0611c6060045afa5061283d612040614574565b61204051611c60526002611c60516020525f5260405f2054156128bf576013612040527f6c6f616e20616c726561647920657869737473000000000000000000000000006120605261204050612040518061206001601f825f031636823750506308c379a061200052602061202052601f19601f61204051011660440161201cfd5b6103e060406103e0611c6060045afa506128da6120406147a6565b612040516002611c60516020525f5260405f20557fadf0e5d2eb7098352961e41ff94c8d5bd1e0d24910d7c8e7ae147610146fef21610240611c605161204052611cc05161206052611ce05161208052611d00516120a052611d20516120c052611d40516120e052611da05161210052611dc05161212052611d605161214052611d805161216052806121805280612040015f611de0518083528060071b5f8260048111615a935780156129ca57905b8060071b60208701018160071b611e000180518252602081015160208301526040810151604083015260608101516060830152505060010181811861298a575b50508201602001915050905081019050612000516121a052610c60516121c052610cc0516121e0526117a05161220052806122205280612040015f6117e051808352606081025f8260048111615a93578015612a5857905b60608102602087010160608202611800018051825260208101516020830152604081015160408301525050600101818118612a22575b50508201602001915050905081019050611c4051612240526112805161226052612040a16020611c60f3613d08565b63304b74ed8118613d085761052436103417615a93576004356004018035610c60526020810135610c80526040810135610ca0526060810135610cc0526080810135610ce05260a08101358060a01c615a9357610d005260c0810135610d205260e0810135610d40526101008101358060a01c615a9357610d60526101208101358060a01c615a9357610d80526101408101358060a01c615a9357610da052610160810135610dc05261018081013581016004813511615a935780355f8160048111615a93578015612ba557905b8060071b610e00018160071b602086010180358060041c615a93578252602081013560208301526040810135604083015260608101358060a01c615a935760608301525050600101818118612b55575b505080610de05250506101a08101358060011c615a9357611000526101c08101358060a01c615a9357611020525060406024611040376064358060a01c615a9357611080526084356110a052606060a46110c037610104358060a01c615a935761112052610124358060031c615a935761114052610144356111605260a061016461118037610204358060a01c615a935761122052610224358060011c615a93576112405260406102446112603760606102846112a0376102e4356004016020813511615a9357803560208160051b018083611300375050506103e06108606103e0610c6060045afa50612c9a611720615308565b61172051612d0757600c611740527f696e76616c6964206c6f616e00000000000000000000000000000000000000006117605261174050611740518061176001601f825f031636823750506308c379a061170052602061172052601f19601f61174051011660440161171cfd5b610d8051604052612d1961172061533d565b61172051612d8657600a611740527f6e6f74206c656e646572000000000000000000000000000000000000000000006117605261174050611740518061176001601f825f031636823750506308c379a061170052602061172052601f19601f61174051011660440161171cfd5b610d2051421115612df657600e611720527f6c6f616e2064656661756c7465640000000000000000000000000000000000006117405261172050611720518061174001601f825f031636823750506308c379a06116e052602061170052601f19601f6117205101166044016116fcfd5b6102c060406102c061104060045afa506112205161030052612e19611720613d0c565b61172051612e8657601a611740527f6f66666572206e6f74207369676e6564206279206c656e6465720000000000006117605261174050611740518061176001601f825f031636823750506308c379a061170052602061172052601f19601f61174051011660440161171cfd5b426112005111612ef557600d611720527f6f666665722065787069726564000000000000000000000000000000000000006117405261172050611720518061174001601f825f031636823750506308c379a06116e052602061170052601f19601f6117205101166044016116fcfd5b6020615ad55f395f51611080511815612f6d576015611720527f696e76616c6964207061796d656e7420746f6b656e00000000000000000000006117405261172050611720518061174001601f825f031636823750506308c379a06116e052602061170052601f19601f6117205101166044016116fcfd5b611040516110c0511115612fe057601c611720527f6f726967696e6174696f6e20666565206774207072696e636970616c000000006117405261172050611720518061174001601f825f031636823750506308c379a06116e052602061170052601f19601f6117205101166044016116fcfd5b610d2051426110a051808201828110615a935790509050101561306257601d611720527f6d61747572697479206265666f7265206c6f616e206d617475726974790000006117405261172050611720518061174001601f825f031636823750506308c379a06116e052602061170052601f19601f6117205101166044016116fcfd5b6020615b355f395f516356108f8a611760526111c051611780526040611760602461177c5f855af1613096573d5f5f3e3d5ffd5b60403d10615a9357611760518060a01c615a93576117c052611780516117e0526117c0905080516117205260208101516117405250610260604061026061104060045afa50610dc0516102a052611720516102c052611740516102e0526113005160208160051b01806103008261130060045afa505050613115613e1f565b610da05161172051181561318857601c611760527f636f6c6c61746572616c20636f6e7472616374206d69736d61746368000000006117805261176050611760518061178001601f825f031636823750506308c379a061172052602061174052601f19601f61176051011660440161173cfd5b6102c06103a06102c061104060045afa506131a1614636565b610ca0516040526131b06154f5565b611040518060ff1c615a9357610cc0518060ff1c615a93578082038281135f831218615a935790509050611760526103e060406103e0610c6060045afa506131f96117a0615370565b6117a051611780526040366117a0375f611960526103e060406103e0610c6060045afa5061178051610420526132306119806153da565b611980805160206060820201806117c0828560045afa5050506101a08101516117a0526101c08101516119605250610260604061026061104060045afa506060366102a037613280611ba0614104565b611ba0805160208160071b0180611980828560045afa505050505f611ba0525f6119805160048111615a9357801561330357905b8060071b6119a0018051611bc0526020810151611be0526040810151611c00526060810151611c205250611ba051611be051808201828110615a935790509050611ba0526001018181186132b4575b50505f6002610c60516020525f5260405f20556103e060406103e0610c6060045afa5061026061042061026061104060045afa506117805161068052611960516106a052613352611be06158ea565b611be051611bc052611bc0518060ff1c615a93576117805161196051808201828110615a9357905090508060ff1c615a9357611760518082038281135f831218615a935790509050808281188284130218905090505f8112615a9357611be05261176051611780518060ff1c615a93578082038281135f831218615a935790509050611960518060ff1c615a93578082038281135f831218615a935790509050611be0518060ff1c615a93578082018281125f831218615a935790509050611c0052610cc05161178051808201828110615a93579050905061196051808201828110615a9357905090506110e051808201828110615a9357905090508060ff1c615a9357611ba0516117a051808201828110615a935790509050611be051808201828110615a9357905090508060ff1c615a93578082038281135f831218615a935790509050611c2052611040516110c051808203828111615a9357905090506110e051808201828110615a935790509050611c40525f611c00511215613538576012611c60527f626f72726f7765722064656c7461203c20300000000000000000000000000000611c8052611c6050611c605180611c8001601f825f031636823750506308c379a0611c20526020611c4052601f19601f611c60510116604401611c3cfd5b61122051610d8051146135f7575f611c205112156135b5576010611c60527f6c656e6465722064656c7461203c203000000000000000000000000000000000611c8052611c6050611c605180611c8001601f825f031636823750506308c379a0611c20526020611c4052601f19601f611c60510116604401611c3cfd5b61122051604052611c40516060526135cb615517565b6001611c2051126136ec57610d8051604052611c20515f8112615a93576060526136ec6155d6566136ec565b611c2051611c40518060ff1c615a93578082038281135f831218615a935790509050611c60525f611c6051131561368d576010611c80527f6c656e6465722064656c7461203e203000000000000000000000000000000000611ca052611c8050611c805180611ca001601f825f031636823750506308c379a0611c40526020611c6052601f19601f611c80510116604401611c5cfd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff611c6051136136ec57610d8051604052611c6051805f03600160ff1b82141582825f03141615615a935790505f8112615a93576060526136ec615517565b6001611c00511261371457610d6051604052611c00515f8112615a93576060526137146155d6565b5f6117c05160048111615a9357801561376b57905b606081026117e0018051611c60526020810151611c80526040810151611ca05250611ca051604052611c80516060526137606155d6565b600101818118613729575b50505f6119805160048111615a935780156137ea57905b8060071b6119a0018051611c60526020810151611c80526040810151611ca0526060810151611cc052506002611c6051146137c257611c805115156137c4565b5f5b156137df57611cc051604052611c80516060526137df6155d6565b600101818118613782575b50506102c060406102c061104060045afa50613807611c8061452b565b611c8051611c60525f611c8052611c6051611ca05261128051611cc05261104051611ce05261106051611d005261108051611d2052426110a051808201828110615a935790509050611d405242611d6052610d6051611d805261122051611da05261172051611dc052610dc051611de0526119805160208160071b0180611e008261198060045afa505050611240516120205261102051612040526103e060406103e0611c8060045afa506138bd612060614574565b61206051611c80526002611c80516020525f5260405f20541561393f576013612060527f6c6f616e20616c726561647920657869737473000000000000000000000000006120805261206050612060518061208001601f825f031636823750506308c379a061202052602061204052601f19601f61206051011660440161203cfd5b6103e060406103e0611c8060045afa5061395a6120606147a6565b612060516002611c80516020525f5260405f20557f3104dd99ab576a709e2bea4bedb076e17210d16fdbc54a86b7db45e9f3be8284610260611c805161206052611ce05161208052611d00516120a052611d20516120c052611d40516120e052611d605161210052611dc05161212052611de05161214052611d805161216052611da05161218052806121a05280612060015f611e00518083528060071b5f8260048111615a93578015613a4a57905b8060071b60208701018160071b611e2001805182526020810151602083015260408101516040830152606081015160608301525050600101818118613a0a575b50508201602001915050905081019050612020516121c052610c60516121e052610cc051612200526117805161222052806122405280612060015f6117c051808352606081025f8260048111615a93578015613ad857905b606081026020870101606082026117e0018051825260208101516020830152604081015160408301525050600101818118613aa2575b50508201602001915050905081019050611be05161226052611c605161228052611280516122a052612060a16020611c80f3613d08565b638199abaf8118613d085734615a93576009336020525f5260405f2054613b8b5760146040527f6e6f2070656e64696e67207472616e736665727300000000000000000000000060605260405060405180606001601f825f031636823750506308c379a05f526020602052601f19601f6040510116604401601cfd5b6009336020525f5260405f20546040525f6009336020525f5260405f20556020615ad55f395f5163a9059cbb6060523360805260405160a052602060606044607c5f855af1613bdc573d5f5f3e3d5ffd5b60203d10615a93576060518060011c615a935760c05260c0905051613c5957601360e0527f6572726f722073656e64696e672066756e6473000000000000000000000000006101005260e05060e0518061010001601f825f031636823750506308c379a060a052602060c052601f19601f60e051011660440160bcfd5b7fb533bf65f7139533fed34316e420b8cefd0c9fb1730ceaf49fa4d0cd42341dd93360605260405160805260406060a100613d08565b63150b7a028118613d085760a436103417615a93576004358060a01c615a93576040526024358060a01c615a9357606052606435600401610400813511615a93576020813501808260803750507f150b7a02000000000000000000000000000000000000000000000000000000006104a05260206104a0f35b5f5ffd5b610300515f610760525f6002610320527f1901000000000000000000000000000000000000000000000000000000000000610340526103208051602082018361068001815181525050808301925050506020615bd5610620397fb54af15efd4078a08fa64b2ca6923174f13b55e91014d675bcae943a355f4335610380526102606103a0610260604060045afa50610280610360526103608051602082012090506106405260406106005261060080516020820183610680018281848460045afa50505080830192505050806106605261066090508051602082012090506106e0526102a051610700526102c051610720526102e05161074052602061076060806106e060015afa506107605114815250565b6102c051613e8c57601a610720527f636f6c6c61746572616c206e6f742077686974656c69737465640000000000006107405261072050610720518061074001601f825f031636823750506308c379a06106e052602061070052601f19601f6107205101166044016106fcfd5b60016101405118613f0e576102a051610160511815614102576015610720527f746f6b656e206964206e6f7420696e206f6666657200000000000000000000006107405261072050610720518061074001601f825f031636823750506308c379a06106e052602061070052601f19601f6107205101166044016106fcfd614102565b6002610140511861400357610180516102a0511015613f8c576019610720527f746f6b656e69642062656c6f77206f666665722072616e6765000000000000006107405261072050610720518061074001601f825f031636823750506308c379a06106e052602061070052601f19601f6107205101166044016106fcfd5b6101a0516102a0511115614102576019610720527f746f6b656e69642061626f7665206f666665722072616e6765000000000000006107405261072050610720518061074001601f825f031636823750506308c379a06106e052602061070052601f19601f6107205101166044016106fcfd614102565b6102c051610760526101e051610780526102a0516107a052606061074052610740805160208201209050610720525f6103005160208111615a9357801561408d57905b8060051b610320015161074052610740515f5260205f20610720515f5260205f20186107805260206107605261076080516020820120905061072052600101818118614046575b5050610720516102e051181561410257600d610740527f70726f6f6620696e76616c6964000000000000000000000000000000000000006107605261074050610740518061076001601f825f031636823750506308c379a061070052602061072052601f19601f61074051011660440161071cfd5b565b5f6103005260c051156141825760405160c051111561418257601c610520527f6f726967696e6174696f6e20666565206774207072696e636970616c000000006105405261052050610520518061054001601f825f031636823750506308c379a06104e052602061050052601f19601f6105205101166044016104fcfd5b6101005115614192576001614198565b60e05115155b1561420a576101205161420a57601a610520527f62726f6b65722066656520776974686f757420616464726573730000000000006105405261052050610520518061054001601f825f031636823750506308c379a06104e052602061050052601f19601f6105205101166044016104fcfd5b6102a0511561421a576001614221565b6102c05115155b15614293576102e05161429357601a610520527f62726f6b65722066656520776974686f757420616464726573730000000000006105405261052050610520518061054001601f825f031636823750506308c379a06104e052602061050052601f19601f6105205101166044016104fcfd5b6020615b955f395f5161010051111561430b57601d610520527f6c656e6465722062726f6b6572206665652065786365656473206d61780000006105405261052050610520518061054001601f825f031636823750506308c379a06104e052602061050052601f19601f6105205101166044016104fcfd5b6020615bb55f395f516102c051111561438357601f610520527f626f72726f7765722062726f6b6572206665652065786365656473206d6178006105405261052050610520518061054001601f825f031636823750506308c379a06104e052602061050052601f19601f6105205101166044016104fcfd5b61271060055461010051808201828110615a935790509050111561440657601c610520527f736574746c656d656e742066656573206774207072696e636970616c000000006105405261052050610520518061054001601f825f031636823750506308c379a06104e052602061050052601f19601f6105205101166044016104fcfd5b6103005160038111615a93578060071b6103200160018152600454604051808202811583838304141715615a93579050905061271081049050602082015260055460408201526003546060820152506001810161030052506103005160038111615a93578060071b610320016002815260c05160208201525f6040820152610220516060820152506001810161030052506103005160038111615a93578060071b610320016004815260e0516020820152610100516040820152610120516060820152506001810161030052506103005160038111615a93578060071b61032001600881526102a05160208201526102c05160408201526102e0516060820152506001810161030052506103005160208160071b0180838261030060045afa50505050565b5f6102a0518161032001526020810190506102c0518161032001526020810190506102e05181610320015260208101905080610300526103009050805160208201209050815250565b5f610140518161044001526020810190506101605181610440015260208101905061012051816104400152602081019050610180518161044001526020810190506101a05181610440015260208101905080610420526104209050805160208201209050815250565b600160076040516020525f5260405f20557f08f7f4fedc8c9bd3165579676da5b715f2babe388ed555519fcae0e56c2e507d6040516103205261024051610340526101e0516103605261016051610380526080610320a1565b6102c060406102c06103a060045afa5061465161068061452b565b61068051610660526007610660516020525f5260405f2054156146d357600d610680527f6f66666572207265766f6b6564000000000000000000000000000000000000006106a0526106805061068051806106a001601f825f031636823750506308c379a061064052602061066052601f19601f61068051011660440161065cfd5b60066105e0516020525f5260405f2054610680526105c05161068051106147595760146106a0527f6f666665722066756c6c79207574696c697a65640000000000000000000000006106c0526106a0506106a051806106c001601f825f031636823750506308c379a061066052602061068052601f19601f6106a051011660440161067cfd5b6106805160018101818110615a9357905060066105e0516020525f5260405f205560016104a051186147a457610660516040526102c060606102c06103a060045afa506147a46145dd565b565b6020806104405280610440016101e060405182526060516020830152608051604083015260a051606083015260c051608083015260e05160a08301526101005160c08301526101205160e08301526101405161010083015261016051610120830152610180516101408301526101a051610160830152806101808301528082015f6101c0518083528060071b5f8260048111615a9357801561488457905b8060071b60208701018160071b6101e001805182526020810151602083015260408101516040830152606081015160608301525050600101818118614844575b505082016020019150509050810190506103e0516101a0830152610400516101c083015290508101905061042052610420805160208201209050815250565b604051635817816860805260605160a052602060806024609c845afa6148eb573d5f5f3e3d5ffd5b60203d10615a93576080518060a01c615a935760c05260c0905051815250565b6020615b155f395f5163088f11f3610140526080516101605260a0610140602461015c845afa61493d573d5f5f3e3d5ffd5b60a03d10615a9357610140518060011c615a9357610200526101605161022052610180518060a01c615a9357610240526101a051610260526101c0518060a01c615a9357610280526102009050805160a052602081015160c052604081015160e0526060810151610100526080810151610120525060a0516149bf575f6149f5565b60805160c051186149f357610100516149ed57610120516149e15760016149f5565b306101205118156149f5565b5f6149f5565b5f5b815250565b60605163088f11f3610140526080516101605260a0610140602461015c845afa614a26573d5f5f3e3d5ffd5b60a03d10615a9357610140518060011c615a9357610200526101605161022052610180518060a01c615a9357610240526101a051610260526101c0518060a01c615a9357610280526102009050805160a052602081015160c052604081015160e0526060810151610100526080810151610120525060a051614b07576017610140527f636f6c6c61746572616c206e6f7420666f722073616c650000000000000000006101605261014050610140518061016001601f825f031636823750506308c379a061010052602061012052601f19601f61014051011660440161011cfd5b60805160c0511815614b7857601f610140527f636f6c6c61746572616c20776974682077726f6e672070756e6b496e646578006101605261014050610140518061016001601f825f031636823750506308c379a061010052602061012052601f19601f61014051011660440161011cfd5b60405160e0511815614be957601e610140527f636f6c6c61746572616c206e6f77206f776e65642062792077616c6c657400006101605261014050610140518061016001601f825f031636823750506308c379a061010052602061012052601f19601f61014051011660440161011cfd5b6101005115614c5757601c610140527f636f6c6c61746572616c206f66666572206973206e6f74207a65726f000000006101605261014050610140518061016001601f825f031636823750506308c379a061010052602061012052601f19601f61014051011660440161011cfd5b61012051614c66576001614c6e565b306101205118155b614cd7576020610140527f636f6c6c61746572616c20627579696e67206e6f7420617574686f72697a65646101605261014050610140518061016001601f825f031636823750506308c379a061010052602061012052601f19601f61014051011660440161011cfd5b606051638264fe986101405260805161016052803b15615a93575f610140602461015c5f855af1614d0a573d5f5f3e3d5ffd5b50565b604051636352211e60805260605160a052602060806024609c845afa614d35573d5f5f3e3d5ffd5b60203d10615a93576080518060a01c615a935760c05260c0905051815250565b60605163e985e9c560a05260405160c0523060e052602060a0604460bc845afa614d81573d5f5f3e3d5ffd5b60203d10615a935760a0518060011c615a935761010052610100905051614df4573060605163081812fc61012052608051610140526020610120602461013c845afa614dcf573d5f5f3e3d5ffd5b60203d10615a9357610120518060a01c615a9357610160526101609050511815614df7565b60015b815250565b60605163b88d4fde60c052608060405160e05230610100526080516101205280610140525f60a05260a08160e0015f81528051806020830101601f825f03163682375050601f19601f825160200101169050905081015050803b15615a93575f60c060a460dc5f855af1614e72573d5f5f3e3d5ffd5b50565b6020615b155f395f5160405114815250565b6102a051614ef4576015610300527f6164647220697320746865207a65726f206164647200000000000000000000006103205261030050610300518061032001601f825f031636823750506308c379a06102c05260206102e052601f19601f6103005101166044016102dcfd5b6102c051614f6157601c610300527f636f6c6c6174206164647220697320746865207a65726f2061646472000000006103205261030050610300518061032001601f825f031636823750506308c379a06102c05260206102e052601f19601f6103005101166044016102dcfd5b6102c051604052614f73610300614e75565b610300516150b5576102a0516102c0516040526102e051606052614f98610300614d0d565b61030051181561500757601e610320527f636f6c6c61746572616c206e6f74206f776e65642062792077616c6c657400006103405261032050610320518061034001601f825f031636823750506308c379a06102e052602061030052601f19601f6103205101166044016102fcfd5b6102a0516040526102c0516060526102e051608052615027610300614d55565b61030051615094576018610320527f7472616e73666572206973206e6f7420617070726f76656400000000000000006103405261032050610320518061034001601f825f031636823750506308c379a06102e052602061030052601f19601f6103205101166044016102fcfd5b6102a0516040526102c0516060526102e0516080526151eb614dfc566151eb565b6102a0516102c0516040526102e0516060526150d26103206148c3565b61032051181561514157601e610340527f636f6c6c61746572616c206e6f74206f776e65642062792077616c6c657400006103605261034050610340518061036001601f825f031636823750506308c379a061030052602061032052601f19601f61034051011660440161031cfd5b6102a0516040526102c0516060526102e05160805261516161032061490b565b610320516151ce576018610340527f7472616e73666572206973206e6f7420617070726f76656400000000000000006103605261034050610340518061036001601f825f031636823750506308c379a061030052602061032052601f19601f61034051011660440161031cfd5b6102a0516040526102c0516060526102e0516080526151eb6149fa565b565b6020615ad55f395f516323b872dd60a05260405160c05260605160e05260805161010052602060a0606460bc5f855af1615229573d5f5f3e3d5ffd5b60203d10615a935760a0518060011c615a9357610120526101209050516152af576013610140527f7472616e7366657246726f6d206661696c6564000000000000000000000000006101605261014050610140518061016001601f825f031636823750506308c379a061010052602061012052601f19601f61014051011660440161011cfd5b565b6020615af55f395f5163b18e2bbb60c05260405160e05260605161010052608051610120525f6101405260a05161016052602060c060a460dc5f855af16152fa573d5f5f3e3d5ffd5b60203d10615a935760c05050565b6103e060406103e061086060045afa50615323610c406147a6565b610c40516002610860516020525f5260405f205414815250565b604051331861534d57600161536b565b6008336020525f5260405f2054615364575f61536b565b3260405118155b815250565b6103e0516153875760c0518152506153d8566153d8565b60c0514261012051808203828111615a935790509050808202811583838304141715615a9357905090506101005161012051808203828111615a9357905090508015615a9357808204905090508152505b565b604036610440375f610600525f6101c05160048111615a935780156154c457905b8060071b6101e0018051610620526020810151610640526040810151610660526060810151610680525061066051156154b9576104205161066051808202811583838304141715615a935790509050612710810490506106a0526104605160038111615a935760608102610480016106205181526106a051602082015261068051604082015250600181016104605250610440516106a051808201828110615a93579050905061044052600861062051186154b9576106a051610600525b6001018181186153fb575b5050610460516020606082020180838261046060045afa505050610440516101a0820152610600516101c082015250565b60066040516020525f5260405f20805460018103818111615a93579050815550565b6020615ad55f395f516323b872dd60805260405160a0523060c05260605160e052602060806064609c5f855af1615550573d5f5f3e3d5ffd5b60203d10615a93576080518060011c615a9357610100526101009050516155d4576013610120527f7472616e7366657246726f6d206661696c6564000000000000000000000000006101405261012050610120518061014001601f825f031636823750506308c379a060e052602061010052601f19601f61012051011660440160fcfd5b565b6040366080376020615ad55f395f515a63a9059cbb60e4526004604051610104526060516101245260400160e05260e050602061018060e0516101005f8686f1905090506080523d602081183d602010021861016052610160805160a052602081015160c0525060805161564b57600161565a565b60c05160a05160200360031b1c155b156156b7577f1c43b9761b3fba5321ca8212bfc231945f668ccc0c446f333999eea9ce8fda8160405160e05260605161010052604060e0a160096040516020525f5260405f208054606051808201828110615a9357905090508155505b565b3061010051604052610120516060526156d36101406148c3565b61014051181561574257601d610160527f636f6c6c61746572616c206e6f74206f776e6564206279207661756c740000006101805261016050610160518061018001601f825f031636823750506308c379a061012052602061014052601f19601f61016051011660440161013cfd5b61010051638b72a2ec6101405260e051610160526101205161018052803b15615a93575f610140604461015c5f855af161577e573d5f5f3e3d5ffd5b50565b30610100516040526101205160605261579b610140614d0d565b61014051181561580a57601d610160527f636f6c6c61746572616c206e6f74206f776e6564206279207661756c740000006101805261016050610160518061018001601f825f031636823750506308c379a061012052602061014052601f19601f61016051011660440161013cfd5b6101005163b88d4fde610160526080306101805260e0516101a052610120516101c052806101e0525f6101405261014081610180015f81528051806020830101601f825f03163682375050601f19601f825160200101169050905081015050803b15615a93575f61016060a461017c5f855af1615889573d5f5f3e3d5ffd5b50565b6102405160405261589e610280614e75565b610280516158c9576102205160e052610240516101005261026051610120526158e8615781566158e8565b6102205160e052610240516101005261026051610120526158e86156b9565b565b5f6106c0525f6101c05160048111615a9357801561594d57905b8060071b6101e00180516106e0526020810151610700526040810151610720526060810151610740525060086106e0511861594257610720516106c0525b600101818118615904575b50506106205161595f57610440615968565b5f610700526107005b516106e0526106205161597b575f6159b0565b60c05161068051808203828111615a9357905090506106c051808202811583838304141715615a935790509050612710810490505b6107005260c05161068051808203828111615a93579050905061072052610620516159dd57610440615a21565b610440516101005142808203828111615a935790509050808202811583838304141715615a935790509050610480518015615a935780820490509050610760526107605b51610740526106e0518060ff1c615a9357610740518060ff1c615a9357610720518060ff1c615a93578082038281135f831218615a935790509050610700518060ff1c615a93578082038281135f831218615a935790509050808281188284130218905090505f8112615a9357815250565b5f80fd11e5075c08193c8f3d0807db2a873b0f09081c683d083d0800643d083d0817103d0801023d0811a608e805a0077e00183d080493092a3d081175115315e8000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000447e69651d841bd8d104bed493000000000000000000000000b47e3cd837ddf8e4c57f05d70ab865de6e193bbb000000000000000000000000a11704b3dd545dc0771d9a9c5572064db2a5c06200000000000000000000000000000000000000000000000000000000000013880000000000000000000000000000000000000000000000000000000000001388000000000000000000000000000000000000000000000000000000000000138800000000000000000000000000000000000000000000000000000000000013886d1b99f1a5c06364c839c0ed8aed09de5cb05b31a10190bbb613cede614558e4

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

000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a11704b3dd545dc0771d9a9c5572064db2a5c06200000000000000000000000000000000000000447e69651d841bd8d104bed493000000000000000000000000b47e3cd837ddf8e4c57f05d70ab865de6e193bbb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007d96cc26566bfca358c61fbe7be3ca771da7ea60000000000000000000000000000000000000000000000000000000000001388000000000000000000000000000000000000000000000000000000000000138800000000000000000000000000000000000000000000000000000000000013880000000000000000000000000000000000000000000000000000000000001388

-----Decoded View---------------
Arg [0] : _payment_token (address): 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
Arg [1] : _p2p_control (address): 0xa11704B3dD545dC0771d9a9c5572064Db2A5C062
Arg [2] : _delegation_registry (address): 0x00000000000000447e69651d841bD8D104Bed493
Arg [3] : _cryptopunks (address): 0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB
Arg [4] : _protocol_upfront_fee (uint256): 0
Arg [5] : _protocol_settlement_fee (uint256): 0
Arg [6] : _protocol_wallet (address): 0x07d96cC26566BFCA358C61fBe7be3Ca771Da7EA6
Arg [7] : _max_protocol_upfront_fee (uint256): 5000
Arg [8] : _max_protocol_settlement_fee (uint256): 5000
Arg [9] : _max_lender_broker_settlement_fee (uint256): 5000
Arg [10] : _max_borrower_broker_settlement_fee (uint256): 5000

-----Encoded View---------------
11 Constructor Arguments found :
Arg [0] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [1] : 000000000000000000000000a11704b3dd545dc0771d9a9c5572064db2a5c062
Arg [2] : 00000000000000000000000000000000000000447e69651d841bd8d104bed493
Arg [3] : 000000000000000000000000b47e3cd837ddf8e4c57f05d70ab865de6e193bbb
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [6] : 00000000000000000000000007d96cc26566bfca358c61fbe7be3ca771da7ea6
Arg [7] : 0000000000000000000000000000000000000000000000000000000000001388
Arg [8] : 0000000000000000000000000000000000000000000000000000000000001388
Arg [9] : 0000000000000000000000000000000000000000000000000000000000001388
Arg [10] : 0000000000000000000000000000000000000000000000000000000000001388


Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

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