S Price: $0.743258 (-2.51%)

Contract

0xfacefeedcc1a5FDdCa97a20511e6641a5c44370F

Overview

S Balance

Sonic LogoSonic LogoSonic Logo0 S

S Value

$0.00

Multichain Info

1 address found via
Transaction Hash
Method
Block
From
To
Set_lz_uln_confi...84837362025-02-18 16:26:247 days ago1739895984IN
0xfacefeed...a5c44370F
0 S0.0035877550.63942202
Set_lz_uln_confi...84621492025-02-18 13:56:117 days ago1739886971IN
0xfacefeed...a5c44370F
0 S0.0035424550
Set_lz_uln_confi...84611442025-02-18 13:46:447 days ago1739886404IN
0xfacefeed...a5c44370F
0 S0.007538750
Set_lz_uln_confi...84611402025-02-18 13:46:417 days ago1739886401IN
0xfacefeed...a5c44370F
0 S0.007538750
Set_lz_uln_confi...84611322025-02-18 13:46:377 days ago1739886397IN
0xfacefeed...a5c44370F
0 S0.007538750
Set_lz_uln_confi...84611252025-02-18 13:46:327 days ago1739886392IN
0xfacefeed...a5c44370F
0 S0.007538750
Set_lz_uln_confi...84611192025-02-18 13:46:297 days ago1739886389IN
0xfacefeed...a5c44370F
0 S0.007538750
Set_lz_uln_confi...84611142025-02-18 13:46:257 days ago1739886385IN
0xfacefeed...a5c44370F
0 S0.007538750
Set_lz_uln_confi...84421602025-02-18 11:11:377 days ago1739877097IN
0xfacefeed...a5c44370F
0 S0.003282650
Set_lz_uln_confi...84421542025-02-18 11:11:347 days ago1739877094IN
0xfacefeed...a5c44370F
0 S0.003282650
Set_lz_uln_confi...84421502025-02-18 11:11:327 days ago1739877092IN
0xfacefeed...a5c44370F
0 S0.003282650
Set_lz_uln_confi...84421462025-02-18 11:11:307 days ago1739877090IN
0xfacefeed...a5c44370F
0 S0.003282650
Set_lz_uln_confi...84421412025-02-18 11:11:277 days ago1739877087IN
0xfacefeed...a5c44370F
0 S0.003282650
Set_lz_uln_confi...84421342025-02-18 11:11:257 days ago1739877085IN
0xfacefeed...a5c44370F
0 S0.003282650
Set_lz_uln_confi...83047202025-02-17 16:53:508 days ago1739811230IN
0xfacefeed...a5c44370F
0 S0.0091438354.47333333
Set_lz_uln_confi...83047142025-02-17 16:53:478 days ago1739811227IN
0xfacefeed...a5c44370F
0 S0.0083929550
Set_lz_uln_confi...83047062025-02-17 16:53:458 days ago1739811225IN
0xfacefeed...a5c44370F
0 S0.0083929550
Set_lz_uln_confi...83047002025-02-17 16:53:438 days ago1739811223IN
0xfacefeed...a5c44370F
0 S0.0083929550
Set_lz_uln_confi...83046932025-02-17 16:53:418 days ago1739811221IN
0xfacefeed...a5c44370F
0 S0.0085868251.155
Set_lz_uln_confi...83046852025-02-17 16:53:388 days ago1739811218IN
0xfacefeed...a5c44370F
0 S0.0090207453.74
Set_block_oracle82978592025-02-17 16:07:368 days ago1739808456IN
0xfacefeed...a5c44370F
0 S0.0022929550
Initialize82964122025-02-17 15:58:338 days ago1739807913IN
0xfacefeed...a5c44370F
0 S0.0508202354.06666666

Latest 1 internal transaction

Parent Transaction Hash Block From To
82958732025-02-17 15:54:488 days ago1739807688  Contract Creation0 S
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Vyper_contract

Compiler Version
vyper:0.4.0

Optimization Enabled:
Yes

Other Settings:
default evmVersion

Contract Source Code (Vyper Json-Input format)

File 1 of 3 : LZBlockRelay.vy
# pragma version ~=0.4
# pragma optimize gas
# pragma evm-version cancun

"""
@title LayerZero Block Relay

@notice Layer Zero messenger for block hashes.
This contract should be deployed on multiple chains along with BlockOracle and MainnetBlockView.

Main functionality includes requesting lzRead of recent ethereum mainnet blockhashes from MainnetBlockView.
Upon receiving LZ message in lzReceive, the blockhash is committed to the BlockOracle, and if it was a read request,
the contract will attempt to broadcast the blockhash to other chains via lzSend.

If chain is read-enabled, it will be able to read the blockhash from MainnetBlockView and broadcast it to other chains.
If chain is not read-enabled, it will only be able to receive blockhashes from other chains.

@license Copyright (c) Curve.Fi, 2025 - all rights reserved

@author curve.fi

@custom:security [email protected]

"""


################################################################
#                           INTERFACES                         #
################################################################

interface IBlockOracle:
    def commit_block(block_number: uint256, block_hash: bytes32) -> bool: nonpayable
    def last_confirmed_block_number() -> uint256: view
    def block_hash(block_number: uint256) -> bytes32: view


################################################################
#                            MODULES                           #
################################################################

# Import LayerZero module for cross-chain messaging
from ..modules import LayerZeroV2 as lz

initializes: lz
exports: (
    lz.LZ_ENDPOINT,
    lz.LZ_PEERS,
    lz.LZ_DELEGATE,
    lz.LZ_READ_CHANNEL,
    lz.default_gas_limit,
    lz.nextNonce,
    lz.allowInitializePath,
    lz.get_configured_eids,
)

# Import ownership management
from snekmate.auth import ownable

initializes: ownable
exports: (
    ownable.owner,
    ownable.transfer_ownership,
    ownable.renounce_ownership,
)


################################################################
#                           CONSTANTS                          #
################################################################

MAX_N_BROADCAST: constant(uint256) = 32
GET_BLOCKHASH_SELECTOR: constant(Bytes[4]) = method_id("get_blockhash(uint256,bool)")
BROADCAST_REQUEST_MESSAGE: constant(Bytes[17]) = b"broadcast_request"


################################################################
#                            STORAGE                           #
################################################################

is_initialized: public(bool)

# Read configuration
is_read_enabled: public(bool)
mainnet_eid: public(uint32)
mainnet_block_view: public(address)

# Block oracle
block_oracle: public(IBlockOracle)

# Refund address
default_lz_refund_address: public(address)

# Struct for cached broadcast info
struct BroadcastTarget:
    eid: uint32
    fee: uint256


# Cached broadcast targets
cached_broadcast_targets: DynArray[BroadcastTarget, MAX_N_BROADCAST]


################################################################
#                            EVENTS                            #
################################################################

event BlockHashBroadcast:
    source_eid: uint32
    block_number: uint256
    block_hash: bytes32
    targets: DynArray[BroadcastTarget, MAX_N_BROADCAST]


################################################################
#                          CONSTRUCTOR                         #
################################################################

@deploy
def __init__(_owner: address):
    """
    @notice Empty constructor for deterministic deployment
    """
    lz.__init__()
    ownable.__init__()
    ownable._transfer_ownership(_owner)


@external
def initialize(
    _endpoint: address,
    _gas_limit: uint256,
    _read_channel: uint32,
    # Can optionally initialize with peers
    _peer_eids: DynArray[uint32, lz.MAX_PEERS],
    _peers: DynArray[address, lz.MAX_PEERS],
    # Also can provide libs per peer (must provide lib types: 1 for lzsend, 2 for lzreceive)
    # We limit to 2 * MAX_PEERS because we have send and receive libs for each peer
    _oapps: DynArray[address, 2 * lz.MAX_PEERS],
    _channels: DynArray[uint32, 2 * lz.MAX_PEERS],
    _libs: DynArray[address, 2 * lz.MAX_PEERS],
    _lib_types: DynArray[uint16, 2 * lz.MAX_PEERS],
):
    """
    @notice Initialize contract with core settings
    @dev Can only be called once, assumes caller is owner, sets as delegate
    @param _endpoint LayerZero endpoint address
    @param _gas_limit Default gas limit for cross-chain messages
    @param _read_channel LZ Read channel ID
    """
    ownable._check_owner()
    assert not self.is_initialized, "Already initialized"
    assert _endpoint != empty(address), "Invalid endpoint"

    self.is_initialized = True
    self.default_lz_refund_address = self

    # Initialize LayerZero module
    lz._initialize(_endpoint, _gas_limit, _read_channel, _peer_eids, _peers)

    # Set owner as delegate
    lz._set_delegate(msg.sender)

    # Set libs if provided
    assert len(_channels) == len(_libs), "Libs-channels length mismatch"
    assert len(_libs) == len(_lib_types), "Libs-types length mismatch"
    for i: uint256 in range(0, len(_channels), bound=2 * lz.MAX_PEERS):
        if _lib_types[i] == 1:
            lz._set_send_lib(_oapps[i], _channels[i], _libs[i])
        elif _lib_types[i] == 2:
            lz._set_receive_lib(_oapps[i], _channels[i], _libs[i])
        else:
            raise ("Invalid lib type")


################################################################
#                      OWNER FUNCTIONS                         #
################################################################

@external
def set_peer(_srcEid: uint32, _peer: address):
    """
    @notice Set trusted peer contract on another chain
    @param _srcEid Target endpoint ID
    @param _peer Contract address on target chain
    """

    ownable._check_owner()
    lz._set_peer(_srcEid, _peer)


@external
def set_default_gas(_gas_limit: uint256):
    """
    @notice Update default gas limit for messages
    @param _gas_limit New gas limit
    """

    ownable._check_owner()
    lz._set_default_gas_limit(_gas_limit)


@external
def set_lz_read_channel(_new_channel: uint32):
    """
    @notice Set new read channel for read requests
    @param _new_channel New read channel ID
    """

    ownable._check_owner()
    lz._set_lz_read_channel(_new_channel)


@external
def set_lz_send_lib(_oapp: address, _channel: uint32, _lib: address):
    """
    @notice Set new send library for send requests
    @param _oapp Peer application address
    @param _channel Send channel ID
    @param _lib New send library address
    """

    ownable._check_owner()
    lz._set_send_lib(_oapp, _channel, _lib)


@external
def set_lz_receive_lib(_oapp: address, _channel: uint32, _lib: address):
    """
    @notice Set new receive library for receive requests
    @param _oapp Peer application address
    @param _channel Receive channel ID
    @param _lib New receive library address
    """

    ownable._check_owner()
    lz._set_receive_lib(_oapp, _channel, _lib)


@external
def set_lz_delegate(_delegate: address):
    """
    @notice Set new delegate for LayerZero operations
    @param _delegate New delegate address
    """

    ownable._check_owner()
    lz._set_delegate(_delegate)


@external
def set_lz_uln_config(
    _eid: uint32,
    _oapp: address,
    _lib: address,
    _config_type: uint32,
    _confirmations: uint64,
    _required_dvns: DynArray[address, 10],
    _optional_dvns: DynArray[address, 10],
    _optional_dvn_threshold: uint8,
    _executor: address = empty(address),
):
    """
    @notice Set new ULN configuration for cross-chain messages
    @param _eid Endpoint ID
    @param _oapp Originating application address
    @param _lib Library address
    @param _config_type Configuration type
    @param _confirmations Number of confirmations required
    @param _required_dvns List of required DVN addresses
    @param _optional_dvns List of optional DVN addresses
    @param _optional_dvn_threshold Optional DVN threshold
    """

    ownable._check_owner()
    lz._set_uln_config(
        _eid,
        _oapp,
        _lib,
        _config_type,
        _confirmations,
        _required_dvns,
        _optional_dvns,
        _optional_dvn_threshold,
        _executor,
    )


@external
def set_read_config(_is_enabled: bool, _mainnet_eid: uint32, _mainnet_view: address):
    """
    @notice Configure read functionality
    @param _is_enabled Whether this contract can initiate reads
    @param _mainnet_eid Mainnet endpoint ID
    @param _mainnet_view MainnetBlockView contract address
    """
    ownable._check_owner()
    self.is_read_enabled = _is_enabled
    self.mainnet_eid = _mainnet_eid
    self.mainnet_block_view = _mainnet_view


@external
def set_block_oracle(_oracle: address):
    """
    @notice Set the block oracle address
    @param _oracle Block oracle address
    """
    ownable._check_owner()
    self.block_oracle = IBlockOracle(_oracle)


@external
def set_default_lz_refund_address(_refund_address: address):
    """
    @notice Set default refund address for LayerZero operations
    @param _refund_address New refund address
    """
    ownable._check_owner()
    self.default_lz_refund_address = _refund_address


@external
def withdraw_eth(_amount: uint256):
    """
    @notice Withdraw ETH from contract
    @param _amount Amount to withdraw
    """

    ownable._check_owner()
    assert self.balance >= _amount, "Insufficient balance"
    send(msg.sender, _amount)


################################################################
#                     INTERNAL FUNCTIONS                       #
################################################################

@internal
def _commit_block(_block_number: uint256, _block_hash: bytes32):
    """
    @notice Commit block hash to oracle
    """
    assert self.block_oracle != empty(IBlockOracle), "Oracle not configured"
    extcall self.block_oracle.commit_block(_block_number, _block_hash)


@view
@internal
def _prepare_read_request(_block_number: uint256) -> Bytes[lz.LZ_MESSAGE_SIZE_CAP]:
    """
    @notice Prepare complete read request message for MainnetBlockView
    @param _block_number Block number to request (0 for latest)
    @return Prepared LayerZero message bytes
    """
    # Build calldata
    calldata: Bytes[lz.LZ_READ_CALLDATA_SIZE] = abi_encode(
        _block_number, True, method_id=GET_BLOCKHASH_SELECTOR
    )

    # Prepare read message
    return lz._prepare_read_message_bytes(
        self.mainnet_eid,  # _dst_eid
        self.mainnet_block_view,  # _target
        calldata,  # _calldata
        False,  # _isBlockNum, we use timestamp
        convert(block.timestamp, uint64),  # _blockNumOrTimestamp, we use latest timestamp
        1,  # _confirmations set to 1 because we read 'older' blocks that cant be affected by reorgs
    )


@internal
def _broadcast_block(
    _block_number: uint256,
    _block_hash: bytes32,
    _broadcast_targets: DynArray[BroadcastTarget, MAX_N_BROADCAST],
    _source_eid: uint32,
    _refund_address: address = empty(address),
):
    """
    @notice Internal function to broadcast block hash to multiple chains
    @param _block_number Block number to broadcast
    @param _block_hash Block hash to broadcast
    @param _broadcast_targets Array of targets with their fees
    @param _source_eid Chain ID where the block hash originated from
    """
    message: Bytes[lz.LZ_MESSAGE_SIZE_CAP] = abi_encode(_block_number, _block_hash)

    for target: BroadcastTarget in _broadcast_targets:
        # BroadcastTarget is a struct with .eid and .fee
        target_address: address = lz.LZ_PEERS[target.eid]  # Use LZ_PEERS directly
        if target_address == empty(address):
            continue

        lz._send_message(
            target.eid,  # _dstEid
            convert(target_address, bytes32),  # _receiver
            message,  # _message
            0,  # _gas_limit: Use default gas limit
            0,  # _lz_receive_value: No value to attach to receive call
            0,  # _data_size: Zero data size (not a read)
            target.fee,  # _request_msg_value: Use cached fee as send message value
            _refund_address,  # _refund_address: shouldn't refund executor
            False,  # _perform_fee_check: No fee check
        )

    log BlockHashBroadcast(_source_eid, _block_number, _block_hash, _broadcast_targets)


@internal
def _request_block_hash(
    _target_eids: DynArray[uint32, MAX_N_BROADCAST],
    _target_fees: DynArray[uint256, MAX_N_BROADCAST],
    _block_number: uint256,
    _gas_limit: uint256,
    _request_msg_value: uint256,
    _refund_address: address,
):
    """
    @notice Internal function to request block hash from mainnet and broadcast to specified targets
    """
    assert self.is_read_enabled, "Read not enabled - call set_read_config"
    assert self.mainnet_block_view != empty(address), "Mainnet view not set - call set_read_config"
    assert len(_target_eids) == len(_target_fees), "Length mismatch"

    # Cache target EIDs and fees for lzReceive
    cached_targets: DynArray[BroadcastTarget, MAX_N_BROADCAST] = []
    sum_target_fees: uint256 = 0
    for i: uint256 in range(0, len(_target_eids), bound=MAX_N_BROADCAST):
        cached_targets.append(BroadcastTarget(eid=_target_eids[i], fee=_target_fees[i]))
        sum_target_fees += _target_fees[i]
    self.cached_broadcast_targets = cached_targets

    message: Bytes[lz.LZ_MESSAGE_SIZE_CAP] = self._prepare_read_request(_block_number)

    # Send to read channel with enough value to cover broadcasts
    lz._send_message(
        lz.LZ_READ_CHANNEL,  # _dstEid
        convert(self, bytes32),  # _receiver
        message,  # _message
        _gas_limit,  # _gas_limit: Use default gas limit
        sum_target_fees,  # _lz_receive_value: Will be available in lzReceive (and pay for broadcasts)
        64,  # _data_size: Expected read size (uint256: block number, bytes32: block hash)
        _request_msg_value,  # _request_msg_value: Use provided value
        _refund_address,  # _refund_address: Refund unspent fees to specified address
        False,  # _perform_fee_check: No fee check
    )


################################################################
#                     EXTERNAL FUNCTIONS                       #
################################################################

@external
@payable
def __default__():
    """
    @notice Default function to receive ETH
    @dev This is needed to receive refunds from LayerZero
    """
    pass


@view
@external
def quote_read_fee(
    _block_number: uint256 = 0,
    _gas_limit: uint256 = 0,
    _value: uint256 = 0,
    _data_size: uint32 = 64,
) -> uint256:
    """
    @notice Quote fee for reading block hash from mainnet
    @param _block_number Optional block number (0 means latest)
    @param _gas_limit Optional gas limit override
    @return Fee in native tokens required for the read operation
    """
    assert self.is_read_enabled, "Read not enabled - call set_read_config"
    assert self.mainnet_block_view != empty(address), "Mainnet view not set - call set_read_config"

    message: Bytes[lz.LZ_MESSAGE_SIZE_CAP] = self._prepare_read_request(_block_number)

    return lz._quote_lz_fee(
        lz.LZ_READ_CHANNEL,
        empty(address),
        message,
        _gas_limit,
        _value,
        _data_size,  # Expected response size
    )


@view
@external
def quote_broadcast_fees(
    _target_eids: DynArray[uint32, MAX_N_BROADCAST], _gas_limit: uint256 = 0
) -> DynArray[uint256, MAX_N_BROADCAST]:
    """
    @notice Quote fees for broadcasting block hash to specified targets
    @param _target_eids List of chain IDs to broadcast to
    @param _gas_limit Optional gas limit override
    @return Array of fees per target chain (0 if target not configured)
    """
    # Prepare dummy broadcast message (uint256 number, bytes32 hash)
    message: Bytes[lz.LZ_MESSAGE_SIZE_CAP] = abi_encode(empty(uint256), empty(bytes32))

    # Get fees per chain
    fees: DynArray[uint256, MAX_N_BROADCAST] = []

    for eid: uint32 in _target_eids:
        target: address = lz.LZ_PEERS[eid]  # Use LZ_PEERS directly
        if target == empty(address):
            fees.append(0)
            continue

        fee: uint256 = lz._quote_lz_fee(eid, target, message, _gas_limit)
        fees.append(fee)

    return fees


@payable
@external
def request_block_hash(
    _target_eids: DynArray[uint32, MAX_N_BROADCAST],
    _target_fees: DynArray[uint256, MAX_N_BROADCAST],
    _block_number: uint256 = 0,
    _gas_limit: uint256 = 0,
):
    """
    @notice Request block hash from mainnet and broadcast to specified targets
    @param _target_eids List of chain IDs to broadcast to
    @param _target_fees List of fees per chain (must match _target_eids length)
    @param _block_number Optional block number (0 means latest)
    @param _gas_limit Optional gas limit override
    @dev User must ensure msg.value is sufficient:
         - must cover read fee (quote_read_fee)
         - must cover broadcast fees (quote_broadcast_fees)
    """
    self._request_block_hash(
        _target_eids,
        _target_fees,
        _block_number,
        _gas_limit,
        msg.value,  # Use full msg.value
        msg.sender,  # Refund to sender
    )


@payable
@external
def broadcast_latest_block(
    _target_eids: DynArray[uint32, MAX_N_BROADCAST],
    _target_fees: DynArray[uint256, MAX_N_BROADCAST],
):
    """
    @notice Broadcast latest confirmed block hash to specified chains
    @param _target_eids List of chain IDs to broadcast to
    @param _target_fees List of fees per chain (must match _target_eids length)
    """
    assert self.is_read_enabled, "Can only broadcast from read-enabled chains"
    assert self.block_oracle != empty(IBlockOracle), "Oracle not configured"
    assert len(_target_eids) == len(_target_fees), "Length mismatch"

    # Get latest block from oracle
    block_number: uint256 = staticcall self.block_oracle.last_confirmed_block_number()
    block_hash: bytes32 = staticcall self.block_oracle.block_hash(block_number)
    assert block_hash != empty(bytes32), "No confirmed blocks"

    # Prepare broadcast targets
    broadcast_targets: DynArray[BroadcastTarget, MAX_N_BROADCAST] = []
    for i: uint256 in range(0, len(_target_eids), bound=MAX_N_BROADCAST):
        broadcast_targets.append(BroadcastTarget(eid=_target_eids[i], fee=_target_fees[i]))

    self._broadcast_block(block_number, block_hash, broadcast_targets, lz.EID, msg.sender)


@payable
@external
def request_remote_read(
    _remote_eid: uint32,
    _read_fee: uint256,
    _broadcast_fee: uint256,
    _request_gas_limit: uint256 = 0,
):
    """
    @notice Request a chain to perform an lzread operation and broadcast the result back to us
    @param _remote_eid Chain ID to request the read from
    @param _read_fee Fee to cover the lzread operation on target chain
    @param _broadcast_fee Fee to cover broadcasting the result back to us
    @dev msg.value must cover both:
         - fee to send request to target chain
         - _read_fee + _broadcast_fee which will be used by target chain
    """
    # Prepare broadcast request message (magic bytes + fee)
    message: Bytes[lz.LZ_MESSAGE_SIZE_CAP] = concat(
        BROADCAST_REQUEST_MESSAGE,  # 17 bytes
        convert(_broadcast_fee, bytes32),  # 32 bytes
    )

    # Send message to target chain
    lz._send_message(
        _remote_eid,  # _dstEid
        convert(
            lz.LZ_PEERS[_remote_eid], bytes32
        ),  # _receiver - can only be configured peer (self)
        message,  # _message
        _request_gas_limit,  # _gas_limit for read request
        _read_fee + _broadcast_fee,  # _lz_receive_value: must cover both read and broadcast
        0,  # _data_size: Zero data size (not a read)
        msg.value,  # _request_msg_value: Use full msg.value
        msg.sender,  # _refund_address: Refund to sender
        True,  # _perform_fee_check: Check fees
    )


@payable
@external
def lzReceive(
    _origin: lz.Origin,
    _guid: bytes32,
    _message: Bytes[lz.LZ_MESSAGE_SIZE_CAP],
    _executor: address,
    _extraData: Bytes[64],
) -> bool:
    """
    @notice Handle messages: read responses, broadcast requests, and regular messages
    @dev Three types of messages:
         1. Read responses (from read channel)
         2. Broadcast requests (magic bytes + fee)
         3. Regular messages (block hash broadcasts)
    @dev Broadcast request format:
         - First 17 bytes: BROADCAST_REQUEST_MESSAGE
         - Next 32 bytes: uint256 fee for return broadcast
    """
    # Verify message source
    assert lz._lz_receive(_origin, _guid, _message, _executor, _extraData)

    if lz._is_read_response(_origin):
        # Only handle read response if read is enabled
        assert self.is_read_enabled, "Read not enabled"

        # Decode block hash and number from response
        block_number: uint256 = 0
        block_hash: bytes32 = empty(bytes32)
        block_number, block_hash = abi_decode(_message, (uint256, bytes32))
        if block_hash == empty(bytes32):
            return True  # Invalid response

        self._commit_block(block_number, block_hash)

        # Get cached targets and broadcast if we have any
        broadcast_targets: DynArray[
            BroadcastTarget, MAX_N_BROADCAST
        ] = self.cached_broadcast_targets
        if len(broadcast_targets) > 0:
            # Perform broadcast and clear cache
            self._broadcast_block(
                block_number,
                block_hash,
                broadcast_targets,
                _origin.srcEid,
                self.default_lz_refund_address,
            )
            self.cached_broadcast_targets = empty(DynArray[BroadcastTarget, MAX_N_BROADCAST])
    elif slice(_message, 0, 17) == BROADCAST_REQUEST_MESSAGE:  # 17 + 32 bytes
        # Handle broadcast request - decode fee and trigger read
        broadcast_fee: uint256 = abi_decode(slice(_message, 17, 32), (uint256))

        # msg.value must cover both read and broadcast
        assert broadcast_fee <= msg.value, "Insufficient message value"

        self._request_block_hash(
            [_origin.srcEid],  # Single target - the requesting chain
            [broadcast_fee],  # Use the decoded fee for broadcast
            0,  # Latest block
            2 * lz.default_gas_limit,  # Default gas limit x2 (read + broadcast)
            msg.value,  # covers read and broadcast
            self.default_lz_refund_address,  #fee refunds destination
        )

    else:
        # Regular message - decode and commit block hash
        block_number: uint256 = 0
        block_hash: bytes32 = empty(bytes32)
        block_number, block_hash = abi_decode(_message, (uint256, bytes32))
        self._commit_block(block_number, block_hash)

    return True

File 2 of 3 : LayerZeroV2.vy
# pragma version ~=0.4

"""
@title Layer Zero V2 Vyper Module

@notice Base contract for LayerZero cross-chain messaging. Provides core
functionality for lzSend messages and lzRead.

@dev Core functionality is organized around:
1. Option building - prepare_message_options and prepare_read_options for different message types
2. Read request preparation - prepare_read_message for encoding read requests from calldata
3. Unified sending - single _send_message function that works with both message types

@license Copyright (c) Curve.Fi, 2025 - all rights reserved

@author curve.fi

@custom:security [email protected]

"""

################################################################
#                         INTERFACES                           #
################################################################

interface ILayerZeroEndpointV2:
    def quote(_params: MessagingParams, _sender: address) -> MessagingFee: view
    def send(_params: MessagingParams, _refundAddress: address) -> (
        bytes32, uint64, uint256, uint256
    ): payable
    def setDelegate(_delegate: address): nonpayable
    def setSendLibrary(_oapp: address, _eid: uint32, _newLib: address): nonpayable
    def setReceiveLibrary(
        _oapp: address, _eid: uint32, _newLib: address, _gracePeriod: uint256
    ): nonpayable
    def setConfig(_oapp: address, _lib: address, _params: DynArray[SetConfigParam, 1]): nonpayable
    def eid() -> uint32: view


################################################################
#                           CONSTANTS                          #
################################################################

# Message size limits
LZ_MESSAGE_SIZE_CAP: public(constant(uint256)) = 512
LZ_READ_CALLDATA_SIZE: public(constant(uint256)) = 256

# LayerZero protocol constants
TYPE_3: constant(bytes2) = 0x0003  # uint16
WORKER_ID: constant(bytes1) = 0x01  # uint8
OPTIONS_HEADER: constant(bytes3) = 0x000301  # concat(TYPE_3, WORKER_ID)

OPTION_TYPE_LZRECEIVE: constant(bytes1) = 0x01
OPTION_TYPE_NATIVE_DROP: constant(bytes1) = 0x02
OPTION_TYPE_LZREAD: constant(bytes1) = 0x05
READ_CHANNEL_THRESHOLD: constant(uint32) = 4294965694  # max(uint32)-1600

# Read codec constants
CMD_VERSION: constant(uint16) = 1
REQUEST_VERSION: constant(uint8) = 1
RESOLVER_TYPE: constant(uint16) = 1

# Options size cap
LZ_OPTION_SIZE: constant(uint256) = 64

#
MAX_DVNS: constant(uint8) = 10
MAX_PEERS: constant(uint256) = 128


################################################################
#                           STORAGE                            #
################################################################

LZ_ENDPOINT: public(ILayerZeroEndpointV2)  # Not immutable for init fcn
EID: public(uint32)
LZ_PEERS: public(HashMap[uint32, address])
LZ_READ_CHANNEL: public(uint32)
LZ_DELEGATE: public(address)
default_gas_limit: public(uint256)
is_initialized: public(bool)

# Track configured peer EIDs
configured_eids: DynArray[uint32, MAX_PEERS]


################################################################
#                           STRUCTS                            #
################################################################

struct MessagingParams:
    dstEid: uint32
    receiver: bytes32  # Low level format for LZ
    message: Bytes[LZ_MESSAGE_SIZE_CAP]
    options: Bytes[LZ_OPTION_SIZE]
    payInLzToken: bool


struct MessagingFee:
    nativeFee: uint256
    lzTokenFee: uint256


struct Origin:
    srcEid: uint32
    sender: bytes32
    nonce: uint64


struct EVMCallRequestV1:
    appRequestLabel: uint16
    targetEid: uint32
    isBlockNum: bool
    blockNumOrTimestamp: uint64
    confirmations: uint16
    to: address
    callData: Bytes[LZ_READ_CALLDATA_SIZE]


struct SetConfigParam:
    eid: uint32
    configType: uint32
    config: Bytes[1024]


struct ULNConfig:
    confirmations: uint64
    required_dvn_count: uint8
    optional_dvn_count: uint8
    optional_dvn_threshold: uint8
    required_dvns: DynArray[address, MAX_DVNS]  # Max 10 DVNs
    optional_dvns: DynArray[address, MAX_DVNS]  # Max 10 DVNs


struct ULNReadConfig:
    executor: address
    required_dvn_count: uint8
    optional_dvn_count: uint8
    optional_dvn_threshold: uint8
    required_dvns: DynArray[address, MAX_DVNS]  # Max 10 DVNs
    optional_dvns: DynArray[address, MAX_DVNS]  # Max 10 DVNs


struct ULNExecutorConfig:
    max_message_size: uint32
    executor: address


################################################################
#                         CONSTRUCTOR                          #
################################################################

@deploy
def __init__():
    """
    @notice Empty constructor for deterministic deployment
    """
    pass


################################################################
#                   SETTERS [GUARD THESE!]                     #
################################################################
# Note: External wrappers to these internal functions must enforce
# proper authorization.
# Exposing these functions without ownership check will lead to anyone
# being able to bridge any message/command (=loss of funds).

@internal
def _initialize(
    _endpoint: address,
    _default_gas_limit: uint256,
    _read_channel: uint32,
    _peer_eids: DynArray[uint32, MAX_PEERS],
    _peers: DynArray[address, MAX_PEERS],
):
    """
    @notice Configure the contract with core settings
    @param _endpoint LayerZero endpoint address
    @param _default_gas_limit Default gas limit for messages
    @param _read_channel LZ Read channel ID
    @dev can only be called once
    """
    assert _endpoint != empty(address), "Invalid endpoint"
    assert len(_peer_eids) == len(_peers), "Invalid peer arrays"
    assert not self.is_initialized, "Already initialized"

    self.LZ_ENDPOINT = ILayerZeroEndpointV2(_endpoint)
    self.EID = staticcall self.LZ_ENDPOINT.eid()
    self._set_default_gas_limit(_default_gas_limit)
    self._set_lz_read_channel(_read_channel)
    for i: uint256 in range(0, len(_peer_eids), bound=MAX_PEERS):
        self._set_peer(_peer_eids[i], _peers[i])
    self.is_initialized = True


@internal
def _set_peer(_srcEid: uint32, _peer: address):
    """@notice Set trusted peer for chain ID"""

    old_peer: address = self.LZ_PEERS[_srcEid]
    self.LZ_PEERS[_srcEid] = _peer

    # Update configured_eids list
    if old_peer == empty(address) and _peer != empty(address):
        # New peer being added
        self.configured_eids.append(_srcEid)
    elif old_peer != empty(address) and _peer == empty(address):
        # Peer being removed
        updated_eids: DynArray[uint32, MAX_PEERS] = []
        for eid: uint32 in self.configured_eids:
            if eid != _srcEid:
                updated_eids.append(eid)
        self.configured_eids = updated_eids


@internal
def _set_default_gas_limit(_gas_limit: uint256):
    """@notice Update default gas limit"""

    self.default_gas_limit = _gas_limit


@internal
def _set_lz_read_channel(_read_channel: uint32):
    """@notice Set read channel ID"""

    self.LZ_READ_CHANNEL = _read_channel


@internal
def _set_delegate(_delegate: address):
    """@notice Set delegate that can change any LZ setting"""

    extcall self.LZ_ENDPOINT.setDelegate(_delegate)
    self.LZ_DELEGATE = _delegate


@internal
def _set_send_lib(_oapp: address, _eid: uint32, _lib: address):
    """@notice Set new send library for send requests"""

    extcall self.LZ_ENDPOINT.setSendLibrary(_oapp, _eid, _lib)


@internal
def _set_receive_lib(_oapp: address, _eid: uint32, _lib: address):
    """@notice Set new receive library for receive requests"""

    extcall self.LZ_ENDPOINT.setReceiveLibrary(_oapp, _eid, _lib, 0)
    # 0 is for grace period, not used in this contract


@internal
def _set_uln_config(
    _eid: uint32,
    _oapp: address,
    _lib: address,
    _config_type: uint32,
    _confirmations: uint64,
    _required_dvns: DynArray[address, MAX_DVNS],
    _optional_dvns: DynArray[address, MAX_DVNS],
    _optional_dvn_threshold: uint8,
    _executor: address = empty(address),
):
    """
    @notice Set ULN config for remote endpoint
    @dev Arrays must be sorted in ascending order with no duplicates, or lz will fail
    """

    config_param: SetConfigParam = self._prepare_uln_config(
        _eid,
        _config_type,
        _confirmations,
        _required_dvns,
        _optional_dvns,
        _optional_dvn_threshold,
        _executor,
    )

    # Call endpoint to set config
    extcall self.LZ_ENDPOINT.setConfig(_oapp, _lib, [config_param])

    if _executor != empty(address) and _eid < READ_CHANNEL_THRESHOLD:
        # Set executor for ULN config
        executor_config: ULNExecutorConfig = ULNExecutorConfig(
            max_message_size=1024,
            executor=_executor,
        )
        config_param_executor: SetConfigParam = SetConfigParam(
            eid=_eid,
            configType=1,  # 1 = ULN executor config
            config=abi_encode(executor_config),
        )
        extcall self.LZ_ENDPOINT.setConfig(_oapp, _lib, [config_param_executor])


################################################################
#                      OPTION PREPARATION                      #
################################################################

@internal
@pure
def _prepare_options(_gas: uint256, _value: uint256, _data_size: uint32) -> Bytes[LZ_OPTION_SIZE]:
    """
    @notice Build options for message sending
    @param _gas Gas limit for execution on destination
    @param _value Optional native value
    @param _data_size If nonzero, indicates a read request; otherwise regular message
    """
    gas_bytes: Bytes[16] = concat(convert(convert(_gas, uint128), bytes16), b"")  # gas
    value_bytes: Bytes[16] = concat(convert(convert(_value, uint128), bytes16), b"")  # value
    data_size_bytes: Bytes[4] = concat(convert(_data_size, bytes4), b"")  # data size

    full_option: Bytes[36] = empty(Bytes[36])
    if _data_size > 0 and _value > 0:
        # read request with value
        full_option = concat(gas_bytes, data_size_bytes, value_bytes)
    elif _data_size > 0:
        # read request without value
        full_option = concat(gas_bytes, data_size_bytes)
    elif _value > 0:
        # regular message with value
        full_option = concat(gas_bytes, value_bytes)
    else:
        # regular message without value
        full_option = gas_bytes

    return concat(
        OPTIONS_HEADER,
        convert(convert(len(full_option) + 1, uint16), bytes2),  # length (option) + 1 [type]
        OPTION_TYPE_LZREAD if _data_size > 0 else OPTION_TYPE_LZRECEIVE,
        full_option,
    )


@internal
@pure
def _prepare_uln_config(
    _eid: uint32,
    _config_type: uint32,
    _confirmations: uint64,
    _required_dvns: DynArray[address, 10],
    _optional_dvns: DynArray[address, 10],
    _optional_dvn_threshold: uint8,
    _executor: address = empty(address),
) -> SetConfigParam:
    """
    @notice Prepare ULN config from arrays, automatically calculating counts
    """

    required_count: uint8 = convert(len(_required_dvns), uint8)
    optional_count: uint8 = convert(len(_optional_dvns), uint8)

    assert _optional_dvn_threshold <= optional_count, "Invalid DVN threshold"

    if _eid > READ_CHANNEL_THRESHOLD:  # read config
        uln_config: ULNReadConfig = ULNReadConfig(
            executor=_executor,
            required_dvn_count=required_count,
            optional_dvn_count=optional_count,
            optional_dvn_threshold=_optional_dvn_threshold,
            required_dvns=_required_dvns,
            optional_dvns=_optional_dvns,
        )
        return SetConfigParam(eid=_eid, configType=_config_type, config=abi_encode(uln_config))
    else:
        uln_config: ULNConfig = ULNConfig(
            confirmations=_confirmations,
            required_dvn_count=required_count,
            optional_dvn_count=optional_count,
            optional_dvn_threshold=_optional_dvn_threshold,
            required_dvns=_required_dvns,
            optional_dvns=_optional_dvns,
        )
        return SetConfigParam(eid=_eid, configType=_config_type, config=abi_encode(uln_config))


################################################################
#                    READ MESSAGE ENCODING                     #
################################################################

@view
@internal
def _is_read_response(_origin: Origin) -> bool:
    return _origin.srcEid > READ_CHANNEL_THRESHOLD


@internal
@pure
def _encode_read_request(_request: EVMCallRequestV1) -> Bytes[LZ_MESSAGE_SIZE_CAP]:
    """
    @notice Encode read request following ReadCmdCodecV1 format
    """

    # Calculate request size (35 bytes of fixed fields + calldata)
    request_size: uint16 = convert(len(_request.callData) + 35, uint16)

    # First part of headers (matches ReadCmdCodecV1.sol:183)
    encoded_headers_1: Bytes[6] = concat(
        convert(CMD_VERSION, bytes2),  # version = 1
        convert(0, bytes2),  # appCmdLabel = 0
        convert(1, bytes2),  # requests length = 1
    )

    # Complete headers (matches ReadCmdCodecV1.sol:195)
    encoded_headers_2: Bytes[13] = concat(
        encoded_headers_1,  # 6 bytes
        convert(REQUEST_VERSION, bytes1),  # version = 1
        convert(_request.appRequestLabel, bytes2),  # request label
        convert(RESOLVER_TYPE, bytes2),  # resolver type = 1
        convert(request_size, bytes2),  # payload size
    )

    # Add request fields (matches ReadCmdCodecV1.sol:204)
    return concat(
        encoded_headers_2,  # 13 bytes
        convert(_request.targetEid, bytes4),  # +4=17
        convert(_request.isBlockNum, bytes1),  # +1=18
        convert(_request.blockNumOrTimestamp, bytes8),  # +8=26
        convert(_request.confirmations, bytes2),  # +2=28
        convert(_request.to, bytes20),  # +20=48 (35 w/o headers)
        _request.callData,  # +variable
    )


################################################################
#                       CORE FUNCTIONS                         #
################################################################

@internal
@view
def _prepare_messaging_params(
    _dstEid: uint32,
    _receiver: bytes32,
    _message: Bytes[LZ_MESSAGE_SIZE_CAP],
    _gas_limit: uint256,
    _value: uint256 = 0,
    _data_size: uint32 = 0,  # Zero indicates regular message, non-zero for read
) -> MessagingParams:
    """
    @notice Prepare parameters for LayerZero endpoint interactions
    @dev This function unifies parameter preparation for both sending and quoting.
    The same structure is needed in both cases since they interact with the same
    endpoint interface. The data_size parameter determines if we're preparing
    for a regular message (data_size=0) or a read request (data_size>0).

    @param _dstEid Destination chain ID
    @param _receiver Target address (empty for reads)
    @param _message Message payload or encoded read request
    @param _gas_limit Gas limit for execution
    @param _data_size For read requests, expected response size
    @return Prepared parameters for endpoint interaction
    """

    gas: uint256 = _gas_limit if _gas_limit != 0 else self.default_gas_limit
    options: Bytes[LZ_OPTION_SIZE] = self._prepare_options(gas, _value, _data_size)
    return MessagingParams(
        dstEid=_dstEid, receiver=_receiver, message=_message, options=options, payInLzToken=False
    )


@view
@internal
def _prepare_read_message_bytes(
    _dst_eid: uint32,
    _target: address,
    _calldata: Bytes[LZ_READ_CALLDATA_SIZE],
    _isBlockNum: bool = False,  # Use timestamp by default
    _blockNumOrTimestamp: uint64 = 0,  # Uses latest ts (or block!) if 0
    _confirmations: uint16 = 15,
) -> Bytes[LZ_MESSAGE_SIZE_CAP]:
    """
    @notice Helper to prepare read request message from basic parameters
    @dev Constructs EVMCallRequestV1, encodes it into message and returns
    all parameters needed for quote or send. Uses current block timestamp
    and default confirmations.

    @param _dst_eid Target chain ID to read from
    @param _target Contract address to read from
    @param _calldata Function call data
    @return Parameters for quoting/sending:
        - destination chain ID (will be READ_CHANNEL)
        - receiver (empty for reads)
        - encoded message
    """

    # Process block number or timestamp
    blockNumOrTimestamp: uint64 = _blockNumOrTimestamp
    if blockNumOrTimestamp == 0:
        if _isBlockNum:
            blockNumOrTimestamp = convert(block.number, uint64)
        else:
            blockNumOrTimestamp = convert(block.timestamp, uint64)

    # Create read request with sensible defaults
    request: EVMCallRequestV1 = EVMCallRequestV1(
        appRequestLabel=1,
        targetEid=_dst_eid,
        isBlockNum=_isBlockNum,
        blockNumOrTimestamp=blockNumOrTimestamp,
        confirmations=_confirmations,  # Default confirmations
        to=_target,
        callData=_calldata,
    )

    # Encode request into message
    message: Bytes[LZ_MESSAGE_SIZE_CAP] = self._encode_read_request(request)

    return message


@view
@internal
def _quote_lz_fee(
    _dstEid: uint32,
    _receiver: address,
    _message: Bytes[LZ_MESSAGE_SIZE_CAP],
    _gas_limit: uint256 = 0,
    _value: uint256 = 0,
    _data_size: uint32 = 0,
) -> uint256:
    """@notice Quote fee using prepared parameters"""

    params: MessagingParams = self._prepare_messaging_params(
        _dstEid, convert(_receiver, bytes32), _message, _gas_limit, _value, _data_size
    )
    fees: MessagingFee = staticcall self.LZ_ENDPOINT.quote(params, self)
    return fees.nativeFee


@payable
@internal
def _send_message(
    _dstEid: uint32,
    _receiver: bytes32,
    _message: Bytes[LZ_MESSAGE_SIZE_CAP],
    _gas_limit: uint256 = 0,
    _lz_receive_value: uint256 = 0,
    _data_size: uint32 = 0,
    _request_msg_value: uint256 = 0,
    _refund_address: address = msg.sender,
    _perform_fee_check: bool = False,
):
    """@notice Send message using prepared parameters
    @dev This function is used to send both regular messages and read requests
    @param _dstEid Destination chain ID
    @param _receiver Target address
    @param _message Message payload or encoded read request
    @param _gas_limit Gas limit for execution
    @param _lz_receive_value Value to send in lzReceive
    @param _data_size For read requests, expected response size
    @param _request_msg_value Value to send in request message (msg.value or less)
    @param _refund_address Address to refund any excess msg.value
    @param _perform_fee_check Whether to perform fee check
    """

    params: MessagingParams = self._prepare_messaging_params(
        _dstEid, _receiver, _message, _gas_limit, _lz_receive_value, _data_size
    )

    # optional logic to call send as part of larger transaction
    message_value: uint256 = 0
    if _request_msg_value == 0:
        message_value = msg.value
    else:
        message_value = _request_msg_value

    if _perform_fee_check:
        fees: MessagingFee = staticcall self.LZ_ENDPOINT.quote(params, self)
        assert message_value >= fees.nativeFee, "Not enough fees"

    extcall self.LZ_ENDPOINT.send(params, _refund_address, value=message_value)


@payable
@internal
def _lz_receive(
    _origin: Origin,
    _guid: bytes32,
    _message: Bytes[LZ_MESSAGE_SIZE_CAP],
    _executor: address,
    _extraData: Bytes[64],
) -> bool:
    """
    @notice Base security checks for received messages
    @dev Must be called by importing contract's lzReceive
    """

    assert msg.sender == self.LZ_ENDPOINT.address, "Not LZ endpoint"
    assert self.LZ_PEERS[_origin.srcEid] != empty(address), "LZ Peer not set"
    assert (
        convert(_origin.sender, address) == self.LZ_PEERS[_origin.srcEid]
    ), "Invalid LZ message source!"
    return True


################################################################
#                     EXTERNAL FUNCTIONS                       #
################################################################

@view
@external
def get_configured_eids() -> DynArray[uint32, MAX_PEERS]:
    """
    @notice Get list of all configured peer EIDs
    @return List of EIDs that have non-zero peer addresses
    """
    return self.configured_eids


@view
@external
def nextNonce(_srcEid: uint32, _sender: bytes32) -> uint64:
    """@notice Protocol endpoint for nonce tracking"""

    return 0


@view
@external
def allowInitializePath(_origin: Origin) -> bool:
    """@notice Protocol endpoint for path initialization"""

    return True

File 3 of 3 : ownable.vy
# pragma version ~=0.4.0
"""
@title Owner-Based Access Control Functions
@custom:contract-name ownable
@license GNU Affero General Public License v3.0 only
@author pcaversaccio
@notice These functions can be used to implement a basic access
        control mechanism, where there is an account (an owner)
        that can be granted exclusive access to specific functions.
        By default, the owner account will be the one that deploys
        the contract. This can later be changed with `transfer_ownership`.
        An exemplary integration can be found in the ERC-20 implementation here:
        https://github.com/pcaversaccio/snekmate/blob/main/src/snekmate/tokens/erc20.vy.
        The implementation is inspired by OpenZeppelin's implementation here:
        https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol.
"""


# @dev Returns the address of the current owner.
# @notice If you declare a variable as `public`,
# Vyper automatically generates an `external`
# getter function for the variable.
owner: public(address)


# @dev Emitted when the ownership is transferred
# from `previous_owner` to `new_owner`.
event OwnershipTransferred:
    previous_owner: indexed(address)
    new_owner: indexed(address)


@deploy
@payable
def __init__():
    """
    @dev To omit the opcodes for checking the `msg.value`
         in the creation-time EVM bytecode, the constructor
         is declared as `payable`.
    @notice The `owner` role will be assigned to
            the `msg.sender`.
    """
    self._transfer_ownership(msg.sender)


@external
def transfer_ownership(new_owner: address):
    """
    @dev Transfers the ownership of the contract
         to a new account `new_owner`.
    @notice Note that this function can only be
            called by the current `owner`. Also,
            the `new_owner` cannot be the zero address.
    @param new_owner The 20-byte address of the new owner.
    """
    self._check_owner()
    assert new_owner != empty(address), "ownable: new owner is the zero address"
    self._transfer_ownership(new_owner)


@external
def renounce_ownership():
    """
    @dev Leaves the contract without an owner.
    @notice Renouncing ownership will leave the
            contract without an owner, thereby
            removing any functionality that is
            only available to the owner.
    """
    self._check_owner()
    self._transfer_ownership(empty(address))


@internal
def _check_owner():
    """
    @dev Throws if the sender is not the owner.
    """
    assert msg.sender == self.owner, "ownable: caller is not the owner"


@internal
def _transfer_ownership(new_owner: address):
    """
    @dev Transfers the ownership of the contract
         to a new account `new_owner`.
    @notice This is an `internal` function without
            access restriction.
    @param new_owner The 20-byte address of the new owner.
    """
    old_owner: address = self.owner
    self.owner = new_owner
    log OwnershipTransferred(old_owner, new_owner)

Settings
{
  "outputSelection": {
    "contracts/messengers/LZBlockRelay.vy": [
      "evm.bytecode",
      "evm.deployedBytecode",
      "abi"
    ]
  },
  "search_paths": [
    ".venv/lib/python3.12/site-packages",
    "."
  ]
}

Contract Security Audit

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"name":"source_eid","type":"uint32"},{"indexed":false,"name":"block_number","type":"uint256"},{"indexed":false,"name":"block_hash","type":"bytes32"},{"components":[{"name":"eid","type":"uint32"},{"name":"fee","type":"uint256"}],"indexed":false,"name":"targets","type":"tuple[]"}],"name":"BlockHashBroadcast","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previous_owner","type":"address"},{"indexed":true,"name":"new_owner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"LZ_ENDPOINT","outputs":[{"name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"arg0","type":"uint32"}],"name":"LZ_PEERS","outputs":[{"name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LZ_DELEGATE","outputs":[{"name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LZ_READ_CHANNEL","outputs":[{"name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"default_gas_limit","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"_srcEid","type":"uint32"},{"name":"_sender","type":"bytes32"}],"name":"nextNonce","outputs":[{"name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"name":"srcEid","type":"uint32"},{"name":"sender","type":"bytes32"},{"name":"nonce","type":"uint64"}],"name":"_origin","type":"tuple"}],"name":"allowInitializePath","outputs":[{"name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"get_configured_eids","outputs":[{"name":"","type":"uint32[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"new_owner","type":"address"}],"name":"transfer_ownership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounce_ownership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_endpoint","type":"address"},{"name":"_gas_limit","type":"uint256"},{"name":"_read_channel","type":"uint32"},{"name":"_peer_eids","type":"uint32[]"},{"name":"_peers","type":"address[]"},{"name":"_oapps","type":"address[]"},{"name":"_channels","type":"uint32[]"},{"name":"_libs","type":"address[]"},{"name":"_lib_types","type":"uint16[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_srcEid","type":"uint32"},{"name":"_peer","type":"address"}],"name":"set_peer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_gas_limit","type":"uint256"}],"name":"set_default_gas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_new_channel","type":"uint32"}],"name":"set_lz_read_channel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_oapp","type":"address"},{"name":"_channel","type":"uint32"},{"name":"_lib","type":"address"}],"name":"set_lz_send_lib","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_oapp","type":"address"},{"name":"_channel","type":"uint32"},{"name":"_lib","type":"address"}],"name":"set_lz_receive_lib","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_delegate","type":"address"}],"name":"set_lz_delegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_eid","type":"uint32"},{"name":"_oapp","type":"address"},{"name":"_lib","type":"address"},{"name":"_config_type","type":"uint32"},{"name":"_confirmations","type":"uint64"},{"name":"_required_dvns","type":"address[]"},{"name":"_optional_dvns","type":"address[]"},{"name":"_optional_dvn_threshold","type":"uint8"}],"name":"set_lz_uln_config","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_eid","type":"uint32"},{"name":"_oapp","type":"address"},{"name":"_lib","type":"address"},{"name":"_config_type","type":"uint32"},{"name":"_confirmations","type":"uint64"},{"name":"_required_dvns","type":"address[]"},{"name":"_optional_dvns","type":"address[]"},{"name":"_optional_dvn_threshold","type":"uint8"},{"name":"_executor","type":"address"}],"name":"set_lz_uln_config","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_is_enabled","type":"bool"},{"name":"_mainnet_eid","type":"uint32"},{"name":"_mainnet_view","type":"address"}],"name":"set_read_config","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_oracle","type":"address"}],"name":"set_block_oracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_refund_address","type":"address"}],"name":"set_default_lz_refund_address","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_amount","type":"uint256"}],"name":"withdraw_eth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"quote_read_fee","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"_block_number","type":"uint256"}],"name":"quote_read_fee","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"_block_number","type":"uint256"},{"name":"_gas_limit","type":"uint256"}],"name":"quote_read_fee","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"_block_number","type":"uint256"},{"name":"_gas_limit","type":"uint256"},{"name":"_value","type":"uint256"}],"name":"quote_read_fee","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"_block_number","type":"uint256"},{"name":"_gas_limit","type":"uint256"},{"name":"_value","type":"uint256"},{"name":"_data_size","type":"uint32"}],"name":"quote_read_fee","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"_target_eids","type":"uint32[]"}],"name":"quote_broadcast_fees","outputs":[{"name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"_target_eids","type":"uint32[]"},{"name":"_gas_limit","type":"uint256"}],"name":"quote_broadcast_fees","outputs":[{"name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"_target_eids","type":"uint32[]"},{"name":"_target_fees","type":"uint256[]"}],"name":"request_block_hash","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"name":"_target_eids","type":"uint32[]"},{"name":"_target_fees","type":"uint256[]"},{"name":"_block_number","type":"uint256"}],"name":"request_block_hash","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"name":"_target_eids","type":"uint32[]"},{"name":"_target_fees","type":"uint256[]"},{"name":"_block_number","type":"uint256"},{"name":"_gas_limit","type":"uint256"}],"name":"request_block_hash","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"name":"_target_eids","type":"uint32[]"},{"name":"_target_fees","type":"uint256[]"}],"name":"broadcast_latest_block","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"name":"_remote_eid","type":"uint32"},{"name":"_read_fee","type":"uint256"},{"name":"_broadcast_fee","type":"uint256"}],"name":"request_remote_read","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"name":"_remote_eid","type":"uint32"},{"name":"_read_fee","type":"uint256"},{"name":"_broadcast_fee","type":"uint256"},{"name":"_request_gas_limit","type":"uint256"}],"name":"request_remote_read","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"name":"srcEid","type":"uint32"},{"name":"sender","type":"bytes32"},{"name":"nonce","type":"uint64"}],"name":"_origin","type":"tuple"},{"name":"_guid","type":"bytes32"},{"name":"_message","type":"bytes"},{"name":"_executor","type":"address"},{"name":"_extraData","type":"bytes"}],"name":"lzReceive","outputs":[{"name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"is_initialized","outputs":[{"name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"is_read_enabled","outputs":[{"name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mainnet_eid","outputs":[{"name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mainnet_block_view","outputs":[{"name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"block_oracle","outputs":[{"name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"default_lz_refund_address","outputs":[{"name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"_owner","type":"address"}],"outputs":[],"stateMutability":"nonpayable","type":"constructor"}]

34610091576020613a3b5f395f518060a01c61009157608052610020610048565b610028610083565b60805160405261003661004a565b61399161009561000039613991610000f35b565b6088546060526040516088556040516060517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f6080a3565b3360405261008f61004a565b565b5f80fd5f3560e01c60026026820660011b61394501601e395f51565b63cd4d1c648118611d195734613941575f5460405260206040f35b6357305508811861006e57602436103417613941576004358060201c6139415760405260026040516020525f5260405f205460605260206060f35b63340cdfa08118611d19576063361115613941575f611020526117e3565b6331b7e2eb8118611d1957346139415760045460405260206040f35b637516188e81186100c457346139415760035460405260206040f35b6383bdec388118611d19573461394157606036610fa0376040611000526115d6565b63ce92f455811861010257346139415760055460405260206040f35b63a947ef3d811861012157602436103417613941575f61136052611231565b6393c708018118611d195760433611156139415760043560040160208135116139415780355f816020811161394157801561017e57905b8060051b6020850101358060201c613941578160051b6123800152600101818118610158575b505080612360525050602435600401602081351161394157803560208160051b01808361278037505050608a5461025157602080612c2052602b612ba0527f43616e206f6e6c792062726f6164636173742066726f6d20726561642d656e61612bc0527f626c656420636861696e73000000000000000000000000000000000000000000612be052612ba081612c200160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0612c005280600401612c1cfd5b608d546102d557602080612c00526015612ba0527f4f7261636c65206e6f7420636f6e666967757265640000000000000000000000612bc052612ba081612c000160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0612be05280600401612bfcfd5b6127805161236051181561036057602080612c0052600f612ba0527f4c656e677468206d69736d617463680000000000000000000000000000000000612bc052612ba081612c000160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0612be05280600401612bfcfd5b608d5463017a494d612bc0526020612bc06004612bdc845afa610385573d5f5f3e3d5ffd5b60203d1061394157612bc0905051612ba052608d5463b509f4ef612be052612ba051612c00526020612be06024612bfc845afa6103c4573d5f5f3e3d5ffd5b60203d1061394157612be0905051612bc052612bc05161045b57602080612c40526013612be0527f4e6f20636f6e6669726d656420626c6f636b7300000000000000000000000000612c0052612be081612c400160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0612c205280600401612c3cfd5b5f612be0525f61236051602081116139415780156104d857905b8061340052612be051601f8111613941578060061b612c000161340051612360518110156139415760051b6123800151815261340051612780518110156139415760051b6127a0015160208201525060018101612be05250600101818118610475575b50506040612ba06110005e612be05160208160061b0180612be06110405e505060015461186052336118805261050c613559565b005b637d25a05e811861053b57604436103417613941576004358060201c613941576040525f60605260206060f35b63fc702c1a8118611d1957604436103417613941576004358060201c613941576110e0526024358060a01c6139415761110052610576611d1b565b60406110e060405e610586611de6565b005b63ff7bd03d8118611d1957606436103417613941576004358060201c613941576040526024356060526044358060401c61394157608052600160a052602060a0f35b63116cbc17811861062f573461394157602080604052806040015f6007548083528060051b5f826080811161394157801561061b57905b80600801548160051b602088010152600101818118610601575b505082016020019150509050810190506040f35b63bb7a53b781186107065760833611156139415760406044612d80375b60043560040160208135116139415780355f816020811161394157801561069557905b8060051b6020850101358060201c613941578160051b612560015260010181811861066f575b505080612540525050602435600401602081351161394157803560208160051b018083612960375050506125405160208160051b01806125406110005e50506129605160208160051b01806129606114205e50506040612d806118405e3461188052336118a05261070461321e565b005b63dc1a2ee98118611d19573461394157608e5460405260206040f35b638da5cb5b811861073e57346139415760885460405260206040f35b63b0303f5f8118611d195761012436103417613941576004358060a01c61394157613240526044358060201c613941576132605260643560040160808135116139415780355f81608081116139415780156107bb57905b8060051b6020850101358060201c613941578160051b6132a00152600101818118610795575b50508061328052505060843560040160808135116139415780355f816080811161394157801561080d57905b8060051b6020850101358060a01c613941578160051b6142c001526001018181186107e7575b5050806142a052505060a4356004016101008135116139415780355f81610100811161394157801561086157905b8060051b6020850101358060a01c613941578160051b6152e0015260010181811861083b575b5050806152c052505060c4356004016101008135116139415780355f8161010081116139415780156108b557905b8060051b6020850101358060201c613941578160051b617300015260010181811861088f575b5050806172e052505060e4356004016101008135116139415780355f81610100811161394157801561090957905b8060051b6020850101358060a01c613941578160051b61932001526001018181186108e3575b505080619300525050610104356004016101008135116139415780355f81610100811161394157801561095e57905b8060051b6020850101358060101c613941578160051b61b3400152600101818118610938575b50508061b32052505061096f611d1b565b608954156109f45760208061d3a052601361d340527f416c726561647920696e697469616c697a65640000000000000000000000000061d3605261d3408161d3a00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a061d380528060040161d39cfd5b61324051610a795760208061d3a052601061d340527f496e76616c696420656e64706f696e740000000000000000000000000000000061d3605261d3408161d3a00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a061d380528060040161d39cfd5b600160895530608e55613240516110e0526024356111005261326051611120526132805160208160051b01806132806111405e50506142a05160208160051b01806142a06121605e5050610acb611ef4565b33604052610ad761216d565b619300516172e0511815610b625760208061d3a052601d61d340527f4c6962732d6368616e6e656c73206c656e677468206d69736d6174636800000061d3605261d3408161d3a00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a061d380528060040161d39cfd5b61b32051619300511815610bed5760208061d3a052601a61d340527f4c6962732d7479706573206c656e677468206d69736d6174636800000000000061d3605261d3408161d3a00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a061d380528060040161d39cfd5b5f6172e0516101008111613941578015610d7857905b8061d34052600161d3405161b320518110156139415760051b61b340015118610c7c5761d340516152c0518110156139415760051b6152e0015160405261d340516172e0518110156139415760051b617300015160605261d34051619300518110156139415760051b6193200151608052610d6d6121a4565b600261d3405161b320518110156139415760051b61b340015118610cf05761d340516152c0518110156139415760051b6152e0015160405261d340516172e0518110156139415760051b617300015160605261d34051619300518110156139415760051b6193200151608052610d6d6121d6565b60208061d3c052601061d360527f496e76616c6964206c696220747970650000000000000000000000000000000061d3805261d3608161d3c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a061d3a0528060040161d3bcfd5b600101818118610c03575b5050005b63f0350c048118610e6357602436103417613941576004358060a01c6139415761010052610da8611d1b565b61010051610e52576020806101a0526026610120527f6f776e61626c653a206e6577206f776e657220697320746865207a65726f2061610140527f646472657373000000000000000000000000000000000000000000000000000061016052610120816101a00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0610180528060040161019cfd5b61010051604052610e61611d9d565b005b631d93097e8118611d19573461394157608a5460405260206040f35b63b15e13ee8118611d19573461394157610e97611d1b565b5f604052610ea3611d9d565b005b6316fd36cc8118610ed25760243610341761394157610ec2611d1b565b600435604052610ed0611dd6565b005b6306080a848118611d195761010436103417613941575f6124c052611067565b63fc0fed5b8118611d1957602436103417613941576004358060201c6139415761010052610f1e611d1b565b61010051604052610f2d611dde565b005b63835a03538118610f8b57606436103417613941576004358060a01c61394157610120526024358060201c61394157610140526044358060a01c6139415761016052610f79611d1b565b606061012060405e610f896121a4565b005b6386e393858118611d19573461394157608c5460405260206040f35b635d3182bb8118611d1957606436103417613941576004358060a01c61394157610140526024358060201c61394157610160526044358060a01c6139415761018052610ff1611d1b565b606061014060405e6110016121d6565b005b6302b651758118611d1957602436103417613941576004358060a01c613941576101005261102f611d1b565b6101005160405261103e61216d565b005b6312865b3a81186111b3576101243610341761394157610104358060a01c613941576124c0525b6004358060201c61394157612140526024358060a01c61394157612160526044358060a01c61394157612180526064358060201c613941576121a0526084358060401c613941576121c05260a435600401600a8135116139415780355f81600a81116139415780156110fb57905b8060051b6020850101358060a01c613941578160051b61220001526001018181186110d5575b5050806121e052505060c435600401600a8135116139415780355f81600a811161394157801561114d57905b8060051b6020850101358060a01c613941578160051b6123600152600101818118611127575b50508061234052505060e4358060081c613941576124a05261116d611d1b565b60a0612140610ae05e6121e05160208160051b01806121e0610b805e50506123405160208160051b0180612340610ce05e505060406124a0610e405e6111b1612555565b005b63fea39928811861121457606436103417613941576004358060011c61394157610100526024358060201c61394157610120526044358060a01c61394157610140526111fd611d1b565b61010051608a5561012051608b5561014051608c55005b63b868c5908118611d195760443610341761394157602435611360525b60043560040160208135116139415780355f816020811161394157801561127a57905b8060051b6020850101358060201c613941578160051b610f600152600101818118611254575b505080610f405250506040366115c03760406115a0526115a0602081510180826113805e50505f6115a0525f610f40516020811161394157801561137057905b8060051b610f6001516119c05260026119c0516020525f5260405f20546119e0526119e051611307576115a051601f8111613941575f8160051b6115c00152600181016115a05250611365565b60406119c06105e05e60206113805101806113806106205e5061136051610840526040366108603761133a611a20612e01565b611a2051611a00526115a051601f811161394157611a00518160051b6115c00152600181016115a052505b6001018181186112ba575b50506020806119c052806119c0015f6115a0518083528060051b5f82602081116139415780156113ba57905b8060051b6115c001518160051b60208801015260010181811861139c575b505082016020019150509050810190506119c0f35b63bd0a22948118611d1957602436103417613941576004358060a01c61394157610100526113fb611d1b565b61010051608d55005b63ab3b78508118611d1957602436103417613941576004358060a01c6139415761010052611430611d1b565b61010051608e55005b6330a95e678118611d195760243610341761394157611456611d1b565b6004354710156114dd57602080610160526014610100527f496e73756666696369656e742062616c616e636500000000000000000000000061012052610100816101600160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0610140528060040161015cfd5b5f5f5f5f600435335ff11561394157005b639b299402811861151c5760243610341761394157600435610fa052604036610fc0376040611000526115d6565b639a01873c811861153857346139415760895460405260206040f35b63b5c3cbd08118611d19573461394157608b5460405260206040f35b63b696ca5a8118611d19576044361034176139415760406004610fa0375f610fe0526040611000526115d6565b63730465758118611d19576064361034176139415760606004610fa0376040611000526115d6565b63050415738118611d19576084361034176139415760606004610fa0376064358060201c61394157611000525b608a5461167f576020806110a0526027611020527f52656164206e6f7420656e61626c6564202d2063616c6c207365745f72656164611040527f5f636f6e6669670000000000000000000000000000000000000000000000000061106052611020816110a00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0611080528060040161109cfd5b608c54611728576020806110a052602b611020527f4d61696e6e65742076696577206e6f7420736574202d2063616c6c207365745f611040527f726561645f636f6e66696700000000000000000000000000000000000000000061106052611020816110a00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0611080528060040161109cfd5b610fa051610c405261173b611240612a49565b611240602081510180826110205e505060206003546105e0525f6106005260206110205101806110206106205e506060610fc06108405e61177d611240612e01565b611240f35b634fe753468118611d1957604336111561394157604036612d803761064c565b63d9e8961b8118611d1957606336111561394157604435612d80525f612da05261064c565b63aa74ed238118611d1957608336111561394157606435611020525b6004358060201c61394157611000525f6011611260527f62726f6164636173745f7265717565737400000000000000000000000000000061128052611260805160208201836112c00181518152505080830192505050604435816112c00152602081019050806112a0526112a09050602081510180826110405e5050611000516105e0526002611000516020525f5260405f20546106005260206110405101806110406106205e5061102051610840526024356044358082018281106139415790509050610860525f61088052346108a052336108c05260016108e0526118c8612f2e565b005b6313137d658118611d195760e3361115613941576004358060201c6139415761254052602435612560526044358060401c6139415761258052608435600401803561020081116139415750602081350180826125a037505060a4358060a01c613941576127c05260c4356004018035604081116139415750602081350180826127e0375050606061254060405e60643560a05260206125a05101806125a060c05e506127c0516102e05260206127e05101806127e06103005e5061198f6128406136a7565b612840511561394157606061254060405e6119ab612840613861565b61284051611b82576011612900527f62726f6164636173745f726571756573740000000000000000000000000000006129205261290080516020820120905060106125a0511115613941576125c0516128e05260116128c0526128c080516020820120905018611b345760306125a0511115613941576125d15161298052602061296052612960602081511861394157602081018151602083010160208201116139415780516129a052506129a09050516129405234612940511115611ae8576020806129c052601a612960527f496e73756666696369656e74206d6573736167652076616c756500000000000061298052612960816129c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06129a052806004016129bcfd5b612540516110205260016110005261294051611440526001611420525f611840526005548060011b818160011c18613941579050611860523461188052608e546118a052611cee61321e565b6040366128403760406125a05118613941576125a0516125c001612600116139415760406125c06128805e61288080516128405260208101516128605250604061284060405e611cee61386f565b608a54611c06576020806128c0526010612860527f52656164206e6f7420656e61626c65640000000000000000000000000000000061288052612860816128c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06128a052806004016128bcfd5b6040366128603760406125a05118613941576125a0516125c001612600116139415760406125c06128a05e6128a08051612860526020810151612880525061288051611c5c5760016128a05260206128a0611cfa565b604061286060405e611c6c61386f565b608f5460208160061b015f81601f0160051c60418111613941578015611ca757905b80608f01548160051b6128a00152600101818118611c8e575b505050506128a05115611cee5760406128606110005e6128a05160208160061b01806128a06110405e50506125405161186052608e5461188052611ce9613559565b5f608f555b60016128405260206128405bf35b636959a37f8118611d19573461394157608d5460405260206040f35b5b005b608854331815611d9b5760208060a05260206040527f6f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260605260408160a00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a060805280600401609cfd5b565b6088546060526040516088556040516060517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f6080a3565b604051600555565b604051600355565b60026040516020525f5260405f205460805260605160026040516020525f5260405f2055608051611e1b576060511515611e1d565b5f5b611ed65760805115611e325760605115611e34565b5f5b15611ef2575f60a0525f60075460808111613941578015611e9157905b80600801546110c0526040516110c05114611e865760a051607f8111613941576110c0518160051b60c001526001810160a052505b600101818118611e51575b505060a05160208160051b015f81601f0160051c60818111613941578015611ecd57905b8060051b60a001518160070155600101818118611eb5575b50505050611ef2565b600754607f811161394157604051816008015560018101600755505b565b6110e051611f79576020806131e0526010613180527f496e76616c696420656e64706f696e74000000000000000000000000000000006131a052613180816131e00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06131c052806004016131dcfd5b61216051611140511815612004576020806131e0526013613180527f496e76616c6964207065657220617272617973000000000000000000000000006131a052613180816131e00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06131c052806004016131dcfd5b60065415612089576020806131e0526013613180527f416c726561647920696e697469616c697a6564000000000000000000000000006131a052613180816131e00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06131c052806004016131dcfd5b6110e0515f555f5463416ecebf613180526020613180600461319c845afa6120b3573d5f5f3e3d5ffd5b3d602081183d602010021880613180016131a01161394157613180518060201c613941576131c052506131c0905051600155611100516040526120f4611dd6565b61112051604052612103611dde565b5f611140516080811161394157801561216457905b806131805261318051611140518110156139415760051b611160015160405261318051612160518110156139415760051b6121800151606052612159611de6565b600101818118612118575b50506001600655565b5f5463ca5eb5e1606052604051608052803b15613941575f60606024607c5f855af161219b573d5f5f3e3d5ffd5b50604051600455565b5f54639535ff3060a0526060604060c05e803b15613941575f60a0606460bc5f855af16121d3573d5f5f3e3d5ffd5b50565b5f54636a14d71560a0526060604060c05e5f61012052803b15613941575f60a0608460bc5f855af161220a573d5f5f3e3d5ffd5b50565b60a0518060081c613941576103a052610200518060081c613941576103c0526103c0516103605113156122b7576020806104405260156103e0527f496e76616c69642044564e207468726573686f6c640000000000000000000000610400526103e0816104400160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0610420528060040161043cfd5b63fffff9bf6040511215612415576080516103e0526103a051610400526103c05161042052610360516104405260a05160208160051b018060a06104605e50506102005160208160051b01806102006105c05e50506040518152606051602082015260208061074052806107400160c06103e05182526104005160208301526104205160408301526104405160608301528060808301528082015f610460518083528060051b5f82600a811161394157801561238d57905b8060051b61048001518160051b60208801015260010181811861236f575b505082016020019150509050810190508060a08301528082015f6105c0518083528060051b5f82600a81116139415780156123e257905b8060051b6105e001518160051b6020880101526001018181186123c4575b50508201602001915050905081019050905081019050610720526107206020815101604083018183825e50505050612553565b60606103806103e05e610360516104405260a05160208160051b018060a06104605e50506102005160208160051b01806102006105c05e50506040518152606051602082015260208061074052806107400160c06103e05182526104005160208301526104205160408301526104405160608301528060808301528082015f610460518083528060051b5f82600a81116139415780156124cf57905b8060051b61048001518160051b6020880101526001018181186124b1575b505082016020019150509050810190508060a08301528082015f6105c0518083528060051b5f82600a811161394157801561252457905b8060051b6105e001518160051b602088010152600101818118612506575b50508201602001915050905081019050905081019050610720526107206020815101604083018183825e505050505b565b610ae051604052610b4051606052610b6051608052610b805160208160051b0180610b8060a05e5050610ce05160208160051b0180610ce06102005e50506040610e406103605e6125a76112e061220d565b6112e061046081610e805e505f54636dbd9f906112e05260606040610b006113005e806113405280611300015f610460610e806118405e6001611820525f611820518084528060051b5f826001811161394157801561267d57905b828160051b602089010152610460810261184001836020890101606082518252602083015160208301528060408301526040830181830160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190509050905083019250600101818118612602575b505082016020019150509050905081015050803b15613941575f6112e06105246112fc5f855af16126b0573d5f5f3e3d5ffd5b50610e6051156126ca5763fffff9bd610ae05113156126cc565b5f5b1561280c576104006112e052610e605161130052610ae0516113205260016113405260406112e06117a05e604061178052611780602081510180826113605e50505f54636dbd9f906117805260606040610b006117a05e806117e052806117a0015f610460611320611ce05e6001611cc0525f611cc0518084528060051b5f82600181116139415780156127d757905b828160051b6020890101526104608102611ce001836020890101606082518252602083015160208301528060408301526040830181830160208251018083835e508051806020830101601f825f03163682375050601f19601f825160200101169050905081019050905090508301925060010181811861275c575b505082016020019150509050905081015050803b15613941575f61178061052461179c5f855af161280a573d5f5f3e3d5ffd5b505b565b61010051602381018181106139415790508060101c61394157610220525f600160f01b816102a001526002810190505f60f01b816102a00152600281019050600160f01b816102a0015260028101905080610280526102809050602081510180826102405e50505f61024051816102e00161026051815250808201915050600160f81b816102e001526001810190506040518060f01b9050816102e00152600281019050600160f01b816102e00152600281019050610220518060f01b9050816102e00152600281019050806102c0526102c09050602081510180826102805e50505f61028051816102e0016102a0518152508082019150506060518060e01b9050816102e001526004810190506080518060f81b9050816102e0015260018101905060a0518060c01b9050816102e0015260088101905060c0518060f01b9050816102e0015260028101905060e0518060601b9050816102e0015260148101905061010051816102e00181610120825e50808201915050806102c0526102c0905060208151018082845e505050565b6105c05161060052610600516129d6576105a0516129c857428060401c61394157610600526129d6565b438060401c61394157610600525b60016106205261044051610640526105a0516106605261060051610680526105e0516106a052610460516106c05260206104805101806104806106e05e506101e061062060405e612a28610a2061280e565b610a20602081510180826108005e50506020610800510180610800835e5050565b637b754d2d610d84526004610c4051610da4526001610dc452604001610d8052610d8060208151018082610c605e5050608b5461044052608c54610460526020610c60510180610c606104805e505f6105a052428060401c613941576105c05260016105e052612aba610d8061299e565b610d8060208151018082845e505050565b5f6040518060801c613941578060801b9050816101200152601081019050806101005261010090506020815101808260a05e50505f6060518060801c613941578060801b9050816101600152601081019050806101405261014090506020815101808260e05e50505f6080518060e01b9050816101a0015260048101905080610180526101809050602081510180826101205e50505f6101605260016080511215612b76575f612b7c565b60605115155b612c335760016080511215612bec5760605115612bd9575f60a051816101e00160c05181525080820191505060e051816101e00161010051815250808201915050806101c0526101c09050602081510180826101605e5050612c8b565b602060a051018060a06101605e50612c8b565b5f60a051816101e00160c05181525080820191505061012051816101e00161014051815250808201915050806101c0526101c09050602081510180826101605e5050612c8b565b5f60a051816101e00160c05181525080820191505061012051816101e0016101405181525080820191505060e051816101e00161010051815250808201915050806101c0526101c09050602081510180826101605e50505b5f7e03010000000000000000000000000000000000000000000000000000000000816101e0015260038101905061016051600181018181106139415790508060101c613941578060f01b9050816101e0015260028101905060016080511215612d14577f0100000000000000000000000000000000000000000000000000000000000000612d36565b7f05000000000000000000000000000000000000000000000000000000000000005b816101e0015260018101905061016051816101e00181610180825e50808201915050806101c0526101c0905060208151018082845e505050565b6104a05115612d81576104a0612d8c565b600554610520526105205b5161050052610500516040526104c0516060526104e051608052612db1610580612acb565b610580602081510180826105205e5050610240518152610260516020820152602061028051016040820181610280825e505060206105205101610260820181610520825e50505f6102c082015250565b6105e05161024052610600516102605260206106205101806106206102805e5060606108406104a05e612e35610b80612d70565b610b806102e0816108a05e505f5463ddc28c58610bc052604080610be05280610be00160a06108a05182526108c051602083015280604083015280820160206108e05101806108e0835e508051806020830101601f825f03163682375050601f19601f825160200101169050810190508060608301528082016020610b00510180610b00835e508051806020830101601f825f03163682375050601f19601f82516020010116905081019050610b6051608083015290508101905030610c0052506040610bc0610364610bdc845afa612f10573d5f5f3e3d5ffd5b60403d1061394157610bc09050604081610b805e50610b8051815250565b60406105e06102405e60206106205101806106206102805e50610840516104a05260406108606104c05e612f63610be0612d70565b610be06102e0816109005e505f610be0526108a051612f865734610be052612f8f565b6108a051610be0525b6108e05115613107575f5463ddc28c58610c4052604080610c605280610c600160a06109005182526109205160208301528060408301528082016020610940510180610940835e508051806020830101601f825f03163682375050601f19601f825160200101169050810190508060608301528082016020610b60510180610b60835e508051806020830101601f825f03163682375050601f19601f82516020010116905081019050610bc051608083015290508101905030610c8052506040610c40610364610c5c845afa613067573d5f5f3e3d5ffd5b60403d1061394157610c409050604081610c005e50610c0051610be051101561310757602080610ca052600f610c40527f4e6f7420656e6f75676820666565730000000000000000000000000000000000610c6052610c4081610ca00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0610c805280600401610c9cfd5b5f54632637a450610c0052604080610c205280610c200160a06109005182526109205160208301528060408301528082016020610940510180610940835e508051806020830101601f825f03163682375050601f19601f825160200101169050810190508060608301528082016020610b60510180610b60835e508051806020830101601f825f03163682375050601f19601f82516020010116905081019050610bc05160808301529050810190506108c051610c4052506080610c00610364610c1c610be051855af16131dd573d5f5f3e3d5ffd5b3d608081183d608010021880610c0001610c801161394157610c0051610f8052610c20518060401c61394157610fa0526040610c40610fc05e50610f805050565b608a546132c7576020806119405260276118c0527f52656164206e6f7420656e61626c6564202d2063616c6c207365745f726561646118e0527f5f636f6e66696700000000000000000000000000000000000000000000000000611900526118c0816119400160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0611920528060040161193cfd5b608c546133705760208061194052602b6118c0527f4d61696e6e65742076696577206e6f7420736574202d2063616c6c207365745f6118e0527f726561645f636f6e666967000000000000000000000000000000000000000000611900526118c0816119400160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0611920528060040161193cfd5b611420516110005118156133fb5760208061192052600f6118c0527f4c656e677468206d69736d6174636800000000000000000000000000000000006118e0526118c0816119200160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0611900528060040161191cfd5b5f6118c0525f6120e0525f61100051602081116139415780156134aa57905b80612100526118c051601f8111613941578060061b6118e00161210051611000518110156139415760051b6110200151815261210051611420518110156139415760051b6114400151602082015250600181016118c052506120e05161210051611420518110156139415760051b611440015180820182811061394157905090506120e05260010181811861341a575b50506118c05160208160061b015f81601f0160051c604181116139415780156134e857905b8060051b6118c0015181608f01556001018181186134cf575b5050505061184051610c40526134ff612320612a49565b612320602081510180826121005e50506003546105e052306106005260206121005101806121006106205e5061186051610840526120e0516108605260406108805260406118806108a05e5f6108e052613557612f2e565b565b6040611000611ae05e6040611ac052611ac0602081510180826118a05e50505f611040516020811161394157801561360957905b8060061b61106001604081611ac05e506002611ac0516020525f5260405f2054611b0052611b0051156135fe57611ac0516105e052611b00516106005260206118a05101806118a06106205e5060603661084037611ae0516108a052611880516108c0525f6108e0526135fe612f2e565b60010181811861358d575b50507f1d1af3b995be68c98b810354734eb3bff44cf05cf8191b5e2c1a3e2db421c8b6608061186051611ac05261100051611ae05261102051611b005280611b205280611ac0015f611040518083528060061b5f826020811161394157801561369157905b8060061b611060018160061b6020880101604082825e505060010181811861366e575b50508201602001915050905081019050611ac0a1565b5f5433181561372d576020806103c052600f610360527f4e6f74204c5a20656e64706f696e74000000000000000000000000000000000061038052610360816103c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06103a052806004016103bcfd5b60026040516020525f5260405f20546137bd576020806103c052600f610360527f4c5a2050656572206e6f7420736574000000000000000000000000000000000061038052610360816103c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06103a052806004016103bcfd5b60026040516020525f5260405f20546060518060a01c61394157181561385a576020806103c052601a610360527f496e76616c6964204c5a206d65737361676520736f757263652100000000000061038052610360816103c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06103a052806004016103bcfd5b6001815250565b63fffff9be60405113815250565b608d546138ec5760208060e05260156080527f4f7261636c65206e6f7420636f6e66696775726564000000000000000000000060a05260808160e00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a060c0528060040160dcfd5b608d5463939074b16080526040604060a05e602060806044609c5f855af1613916573d5f5f3e3d5ffd5b3d602081183d60201002188060800160a011613941576080518060011c6139415760e0525060e05050565b5f80fd0ea5058814ee10031d1817c7001800e61d1817a2050e0fa71d181d1800a81d181d1815a915541cfc1040143913cf1d180d7c0722003315810e7f18ca1404008c1d180f2f1d180ef2178205ca8419399181184c00a1657679706572830004000015000000000000000000000000b101b2b0aa02b7167d238b98dc1b0b0404a760e8

Deployed Bytecode

0x5f3560e01c60026026820660011b61394501601e395f51565b63cd4d1c648118611d195734613941575f5460405260206040f35b6357305508811861006e57602436103417613941576004358060201c6139415760405260026040516020525f5260405f205460605260206060f35b63340cdfa08118611d19576063361115613941575f611020526117e3565b6331b7e2eb8118611d1957346139415760045460405260206040f35b637516188e81186100c457346139415760035460405260206040f35b6383bdec388118611d19573461394157606036610fa0376040611000526115d6565b63ce92f455811861010257346139415760055460405260206040f35b63a947ef3d811861012157602436103417613941575f61136052611231565b6393c708018118611d195760433611156139415760043560040160208135116139415780355f816020811161394157801561017e57905b8060051b6020850101358060201c613941578160051b6123800152600101818118610158575b505080612360525050602435600401602081351161394157803560208160051b01808361278037505050608a5461025157602080612c2052602b612ba0527f43616e206f6e6c792062726f6164636173742066726f6d20726561642d656e61612bc0527f626c656420636861696e73000000000000000000000000000000000000000000612be052612ba081612c200160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0612c005280600401612c1cfd5b608d546102d557602080612c00526015612ba0527f4f7261636c65206e6f7420636f6e666967757265640000000000000000000000612bc052612ba081612c000160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0612be05280600401612bfcfd5b6127805161236051181561036057602080612c0052600f612ba0527f4c656e677468206d69736d617463680000000000000000000000000000000000612bc052612ba081612c000160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0612be05280600401612bfcfd5b608d5463017a494d612bc0526020612bc06004612bdc845afa610385573d5f5f3e3d5ffd5b60203d1061394157612bc0905051612ba052608d5463b509f4ef612be052612ba051612c00526020612be06024612bfc845afa6103c4573d5f5f3e3d5ffd5b60203d1061394157612be0905051612bc052612bc05161045b57602080612c40526013612be0527f4e6f20636f6e6669726d656420626c6f636b7300000000000000000000000000612c0052612be081612c400160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0612c205280600401612c3cfd5b5f612be0525f61236051602081116139415780156104d857905b8061340052612be051601f8111613941578060061b612c000161340051612360518110156139415760051b6123800151815261340051612780518110156139415760051b6127a0015160208201525060018101612be05250600101818118610475575b50506040612ba06110005e612be05160208160061b0180612be06110405e505060015461186052336118805261050c613559565b005b637d25a05e811861053b57604436103417613941576004358060201c613941576040525f60605260206060f35b63fc702c1a8118611d1957604436103417613941576004358060201c613941576110e0526024358060a01c6139415761110052610576611d1b565b60406110e060405e610586611de6565b005b63ff7bd03d8118611d1957606436103417613941576004358060201c613941576040526024356060526044358060401c61394157608052600160a052602060a0f35b63116cbc17811861062f573461394157602080604052806040015f6007548083528060051b5f826080811161394157801561061b57905b80600801548160051b602088010152600101818118610601575b505082016020019150509050810190506040f35b63bb7a53b781186107065760833611156139415760406044612d80375b60043560040160208135116139415780355f816020811161394157801561069557905b8060051b6020850101358060201c613941578160051b612560015260010181811861066f575b505080612540525050602435600401602081351161394157803560208160051b018083612960375050506125405160208160051b01806125406110005e50506129605160208160051b01806129606114205e50506040612d806118405e3461188052336118a05261070461321e565b005b63dc1a2ee98118611d19573461394157608e5460405260206040f35b638da5cb5b811861073e57346139415760885460405260206040f35b63b0303f5f8118611d195761012436103417613941576004358060a01c61394157613240526044358060201c613941576132605260643560040160808135116139415780355f81608081116139415780156107bb57905b8060051b6020850101358060201c613941578160051b6132a00152600101818118610795575b50508061328052505060843560040160808135116139415780355f816080811161394157801561080d57905b8060051b6020850101358060a01c613941578160051b6142c001526001018181186107e7575b5050806142a052505060a4356004016101008135116139415780355f81610100811161394157801561086157905b8060051b6020850101358060a01c613941578160051b6152e0015260010181811861083b575b5050806152c052505060c4356004016101008135116139415780355f8161010081116139415780156108b557905b8060051b6020850101358060201c613941578160051b617300015260010181811861088f575b5050806172e052505060e4356004016101008135116139415780355f81610100811161394157801561090957905b8060051b6020850101358060a01c613941578160051b61932001526001018181186108e3575b505080619300525050610104356004016101008135116139415780355f81610100811161394157801561095e57905b8060051b6020850101358060101c613941578160051b61b3400152600101818118610938575b50508061b32052505061096f611d1b565b608954156109f45760208061d3a052601361d340527f416c726561647920696e697469616c697a65640000000000000000000000000061d3605261d3408161d3a00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a061d380528060040161d39cfd5b61324051610a795760208061d3a052601061d340527f496e76616c696420656e64706f696e740000000000000000000000000000000061d3605261d3408161d3a00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a061d380528060040161d39cfd5b600160895530608e55613240516110e0526024356111005261326051611120526132805160208160051b01806132806111405e50506142a05160208160051b01806142a06121605e5050610acb611ef4565b33604052610ad761216d565b619300516172e0511815610b625760208061d3a052601d61d340527f4c6962732d6368616e6e656c73206c656e677468206d69736d6174636800000061d3605261d3408161d3a00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a061d380528060040161d39cfd5b61b32051619300511815610bed5760208061d3a052601a61d340527f4c6962732d7479706573206c656e677468206d69736d6174636800000000000061d3605261d3408161d3a00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a061d380528060040161d39cfd5b5f6172e0516101008111613941578015610d7857905b8061d34052600161d3405161b320518110156139415760051b61b340015118610c7c5761d340516152c0518110156139415760051b6152e0015160405261d340516172e0518110156139415760051b617300015160605261d34051619300518110156139415760051b6193200151608052610d6d6121a4565b600261d3405161b320518110156139415760051b61b340015118610cf05761d340516152c0518110156139415760051b6152e0015160405261d340516172e0518110156139415760051b617300015160605261d34051619300518110156139415760051b6193200151608052610d6d6121d6565b60208061d3c052601061d360527f496e76616c6964206c696220747970650000000000000000000000000000000061d3805261d3608161d3c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a061d3a0528060040161d3bcfd5b600101818118610c03575b5050005b63f0350c048118610e6357602436103417613941576004358060a01c6139415761010052610da8611d1b565b61010051610e52576020806101a0526026610120527f6f776e61626c653a206e6577206f776e657220697320746865207a65726f2061610140527f646472657373000000000000000000000000000000000000000000000000000061016052610120816101a00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0610180528060040161019cfd5b61010051604052610e61611d9d565b005b631d93097e8118611d19573461394157608a5460405260206040f35b63b15e13ee8118611d19573461394157610e97611d1b565b5f604052610ea3611d9d565b005b6316fd36cc8118610ed25760243610341761394157610ec2611d1b565b600435604052610ed0611dd6565b005b6306080a848118611d195761010436103417613941575f6124c052611067565b63fc0fed5b8118611d1957602436103417613941576004358060201c6139415761010052610f1e611d1b565b61010051604052610f2d611dde565b005b63835a03538118610f8b57606436103417613941576004358060a01c61394157610120526024358060201c61394157610140526044358060a01c6139415761016052610f79611d1b565b606061012060405e610f896121a4565b005b6386e393858118611d19573461394157608c5460405260206040f35b635d3182bb8118611d1957606436103417613941576004358060a01c61394157610140526024358060201c61394157610160526044358060a01c6139415761018052610ff1611d1b565b606061014060405e6110016121d6565b005b6302b651758118611d1957602436103417613941576004358060a01c613941576101005261102f611d1b565b6101005160405261103e61216d565b005b6312865b3a81186111b3576101243610341761394157610104358060a01c613941576124c0525b6004358060201c61394157612140526024358060a01c61394157612160526044358060a01c61394157612180526064358060201c613941576121a0526084358060401c613941576121c05260a435600401600a8135116139415780355f81600a81116139415780156110fb57905b8060051b6020850101358060a01c613941578160051b61220001526001018181186110d5575b5050806121e052505060c435600401600a8135116139415780355f81600a811161394157801561114d57905b8060051b6020850101358060a01c613941578160051b6123600152600101818118611127575b50508061234052505060e4358060081c613941576124a05261116d611d1b565b60a0612140610ae05e6121e05160208160051b01806121e0610b805e50506123405160208160051b0180612340610ce05e505060406124a0610e405e6111b1612555565b005b63fea39928811861121457606436103417613941576004358060011c61394157610100526024358060201c61394157610120526044358060a01c61394157610140526111fd611d1b565b61010051608a5561012051608b5561014051608c55005b63b868c5908118611d195760443610341761394157602435611360525b60043560040160208135116139415780355f816020811161394157801561127a57905b8060051b6020850101358060201c613941578160051b610f600152600101818118611254575b505080610f405250506040366115c03760406115a0526115a0602081510180826113805e50505f6115a0525f610f40516020811161394157801561137057905b8060051b610f6001516119c05260026119c0516020525f5260405f20546119e0526119e051611307576115a051601f8111613941575f8160051b6115c00152600181016115a05250611365565b60406119c06105e05e60206113805101806113806106205e5061136051610840526040366108603761133a611a20612e01565b611a2051611a00526115a051601f811161394157611a00518160051b6115c00152600181016115a052505b6001018181186112ba575b50506020806119c052806119c0015f6115a0518083528060051b5f82602081116139415780156113ba57905b8060051b6115c001518160051b60208801015260010181811861139c575b505082016020019150509050810190506119c0f35b63bd0a22948118611d1957602436103417613941576004358060a01c61394157610100526113fb611d1b565b61010051608d55005b63ab3b78508118611d1957602436103417613941576004358060a01c6139415761010052611430611d1b565b61010051608e55005b6330a95e678118611d195760243610341761394157611456611d1b565b6004354710156114dd57602080610160526014610100527f496e73756666696369656e742062616c616e636500000000000000000000000061012052610100816101600160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0610140528060040161015cfd5b5f5f5f5f600435335ff11561394157005b639b299402811861151c5760243610341761394157600435610fa052604036610fc0376040611000526115d6565b639a01873c811861153857346139415760895460405260206040f35b63b5c3cbd08118611d19573461394157608b5460405260206040f35b63b696ca5a8118611d19576044361034176139415760406004610fa0375f610fe0526040611000526115d6565b63730465758118611d19576064361034176139415760606004610fa0376040611000526115d6565b63050415738118611d19576084361034176139415760606004610fa0376064358060201c61394157611000525b608a5461167f576020806110a0526027611020527f52656164206e6f7420656e61626c6564202d2063616c6c207365745f72656164611040527f5f636f6e6669670000000000000000000000000000000000000000000000000061106052611020816110a00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0611080528060040161109cfd5b608c54611728576020806110a052602b611020527f4d61696e6e65742076696577206e6f7420736574202d2063616c6c207365745f611040527f726561645f636f6e66696700000000000000000000000000000000000000000061106052611020816110a00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0611080528060040161109cfd5b610fa051610c405261173b611240612a49565b611240602081510180826110205e505060206003546105e0525f6106005260206110205101806110206106205e506060610fc06108405e61177d611240612e01565b611240f35b634fe753468118611d1957604336111561394157604036612d803761064c565b63d9e8961b8118611d1957606336111561394157604435612d80525f612da05261064c565b63aa74ed238118611d1957608336111561394157606435611020525b6004358060201c61394157611000525f6011611260527f62726f6164636173745f7265717565737400000000000000000000000000000061128052611260805160208201836112c00181518152505080830192505050604435816112c00152602081019050806112a0526112a09050602081510180826110405e5050611000516105e0526002611000516020525f5260405f20546106005260206110405101806110406106205e5061102051610840526024356044358082018281106139415790509050610860525f61088052346108a052336108c05260016108e0526118c8612f2e565b005b6313137d658118611d195760e3361115613941576004358060201c6139415761254052602435612560526044358060401c6139415761258052608435600401803561020081116139415750602081350180826125a037505060a4358060a01c613941576127c05260c4356004018035604081116139415750602081350180826127e0375050606061254060405e60643560a05260206125a05101806125a060c05e506127c0516102e05260206127e05101806127e06103005e5061198f6128406136a7565b612840511561394157606061254060405e6119ab612840613861565b61284051611b82576011612900527f62726f6164636173745f726571756573740000000000000000000000000000006129205261290080516020820120905060106125a0511115613941576125c0516128e05260116128c0526128c080516020820120905018611b345760306125a0511115613941576125d15161298052602061296052612960602081511861394157602081018151602083010160208201116139415780516129a052506129a09050516129405234612940511115611ae8576020806129c052601a612960527f496e73756666696369656e74206d6573736167652076616c756500000000000061298052612960816129c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06129a052806004016129bcfd5b612540516110205260016110005261294051611440526001611420525f611840526005548060011b818160011c18613941579050611860523461188052608e546118a052611cee61321e565b6040366128403760406125a05118613941576125a0516125c001612600116139415760406125c06128805e61288080516128405260208101516128605250604061284060405e611cee61386f565b608a54611c06576020806128c0526010612860527f52656164206e6f7420656e61626c65640000000000000000000000000000000061288052612860816128c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06128a052806004016128bcfd5b6040366128603760406125a05118613941576125a0516125c001612600116139415760406125c06128a05e6128a08051612860526020810151612880525061288051611c5c5760016128a05260206128a0611cfa565b604061286060405e611c6c61386f565b608f5460208160061b015f81601f0160051c60418111613941578015611ca757905b80608f01548160051b6128a00152600101818118611c8e575b505050506128a05115611cee5760406128606110005e6128a05160208160061b01806128a06110405e50506125405161186052608e5461188052611ce9613559565b5f608f555b60016128405260206128405bf35b636959a37f8118611d19573461394157608d5460405260206040f35b5b005b608854331815611d9b5760208060a05260206040527f6f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260605260408160a00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a060805280600401609cfd5b565b6088546060526040516088556040516060517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f6080a3565b604051600555565b604051600355565b60026040516020525f5260405f205460805260605160026040516020525f5260405f2055608051611e1b576060511515611e1d565b5f5b611ed65760805115611e325760605115611e34565b5f5b15611ef2575f60a0525f60075460808111613941578015611e9157905b80600801546110c0526040516110c05114611e865760a051607f8111613941576110c0518160051b60c001526001810160a052505b600101818118611e51575b505060a05160208160051b015f81601f0160051c60818111613941578015611ecd57905b8060051b60a001518160070155600101818118611eb5575b50505050611ef2565b600754607f811161394157604051816008015560018101600755505b565b6110e051611f79576020806131e0526010613180527f496e76616c696420656e64706f696e74000000000000000000000000000000006131a052613180816131e00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06131c052806004016131dcfd5b61216051611140511815612004576020806131e0526013613180527f496e76616c6964207065657220617272617973000000000000000000000000006131a052613180816131e00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06131c052806004016131dcfd5b60065415612089576020806131e0526013613180527f416c726561647920696e697469616c697a6564000000000000000000000000006131a052613180816131e00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06131c052806004016131dcfd5b6110e0515f555f5463416ecebf613180526020613180600461319c845afa6120b3573d5f5f3e3d5ffd5b3d602081183d602010021880613180016131a01161394157613180518060201c613941576131c052506131c0905051600155611100516040526120f4611dd6565b61112051604052612103611dde565b5f611140516080811161394157801561216457905b806131805261318051611140518110156139415760051b611160015160405261318051612160518110156139415760051b6121800151606052612159611de6565b600101818118612118575b50506001600655565b5f5463ca5eb5e1606052604051608052803b15613941575f60606024607c5f855af161219b573d5f5f3e3d5ffd5b50604051600455565b5f54639535ff3060a0526060604060c05e803b15613941575f60a0606460bc5f855af16121d3573d5f5f3e3d5ffd5b50565b5f54636a14d71560a0526060604060c05e5f61012052803b15613941575f60a0608460bc5f855af161220a573d5f5f3e3d5ffd5b50565b60a0518060081c613941576103a052610200518060081c613941576103c0526103c0516103605113156122b7576020806104405260156103e0527f496e76616c69642044564e207468726573686f6c640000000000000000000000610400526103e0816104400160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0610420528060040161043cfd5b63fffff9bf6040511215612415576080516103e0526103a051610400526103c05161042052610360516104405260a05160208160051b018060a06104605e50506102005160208160051b01806102006105c05e50506040518152606051602082015260208061074052806107400160c06103e05182526104005160208301526104205160408301526104405160608301528060808301528082015f610460518083528060051b5f82600a811161394157801561238d57905b8060051b61048001518160051b60208801015260010181811861236f575b505082016020019150509050810190508060a08301528082015f6105c0518083528060051b5f82600a81116139415780156123e257905b8060051b6105e001518160051b6020880101526001018181186123c4575b50508201602001915050905081019050905081019050610720526107206020815101604083018183825e50505050612553565b60606103806103e05e610360516104405260a05160208160051b018060a06104605e50506102005160208160051b01806102006105c05e50506040518152606051602082015260208061074052806107400160c06103e05182526104005160208301526104205160408301526104405160608301528060808301528082015f610460518083528060051b5f82600a81116139415780156124cf57905b8060051b61048001518160051b6020880101526001018181186124b1575b505082016020019150509050810190508060a08301528082015f6105c0518083528060051b5f82600a811161394157801561252457905b8060051b6105e001518160051b602088010152600101818118612506575b50508201602001915050905081019050905081019050610720526107206020815101604083018183825e505050505b565b610ae051604052610b4051606052610b6051608052610b805160208160051b0180610b8060a05e5050610ce05160208160051b0180610ce06102005e50506040610e406103605e6125a76112e061220d565b6112e061046081610e805e505f54636dbd9f906112e05260606040610b006113005e806113405280611300015f610460610e806118405e6001611820525f611820518084528060051b5f826001811161394157801561267d57905b828160051b602089010152610460810261184001836020890101606082518252602083015160208301528060408301526040830181830160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190509050905083019250600101818118612602575b505082016020019150509050905081015050803b15613941575f6112e06105246112fc5f855af16126b0573d5f5f3e3d5ffd5b50610e6051156126ca5763fffff9bd610ae05113156126cc565b5f5b1561280c576104006112e052610e605161130052610ae0516113205260016113405260406112e06117a05e604061178052611780602081510180826113605e50505f54636dbd9f906117805260606040610b006117a05e806117e052806117a0015f610460611320611ce05e6001611cc0525f611cc0518084528060051b5f82600181116139415780156127d757905b828160051b6020890101526104608102611ce001836020890101606082518252602083015160208301528060408301526040830181830160208251018083835e508051806020830101601f825f03163682375050601f19601f825160200101169050905081019050905090508301925060010181811861275c575b505082016020019150509050905081015050803b15613941575f61178061052461179c5f855af161280a573d5f5f3e3d5ffd5b505b565b61010051602381018181106139415790508060101c61394157610220525f600160f01b816102a001526002810190505f60f01b816102a00152600281019050600160f01b816102a0015260028101905080610280526102809050602081510180826102405e50505f61024051816102e00161026051815250808201915050600160f81b816102e001526001810190506040518060f01b9050816102e00152600281019050600160f01b816102e00152600281019050610220518060f01b9050816102e00152600281019050806102c0526102c09050602081510180826102805e50505f61028051816102e0016102a0518152508082019150506060518060e01b9050816102e001526004810190506080518060f81b9050816102e0015260018101905060a0518060c01b9050816102e0015260088101905060c0518060f01b9050816102e0015260028101905060e0518060601b9050816102e0015260148101905061010051816102e00181610120825e50808201915050806102c0526102c0905060208151018082845e505050565b6105c05161060052610600516129d6576105a0516129c857428060401c61394157610600526129d6565b438060401c61394157610600525b60016106205261044051610640526105a0516106605261060051610680526105e0516106a052610460516106c05260206104805101806104806106e05e506101e061062060405e612a28610a2061280e565b610a20602081510180826108005e50506020610800510180610800835e5050565b637b754d2d610d84526004610c4051610da4526001610dc452604001610d8052610d8060208151018082610c605e5050608b5461044052608c54610460526020610c60510180610c606104805e505f6105a052428060401c613941576105c05260016105e052612aba610d8061299e565b610d8060208151018082845e505050565b5f6040518060801c613941578060801b9050816101200152601081019050806101005261010090506020815101808260a05e50505f6060518060801c613941578060801b9050816101600152601081019050806101405261014090506020815101808260e05e50505f6080518060e01b9050816101a0015260048101905080610180526101809050602081510180826101205e50505f6101605260016080511215612b76575f612b7c565b60605115155b612c335760016080511215612bec5760605115612bd9575f60a051816101e00160c05181525080820191505060e051816101e00161010051815250808201915050806101c0526101c09050602081510180826101605e5050612c8b565b602060a051018060a06101605e50612c8b565b5f60a051816101e00160c05181525080820191505061012051816101e00161014051815250808201915050806101c0526101c09050602081510180826101605e5050612c8b565b5f60a051816101e00160c05181525080820191505061012051816101e0016101405181525080820191505060e051816101e00161010051815250808201915050806101c0526101c09050602081510180826101605e50505b5f7e03010000000000000000000000000000000000000000000000000000000000816101e0015260038101905061016051600181018181106139415790508060101c613941578060f01b9050816101e0015260028101905060016080511215612d14577f0100000000000000000000000000000000000000000000000000000000000000612d36565b7f05000000000000000000000000000000000000000000000000000000000000005b816101e0015260018101905061016051816101e00181610180825e50808201915050806101c0526101c0905060208151018082845e505050565b6104a05115612d81576104a0612d8c565b600554610520526105205b5161050052610500516040526104c0516060526104e051608052612db1610580612acb565b610580602081510180826105205e5050610240518152610260516020820152602061028051016040820181610280825e505060206105205101610260820181610520825e50505f6102c082015250565b6105e05161024052610600516102605260206106205101806106206102805e5060606108406104a05e612e35610b80612d70565b610b806102e0816108a05e505f5463ddc28c58610bc052604080610be05280610be00160a06108a05182526108c051602083015280604083015280820160206108e05101806108e0835e508051806020830101601f825f03163682375050601f19601f825160200101169050810190508060608301528082016020610b00510180610b00835e508051806020830101601f825f03163682375050601f19601f82516020010116905081019050610b6051608083015290508101905030610c0052506040610bc0610364610bdc845afa612f10573d5f5f3e3d5ffd5b60403d1061394157610bc09050604081610b805e50610b8051815250565b60406105e06102405e60206106205101806106206102805e50610840516104a05260406108606104c05e612f63610be0612d70565b610be06102e0816109005e505f610be0526108a051612f865734610be052612f8f565b6108a051610be0525b6108e05115613107575f5463ddc28c58610c4052604080610c605280610c600160a06109005182526109205160208301528060408301528082016020610940510180610940835e508051806020830101601f825f03163682375050601f19601f825160200101169050810190508060608301528082016020610b60510180610b60835e508051806020830101601f825f03163682375050601f19601f82516020010116905081019050610bc051608083015290508101905030610c8052506040610c40610364610c5c845afa613067573d5f5f3e3d5ffd5b60403d1061394157610c409050604081610c005e50610c0051610be051101561310757602080610ca052600f610c40527f4e6f7420656e6f75676820666565730000000000000000000000000000000000610c6052610c4081610ca00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0610c805280600401610c9cfd5b5f54632637a450610c0052604080610c205280610c200160a06109005182526109205160208301528060408301528082016020610940510180610940835e508051806020830101601f825f03163682375050601f19601f825160200101169050810190508060608301528082016020610b60510180610b60835e508051806020830101601f825f03163682375050601f19601f82516020010116905081019050610bc05160808301529050810190506108c051610c4052506080610c00610364610c1c610be051855af16131dd573d5f5f3e3d5ffd5b3d608081183d608010021880610c0001610c801161394157610c0051610f8052610c20518060401c61394157610fa0526040610c40610fc05e50610f805050565b608a546132c7576020806119405260276118c0527f52656164206e6f7420656e61626c6564202d2063616c6c207365745f726561646118e0527f5f636f6e66696700000000000000000000000000000000000000000000000000611900526118c0816119400160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0611920528060040161193cfd5b608c546133705760208061194052602b6118c0527f4d61696e6e65742076696577206e6f7420736574202d2063616c6c207365745f6118e0527f726561645f636f6e666967000000000000000000000000000000000000000000611900526118c0816119400160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0611920528060040161193cfd5b611420516110005118156133fb5760208061192052600f6118c0527f4c656e677468206d69736d6174636800000000000000000000000000000000006118e0526118c0816119200160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a0611900528060040161191cfd5b5f6118c0525f6120e0525f61100051602081116139415780156134aa57905b80612100526118c051601f8111613941578060061b6118e00161210051611000518110156139415760051b6110200151815261210051611420518110156139415760051b6114400151602082015250600181016118c052506120e05161210051611420518110156139415760051b611440015180820182811061394157905090506120e05260010181811861341a575b50506118c05160208160061b015f81601f0160051c604181116139415780156134e857905b8060051b6118c0015181608f01556001018181186134cf575b5050505061184051610c40526134ff612320612a49565b612320602081510180826121005e50506003546105e052306106005260206121005101806121006106205e5061186051610840526120e0516108605260406108805260406118806108a05e5f6108e052613557612f2e565b565b6040611000611ae05e6040611ac052611ac0602081510180826118a05e50505f611040516020811161394157801561360957905b8060061b61106001604081611ac05e506002611ac0516020525f5260405f2054611b0052611b0051156135fe57611ac0516105e052611b00516106005260206118a05101806118a06106205e5060603661084037611ae0516108a052611880516108c0525f6108e0526135fe612f2e565b60010181811861358d575b50507f1d1af3b995be68c98b810354734eb3bff44cf05cf8191b5e2c1a3e2db421c8b6608061186051611ac05261100051611ae05261102051611b005280611b205280611ac0015f611040518083528060061b5f826020811161394157801561369157905b8060061b611060018160061b6020880101604082825e505060010181811861366e575b50508201602001915050905081019050611ac0a1565b5f5433181561372d576020806103c052600f610360527f4e6f74204c5a20656e64706f696e74000000000000000000000000000000000061038052610360816103c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06103a052806004016103bcfd5b60026040516020525f5260405f20546137bd576020806103c052600f610360527f4c5a2050656572206e6f7420736574000000000000000000000000000000000061038052610360816103c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06103a052806004016103bcfd5b60026040516020525f5260405f20546060518060a01c61394157181561385a576020806103c052601a610360527f496e76616c6964204c5a206d65737361676520736f757263652100000000000061038052610360816103c00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a06103a052806004016103bcfd5b6001815250565b63fffff9be60405113815250565b608d546138ec5760208060e05260156080527f4f7261636c65206e6f7420636f6e66696775726564000000000000000000000060a05260808160e00160208251018083835e508051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506308c379a060c0528060040160dcfd5b608d5463939074b16080526040604060a05e602060806044609c5f855af1613916573d5f5f3e3d5ffd5b3d602081183d60201002188060800160a011613941576080518060011c6139415760e0525060e05050565b5f80fd0ea5058814ee10031d1817c7001800e61d1817a2050e0fa71d181d1800a81d181d1815a915541cfc1040143913cf1d180d7c0722003315810e7f18ca1404008c1d180f2f1d180ef2178205ca

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

000000000000000000000000b101b2b0aa02b7167d238b98dc1b0b0404a760e8

-----Decoded View---------------
Arg [0] : _owner (address): 0xb101b2b0aa02b7167D238B98dc1B0b0404a760E8

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000b101b2b0aa02b7167d238b98dc1b0b0404a760e8


Block Transaction Gas Used Reward
view all blocks produced

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

Validator Index Block Amount
View All Withdrawals

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

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