ETH Price: $4,002.78 (+2.50%)

Contract

0x8C8727276725b7Da11fDA6e2646B2d2448E5B3c5
Transaction Hash
Method
Block
From
To
Process Packet1289687402024-12-07 1:50:572 hrs ago1733536257IN
0x8C872727...448E5B3c5
0 ETH0.0000152309270.00010185
Process Packet1289658642024-12-07 0:15:054 hrs ago1733530505IN
0x8C872727...448E5B3c5
0 ETH0.0000026391570.0001021
Process Packet1289656722024-12-07 0:08:414 hrs ago1733530121IN
0x8C872727...448E5B3c5
0 ETH0.0000024154940.0001022
Process Packet1289652582024-12-06 23:54:534 hrs ago1733529293IN
0x8C872727...448E5B3c5
0 ETH0.000002480550.00000151
Process Packet1289648782024-12-06 23:42:135 hrs ago1733528533IN
0x8C872727...448E5B3c5
0 ETH0.0000032312450.00010249
Process Packet1289639092024-12-06 23:09:555 hrs ago1733526595IN
0x8C872727...448E5B3c5
0 ETH0.0000065658360.00102134
Process Packet1289501202024-12-06 15:30:1713 hrs ago1733499017IN
0x8C872727...448E5B3c5
0 ETH0.0000662245870.00010165
Process Packet1289460622024-12-06 13:15:0115 hrs ago1733490901IN
0x8C872727...448E5B3c5
0 ETH0.0000366888890.00010135
Process Packet1289445282024-12-06 12:23:5316 hrs ago1733487833IN
0x8C872727...448E5B3c5
0 ETH0.0000134262290.0001014
Process Packet1289347502024-12-06 6:57:5721 hrs ago1733468277IN
0x8C872727...448E5B3c5
0 ETH0.0000108221530.00010137
Process Packet1289345422024-12-06 6:51:0121 hrs ago1733467861IN
0x8C872727...448E5B3c5
0 ETH0.0000214976060.00010137
Process Packet1289295752024-12-06 4:05:2724 hrs ago1733457927IN
0x8C872727...448E5B3c5
0 ETH0.0000140197220.00010136
Process Packet1289291672024-12-06 3:51:5124 hrs ago1733457111IN
0x8C872727...448E5B3c5
0 ETH0.0000361636060.00010134
Process Packet1289283982024-12-06 3:26:1325 hrs ago1733455573IN
0x8C872727...448E5B3c5
0 ETH0.0000234725590.00010135
Process Packet1289209222024-12-05 23:17:0129 hrs ago1733440621IN
0x8C872727...448E5B3c5
0 ETH0.0000044453860.00010203
Process Packet1289205432024-12-05 23:04:2329 hrs ago1733439863IN
0x8C872727...448E5B3c5
0 ETH0.0000058830570.00009717
Process Packet1289178642024-12-05 21:35:0531 hrs ago1733434505IN
0x8C872727...448E5B3c5
0 ETH0.0000191161060.0001014
Process Packet1289130542024-12-05 18:54:4533 hrs ago1733424885IN
0x8C872727...448E5B3c5
0 ETH0.0000066504190.00010162
Process Packet1289122702024-12-05 18:28:3734 hrs ago1733423317IN
0x8C872727...448E5B3c5
0 ETH0.00000492140.00010156
Process Packet1289105422024-12-05 17:31:0135 hrs ago1733419861IN
0x8C872727...448E5B3c5
0 ETH0.0000123278190.00010149
Process Packet1289103502024-12-05 17:24:3735 hrs ago1733419477IN
0x8C872727...448E5B3c5
0 ETH0.0000162141340.00010148
Process Packet1289101582024-12-05 17:18:1335 hrs ago1733419093IN
0x8C872727...448E5B3c5
0 ETH0.0000154143750.00010148
Process Packet1289053752024-12-05 14:38:4738 hrs ago1733409527IN
0x8C872727...448E5B3c5
0 ETH0.0000143393730.00010147
Process Packet1289023032024-12-05 12:56:2339 hrs ago1733403383IN
0x8C872727...448E5B3c5
0 ETH0.0000340929920.00010137
Process Packet1288915342024-12-05 6:57:2545 hrs ago1733381845IN
0x8C872727...448E5B3c5
0 ETH0.0000146652280.00010134
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
1289687402024-12-07 1:50:572 hrs ago1733536257
0x8C872727...448E5B3c5
0.000000910171115 ETH
1289687402024-12-07 1:50:572 hrs ago1733536257
0x8C872727...448E5B3c5
0.000000213956274 ETH
1289668672024-12-07 0:48:313 hrs ago1733532511
0x8C872727...448E5B3c5
0.000000224825478 ETH
1289668672024-12-07 0:48:313 hrs ago1733532511
0x8C872727...448E5B3c5
0.000001348952868 ETH
1289658642024-12-07 0:15:054 hrs ago1733530505
0x8C872727...448E5B3c5
0.000000042236572 ETH
1289658642024-12-07 0:15:054 hrs ago1733530505
0x8C872727...448E5B3c5
0.000005161566398 ETH
1289658642024-12-07 0:15:054 hrs ago1733530505
0x8C872727...448E5B3c5
0.000005222269635 ETH
1289656722024-12-07 0:08:414 hrs ago1733530121
0x8C872727...448E5B3c5
0.00000004218053 ETH
1289656722024-12-07 0:08:414 hrs ago1733530121
0x8C872727...448E5B3c5
0.000005313850221 ETH
1289656722024-12-07 0:08:414 hrs ago1733530121
0x8C872727...448E5B3c5
0.000005375248609 ETH
1289645222024-12-06 23:30:215 hrs ago1733527821
0x8C872727...448E5B3c5
0.000002085214521 ETH
1289645222024-12-06 23:30:215 hrs ago1733527821
0x8C872727...448E5B3c5
0.000012511287127 ETH
1289642962024-12-06 23:22:495 hrs ago1733527369
0x8C872727...448E5B3c5
0.000002146256211 ETH
1289642962024-12-06 23:22:495 hrs ago1733527369
0x8C872727...448E5B3c5
0.000012877535572 ETH
1289501202024-12-06 15:30:1713 hrs ago1733499017
0x8C872727...448E5B3c5
0.000003523283604 ETH
1289501202024-12-06 15:30:1713 hrs ago1733499017
0x8C872727...448E5B3c5
0.000001810481069 ETH
1289483672024-12-06 14:31:5114 hrs ago1733495511
0x8C872727...448E5B3c5
0.000001066753613 ETH
1289483672024-12-06 14:31:5114 hrs ago1733495511
0x8C872727...448E5B3c5
0.000006400518287 ETH
1289178642024-12-05 21:35:0531 hrs ago1733434505
0x8C872727...448E5B3c5
0.000000041817626 ETH
1289178642024-12-05 21:35:0531 hrs ago1733434505
0x8C872727...448E5B3c5
0.000011366240954 ETH
1289178642024-12-05 21:35:0531 hrs ago1733434505
0x8C872727...448E5B3c5
0.000011456340534 ETH
1289141982024-12-05 19:32:5333 hrs ago1733427173
0x8C872727...448E5B3c5
0.000004572879823 ETH
1289141982024-12-05 19:32:5333 hrs ago1733427173
0x8C872727...448E5B3c5
0.000027437278938 ETH
1288875272024-12-05 4:43:512 days ago1733373831
0x8C872727...448E5B3c5
0.000000041085938 ETH
1288875272024-12-05 4:43:512 days ago1733373831
0x8C872727...448E5B3c5
0.000010584115225 ETH
View All Internal Transactions

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
IncentivizedWormholeEscrow

Compiler Version
v0.8.22+commit.4fc1097e

Optimization Enabled:
Yes with 100000 runs

Other Settings:
paris EvmVersion, MIT license
File 1 of 18 : IncentivizedWormholeEscrow.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;

import { IncentivizedMessageEscrow } from "../../IncentivizedMessageEscrow.sol";

import { SmallStructs } from "./external/callworm/SmallStructs.sol";
import { WormholeVerifier } from "./external/callworm/WormholeVerifier.sol";
import { IWormhole } from "./interfaces/IWormhole.sol";

/**
 * @title Incentivized Wormhole Message Escrow
 * @notice Incentivizes Wormhole messages through Generalised Incentives.
 * Wormhole does not have any native way of relaying messages, this implemention adds one.
 *
 * When using Wormhole with Generalised Incentives and you don't want to lose message, be very careful regarding
 * emitting messages to destinationChainIdentifiers that does not exist. Wormhole has no way to verify if a
 * chain identifier exists or not. If the chain identifier does not exist, it is not possible to get a timeout or ack back.
 *
 * @dev This implementation only uses the Wormhole contracts to emit messages, it does not use the Wormhole contracts
 * to verify if messages are authentic. A custom verification library is used that is more gas efficient and skips
 * parts of the VAA that is not relevant to us. This provides significant gas savings compared to verifying packages
 * against the Wormhole implementation.
 */
contract IncentivizedWormholeEscrow is IncentivizedMessageEscrow, WormholeVerifier {
    error BadChainIdentifier();

    IWormhole public immutable WORMHOLE;

    // Wormhole's chain identifier can be changed. However, we generally expect to redeploy
    // in cases where they would change it.
    bytes32 public immutable UNIQUE_SOURCE_IDENTIFIER;

    // For EVM it is generally set that 15 => Finality
    uint8 constant WORMHOLE_CONSISTENCY = 15;

    constructor(address sendLostGasTo, address wormhole_) payable IncentivizedMessageEscrow(sendLostGasTo) WormholeVerifier(wormhole_) {
        WORMHOLE = IWormhole(wormhole_);

        // Collect chainId from Wormhole.
        UNIQUE_SOURCE_IDENTIFIER = bytes32(uint256(WORMHOLE.chainId()));
    }

    function estimateAdditionalCost() external view returns(address asset, uint256 amount) {
        asset =  address(0);
        amount = WORMHOLE.messageFee();
    }

    /** @notice Wormhole proofs are valid until the guardian set is changed. The new guradian set may sign a new VAA */
    function _proofValidPeriod(bytes32 /* destinationIdentifier */) override internal pure returns(uint64) {
        return 0;
    }

    function _uniqueSourceIdentifier() override internal view returns(bytes32 sourceIdentifier) {
        return sourceIdentifier = UNIQUE_SOURCE_IDENTIFIER;
    }

    /** @dev _message is the entire Wormhole VAA. It contains both the proof & the message as a slice. */
    function _verifyPacket(bytes calldata /* _metadata */, bytes calldata _message) internal view override returns(bytes32 sourceIdentifier, bytes memory implementationIdentifier, bytes calldata message_) {

        // Decode & verify the VAA.
        // This uses the custom verification logic found in ./external/callworm/WormholeVerifier.sol.
        (
            SmallStructs.SmallVM memory vm,
            bytes calldata payload,
            bool valid,
            string memory reason
        ) = parseAndVerifyVM(_message);

        // This is the preferred flow used by Wormhole.
        require(valid, reason);

        // We added the destination chain to the payload since Wormhole messages are broadcast.
        // Get the chain identifier for the destination chain according to the payload.
        bytes32 destinationChainIdentifier = bytes32(payload[0:32]);

        // Check that the message is intended for this chain.
        if (destinationChainIdentifier != UNIQUE_SOURCE_IDENTIFIER) revert BadChainIdentifier();

        // Get the identifier for the source chain.
        sourceIdentifier = bytes32(uint256(vm.emitterChainId));

        // Load the identifier for the calling contract.
        implementationIdentifier = bytes.concat(vm.emitterAddress);

        // Get the application message.
        message_ = payload[32:];
    }

    /**
     * @dev Wormhole messages are broadcast, as a result we set destinationChainIdentifier in the message.
     */
    function _sendPacket(bytes32 destinationChainIdentifier, bytes memory /* destinationImplementation */, bytes memory message, uint64 /* deadline */) internal override returns(uint128 costOfsendPacketInNativeToken) {
        // Get the cost of sending wormhole messages.
        costOfsendPacketInNativeToken = uint128(WORMHOLE.messageFee());

        // Relayers can collect the destination chain from the payload and destinationImplementation from storage / their whitelist.

        // Handoff the message to wormhole.
        WORMHOLE.publishMessage{value: costOfsendPacketInNativeToken}(
            0,
            bytes.concat(
                destinationChainIdentifier,
                message
            ),
            WORMHOLE_CONSISTENCY
        );
    }
}

File 2 of 18 : IncentivizedMessageEscrow.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;

import { Address } from "openzeppelin/utils/Address.sol";

import { IIncentivizedMessageEscrow } from "./interfaces/IIncentivizedMessageEscrow.sol";
import { ICrossChainReceiver } from "./interfaces/ICrossChainReceiver.sol";
import { Bytes65 } from "./utils/Bytes65.sol";
import { CTX_SOURCE_TO_DESTINATION, CTX_DESTINATION_TO_SOURCE, CTX_TIMEDOUT_ON_DESTINATION } from "./MessagePayload.sol";
import "./MessagePayload.sol";


/**
 * @title Generalised Incentive Escrow
 * @author Cata labs Inc.
 * @notice Main logic for placing transparent incentives on message relaying.
 * This contract is intended to sit between an application and a cross-chain message protocol.
 * The goal is to overload the existing incentive scheme with one that is open to anyone.
 *
 * Each messaging protocol will have a respective implementation that understands how to send
 * and verify messages. There are 4 functions that an integration has to implement.
 * Any implementation of this contract, allows applications to deliver a message to ::submitMessage
 * along with the respective incentives. 
 * The integration (this contract) will handle transfering the message to the destination and
 * returning an ack from the destination to the integrating application.
 *
 * The incentive is released when an ack from the destination chain is delivered to this contract.
 *
 * Beyond making relayer incentives stronger, this contract also implements several quality of life features:
 * - Refund unused gas.
 * - Seperate gas payments for call and ack.
 * - Simple implementation of new messaging protocols.
 *
 * Applications integration with Generalised Incentives have to be aware that Acks are replayable.
 */
abstract contract IncentivizedMessageEscrow is IIncentivizedMessageEscrow, Bytes65 {
    
    //--- Constants ---//

    /**
     * @notice If the message reverts on the destination chain,
     * 1 byte is prepended to the original message on ack. This is the byte.
     */
    bytes1 constant MESSAGE_REVERTED = 0xff;

    /** 
     * @notice If the original sender is not authorised on the application on the destination chain,
     * 1 byte is prepended to the original message on ack. This is the byte.
     */
    bytes1 constant NO_AUTHENTICATION = 0xfe;

    /** 
     * @notice If the message timed out on destination chain,
     * 1 byte is prepended to the original message on ack. This is the byte.
     */
    bytes1 constant MESSAGE_TIMED_OUT = 0xfd;

    /**
     * @notice If setRemoteImplementation is called with this as the destination implementation
     * (abi.encodePacked(DISABLE_ROUTE_IMPLEMENTATION)), then the route is permanently disabled
     * This is treated as a magic value so that incase an implementations treats abi.encodePacked(0x00)
     * as a valid destination (say address(0)).
     */
    bytes1 constant DISABLE_ROUTE_IMPLEMENTATION = 0x00;

    /**
     * @notice If a relayer or application provides an address that cannot accept gas and
     * the transfer fails the gas is sent here instead.
     * @dev This may not invoke any logic on receive() or be a proxy.
     */
    address immutable public SEND_LOST_GAS_TO;

    //--- Storage ---//
    
    /** 
     * @notice Get incentive description based on message context: messageIdentifier, fromApplication, and destChain
     * @dev fromApplication and destChain are required to fetch the bounty. Together they
     * match exactly 1 remote escrow implementation. As a result, this restricts the storage
     * slot's security to the security of the specified remote escrow implementation.
     */
    mapping(address fromApplication => mapping(bytes32 destChain => mapping(bytes32 messageIdentifier => IncentiveDescription))) _bounty;

    /** @notice A hash of the emitted message on receive such that we can emit a similar one. */
    mapping(bytes32 => mapping(bytes => mapping(bytes32 => bytes32))) _messageDelivered;

    // Maps applications to their escrow implementations.
    mapping(address => mapping(bytes32 => bytes)) public implementationAddress;
    mapping(address => mapping(bytes32 => bytes32)) public implementationAddressHash;

    //--- Virtual Functions ---//
    // To integrate a messaging protocol, a contract has to inherit this contract and implement 4 functions below.

    /** 
     * @notice Verifies the authenticity of a message.
     * @dev Should be overwritten by the specific messaging protocol verification structure.
     * onRecv. implementations should collect acks so _verifyPacket returns true after acks have been executed once.
     * @param messagingProtocolContext Some context that is useful for verifing the message.
     * It should not contain the message but instead verification context like signatures, header, etc.
     * Context may not be needed for verifying the message and can be prepended to rawMessage.
     * @param rawMessage Some kind of package, initially untrusted. Should contain the message as a slice
     * It may contain more than just the message, like signatures, headers, etc.
     *
     * @return sourceIdentifier The source chain identifier. A chainID, a channel ID, or similarly.
     * @return implementationIdentifier An identifier for the address that emitted the message.
     * @return message The emitted message as a calldata slice. Should not contain anything AMB specific
     * and should be the exact message as delivered to _sendPacket
     */
    function _verifyPacket(
        bytes calldata messagingProtocolContext,
        bytes calldata rawMessage
    ) virtual internal returns(
        bytes32 sourceIdentifier,
        bytes memory implementationIdentifier,
        bytes calldata message
    );

    /** 
     * @notice Deliver the message to the messaging protocol to generate a proof.
     * @dev Should be overwritten to send a message using the specific messaging protocol.
     * The function is allowed to claim native tokens (set costOfsendPacketInNativeToken). 
     * The function is allowed to take ERC20 tokens (transferFrom(msg.sender,...)) 
     * in which case set costOfsendPacketInNativeToken to 0.
     * @param destinationIdentifier The destination chain for the message.
     * @param destinationImplementation The destination escrow contract.
     * @param message The message. Contains relevant escrow context.
     * @param deadline A timestamp that the message should be delivered before. If the AMB does not nativly
     * support a timeout on their messages this parameter should be ignored. If 0 is provided, parse it as MAX.
     * @return costOfsendPacketInNativeToken An additional cost to emitting messages in NATIVE tokens.
     */
    function _sendPacket(
        bytes32 destinationIdentifier,
        bytes memory destinationImplementation,
        bytes memory message, uint64 deadline
    ) virtual internal returns(uint128 costOfsendPacketInNativeToken);

    /**
     *  @notice A unique source identifier used to generate the message identifier.
     *  @dev Should generally be the same as the one set by the AMB such that we can verify messages with this identifier
     */
    function _uniqueSourceIdentifier() virtual internal view returns(bytes32 sourceIdentifier);

    /**
     * @notice The duration for which a proof is valid for. It may vary by destination.
     * @dev On checks, block.timestamp is added to the return of this function such that
     * block.timestamp + _proofValidPeriod > deadline.
     * If any deadline is valid, set to **0** instead of ~~type(uint64).max~~.
     * @param destinationIdentifier The destination chain identifier.
     * @return duration The maximum proof duration. Includes the time from message emitted (proof gen)
     * to message finalised.
     */
    function _proofValidPeriod(bytes32 destinationIdentifier) virtual internal view returns(uint64 duration);

    /**
     * @notice The duration for which a proof is valid for.
     * @dev On checks, block.timestamp is added to the return of this function such that
     * block.timestamp + _proofValidPeriod > deadline.
     * If 0, implies that any deadline is valid.
     * @param destinationIdentifier The destination chain identifier.
     * @return duration The maximum proof duration. Includes the time from message emitted (proof gen)
     * to message finalised.
     */
    function proofValidPeriod(bytes32 destinationIdentifier) external view returns(uint64 duration) {
        return duration = _proofValidPeriod(destinationIdentifier);
    }

    /**
     * @param sendLostGasTo It should only be set to an EOA or a contract that has no logic on receive nor be a proxy.
     * If no-one wants to take responsibility of the lost Ether, use a burn address (0xdead) instead of address(0). 
     */
    constructor(address sendLostGasTo) {
        if (sendLostGasTo == address(0)) revert SendLostGasToIsZero();
        SEND_LOST_GAS_TO = sendLostGasTo;
    }

    /**
     * @notice Generates a unique message identifier for a message
     * @dev The identifier should:
     *  - Be unique within a trusted ecosystem.
     *  - Be unique based on the sender such that applications can't be DoS'ed.
     *  - Contain the deadline for timeout validation.
     *  - Be unique over time: Use blocknumber or blockhash.
     *  - Be unique on the source chain: Use a unique destinationIdentifier.
     *  - Be unique on destination chain: Use a unique source identifier.
     *  - Depend on the message, for uniqueness & for timeouts.
     * Point 2 implies that applications are allowed to DoS themselves. To protect against this, applications
     * should include some user unique information, say include a user address.
     */
    function _getMessageIdentifier(
        address messageSender,
        uint64 deadline,
        uint256 blockNumber,
        bytes32 sourceIdentifier,
        bytes32 destinationIdentifier,
        bytes memory message
    ) view internal virtual returns(bytes32) {
        return keccak256(
            bytes.concat(
                bytes20(address(this)),
                bytes20(messageSender),
                bytes8(deadline),
                bytes32(blockNumber),
                sourceIdentifier, 
                destinationIdentifier,
                message
            )
        );
    }

    /**
     * @notice Generates a unique message identifier for a message
     * @dev Simplifies using _getMessageIdentifier raw by assuming what the inputs
     * to the other parameters should be.
     */
    function _getMessageIdentifier(
        uint64 deadline,
        bytes32 destinationIdentifier,
        bytes calldata message
    ) view internal virtual returns(bytes32) {
        return _getMessageIdentifier(
            msg.sender,
            deadline,
            block.number,
            _uniqueSourceIdentifier(),
            destinationIdentifier,
            message
        );
    }

    //--- Getter Functions ---//
    /**
     * @notice Returns the bounty associated with a specific messageIdentifier.
     * @param fromApplication The application that submitted the message.
     * @param destinationIdentifier The destination chain for the message.
     * @param messageIdentifier The message identifier for a specific bounty.
     * @return incentive The message incentive / bounty as read from memory. If refundGasTo is address(0), it has been claimed.
     */
    function bounty(address fromApplication, bytes32 destinationIdentifier, bytes32 messageIdentifier) external view returns(IncentiveDescription memory incentive) {
        return _bounty[fromApplication][destinationIdentifier][messageIdentifier];
    }

    /**
     * @notice Get the message statue through the an ack hash.
     * If the message hasn't been delivered yet it returns bytes32(0)
     * @param sourceIdentifier The source chain the message was emitted from.
     * @param sourceImplementationIdentifier The source escrow implementation that emitted the message.
     * @param messageIdentifier The message identifier of the message.
     * @return hasMessageBeenExecuted Hash of the ack message. If not ack, then bytes32(uint256(1)). If not
     * executed then bytes32(0).
     */
   function messageDelivered(
        bytes32 sourceIdentifier,
        bytes calldata sourceImplementationIdentifier,
        bytes32 messageIdentifier
    ) external view returns(bytes32 hasMessageBeenExecuted) {
        return _messageDelivered[sourceIdentifier][sourceImplementationIdentifier][messageIdentifier];
   }

     /**
     * @notice Sets the escrow implementation for a specific chain
     * @dev This can only be set once. When set, it cannot be changed.
     * This is to protect relayers as this could be used to fail acks.
     * @param destinationIdentifier An identifier for the destination chain. Varies from AMB.
     * @param implementation Implementation address. Encoding varies between AMBs.
     * You are not allowed to set a 0 length implementation address. Beaware that while some implementations
     * are valid for sending (say hex"0x01" which may be read as address(uint160(1))), they break acks / delivery.
     * If you want to disable a specific route, set implementation to hex"00" (DISABLE_ROUTE_IMPLEMENTATION).
     */
    function setRemoteImplementation(bytes32 destinationIdentifier, bytes calldata implementation) external virtual {
        if (implementationAddressHash[msg.sender][destinationIdentifier] != bytes32(0)) revert ImplementationAddressAlreadySet(
            implementationAddress[msg.sender][destinationIdentifier]
        );
        if (implementation.length == 0) revert NoImplementationAddressSet();

        implementationAddress[msg.sender][destinationIdentifier] = implementation;
        bytes32 _implementationHash = keccak256(implementation);
        implementationAddressHash[msg.sender][destinationIdentifier] = _implementationHash;

        emit RemoteImplementationSet(msg.sender, destinationIdentifier, _implementationHash, implementation);
    }

    //--- Public Endpoints ---//

    /**
     * @notice Increases the bounty for relaying messages
     * @dev It is not possible to increase the gas budget for a message. 
     * The increase should be paid and is generally:
     *      incentive.maxGasDelivery * deliveryGasPriceIncrease + incentive.maxGasAck * ackGasPriceIncrease
     * Value has to be provided exact.
     * 
     * @param messageIdentifier The message identifier of the message to increase the bounty price for.
     * @param deliveryGasPriceIncrease The INCREASE in the gas price of the delivery gas
     * @param ackGasPriceIncrease The INCREASE in the gas price of ack gas.
     */
    function increaseBounty(
        address fromApplication,
        bytes32 destinationIdentifier,
        bytes32 messageIdentifier,
        uint96 deliveryGasPriceIncrease,
        uint96 ackGasPriceIncrease
    ) external payable {
        // Find incentive scheme.
        IncentiveDescription storage incentive = _bounty[fromApplication][destinationIdentifier][messageIdentifier];
        if (incentive.refundGasTo == address(0)) revert MessageDoesNotExist();

        // Compute incentive metrics.
        uint128 maxDeliveryFee = incentive.maxGasDelivery * deliveryGasPriceIncrease;
        uint128 maxAckFee = incentive.maxGasAck * ackGasPriceIncrease;
        uint128 sum = maxDeliveryFee + maxAckFee;
        // Check that the provided gas is exact
        if (msg.value != sum) revert IncorrectValueProvided(sum, uint128(msg.value));

        uint96 newPriceOfDeliveryGas = incentive.priceOfDeliveryGas + deliveryGasPriceIncrease;
        uint96 newPriceOfAckGas = incentive.priceOfAckGas + ackGasPriceIncrease;
        // Update storage.
        incentive.priceOfDeliveryGas = newPriceOfDeliveryGas;
        incentive.priceOfAckGas = newPriceOfAckGas;

        // Emit the event with the increased values.
        emit BountyIncreased(
            messageIdentifier,
            newPriceOfDeliveryGas,
            newPriceOfAckGas
        );
    }

    /** 
     * @notice Set a bounty on a message and transfer the message to the messaging protocol.
     * @dev Called by applications. These application should ensure:
     *     1. incentive.maxGasAck is sufficient! Otherwise, an off-chain agent needs to re-submit the ack.
     *     2. incentive.maxGasDelivery is sufficient. Otherwise, the call will fail within the try - catch.
     *     3. The relay incentive is enough to get the message relayed within the expected time. If that is never, this check is not needed.
     * Furthermore, if the package times out there is no gas refund.
     * Sending too much value results in the excess being refunded to refundGasTo via a call. This may allow refundGasTo to throw the call.
     * @param destinationIdentifier 32 bytes that identifies the destination chain.
     * @param destinationAddress The destination application encoded in 65 bytes: First byte is the length and last 64 is the destination application.
     * @param message The message to be sent to the destination. Please ensure the message is block-unique.
     *     This means that you don't send the same message twice in a single block. If you need to do that, add a nonce or noice.
     * @param incentive The incentive to attatch to the bounty. The price of this incentive has to be paid,
     * any excess is refunded to refundGasTo. (not msg.sender)
     * @param deadline After this date, do not allow relayers to execute the message on the destination chain. If set to 0, disable timeouts.
     * Not all AMBs may support disabling the deadline. If acks are required it is recommended to set the deadline sometime in the future.
     * Note, it may still take a significant amount of time to bring back the timeout.
     * @return gasRefund The amount of excess gas that was paid to this call. The app should handle the excess.
     * @return messageIdentifier An unique identifier for a message.
     */
    function submitMessage(
        bytes32 destinationIdentifier,
        bytes calldata destinationAddress,
        bytes calldata message,
        IncentiveDescription calldata incentive,
        uint64 deadline
    ) checkBytes65Address(destinationAddress) external payable returns(uint256 gasRefund, bytes32 messageIdentifier) {
        // Valid refund to.
        if (incentive.refundGasTo == address(0)) revert RefundGasToIsZero();

        // Check that the application has set a destination implementation by checking if the length of the destinationImplementation entry is not 0.
        bytes memory destinationImplementation = implementationAddress[msg.sender][destinationIdentifier];
        if (destinationImplementation.length == 0) revert NoImplementationAddressSet();
        if (destinationImplementation.length == 1 && destinationImplementation[0] == DISABLE_ROUTE_IMPLEMENTATION) revert RouteDisabled();

        // Check that the deadline is lower than the AMB specification.
        unchecked {
            // Timestamps do not overflow in uint64 within reason.
            uint64 ambMaxDeadline = _proofValidPeriod(destinationIdentifier);
            if (ambMaxDeadline != 0 && deadline == 0) revert DeadlineTooLong(ambMaxDeadline, 0);
            if (ambMaxDeadline != 0 && deadline > uint64(block.timestamp) + ambMaxDeadline) revert DeadlineTooLong(uint64(block.timestamp) + ambMaxDeadline, deadline);
            // Check that the deadline is in the future = not (block.timestamp < deadline) = block.timestamp >= deadline.
            if (deadline != 0 && block.timestamp >= deadline) revert DeadlineInPast(uint64(block.timestamp), deadline);
        }

        // Prepare to store incentive
        messageIdentifier = _getMessageIdentifier(
            deadline,
            destinationIdentifier,
            message
        );
        // Store the bounty, get the sum to refunding excess later.
        uint128 sum = _setBounty(msg.sender, destinationIdentifier, messageIdentifier, incentive);

        // Add escrow context to the message.
        bytes memory messageWithContext = bytes.concat(
            bytes1(CTX_SOURCE_TO_DESTINATION),      // This is a sendPacket intended for the _destination_
            bytes32(messageIdentifier),             // A unique message identifier.
            convertEVMTo65(msg.sender),             // Original sender / application.
            destinationAddress,                     // The address to deliver the provided message to.
            bytes8(uint64(deadline)),
            bytes6(incentive.maxGasDelivery),       // The delivery gas limit, to enforce on the destination.
            message                                 // The message to deliver to the destination.
        );

        // Emit the event for off-chain relayers.
        emit BountyPlaced(
            destinationImplementation,
            destinationIdentifier,
            messageIdentifier,
            incentive
        );

        // Bounty is emitted before event to standardized with the other event before sending message scheme.

        // Send message to messaging protocol
        // This call will collect payments for sending the message. It can be in any token but if it is in 
        // native gas, it should return the amount it took.
        uint128 costOfsendPacketInNativeToken = _sendPacket(
            destinationIdentifier,
            destinationImplementation,
            messageWithContext,
            deadline
        );
        // Add the cost of the send message.
        sum += costOfsendPacketInNativeToken;

        // Check that the provided gas is sufficient. The refund will be sent later.
        if (msg.value < sum) revert NotEnoughGasProvided(sum, uint128(msg.value));


        // Return excess incentives to the user (found from incentive.refundGasTo).
        unchecked {
            if (msg.value > sum) {
                // We know: msg.value > sum, thus msg.value - sum > 0.
                gasRefund = msg.value - sum;
                Address.sendValue(payable(incentive.refundGasTo), uint256(gasRefund));
                return (gasRefund, messageIdentifier);
            }
        }
        return (0, messageIdentifier);
    }

    /**
     * @notice Deliver a message & proof of validity.
     * @dev This function is intended to be called by off-chain agents.
     *  Please ensure that feeRecipient can receive gas token: EOA or implements fallback() / receive() with no logic.
     *  Likewise for any non-evm chains. Otherwise the message fails (ack) or the relay payment is lost (deliver).
     *  You need to pass in incentive.maxGas(Delivery|Ack) + messaging protocol dependent buffer, otherwise this call might fail.
     *
     * OnReceive implementations should make _verifyPacket revert. The result is that this function is disabled.
     * Though this function is _virtual_ so feel free to override.
     * @param messagingProtocolContext Additional context required to verify the message by the messaging protocol.
     * @param rawMessage A messaging protocol message, including the message as it was sent as a slice.
     * @param feeRecipient An identifier for the the fee recipient. The identifier should identify the relayer on the source chain.
     *  For EVM (and this contract as a source), use the bytes32 encoded address. For other VMs you might have to register your address.
     */
    function processPacket(
        bytes calldata messagingProtocolContext,
        bytes calldata rawMessage,
        bytes32 feeRecipient
    ) external virtual payable {
        uint256 gasLimit = gasleft();  // uint256 is used here instead of uint48, since there is no advantage to uint48 until after we calculate the difference.
        if (feeRecipient == bytes32(0)) revert FeeRecipientIsZero();

        // Verify that the message is authentic and remove potential context that the messaging protocol added to the message.
        (bytes32 chainIdentifier, bytes memory implementationIdentifier, bytes calldata message) = _verifyPacket(messagingProtocolContext, rawMessage);

        // Figure out if this is deliver or ack.
        uint128 cost = 0;
        bytes1 context = bytes1(message[0]);
        if (context == CTX_SOURCE_TO_DESTINATION) {
            bytes memory receiveAckWithContext = _handleMessage(chainIdentifier, implementationIdentifier, message, feeRecipient, gasLimit);

            // The cost management is made by _sendPacket so we don't have to check if enough gas has been provided.
            cost = _sendPacket(chainIdentifier, implementationIdentifier, receiveAckWithContext, 0);
        } else if (context == CTX_DESTINATION_TO_SOURCE) {
            // Notice that sometimes ack actually handles deadlines which have been passed.
            // However, these are much different from "timeouts".
            _handleAck(chainIdentifier, implementationIdentifier, message, feeRecipient, gasLimit);
        } else if (context == CTX_TIMEDOUT_ON_DESTINATION) {
            // Verify that the timeout is valid.
            // Anyone is able to not only get here but also control the inputs to this code section
            // This logic is not protected by us controlling the logic for the roundtrip.
            // Instead, we need to authenticate the whole message:
            (bytes32 messageIdentifier, address fromApplication, bytes calldata applicationMessage) = _verifyTimeout(chainIdentifier, implementationIdentifier, message);

            // Now that we have the verified the inputs, we can actually use them. Execute the timeout:
            _handleTimeout(chainIdentifier, implementationIdentifier, messageIdentifier, fromApplication, applicationMessage, feeRecipient, gasLimit);
        } else {
            revert NotImplementedError();
        }

        // Check if there is a mis-match between the cost and the value of the message.
        if (uint128(msg.value) != cost) {
            if (uint128(msg.value) > cost) {
                // Send the unused gas back to the the user.
                Address.sendValue(payable(msg.sender), msg.value - uint256(cost));
                return;
            }
            // => uint128(msg.value) < cost, so revert.
            revert NotEnoughGasProvided(uint128(msg.value), cost);
        }
    }

    //--- Internal Functions ---//

    /**
     * @notice Handles messages deliveries (SOURCE_TO_DESTINATION)
     */
    function _handleMessage(
        bytes32 sourceIdentifier,
        bytes memory sourceImplementationIdentifier,
        bytes calldata message,
        bytes32 feeRecipient,
        uint256 gasLimit
    ) internal returns(bytes memory receiveAckWithContext) {
        // Ensure message is unique and can only be execyted once
        bytes32 messageIdentifier = bytes32(message[MESSAGE_IDENTIFIER_START:MESSAGE_IDENTIFIER_END]);

        // The 3 next lines act as a reentry guard, so this call doesn't have to be protected by reentry.
        // We will re-set _messageDelivered[messageIdentifier] again later as the hash of the ack, however, we need re-entry protection
        // so applications don't try to claim incentives multiple times.
        bytes32 messageState = _messageDelivered[sourceIdentifier][sourceImplementationIdentifier][messageIdentifier];
        if (messageState != bytes32(0)) revert MessageAlreadySpent();
        // This is where the "magic-byte" of bytes32(uint256(1)) comes from. Generally, it should always be overwritten by
        // an ack hash.
        _messageDelivered[sourceIdentifier][sourceImplementationIdentifier][messageIdentifier] = bytes32(uint256(1));

        // Prepare to deliver the message to application.
        // We need toApplication to check if the source implementation is valid
        // and we opportunistic decode fromApplication since it is needed in all cases.
        address toApplication = address(bytes20(message[CTX0_TO_APPLICATION_START_EVM:CTX0_TO_APPLICATION_END])); 
        bytes calldata fromApplication = message[FROM_APPLICATION_LENGTH_POS:FROM_APPLICATION_END];

        // Check if the message is valid. This includes:
        // - Checking if the sender is valid.
        // - Checking if the message has expired.

        bytes memory acknowledgement;

        bytes32 expectedSourceImplementationHash = implementationAddressHash[toApplication][sourceIdentifier];
        // Check that the application allows the source implementation.
        // This is not the case when another implementation calls this contract from the source chain.
        // This could be a mistake, send back an ack with the relevant information.
        if (expectedSourceImplementationHash != keccak256(sourceImplementationIdentifier)) {
            // If they are different, return send a failed message back with NO_AUTHENTICATION.
            acknowledgement = bytes.concat(
                NO_AUTHENTICATION,
                message[CTX0_MESSAGE_START: ]
            );

            // Encode a new message to send back. This lets the relayer claim their payment.
            receiveAckWithContext = bytes.concat(
                bytes1(CTX_DESTINATION_TO_SOURCE),  // Context
                messageIdentifier,  // message identifier
                fromApplication,
                feeRecipient,
                bytes6(uint48(gasLimit - gasleft())),  // Delay the gas limit computation until as late as possible. This should include the majority of gas spent.
                bytes8(uint64(block.timestamp)),  // If this overflows, it is fine. It is used in conjunction with a delta.
                acknowledgement
            );

            // Store a hash of the acknowledgement so we can later retry the ack if the ack proofs expires / becomes invalid.
            _messageDelivered[sourceIdentifier][sourceImplementationIdentifier][messageIdentifier] = keccak256(receiveAckWithContext);

            // Message has been delivered and shouldn't be executed again.
            emit MessageDelivered(sourceImplementationIdentifier, sourceIdentifier, messageIdentifier);
            return receiveAckWithContext;
        }

        // Check that if the deadline has been set (deadline != 0). If the deadline has been set,
        // check if the current timestamp is beyond the deadline and return MESSAGE_TIMED_OUT if it is.
        uint64 deadline = uint64(bytes8(message[CTX0_DEADLINE_START:CTX0_DEADLINE_END]));
        if (deadline != 0 && deadline < block.timestamp) {
            acknowledgement = bytes.concat(
                MESSAGE_TIMED_OUT,
                message[CTX0_MESSAGE_START: ]
            );

            // Encode a new message to send back. This lets the relayer claim their payment.
            // Incase of timeouts, we give all of the gas.
            receiveAckWithContext = bytes.concat(
                bytes1(CTX_DESTINATION_TO_SOURCE),  // Context
                messageIdentifier,  // message identifier
                fromApplication,
                feeRecipient,
                bytes6(uint48(2**47)),  // We set the gas spent as max. Why 2**47 instead of maxGasDelivery? 2**47 is only 1 high bit and it saves gas. Furthermore, min(2**47, maxGasDelivery) is checked on the source.
                bytes8(uint64(block.timestamp)),  // If this overflows, it is fine. It is used in conjunction with a delta.
                acknowledgement
            );

            // Store a hash of the acknowledgement so we can later retry a potentially invalid ack proof.
            _messageDelivered[sourceIdentifier][sourceImplementationIdentifier][messageIdentifier] = keccak256(receiveAckWithContext);

            // Message has been delivered and shouldn't be executed again.
            emit MessageDelivered(sourceImplementationIdentifier, sourceIdentifier, messageIdentifier);
            return receiveAckWithContext;
        }

        // Load the max gas.
        uint48 maxGas = uint48(bytes6(message[CTX0_MAX_GAS_LIMIT_START:CTX0_MAX_GAS_LIMIT_END]));

        // Execute call to application. Gas limit is set explicitly to ensure enough gas has been sent.

        // This call might fail because the abi.decode of the return value can fail. It is too gas costly to check co full correctness 
        // of the returned value and then error if decoding is not possible.
        // As a result, relayers needs to simulate the tx. If the call fails, then they should blacklist the message.
        // The call will only fall if the application doesn't expose receiveMessage or captures the message via a fallback. 
        // As a result, if message delivery once executed, then it will always execute.
        try ICrossChainReceiver(toApplication).receiveMessage{gas: maxGas}(sourceIdentifier, messageIdentifier, fromApplication, message[CTX0_MESSAGE_START: ])
        returns (bytes memory ack) {
            acknowledgement = ack;
        } catch (bytes memory /* err */) {
            // Check that enough gas was provided to the application. For further documentation of this statement, check
            // the long description on ack. TLDR: The relayer can cheat the application by providing less gas
            // but this statement ensures that if they try to do that, then it will fail (assuming the application reverts).
            if(gasleft() < maxGas * 1 / 63) revert NotEnoughGasExecution();

            // Send the message back if the execution failed.
            // This lets you store information in the message that you can trust gets returned.
            // (You just have to understand that the status is appended as the first byte.)
            acknowledgement = bytes.concat(
                MESSAGE_REVERTED,
                message[CTX0_MESSAGE_START: ]
            );
        }
        
        // Encode a new message to send back. This lets the relayer claim their payment.
        receiveAckWithContext = bytes.concat(
            bytes1(CTX_DESTINATION_TO_SOURCE), // Context
            messageIdentifier,  // message identifier
            fromApplication,
            feeRecipient,
            bytes6(uint48(gasLimit - gasleft())),  // Delay the gas limit computation until as late as possible. This should include the majority of gas spent.
            bytes8(uint64(block.timestamp)),  // If this overflows, it is fine. It is used in conjunction with a delta.
            acknowledgement
        );

        // Store a hash of the acknowledgement so we can later retry a potentially invalid ack proof.
        _messageDelivered[sourceIdentifier][sourceImplementationIdentifier][messageIdentifier] = keccak256(receiveAckWithContext);

        // Why is the messageDelivered event emitted before _sendPacket?
        // Because it lets us pop messageIdentifier from the stack. This avoid a stack limit reached error. 
        // Not optimal but okay-ish.

        // Emit event to inform relayers that the message has been delivered.
        emit MessageDelivered(sourceImplementationIdentifier, sourceIdentifier, messageIdentifier);
        // Send message to messaging protocol in processMessage.
        return receiveAckWithContext;
    }

    /**
     * @notice Handles ack messages (DESTINATION_TO_SOURCE).
     */
    function _handleAck(
        bytes32 destinationIdentifier,
        bytes memory destinationImplementationIdentifier,
        bytes calldata message,
        bytes32 feeRecipient,
        uint256 gasLimit
    ) internal {
        // Ensure the bounty can only be claimed once.
        bytes32 messageIdentifier = bytes32(message[MESSAGE_IDENTIFIER_START:MESSAGE_IDENTIFIER_END]);
        address fromApplication = address(bytes20(message[FROM_APPLICATION_START_EVM:FROM_APPLICATION_END]));

        // The 3 (9, loading the variables out of storage fills a bit.) next lines act as a reentry guard,
        // so this call doesn't have to be protected by reentry.
        IncentiveDescription storage incentive = _bounty[fromApplication][destinationIdentifier][messageIdentifier];
        // Load all variables from storage onto the stack.
        uint48 maxGasDelivery = incentive.maxGasDelivery;
        uint48 maxGasAck = incentive.maxGasAck;
        address refundGasTo = incentive.refundGasTo;
        uint96 priceOfDeliveryGas = incentive.priceOfDeliveryGas;
        uint96 priceOfAckGas = incentive.priceOfAckGas;
        uint64 targetDelta = incentive.targetDelta;

        // Ensure the bounty can only be claimed once. This call is matched on the timeout side,
        // so it also ensures that an ack cannot be delivered if a timeout has been seen.
        if (refundGasTo == address(0)) revert MessageAlreadyAcked();
        delete _bounty[fromApplication][destinationIdentifier][messageIdentifier];  // The bounty cannot be accessed anymore.


        // First check if the application trusts the implementation on the destination chain.
        bytes32 expectedDestinationImplementationHash = implementationAddressHash[fromApplication][destinationIdentifier];
        // Check that the application approves the source implementation
        // For acks, this should always be the case except when a fradulent applications sends a message to this contract.
        if (expectedDestinationImplementationHash != keccak256(destinationImplementationIdentifier)) revert InvalidImplementationAddress();

        // Deliver the ack to the application.
        // Ensure that if the call reverts it doesn't boil up.
        // We don't need any return values and don't care if the call reverts.
        // This call implies we need reentry protection.
        bytes memory payload = abi.encodeWithSignature("receiveAck(bytes32,bytes32,bytes)", destinationIdentifier, messageIdentifier, message[CTX1_MESSAGE_START: ]);
        bool success;
        assembly ("memory-safe") {
            // Because Solidity always create RETURNDATACOPY for external calls, even low-level calls where no variables are assigned,
            // the contract can be attacked by a so called return bomb. This incur additional cost to the relayer they aren't paid for.
            // To protect the relayer, the call is made in inline assembly.
            success := call(maxGasAck, fromApplication, 0, add(payload, 0x20), mload(payload), 0, 0)
            // This is what the call would look like non-assembly.
            // fromApplication.call{gas: maxGasAck}(
            //     abi.encodeWithSignature("receiveAck(bytes32,bytes32,bytes)", destinationIdentifier, messageIdentifier, message[CTX1_MESSAGE_START: ])
            // );
        }

        // External calls are allocated gas according roughly the following: min( gasleft * 63/64, gasArg ).
        // If there is no check against gasleft, then a relayer could potentially cheat by providing less gas.
        // Without a check, they only have to provide enough gas such that any further logic executees on 1/64 of gasleft
        // To ensure maximum compatibility with external tx simulation and gas estimation tools we will check a more complex
        // but more forgiving expression.
        // Before the call, there needs to be at least maxGasAck * 64/63 gas available. With that available, then
        // the call is allocated exactly min(+(maxGasAck * 64/63 * 63/64), maxGasAck) = maxGasAck.
        // If the call uses up all of the gas, then there must be maxGasAck * 64/63 - maxGasAck = maxGasAck * 1/63
        // gas left. It is sufficient to check that smaller limit rather than the larger limit.
        // Furthermore, if we only check when the call failed we don't have to read gasleft if it is not needed.
        unchecked {
            if (!success) if(gasleft() < maxGasAck * 1 / 63) revert NotEnoughGasExecution();
        }
        // Why is this better (than checking before)?
        // 1. We only have to check when the call failed. The vast majority of acks should not revert so it won't be checked.
        // 2. For the majority of applications it is going to be hold that: gasleft > rest of logic > maxGasAck * 1 / 63
        // and as such won't impact and execution/gas simuatlion/estimation libs.
        
        // Why is this worse?
        // 1. What if the application expected us to check that it got maxGasAck? It might assume that it gets
        // maxGasAck, when it turns out it got less it silently reverts (say by a low level call ala ours).

        // Get the gas used by the destination call.
        uint48 gasSpentOnDestination = uint48(bytes6(message[CTX1_GAS_SPENT_START:CTX1_GAS_SPENT_END]));

        (uint256 gasSpentOnSource, uint256 deliveryFee, uint256 ackFee) = _payoutIncentive(
            gasLimit,
            gasSpentOnDestination,
            maxGasDelivery,
            priceOfDeliveryGas,
            maxGasAck,
            priceOfAckGas,
            refundGasTo,
            address(uint160(uint256(bytes32(message[CTX1_RELAYER_RECIPIENT_START:CTX1_RELAYER_RECIPIENT_END])))),
            address(uint160(uint256(feeRecipient))),
            targetDelta,
            uint64(bytes8(message[CTX1_EXECUTION_TIME_START:CTX1_EXECUTION_TIME_END]))
        );

        emit MessageAcked(destinationImplementationIdentifier, destinationIdentifier, messageIdentifier);
        emit BountyClaimed(
            destinationImplementationIdentifier,
            destinationIdentifier,
            messageIdentifier,
            uint64(gasSpentOnDestination),
            uint64(gasSpentOnSource),
            uint128(deliveryFee),
            uint128(ackFee)
        );
    }

    /**
     * @notice Handles timeout messages.
     * @dev This function is very light. That is because it is intended to be used for both:
     * 1. Handling authentic timeouts from some AMBs.
     * 2. Handling returning timedout functions.
     * Before calling, check if the destination implementation is correct.
     */
    function _handleTimeout(
        bytes32 destinationIdentifier,
        bytes memory destinationImplementationIdentifier,
        bytes32 messageIdentifier,
        address fromApplication,
        bytes calldata applicationMessage,
        bytes32 feeRecipient,
        uint256 gasLimit
    ) internal {
        // The 3 (9, loading the variables out of storage fills a bit.) next lines act as a reentry guard,
        // so this call doesn't have to be protected by reentry.
        IncentiveDescription storage incentive = _bounty[fromApplication][destinationIdentifier][messageIdentifier];
        // Load all variables from storage onto the stack.
        uint48 maxGasDelivery = incentive.maxGasDelivery;
        uint48 maxGasAck = incentive.maxGasAck;
        address refundGasTo = incentive.refundGasTo;
        uint96 priceOfDeliveryGas = incentive.priceOfDeliveryGas;
        uint96 priceOfAckGas = incentive.priceOfAckGas;

        // Ensure the bounty can only be claimed once. This call is matched on the ack side,
        // so it also ensures that an ack cannot be delivered if a timeout has been seen.
        if (refundGasTo == address(0)) revert MessageAlreadyAcked();
        delete _bounty[fromApplication][destinationIdentifier][messageIdentifier];  // The bounty cannot be accessed anymore.

        // We delegate checking the if the destination implementation is correct to outside this contract.
        // This is done such that this function can be as light as possible.

        // Deliver the ack to the application.
        // Ensure that if the call reverts it doesn't boil up.
        // We don't need any return values and don't care if the call reverts.
        // This call implies we need reentry protection.
        bytes memory payload = abi.encodeWithSignature("receiveAck(bytes32,bytes32,bytes)", destinationIdentifier, messageIdentifier, bytes.concat(MESSAGE_TIMED_OUT, applicationMessage));
        bool success;
        assembly ("memory-safe") {
            // Because Solidity always create RETURNDATACOPY for external calls, even low-level calls where no variables are assigned,
            // the contract can be attacked by a so called return bomb. This incur additional cost to the relayer they aren't paid for.
            // To protect the relayer, the call is made in inline assembly.
            success := call(maxGasAck, fromApplication, 0, add(payload, 0x20), mload(payload), 0, 0)
            // This is what the call would look like non-assembly.
            // fromApplication.call{gas: maxGasAck}(
            //     abi.encodeWithSignature("receiveAck(bytes32,bytes32,bytes)", destinationIdentifier, messageIdentifier, abi.encodePacked(bytes1(0xfd), message[CTX0_MESSAGE_START: ]))
            // );
        }
        // Check that enough gas was provided to the application. For further documentation of this statement, check
        // the long description on ack. TLDR: The relayer can cheat the application by providing less gas
        // but this statement ensures that if they try to do that, then it will fail (assuming the application reverts).
        unchecked {
            if (!success) if(gasleft() < maxGasAck * 1 / 63) revert NotEnoughGasExecution();
        }

        (uint256 gasSpentOnSource, uint256 deliveryFee, uint256 ackFee) = _payoutIncentive(
            gasLimit,
            maxGasDelivery, // We set gas spent on destination as the entire allowance.
            maxGasDelivery,
            priceOfDeliveryGas,
            maxGasAck,
            priceOfAckGas,
            refundGasTo,
            address(uint160(uint256(feeRecipient))),
            address(uint160(uint256(feeRecipient))),
            0, // Disable target delta, since there is only 1 relayer.
            0
        );

        emit MessageTimedOut(destinationImplementationIdentifier, destinationIdentifier, messageIdentifier);
        emit BountyClaimed(
            destinationImplementationIdentifier,
            destinationIdentifier,
            messageIdentifier,
            uint64(maxGasDelivery),
            uint64(gasSpentOnSource),
            uint128(deliveryFee),
            uint128(ackFee)
        );
    }

    /**
     * @notice Verifies the input parameters are contained messageIdentfier and that the other arguments are valid.
     * The usage of this function is intended when no parameters of a message can be trusted and we have to verify them.
     * This is the case when we receive a timeout, as the timeout had to be emitted without any verification
     * on the remote chain, for us to then verify since we know when a message identifier is good AND how to compute it.
     *
     * @dev This function uses the fact that hash(a) == hash(b) IFF a == b. So if someone proposes b, we have hash(a)
     * then we can check if b == a by hashing b and comparing to a.
     * a is the initial state when the message was initiated and b is the proposed state from the timeout.
     *
     * When hash(a) is the message identifier, this allows us to verify authenticity by:
     *  1. The package is correctly formatted. The data within matches the message identifier.
     *  2. The remote implementation can verify that no package has previously been executed with that message identifier.
     *  3. If we check if the message identifier has a bounty, we must have emitted that message. (in _handleTimeout)
     */
    function _verifyTimeout(
        bytes32 destinationIdentifier,
        bytes memory implementationIdentifier,
        bytes calldata message
    ) internal view returns(bytes32 messageIdentifier, address fromApplication, bytes calldata applicationMessage) {
        // First check if the application trusts the implementation on the destination chain. This is very important
        // since the remote implementation NEEDS to check that the message hasn't been executed before the deadline
        // and if the message get relayed post deadline, then it should never arrive at the application.
        // Without those checks the whole concept of timeouts doesn't matter
        fromApplication = address(uint160(bytes20(message[FROM_APPLICATION_START_EVM:FROM_APPLICATION_END])));
        bytes32 expectedDestinationImplementationHash = implementationAddressHash[fromApplication][destinationIdentifier];
        // Check that the application approves of the remote implementation.
        // For timeouts, this could fail because of fradulent sender or bad data.
        if (expectedDestinationImplementationHash != keccak256(implementationIdentifier)) revert InvalidImplementationAddress();

        // Do we need to check deadline again?
        // Considering the cost: cheap, we will do it. In most instances it is not needed.
        // This is because we must expect the remote implementation to also do the check to save gas
        // since it is an obvious and valid check on the remote.
        uint64 deadline = uint64(bytes8(message[CTX2_DEADLINE_START:CTX2_DEADLINE_END]));
        if (deadline >= block.timestamp || deadline == 0) revert DeadlineNotPassed(deadline, uint64(block.timestamp));

        // The entirety of the incoming message is untrusted. So far we havn't done any verification of
        // the message but rather of the origin of the message.
        // As a result, we need to verify the rest of the message, specifically:
        // - MESSAGE_IDENTIFIER
        // - FROM_APPLICATION      \
        // - DEADLINE               \
        // - ORIGIN_BLOCK_NUMBER     > Message Identifier
        // - SOURCE_IDENTIFIER      /
        // - MESSAGE               /

        // We need to verify that the message identifier sent is correct because the messageIdentifier
        // should have been used to check if the message would have been executed before.
        // We can check if the message identifier is correct by checking the bounty. (See _handleTimeout)
        // However, we still need to check the rest of the information. The message identifier has been crafted
        // so it is dependent on the rest of the information we use.
        
        applicationMessage = message[CTX2_MESSAGE_START: ];

        // Lets compute the messageIdentifier based on the message.
        bytes32 computedMessageIdentifier = _getMessageIdentifier(
            fromApplication,
            deadline,
            uint256(bytes32(message[CTX2_ORIGIN_BLOCK_NUMBER_START:CTX2_ORIGIN_BLOCK_NUMBER_END])),
            _uniqueSourceIdentifier(),
            destinationIdentifier,
            applicationMessage
        );

        // Get the reference message identifier from the package. We need to verify this since it was used on the sending chain.
        messageIdentifier = bytes32(message[MESSAGE_IDENTIFIER_START:MESSAGE_IDENTIFIER_END]);
        if (computedMessageIdentifier != messageIdentifier) revert InvalidTimeoutPackage(messageIdentifier, computedMessageIdentifier);
    }

    /** 
     * @notice Payout incentives to the relayers.
     * @dev Timeouts needs to set targetDelta == 0 to cut off logic.
     */
    function _payoutIncentive(
        uint256 gasLimit,
        uint48 gasSpentOnDestination,
        uint48 maxGasDelivery,
        uint96 priceOfDeliveryGas,
        uint48 maxGasAck,
        uint96 priceOfAckGas,
        address refundGasTo,
        address destinationFeeRecipient,
        address sourceFeeRecipient,
        uint64 targetDelta,
        uint64 messageExecutionTimestamp
    ) internal returns(uint256 gasSpentOnSource, uint256 deliveryFee, uint256 ackFee) {

        // Find the respective rewards for delivery and ack.
        uint256 actualFee; uint256 refund;
        unchecked {
            // gasSpentOnDestination * priceOfDeliveryGas < 2**48 * 2**96 = 2**144
            if (maxGasDelivery <= gasSpentOnDestination) gasSpentOnDestination = maxGasDelivery;  // If more gas was spent then allocated, then only use the allocation.
            deliveryFee = gasSpentOnDestination * priceOfDeliveryGas;  
            // Delay the gas limit computation until as late as possible. This should include the majority of gas spent.
            // gasLimit = gasleft() when less gas was spent, thus it is always larger than gasleft().
            gasSpentOnSource = gasLimit - gasleft();
            if (maxGasAck <= gasSpentOnSource) gasSpentOnSource = maxGasAck;  // If more gas was spent then allocated, then only use the allocation.
            // gasSpentOnSource * priceOfAckGas < 2**48 * 2**96 = 2**144
            ackFee = gasSpentOnSource * priceOfAckGas;  
            // deliveryFee + ackFee < 2**144 + 2**144 = 2**145
            actualFee = deliveryFee + ackFee;
            // (priceOfDeliveryGas * maxGasDelivery + priceOfDeliveryGas * maxGasAck) has been caculated before (escrowBounty) < (2**48 * 2**96) + (2**48 * 2**96) = 2**144 + 2**144 = 2**145
            uint256 maxDeliveryFee = maxGasDelivery * priceOfDeliveryGas;
            uint256 maxAckFee = maxGasAck * priceOfAckGas;
            uint256 maxFee = maxDeliveryFee + maxAckFee;
            refund = maxFee - actualFee;
        }

        // send is used to ensure this doesn't revert. ".transfer" could revert and block the ack from ever being delivered.
        if(!payable(refundGasTo).send(refund)) {
            payable(SEND_LOST_GAS_TO).transfer(refund);  // If we don't send the gas somewhere, the gas is lost forever.
        }

        // If both the destination relayer and source relayer are the same then we don't have to figure out which fraction goes to who. For timeouts, logic should end here.
        if (destinationFeeRecipient == sourceFeeRecipient) {
            payable(sourceFeeRecipient).transfer(actualFee);  // If this reverts, then the relayer that is executing this tx provided a bad input.
            return (gasSpentOnSource, deliveryFee, ackFee);
        }

        // If targetDelta is 0, then distribute exactly the rewards.
        if (targetDelta == 0) {
            // ".send" is used to ensure this doesn't revert. ".transfer" could revert and block the ack from ever being delivered.
            if(!payable(destinationFeeRecipient).send(deliveryFee)) {  // If this returns false, it implies that the transfer failed.
                // The result is that this contract still has deliveryFee. As a result, send it somewhere else.
                payable(SEND_LOST_GAS_TO).transfer(deliveryFee);  // If we don't send the gas somewhere, the gas is lost forever.
            }
            Address.sendValue(payable(sourceFeeRecipient), ackFee); // If this reverts, then the relayer that is executing this tx provided a bad input.
            return (gasSpentOnSource, deliveryFee, ackFee);
        }

        // Compute the reward distribution. We need the time it took to deliver the ack back.
        uint64 executionTime;
        unchecked {
            // Overflow is desired in this code chuck. It ensures that the code piece continues working
            // past the time when uint64 stops working. *As long as any timedelta is less than uint64.
            executionTime = uint64(block.timestamp) - messageExecutionTimestamp;
            // Check if the overflow (/underflow) was because block.timestamp < messageExecutionTimestamp rather
            // than because block.timestamp has overflowed and messageExecutionTimestamp has now.
            // We do this by checking if executionTime is greater than an unrealistic period of time.
            // 32768 days is chosen since that is the neatest value close to the uint32 limit: 49710 days.
            // If this is the cause, we must assume that block.timestamp was slightly less than messageExecutionTimestamp
            // and an overflow happened and the execution time was set significantly too large as a result.
            // If this is true, then the delivery was quick (based on all available information) and the source to destination
            // should get everything.
            if (executionTime > 32768 days) executionTime = 0;
        }
        // The incentive scheme is as follows: When executionTime = targetDelta then
        // the rewards are distributed as per the incentive spec. If the time is less, then
        // more incentives are given to the destination relayer while if the time is more, 
        // then more incentives are given to the sourceRelayer.
        uint256 forDestinationRelayer = deliveryFee;
        unchecked {
            // |executionTime - targetDelta| < |2**64 + 2**64| = 2**65
            int256 timeBetweenTargetAndExecution = int256(uint256(executionTime)) - int256(uint256(targetDelta));
            if (timeBetweenTargetAndExecution <= 0) {
                // Less time than target passed and the destination relayer should get a larger chunk.
                // targetDelta != 0, we checked for that.
                // max abs timeBetweenTargetAndExecution = | - targetDelta| = targetDelta
                //                    => ackFee * targetDelta < actualFee * targetDelta < 2**127 * 2**64 = 2**191
                forDestinationRelayer += ackFee * uint256(- timeBetweenTargetAndExecution) / targetDelta;
            } else { // timeBetweenTargetAndExecution > 0
                // More time than target passed and the ack relayer should get a larger chunk.
                // If more time than double the target passed, the ack relayer should get everything
                if (uint256(timeBetweenTargetAndExecution) < targetDelta) {
                    // targetDelta != 0, we checked for that. 
                    // max abs timeBetweenTargetAndExecution = targetDelta from previous
                    //                    => deliveryFee * targetDelta < actualFee * targetDelta < 2**127 * 2**64 = 2**191
                    forDestinationRelayer -= deliveryFee * uint256(timeBetweenTargetAndExecution) / targetDelta;
                } else { 
                    // timeBetweenTargetAndExecution > targetDelta === executionTime - targetDelta > targetDelta === executionTime > 2 * targetDelta
                    // This doesn't discourage relaying, since executionTime first begins counting once the destination call has been executed.
                    // As a result, this only encourages delivery of the ack.
                    forDestinationRelayer = 0;
                }
            }
        }
        // send is used to ensure this doesn't revert. ".transfer" could revert and block the ack from ever being delivered.
        if(!payable(destinationFeeRecipient).send(forDestinationRelayer)) {
            payable(SEND_LOST_GAS_TO).transfer(forDestinationRelayer);  // If we don't send the gas somewhere, the gas is lost forever.
        }
        uint256 forSourceRelayer;
        unchecked {
            // max forDestinationRelayer is deliveryFee + ackFee = actualFee => actualFee - forDestinationRelayer == 0
            // min forDestinationRelayer = 0 => actualFee - 0 = actualFee
            forSourceRelayer = actualFee - forDestinationRelayer;
        }
        Address.sendValue(payable(sourceFeeRecipient), forSourceRelayer); // If this reverts, then the relayer that is executing this tx provided a bad input.

        return (gasSpentOnSource, forDestinationRelayer, forSourceRelayer);
    }

    /** 
     * @notice Sets a bounty for a message
     * @dev Does not check if enough incentives have been provided, this is delegated as responsiblity 
     * of the caller of this function.
     * @param fromApplication The application that called the contract. Should generally be msg.sender. Is used to separate storage between applications.
     * @param destinationIdentifier The destination chain. Combined with fromApplication, this specifics a unique remote escrow implementation.
     * @param messageIdentifier A unique identifier for the message. Is used to check if bounties have been paid, on ack and timeout.
     * @param incentive The incentive structure. ".refundGasTo" is not allowed to be address(0).
     *
     * @return sum The total cost of the bounty. It not checked against msg.value in this contract.
     */
    function _setBounty(
        address fromApplication,
        bytes32 destinationIdentifier,
        bytes32 messageIdentifier, 
        IncentiveDescription calldata incentive
    ) internal returns(uint128 sum) {
        if (_bounty[fromApplication][destinationIdentifier][messageIdentifier].refundGasTo != address(0)) revert MessageAlreadyBountied();
        // Compute incentive metrics.
        uint128 maxDeliveryFee = incentive.maxGasDelivery * incentive.priceOfDeliveryGas;
        uint128 maxAckFee = incentive.maxGasAck * incentive.priceOfAckGas;
        sum = maxDeliveryFee + maxAckFee;
        
        _bounty[fromApplication][destinationIdentifier][messageIdentifier] = incentive;
    }

    /**
     * @notice Allows anyone to re-execute an ack which didn't properly execute.
     * @dev No applciation should rely on this function. It should only be used incase an application has faulty logic. 
     * Example: Faulty logic results in wrong enforcement on gas limit => out of gas?
     *
     * This function allows replaying acks.
     *
     * For further parameter documentation, read processPacket.
     * @param messagingProtocolContext Argument that once made _verifyPacket pass on processPacket
     * @param rawMessage Argument that once made _verifyPacket pass on processPacket.
     */
    function recoverAck(
        bytes calldata messagingProtocolContext,
        bytes calldata rawMessage
    ) external {
        // onRecv. implementations should collect acks so _verifyPacket returns true after first execution of the ack.
        (bytes32 chainIdentifier,  bytes memory implementationIdentifier, bytes calldata message) = _verifyPacket(messagingProtocolContext, rawMessage);

        bytes1 context = bytes1(message[0]);
        
        // Only allow acks to do this. Normal messages are invalid after first execution.
        if (context == CTX_DESTINATION_TO_SOURCE) {
            bytes32 messageIdentifier = bytes32(message[MESSAGE_IDENTIFIER_START:MESSAGE_IDENTIFIER_END]);
            address fromApplication = address(bytes20(message[FROM_APPLICATION_START_EVM:FROM_APPLICATION_END]));
            if(_bounty[fromApplication][chainIdentifier][messageIdentifier].refundGasTo != address(0)) revert AckHasNotBeenExecuted();
            
            // check if the application trusts the implementation on the destination chain.
            bytes32 expectedDestinationImplementationHash = implementationAddressHash[fromApplication][chainIdentifier];
            if (expectedDestinationImplementationHash != keccak256(implementationIdentifier)) revert InvalidImplementationAddress();
            ICrossChainReceiver(fromApplication).receiveAck(chainIdentifier, messageIdentifier, message[CTX1_MESSAGE_START: ]);
            emit MessageAcked(implementationIdentifier, chainIdentifier, messageIdentifier);
        } else {
            revert NotImplementedError();
        }
    }

    /** 
     * @notice Emit a new ack message incase the proof for the old got lost.
     * This function is intended for manual usage in case the ack was critical to the application
     * and the ack proof expired.
     * @dev If an AMB controls the entire flow of the message, disable this function.
     * @param sourceIdentifier Which chain to send the ack to? Is checked against stored ack hash to ensure
     * the message can only be sent to the correct source chain.
     * @param implementationIdentifier Which escrow contract to send the ack to? Is checked against stored ack hash
     * to ensure the message can only be sent to the original implementation.
     * @param receiveAckWithContext The message as this contract delivered to _sendMessage via processMessage.
     */
    function reemitAckMessage(
        bytes32 sourceIdentifier,
        bytes calldata implementationIdentifier,
        bytes calldata receiveAckWithContext
    ) external payable virtual {
        // Has the package previously been executed? (otherwise timeout might be more appropiate)

        // Load the messageIdentifier from receiveAckWithContext.
        // This makes it slighly easier to retry messages.
        bytes32 messageIdentifier = bytes32(receiveAckWithContext[MESSAGE_IDENTIFIER_START:MESSAGE_IDENTIFIER_END]);

        bytes32 storedAckHash = _messageDelivered[sourceIdentifier][implementationIdentifier][messageIdentifier];
        // First, check if there is actually an appropiate hash at the message identifier.
        // Then, check if the storedAckHash & the source target (sourceIdentifier & implementationIdentifier) matches the executed one.
        if (storedAckHash == bytes32(0) || storedAckHash != keccak256(receiveAckWithContext)) revert CannotRetryWrongMessage(storedAckHash, keccak256(receiveAckWithContext));

        // Send the package again.
        uint128 cost = _sendPacket(sourceIdentifier, implementationIdentifier, receiveAckWithContext, 0);

        // Check if there is a mis-match between the cost and the value of the message.
        if (uint128(msg.value) != cost) {
            if (uint128(msg.value) > cost) {
                // Send the unused gas back to the the user.
                Address.sendValue(payable(msg.sender), msg.value - uint256(cost));
                return;
            }
            revert NotEnoughGasProvided(uint128(msg.value), cost);
        }
    }

    /**
     * @notice This function will timeout a message.
     * If a message has been executed but the proof for the ack might have been lost
     * then the message can be retried.
     * If a message has not been executed and the message is beyond timeout, then it can be
     * timed out. The intended usecase for this function is the latter case AND when the proof is lost.
     * If the proof is intact, delivering the proof normally is safer.
     * @dev If an AMB has a native way to timeout messages, disable this function.
     * The reason why we don't verify that the message is contained within the message identifier
     * is because we don't know where the messageIdentifier was computed and don't know what hashing function was used
     * As a result, it is expected that the sender of this function checks for inclusion manually, otherwise they could
     * waste a lot of gas.
     * There is no reliable way to block this function such that it can't be called twice after a message has been timed out
     * since the content could we wrong or the proof may still exist.
     * @param sourceIdentifier The identifier for the source chain (where to send the message)
     * @param implementationIdentifier The address of the source generalisedIncentives that emitted the original message
     * @param originBlockNumber The block number when the message was originally emitted. 
     * Note that for some L2 this could be the block number of the underlying chain. 
     * Regardless: It is the same block number that originally generated themessage identifier.
     * @param message Original Generalised Incentives message
     */
    function timeoutMessage(
        bytes32 sourceIdentifier,
        bytes calldata implementationIdentifier,
        uint256 originBlockNumber,
        bytes calldata message
    ) external payable virtual {
        //! When reading this function, it is important to remember that 'message' is
        // entirely untrusted. We do no verification on it. As a result, we shouldn't
        // trust any data within it. It is first when this message hits the source chain we can begin to verify data.

        // Check that at least the context is set correctly.
        if (message[CONTEXT_POS] != CTX_SOURCE_TO_DESTINATION) revert MessageHasInvalidContext();

        // Get the message identifier from the message.
        bytes32 messageIdentifier = bytes32(message[MESSAGE_IDENTIFIER_START:MESSAGE_IDENTIFIER_END]);
        // Read the status of the package at MessageIdentifier.
        bytes32 storedAckHash = _messageDelivered[sourceIdentifier][implementationIdentifier][messageIdentifier];
        // If has already been processed, then don't allow timeouting the message. Instead, it should be retried.
        if (storedAckHash != bytes32(0)) revert MessageAlreadyProcessed();
        // This also protects a relayer that delivered a timedout message.
        // ! It could still be that someone delivers the "true" message along with the proof after this has been emitted!
        // As a result, the above check only ensures that if the message properly arrives, then this cannot be called afterwards.
        // ensuring that the original relayer isn't cheated.
        // When the message arrives, the usual incentive check ensures only 1 message can arrive. Since the incentive check is based on
        // messageIdentifier, we need to verify it.
        // Remember, the messageIdentifier is actually untrusted. So it is trivial to pass the above check. However, any way to pass
        // the above check fradulently would result in messageIdentifier being wrong and unable to be reproduced on the source chain.

        // Load the deadline from the message.
        uint64 deadline = uint64(bytes8(message[CTX0_DEADLINE_START:CTX0_DEADLINE_END]));

        // Check that the deadline has passed AND that there is no opt out.
        // This isn't a strong check but if a relayer is honest, then it can be used as a sanity check.
        // This protects against emitting rouge messages of timeout before the message has had a time to execute IF deadline belong to messageIdentifier.
        if (deadline == 0 || deadline >= block.timestamp) revert DeadlineNotPassed(deadline, uint64(block.timestamp));

        // Reconstruct message
        bytes memory receiveAckWithContext = bytes.concat(
            CTX_TIMEDOUT_ON_DESTINATION,
            messageIdentifier,
            message[FROM_APPLICATION_LENGTH_POS:FROM_APPLICATION_END],
            bytes8(deadline),
            bytes32(originBlockNumber),
            message[CTX0_MESSAGE_START: ]
        );

        // To maintain a common implementation language, emit our event before message.
        emit TimeoutInitiated(implementationIdentifier, sourceIdentifier, messageIdentifier);

        // Send the message
        uint128 cost = _sendPacket(
            sourceIdentifier,
            implementationIdentifier,
            receiveAckWithContext,
            0
        );

        // Check if there is a mis-match between the cost and the value of the message.
        if (uint128(msg.value) != cost) {
            if (uint128(msg.value) > cost) {
                // Send the unused gas back to the the user.
                Address.sendValue(payable(msg.sender), msg.value - uint256(cost));
                return;
            }
            revert NotEnoughGasProvided(uint128(msg.value), cost);
        }
    }
}

File 3 of 18 : SmallStructs.sol
// SPDX-License-Identifier: Apache 2

pragma solidity ^0.8.0;

interface SmallStructs {

	struct SmallVM {
		// uint8 version;
		// uint32 timestamp;
		// uint32 nonce;
		uint16 emitterChainId;
		bytes32 emitterAddress;
		// uint64 sequence;
		// uint8 consistencyLevel;

		uint32 guardianSetIndex;
	}
}

File 4 of 18 : WormholeVerifier.sol
// SPDX-License-Identifier: Apache 2

pragma solidity ^0.8.0;

import "./GettersGetter.sol";
import "../wormhole/Structs.sol";
import "./SmallStructs.sol";
import "../wormhole/libraries/external/BytesLib.sol";


/**
 * @notice Optimised message verifier for Wormhole
 * @dev Is based on the Wormhole verification library.
 */
contract WormholeVerifier is GettersGetter {
    using BytesLib for bytes;

    error InvalidSignatory();
    error SignatureIndicesNotAscending();
    error GuardianIndexOutOfBounds();
    error VMVersionIncompatible();
    error TooManyGuardians();

    constructor(address wormholeState) payable GettersGetter(wormholeState) {}

    /// @dev parseAndVerifyVM serves to parse an encodedVM and wholy validate it for consumption
    function parseAndVerifyVM(bytes calldata encodedVM) public view returns (
        SmallStructs.SmallVM memory vm,
        bytes calldata payload,
        bool valid,
        string memory reason
    ) {
        bytes calldata signatures;
        bytes32 bodyHash;
        (vm, signatures, bodyHash, payload) = parseVM(encodedVM);
        /// setting checkHash to false as we can trust the hash field in this case given that parseVM computes and then sets the hash field above
        (valid, reason) = verifyVMInternal(vm, signatures, bodyHash);
    }

    /**
    * @dev `verifyVMInternal` serves to validate an arbitrary vm against a valid Guardian set
    * if checkHash is set then the hash field of the vm is verified against the hash of its contents
    * in the case that the vm is securely parsed and the hash field can be trusted, checkHash can be set to false
    * as the check would be redundant
    */
    function verifyVMInternal(
        SmallStructs.SmallVM memory vm,
        bytes calldata signatures,
        bytes32 bodyHash
    ) internal view returns (bool valid, string memory reason) {
        /// @dev Obtain the current guardianSet for the guardianSetIndex provided
        Structs.GuardianSet memory guardianSet = getGuardianSet(vm.guardianSetIndex);
        
       /**
        * @dev Checks whether the guardianSet has zero keys
        * WARNING: This keys check is critical to ensure the guardianSet has keys present AND to ensure
        * that guardianSet key size doesn't fall to zero and negatively impact quorum assessment.  If guardianSet
        * key length is 0 and vm.signatures length is 0, this could compromise the integrity of both vm and
        * signature verification.
        */
        if(guardianSet.keys.length == 0){
            return (false, "invalid guardian set");
        }

        /// @dev Checks if VM guardian set index matches the current index (unless the current set is expired).
        if (guardianSet.expirationTime < block.timestamp) {
            if (vm.guardianSetIndex != getCurrentGuardianSetIndex()) {
                return (false, "guardian set has expired");
            }
        }

       /**
        * @dev We're using a fixed point number transformation with 1 decimal to deal with rounding.
        *   WARNING: This quorum check is critical to assessing whether we have enough Guardian signatures to validate a VM
        *   if making any changes to this, obtain additional peer review. If guardianSet key length is 0 and
        *   vm.signatures length is 0, this could compromise the integrity of both vm and signature verification.
        */
        if (signatures.length < quorum(guardianSet.keys.length)){
            return (false, "no quorum");
        }

        /// @dev Verify the proposed vm.signatures against the guardianSet
        (bool signaturesValid, string memory invalidReason) = verifySignatures(bodyHash, signatures, guardianSet);
        if(!signaturesValid){
            return (false, invalidReason);
        }

        /// If we are here, we've validated the VM is a valid multi-sig that matches the guardianSet.
        return (true, "");
    }


    /**
     * @dev verifySignatures serves to validate arbitrary sigatures against an arbitrary guardianSet
     *  - it intentionally does not solve for expectations within guardianSet (you should use verifyVM if you need these protections)
     *  - it intentioanlly does not solve for quorum (you should use verifyVM if you need these protections)
     *  - it intentionally returns true when signatures is an empty set (you should use verifyVM if you need these protections)
     */
    function verifySignatures(bytes32 hash, bytes calldata signatures, Structs.GuardianSet memory guardianSet) public pure returns (bool valid, string memory reason) {
        uint8 lastIndex = 0;
        uint256 guardianCount = guardianSet.keys.length;
        uint256 signersLen = uint8(bytes1(signatures[0]));
        uint256 index = 1;
        unchecked {
        for (uint i = 0; i < signersLen; ++i) {
            uint8 guardianIndex = uint8(bytes1(signatures[index]));
            index += 1;
            bytes32 r = bytes32(signatures[index: index + 32]);
            index += 32;
            bytes32 s = bytes32(signatures[index: index + 32]);
            index += 32;
            uint8 v = uint8(bytes1(signatures[index: index + 1])) + 27;
            index += 1;
            address signatory = ecrecover(hash, v, r, s);
            // ecrecover returns 0 for invalid signatures. We explicitly require valid signatures to avoid unexpected
            // behaviour due to the default storage slot value also being 0.
             if (signatory == address(0)) revert InvalidSignatory();

            /// Ensure that provided signature indices are ascending only
            if(!(i == 0 || guardianIndex > lastIndex)) revert SignatureIndicesNotAscending();
            lastIndex = guardianIndex;

            /// @dev Ensure that the provided signature index is within the
            /// bounds of the guardianSet. This is implicitly checked by the array
            /// index operation below, so this check is technically redundant.
            /// However, reverting explicitly here ensures that a bug is not
            /// introduced accidentally later due to the nontrivial storage
            /// semantics of solidity.
            if (guardianIndex >= guardianCount) revert GuardianIndexOutOfBounds();

            /// Check to see if the signer of the signature does not match a specific Guardian key at the provided index
            if(signatory != guardianSet.keys[guardianIndex]){
                return (false, "VM signature invalid");
            }
        }

        /// If we are here, we've validated that the provided signatures are valid for the provided guardianSet
        return (true, "");
        }
    }

    /**
     * @dev parseVM serves to parse an encodedVM into a vm struct
     *  - it intentionally performs no validation functions, it simply parses raw into a struct
     */
    function parseVM(bytes calldata encodedVM) public view virtual returns (SmallStructs.SmallVM memory vm, bytes calldata signatures, bytes32 bodyHash, bytes calldata payload) {
        unchecked {
            
        
        uint index = 0;

        uint8 version = uint8(bytes1(encodedVM[0:1]));
        
        index += 1;
        
        // SECURITY: Note that currently the VM.version is not part of the hash 
        // and for reasons described below it cannot be made part of the hash. 
        // This means that this field's integrity is not protected and cannot be trusted. 
        // This is not a problem today since there is only one accepted version, but it 
        // could be a problem if we wanted to allow other versions in the future. 
        if(version != 1) revert VMVersionIncompatible();

        vm.guardianSetIndex = uint32(bytes4(encodedVM[1:4+1]));
        index += 4;
        

        // Parse Signatures
        uint256 signersLen = uint8(bytes1(encodedVM[5:5+1]));
        signatures = encodedVM[5:5 + 1 + signersLen*(1+32+32+1)];
        index += 1 + signersLen*(1+32+32+1);
        // signatures = new Structs.Signature[](signersLen);
        // for (uint i = 0; i < signersLen; ++i) {
        //     signatures[i].guardianIndex = uint8(bytes1(encodedVM[index:index+1]));
        //     index += 1;

        //     signatures[i].r = bytes32(encodedVM[index:index+32]);
        //     index += 32;
        //     signatures[i].s = bytes32(encodedVM[index:index+32]);
        //     index += 32;
        //     signatures[i].v = uint8(bytes1(encodedVM[index:index+1])) + 27;
        //     index += 1;
        // }
        
        /*
        Hash the body

        SECURITY: Do not change the way the hash of a VM is computed! 
        Changing it could result into two different hashes for the same observation. 
        But xDapps rely on the hash of an observation for replay protection.
        */
        bytes calldata body = encodedVM[index:];
        bodyHash = keccak256(bytes.concat(keccak256(body)));

        // Parse the body
        // vm.timestamp = uint32(bytes4(encodedVM[index:index+4]));
        index += 4;

        // vm.nonce = uint32(bytes4(encodedVM[index:index+4]));
        index += 4;

        vm.emitterChainId = uint16(bytes2(encodedVM[index:index+2]));
        index += 2;

        vm.emitterAddress = bytes32(encodedVM[index:index+32]);
        index += 32;

        // vm.sequence = uint64(bytes8(encodedVM[index:index+8]));
        index += 8;

        // vm.consistencyLevel = uint8(bytes1(encodedVM[index:index+1]));
        index += 1;

        payload = encodedVM[index:];
        }
    }

    /**
     * @dev quorum serves solely to determine the number of signatures required to acheive quorum
     */
    function quorum(uint numGuardians) public pure virtual returns (uint numSignaturesRequiredForQuorum) {
        unchecked {
            
        // The max number of guardians is 255
        if (numGuardians >= 256) revert TooManyGuardians();
        return ((numGuardians * 2) / 3) + 1;
        
        }
    }
}

File 5 of 18 : IWormhole.sol
// contracts/Messages.sol
// SPDX-License-Identifier: Apache 2

pragma solidity ^0.8.0;

interface IWormhole {
    struct GuardianSet {
        address[] keys;
        uint32 expirationTime;
    }

    struct Signature {
        bytes32 r;
        bytes32 s;
        uint8 v;
        uint8 guardianIndex;
    }

    struct VM {
        uint8 version;
        uint32 timestamp;
        uint32 nonce;
        uint16 emitterChainId;
        bytes32 emitterAddress;
        uint64 sequence;
        uint8 consistencyLevel;
        bytes payload;

        uint32 guardianSetIndex;
        Signature[] signatures;

        bytes32 hash;
    }

    struct ContractUpgrade {
        bytes32 module;
        uint8 action;
        uint16 chain;

        address newContract;
    }

    struct GuardianSetUpgrade {
        bytes32 module;
        uint8 action;
        uint16 chain;

        GuardianSet newGuardianSet;
        uint32 newGuardianSetIndex;
    }

    struct SetMessageFee {
        bytes32 module;
        uint8 action;
        uint16 chain;

        uint256 messageFee;
    }

    struct TransferFees {
        bytes32 module;
        uint8 action;
        uint16 chain;

        uint256 amount;
        bytes32 recipient;
    }

    struct RecoverChainId {
        bytes32 module;
        uint8 action;

        uint256 evmChainId;
        uint16 newChainId;
    }

    event LogMessagePublished(address indexed sender, uint64 sequence, uint32 nonce, bytes payload, uint8 consistencyLevel);
    event ContractUpgraded(address indexed oldContract, address indexed newContract);
    event GuardianSetAdded(uint32 indexed index);

    function publishMessage(
        uint32 nonce,
        bytes memory payload,
        uint8 consistencyLevel
    ) external payable returns (uint64 sequence);

    function initialize() external;

    function parseAndVerifyVM(bytes calldata encodedVM) external view returns (VM memory vm, bool valid, string memory reason);

    function verifyVM(VM memory vm) external view returns (bool valid, string memory reason);

    function verifySignatures(bytes32 hash, Signature[] memory signatures, GuardianSet memory guardianSet) external pure returns (bool valid, string memory reason);

    function parseVM(bytes memory encodedVM) external pure returns (VM memory vm);

    function quorum(uint numGuardians) external pure returns (uint numSignaturesRequiredForQuorum);

    function getGuardianSet(uint32 index) external view returns (GuardianSet memory);

    function getCurrentGuardianSetIndex() external view returns (uint32);

    function getGuardianSetExpiry() external view returns (uint32);

    function governanceActionIsConsumed(bytes32 hash) external view returns (bool);

    function isInitialized(address impl) external view returns (bool);

    function chainId() external view returns (uint16);

    function isFork() external view returns (bool);

    function governanceChainId() external view returns (uint16);

    function governanceContract() external view returns (bytes32);

    function messageFee() external view returns (uint256);

    function evmChainId() external view returns (uint256);

    function nextSequence(address emitter) external view returns (uint64);

    function parseContractUpgrade(bytes memory encodedUpgrade) external pure returns (ContractUpgrade memory cu);

    function parseGuardianSetUpgrade(bytes memory encodedUpgrade) external pure returns (GuardianSetUpgrade memory gsu);

    function parseSetMessageFee(bytes memory encodedSetMessageFee) external pure returns (SetMessageFee memory smf);

    function parseTransferFees(bytes memory encodedTransferFees) external pure returns (TransferFees memory tf);

    function parseRecoverChainId(bytes memory encodedRecoverChainId) external pure returns (RecoverChainId memory rci);

    function submitContractUpgrade(bytes memory _vm) external;

    function submitSetMessageFee(bytes memory _vm) external;

    function submitNewGuardianSet(bytes memory _vm) external;

    function submitTransferFees(bytes memory _vm) external;

    function submitRecoverChainId(bytes memory _vm) external;
}

File 6 of 18 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     *
     * Furthermore, `isContract` will also return true if the target contract within
     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
     * which only has an effect at the end of a transaction.
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

File 7 of 18 : IIncentivizedMessageEscrow.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import { IMessageEscrowStructs } from "./IMessageEscrowStructs.sol";
import { IMessageEscrowErrors } from "./IMessageEscrowErrors.sol";
import { IMessageEscrowEvents } from "./IMessageEscrowEvents.sol";

interface IIncentivizedMessageEscrow is IMessageEscrowStructs, IMessageEscrowErrors, IMessageEscrowEvents {
   function bounty(address fromApplication, bytes32 destinationIdentifier, bytes32 messageIdentifier) external view returns(IncentiveDescription memory incentive);

   function messageDelivered(bytes32 sourceIdentifier, bytes calldata sourceImplementationIdentifier, bytes32 messageIdentifier) external view returns(bytes32 hasMessageBeenExecuted);

    function increaseBounty(
        address fromApplication,
        bytes32 destinationIdentifier,
        bytes32 messageIdentifier,
        uint96 priceOfDeliveryGas,
        uint96 priceOfAckGas
    ) external payable;

    function submitMessage(
        bytes32 destinationIdentifier,
        bytes calldata destinationAddress,
        bytes calldata message,
        IncentiveDescription calldata incentive,
        uint64 deadline
    ) external payable returns(uint256 gasRefund, bytes32 messageIdentifier);

    function processPacket(bytes calldata messagingProtocolContext, bytes calldata message, bytes32 feeRecipient) payable external;

    function setRemoteImplementation(bytes32 chainIdentifier, bytes calldata implementation) external;

    /**
     * @notice Estimates the additional cost to the messaging router to validate the message
     * @return asset The asset the token is in. If native token, returns address(0);
     * @return amount The number of assets to pay.
     */
    function estimateAdditionalCost() external view returns(address asset, uint256 amount);

    function timeoutMessage(
        bytes32 sourceIdentifier,
        bytes calldata implementationIdentifier,
        uint256 originBlockNumber,
        bytes calldata message
    ) external payable;

    function reemitAckMessage(
        bytes32 sourceIdentifier,
        bytes calldata implementationIdentifier,
        bytes calldata receiveAckWithContext
    ) external payable;
}

File 8 of 18 : ICrossChainReceiver.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

interface ICrossChainReceiver {
    /**
     * @notice Handles the acknowledgement from the destination
     * @dev acknowledgement is exactly the output of receiveMessage except if receiveMessage failed, then it is error code (0xff or 0xfe) + original message.
     * If an acknowledgement isn't needed, this can be implemented as {}.
     * - This function can be called by someone else again! Ensure that if this endpoint is called twice with the same message nothing bad happens.
     * - If the application expects that the maxGasAck will be provided, then it should check that it got enough and revert if it didn't.
     * Otherwise, it is assumed that you didn't need the extra gas.
     * @param destinationIdentifier An identifier for the destination chain.
     * @param messageIdentifier A unique identifier for the message. The identifier matches the identifier returned when escrowed the message.
     * This identifier can be mismanaged by the messaging protocol.
     * @param acknowledgement The acknowledgement sent back by receiveMessage. Is 0xff if receiveMessage reverted.
     */
    function receiveAck(bytes32 destinationIdentifier, bytes32 messageIdentifier, bytes calldata acknowledgement) external;

    /**
     * @notice receiveMessage from a cross-chain call.
     * @dev The application needs to check the fromApplication combined with sourceIdentifierbytes to figure out if the call is authenticated.
     * - If the application expects that the maxGasDelivery will be provided, then it should check that it got enough and revert if it didn't.
     * Otherwise, it is assumed that you didn't need the extra gas.
     * @return acknowledgement Information which is passed to receiveAck. 
     *  If you return 0xff, you cannot know the difference between Executed but "failed" and outright failed.
     */
    function receiveMessage(bytes32 sourceIdentifierbytes, bytes32 messageIdentifier, bytes calldata fromApplication, bytes calldata message) external returns(bytes memory acknowledgement);
}

File 9 of 18 : Bytes65.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;

contract Bytes65 {
    error InvalidBytes65Address();

    function _checkBytes65(bytes calldata supposedlyBytes65) internal pure returns(bool) {
        return supposedlyBytes65.length == 65;
    }

    modifier checkBytes65Address(bytes calldata supposedlyBytes65) {
        if (!_checkBytes65(supposedlyBytes65)) revert InvalidBytes65Address();
        _;
    }

    function convertEVMTo65(address evmAddress) public pure returns(bytes memory) {
        return bytes.concat(
            bytes1(uint8(20)),                      // Size of address. Is always 20 for EVM
            bytes32(0),                             // First 32 bytes on EVM are 0
            bytes32(uint256(uint160((evmAddress)))) // Encode the address in bytes32.
        );
    }

    function thisBytes65() public view returns(bytes memory) {
        return convertEVMTo65(address(this));
    }
}

File 10 of 18 : MessagePayload.sol
//SPDX-License-Identifier: MIT

pragma solidity ^0.8.22;

// IncentivizedMessageEscrow Payload***********************************************************************************************
//
// Common Payload (beginning)
//    CONTEXT                           0   (1 byte)
//    + MESSAGE_IDENTIFIER              1   (32 bytes)
//    + FROM_APPLICATION_LENGTH         33  (1 byte)
//    + FROM_APPLICATION                34  (64 bytes)
// 
// Context-depending Payload
//    CTX0 - 0x00 - Source to Destination
//      + TO_APPLICATION_LENGTH         98  (1 byte)
//      + TO_APPLICATION                99  (64 bytes)
//      + DEADLINE                      163 (8 bytes)
//      + MAX_GAS                       171 (6 bytes)
//     => MESSAGE_START                 177 (remainder)
//
//    CTX1 - 0x01 - Destination to Source
//      + RELAYER_RECIPIENT             98  (32 bytes)
//      + GAS_SPENT                     130 (6 bytes)
//      + EXECUTION_TIME                136 (8 bytes)
//     => MESSAGE_START                 144 (remainder)
//
//    CTX2 - 0x02 - Timed Out on Destination
//      + DEADLINE                      98 (8 bytes)
//      + ORIGIN_BLOCKNUMER             106 (32 bytes)
//     => MESSAGE_START                 138 (remainder)


// Contexts *********************************************************************************************************************

bytes1 constant CTX_SOURCE_TO_DESTINATION       = 0x00;
bytes1 constant CTX_DESTINATION_TO_SOURCE       = 0x01;
bytes1 constant CTX_TIMEDOUT_ON_DESTINATION     = 0x02;


// Common Payload ***************************************************************************************************************

uint constant CONTEXT_POS                       = 0;

uint constant MESSAGE_IDENTIFIER_START          = 1;
uint constant MESSAGE_IDENTIFIER_END            = 33;

uint constant FROM_APPLICATION_LENGTH_POS       = 33;
uint constant FROM_APPLICATION_START            = 34;
uint constant FROM_APPLICATION_START_EVM        = 78;  // If the address is an EVM address, this is the start
uint constant FROM_APPLICATION_END              = 98;


// CTX0 Source to Destination ******************************************************************************************************

uint constant CTX0_TO_APPLICATION_LENGTH_POS        = 98;
uint constant CTX0_TO_APPLICATION_START             = 99;
uint constant CTX0_TO_APPLICATION_START_EVM         = 143;  // If the address is an EVM address, this is the start
uint constant CTX0_TO_APPLICATION_END               = 163;

uint constant CTX0_DEADLINE_START                   = 163;
uint constant CTX0_DEADLINE_END                     = 171;

uint constant CTX0_MAX_GAS_LIMIT_START              = 171;
uint constant CTX0_MAX_GAS_LIMIT_END                = 177;

uint constant CTX0_MESSAGE_START                    = 177;

// CTX1 Destination to Source **************************************************************************************************

uint constant CTX1_RELAYER_RECIPIENT_START          = 98;
uint constant CTX1_RELAYER_RECIPIENT_END            = 130;

uint constant CTX1_GAS_SPENT_START                  = 130;
uint constant CTX1_GAS_SPENT_END                    = 136;

uint constant CTX1_EXECUTION_TIME_START             = 136;
uint constant CTX1_EXECUTION_TIME_END               = 144;

uint constant CTX1_MESSAGE_START                    = 144;

// CTX2 Message Timed out **************************************************************************************************

uint constant CTX2_DEADLINE_START                   = 98;
uint constant CTX2_DEADLINE_END                     = 106;

uint constant CTX2_ORIGIN_BLOCK_NUMBER_START        = 106;
uint constant CTX2_ORIGIN_BLOCK_NUMBER_END          = 138;

uint constant CTX2_MESSAGE_START                    = 138;

File 11 of 18 : GettersGetter.sol
// contracts/Getters.sol
// SPDX-License-Identifier: Apache 2

pragma solidity ^0.8.0;

import "../wormhole/Getters.sol";

contract GettersGetter {
    error WormholeStateAddressZero();
    
    Getters immutable internal WORMHOLE_STATE;

    constructor(address wormholeState) payable {
        if (wormholeState == address(0)) revert WormholeStateAddressZero();
        WORMHOLE_STATE = Getters(wormholeState);
    }

    function getGuardianSet(uint32 index) public view returns (Structs.GuardianSet memory) {
        return WORMHOLE_STATE.getGuardianSet(index);
    }

    function getCurrentGuardianSetIndex() public view returns (uint32) {
        return WORMHOLE_STATE.getCurrentGuardianSetIndex();
    }

    function getGuardianSetExpiry() public view returns (uint32) {
        return WORMHOLE_STATE.getGuardianSetExpiry();
    }

    function governanceActionIsConsumed(bytes32 hash) public view returns (bool) {
        return WORMHOLE_STATE.governanceActionIsConsumed(hash);
    }

    function isInitialized(address impl) public view returns (bool) {
        return WORMHOLE_STATE.isInitialized(impl);
    }

    function chainId() public view returns (uint16) {
        return WORMHOLE_STATE.chainId();
    }

    function evmChainId() public view returns (uint256) {
        return WORMHOLE_STATE.evmChainId();
    }

    function isFork() public view returns (bool) {
        return WORMHOLE_STATE.isFork();
    }

    function governanceChainId() public view returns (uint16){
        return WORMHOLE_STATE.governanceChainId();
    }

    function governanceContract() public view returns (bytes32){
        return WORMHOLE_STATE.governanceContract();
    }

    function messageFee() public view returns (uint256) {
        return WORMHOLE_STATE.messageFee();
    }

    function nextSequence(address emitter) public view returns (uint64) {
        return WORMHOLE_STATE.nextSequence(emitter);
    }
}

File 12 of 18 : Structs.sol
// contracts/Structs.sol
// SPDX-License-Identifier: Apache 2

pragma solidity ^0.8.0;

interface Structs {
	struct Provider {
		uint16 chainId;
		uint16 governanceChainId;
		bytes32 governanceContract;
	}

	struct GuardianSet {
		address[] keys;
		uint32 expirationTime;
	}

	struct Signature {
		bytes32 r;
		bytes32 s;
		uint8 v;
		uint8 guardianIndex;
	}

	struct VM {
		uint8 version;
		uint32 timestamp;
		uint32 nonce;
		uint16 emitterChainId;
		bytes32 emitterAddress;
		uint64 sequence;
		uint8 consistencyLevel;
		bytes payload;

		uint32 guardianSetIndex;
		Signature[] signatures;

		bytes32 hash;
	}
}

File 13 of 18 : BytesLib.sol
// SPDX-License-Identifier: Unlicense
/*
 * @title Solidity Bytes Arrays Utils
 * @author Gonçalo Sá <[email protected]>
 *
 * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.
 *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.
 */
pragma solidity >=0.8.0 <0.9.0;


library BytesLib {
    function concat(
        bytes memory _preBytes,
        bytes memory _postBytes
    )
        internal
        pure
        returns (bytes memory)
    {
        bytes memory tempBytes;

        assembly {
            // Get a location of some free memory and store it in tempBytes as
            // Solidity does for memory variables.
            tempBytes := mload(0x40)

            // Store the length of the first bytes array at the beginning of
            // the memory for tempBytes.
            let length := mload(_preBytes)
            mstore(tempBytes, length)

            // Maintain a memory counter for the current write location in the
            // temp bytes array by adding the 32 bytes for the array length to
            // the starting location.
            let mc := add(tempBytes, 0x20)
            // Stop copying when the memory counter reaches the length of the
            // first bytes array.
            let end := add(mc, length)

            for {
                // Initialize a copy counter to the start of the _preBytes data,
                // 32 bytes into its memory.
                let cc := add(_preBytes, 0x20)
            } lt(mc, end) {
                // Increase both counters by 32 bytes each iteration.
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } {
                // Write the _preBytes data into the tempBytes memory 32 bytes
                // at a time.
                mstore(mc, mload(cc))
            }

            // Add the length of _postBytes to the current length of tempBytes
            // and store it as the new length in the first 32 bytes of the
            // tempBytes memory.
            length := mload(_postBytes)
            mstore(tempBytes, add(length, mload(tempBytes)))

            // Move the memory counter back from a multiple of 0x20 to the
            // actual end of the _preBytes data.
            mc := end
            // Stop copying when the memory counter reaches the new combined
            // length of the arrays.
            end := add(mc, length)

            for {
                let cc := add(_postBytes, 0x20)
            } lt(mc, end) {
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } {
                mstore(mc, mload(cc))
            }

            // Update the free-memory pointer by padding our last write location
            // to 32 bytes: add 31 bytes to the end of tempBytes to move to the
            // next 32 byte block, then round down to the nearest multiple of
            // 32. If the sum of the length of the two arrays is zero then add
            // one before rounding down to leave a blank 32 bytes (the length block with 0).
            mstore(0x40, and(
              add(add(end, iszero(add(length, mload(_preBytes)))), 31),
              not(31) // Round down to the nearest 32 bytes.
            ))
        }

        return tempBytes;
    }

    function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {
        assembly {
            // Read the first 32 bytes of _preBytes storage, which is the length
            // of the array. (We don't need to use the offset into the slot
            // because arrays use the entire slot.)
            let fslot := sload(_preBytes.slot)
            // Arrays of 31 bytes or less have an even value in their slot,
            // while longer arrays have an odd value. The actual length is
            // the slot divided by two for odd values, and the lowest order
            // byte divided by two for even values.
            // If the slot is even, bitwise and the slot with 255 and divide by
            // two to get the length. If the slot is odd, bitwise and the slot
            // with -1 and divide by two.
            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
            let mlength := mload(_postBytes)
            let newlength := add(slength, mlength)
            // slength can contain both the length and contents of the array
            // if length < 32 bytes so let's prepare for that
            // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
            switch add(lt(slength, 32), lt(newlength, 32))
            case 2 {
                // Since the new array still fits in the slot, we just need to
                // update the contents of the slot.
                // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length
                sstore(
                    _preBytes.slot,
                    // all the modifications to the slot are inside this
                    // next block
                    add(
                        // we can just add to the slot contents because the
                        // bytes we want to change are the LSBs
                        fslot,
                        add(
                            mul(
                                div(
                                    // load the bytes from memory
                                    mload(add(_postBytes, 0x20)),
                                    // zero all bytes to the right
                                    exp(0x100, sub(32, mlength))
                                ),
                                // and now shift left the number of bytes to
                                // leave space for the length in the slot
                                exp(0x100, sub(32, newlength))
                            ),
                            // increase length by the double of the memory
                            // bytes length
                            mul(mlength, 2)
                        )
                    )
                )
            }
            case 1 {
                // The stored value fits in the slot, but the combined value
                // will exceed it.
                // get the keccak hash to get the contents of the array
                mstore(0x0, _preBytes.slot)
                let sc := add(keccak256(0x0, 0x20), div(slength, 32))

                // save new length
                sstore(_preBytes.slot, add(mul(newlength, 2), 1))

                // The contents of the _postBytes array start 32 bytes into
                // the structure. Our first read should obtain the `submod`
                // bytes that can fit into the unused space in the last word
                // of the stored array. To get this, we read 32 bytes starting
                // from `submod`, so the data we read overlaps with the array
                // contents by `submod` bytes. Masking the lowest-order
                // `submod` bytes allows us to add that value directly to the
                // stored value.

                let submod := sub(32, slength)
                let mc := add(_postBytes, submod)
                let end := add(_postBytes, mlength)
                let mask := sub(exp(0x100, submod), 1)

                sstore(
                    sc,
                    add(
                        and(
                            fslot,
                            0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00
                        ),
                        and(mload(mc), mask)
                    )
                )

                for {
                    mc := add(mc, 0x20)
                    sc := add(sc, 1)
                } lt(mc, end) {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } {
                    sstore(sc, mload(mc))
                }

                mask := exp(0x100, sub(mc, end))

                sstore(sc, mul(div(mload(mc), mask), mask))
            }
            default {
                // get the keccak hash to get the contents of the array
                mstore(0x0, _preBytes.slot)
                // Start copying to the last used word of the stored array.
                let sc := add(keccak256(0x0, 0x20), div(slength, 32))

                // save new length
                sstore(_preBytes.slot, add(mul(newlength, 2), 1))

                // Copy over the first `submod` bytes of the new data as in
                // case 1 above.
                let slengthmod := mod(slength, 32)
                let mlengthmod := mod(mlength, 32)
                let submod := sub(32, slengthmod)
                let mc := add(_postBytes, submod)
                let end := add(_postBytes, mlength)
                let mask := sub(exp(0x100, submod), 1)

                sstore(sc, add(sload(sc), and(mload(mc), mask)))

                for {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } lt(mc, end) {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } {
                    sstore(sc, mload(mc))
                }

                mask := exp(0x100, sub(mc, end))

                sstore(sc, mul(div(mload(mc), mask), mask))
            }
        }
    }

    function slice(
        bytes memory _bytes,
        uint256 _start,
        uint256 _length
    )
        internal
        pure
        returns (bytes memory)
    {
        require(_length + 31 >= _length, "slice_overflow");
        require(_bytes.length >= _start + _length, "slice_outOfBounds");

        bytes memory tempBytes;

        assembly {
            switch iszero(_length)
            case 0 {
                // Get a location of some free memory and store it in tempBytes as
                // Solidity does for memory variables.
                tempBytes := mload(0x40)

                // The first word of the slice result is potentially a partial
                // word read from the original array. To read it, we calculate
                // the length of that partial word and start copying that many
                // bytes into the array. The first word we copy will start with
                // data we don't care about, but the last `lengthmod` bytes will
                // land at the beginning of the contents of the new array. When
                // we're done copying, we overwrite the full first word with
                // the actual length of the slice.
                let lengthmod := and(_length, 31)

                // The multiplication in the next line is necessary
                // because when slicing multiples of 32 bytes (lengthmod == 0)
                // the following copy loop was copying the origin's length
                // and then ending prematurely not copying everything it should.
                let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
                let end := add(mc, _length)

                for {
                    // The multiplication in the next line has the same exact purpose
                    // as the one above.
                    let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
                } lt(mc, end) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    mstore(mc, mload(cc))
                }

                mstore(tempBytes, _length)

                //update free-memory pointer
                //allocating the array padded to 32 bytes like the compiler does now
                mstore(0x40, and(add(mc, 31), not(31)))
            }
            //if we want a zero-length slice let's just return a zero-length array
            default {
                tempBytes := mload(0x40)
                //zero out the 32 bytes slice we are about to return
                //we need to do it because Solidity does not garbage collect
                mstore(tempBytes, 0)

                mstore(0x40, add(tempBytes, 0x20))
            }
        }

        return tempBytes;
    }

    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {
        require(_bytes.length >= _start + 20, "toAddress_outOfBounds");
        address tempAddress;

        assembly {
            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
        }

        return tempAddress;
    }

    function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {
        require(_bytes.length >= _start + 1 , "toUint8_outOfBounds");
        uint8 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x1), _start))
        }

        return tempUint;
    }

    function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {
        require(_bytes.length >= _start + 2, "toUint16_outOfBounds");
        uint16 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x2), _start))
        }

        return tempUint;
    }

    function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {
        require(_bytes.length >= _start + 4, "toUint32_outOfBounds");
        uint32 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x4), _start))
        }

        return tempUint;
    }

    function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {
        require(_bytes.length >= _start + 8, "toUint64_outOfBounds");
        uint64 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x8), _start))
        }

        return tempUint;
    }

    function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) {
        require(_bytes.length >= _start + 12, "toUint96_outOfBounds");
        uint96 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0xc), _start))
        }

        return tempUint;
    }

    function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {
        require(_bytes.length >= _start + 16, "toUint128_outOfBounds");
        uint128 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x10), _start))
        }

        return tempUint;
    }

    function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {
        require(_bytes.length >= _start + 32, "toUint256_outOfBounds");
        uint256 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x20), _start))
        }

        return tempUint;
    }

    function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {
        require(_bytes.length >= _start + 32, "toBytes32_outOfBounds");
        bytes32 tempBytes32;

        assembly {
            tempBytes32 := mload(add(add(_bytes, 0x20), _start))
        }

        return tempBytes32;
    }

    function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {
        bool success = true;

        assembly {
            let length := mload(_preBytes)

            // if lengths don't match the arrays are not equal
            switch eq(length, mload(_postBytes))
            case 1 {
                // cb is a circuit breaker in the for loop since there's
                //  no said feature for inline assembly loops
                // cb = 1 - don't breaker
                // cb = 0 - break
                let cb := 1

                let mc := add(_preBytes, 0x20)
                let end := add(mc, length)

                for {
                    let cc := add(_postBytes, 0x20)
                // the next line is the loop condition:
                // while(uint256(mc < end) + cb == 2)
                } eq(add(lt(mc, end), cb), 2) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    // if any of these checks fails then arrays are not equal
                    if iszero(eq(mload(mc), mload(cc))) {
                        // unsuccess:
                        success := 0
                        cb := 0
                    }
                }
            }
            default {
                // unsuccess:
                success := 0
            }
        }

        return success;
    }

    function equalStorage(
        bytes storage _preBytes,
        bytes memory _postBytes
    )
        internal
        view
        returns (bool)
    {
        bool success = true;

        assembly {
            // we know _preBytes_offset is 0
            let fslot := sload(_preBytes.slot)
            // Decode the length of the stored array like in concatStorage().
            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
            let mlength := mload(_postBytes)

            // if lengths don't match the arrays are not equal
            switch eq(slength, mlength)
            case 1 {
                // slength can contain both the length and contents of the array
                // if length < 32 bytes so let's prepare for that
                // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
                if iszero(iszero(slength)) {
                    switch lt(slength, 32)
                    case 1 {
                        // blank the last byte which is the length
                        fslot := mul(div(fslot, 0x100), 0x100)

                        if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {
                            // unsuccess:
                            success := 0
                        }
                    }
                    default {
                        // cb is a circuit breaker in the for loop since there's
                        //  no said feature for inline assembly loops
                        // cb = 1 - don't breaker
                        // cb = 0 - break
                        let cb := 1

                        // get the keccak hash to get the contents of the array
                        mstore(0x0, _preBytes.slot)
                        let sc := keccak256(0x0, 0x20)

                        let mc := add(_postBytes, 0x20)
                        let end := add(mc, mlength)

                        // the next line is the loop condition:
                        // while(uint256(mc < end) + cb == 2)
                        for {} eq(add(lt(mc, end), cb), 2) {
                            sc := add(sc, 1)
                            mc := add(mc, 0x20)
                        } {
                            if iszero(eq(sload(sc), mload(mc))) {
                                // unsuccess:
                                success := 0
                                cb := 0
                            }
                        }
                    }
                }
            }
            default {
                // unsuccess:
                success := 0
            }
        }

        return success;
    }
}

File 14 of 18 : IMessageEscrowStructs.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

interface IMessageEscrowStructs {
    struct IncentiveDescription {
        uint48 maxGasDelivery;      // 0: 6/32 bytes
        uint48 maxGasAck;           // 0: 12/32 bytes
        address refundGasTo;        // 0: 32/32 bytes
        uint96 priceOfDeliveryGas;  // 1: 12/32 bytes
        uint96 priceOfAckGas;       // 1: 24/32 bytes
        uint64 targetDelta;         // 1: 32/32 bytes
    }
}

File 15 of 18 : IMessageEscrowErrors.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

interface IMessageEscrowErrors {
    error AckHasNotBeenExecuted(); // 0x3d1553f8
    error CannotRetryWrongMessage(bytes32,bytes32); // 0x48ce7fac
    error DeadlineInPast(uint64 blocktimestamp, uint64 actual); // 0x2d098d59
    error DeadlineNotPassed(uint64 expected, uint64 actual); // 0x862c57f4
    error DeadlineTooLong(uint64 maxAllowed, uint64 actual); // 0x3c06f369
    error FeeRecipientIsZero(); // 0xfc53a835
    error ImplementationAddressAlreadySet(bytes currentImplementation); // 0xdba47850
    error IncorrectValueProvided(uint128 expected, uint128 actual); // 0x0b52a60b
    error InvalidImplementationAddress(); // 0xc970156c
    error InvalidTimeoutPackage(bytes32 expected, bytes32 actual); // 0xe020885d
    error MessageAlreadyAcked(); // 0x8af35858
    error MessageAlreadyBountied(); // 0x068a62ee
    error MessageAlreadyProcessed(); // 0x7b042609
    error MessageAlreadySpent(); // 0xe954aba2
    error MessageDoesNotExist(); // 0x970e41ec
    error MessageHasInvalidContext(); // 0x3fcdbaba
    error NoImplementationAddressSet(); // 0x9f994b4b
    error NotEnoughGasExecution(); // 0x6bc33587
    error NotEnoughGasProvided(uint128 expected, uint128 actual); // 0x030748b5
    error NotImplementedError(); // 0xd41c17e7
    error RefundGasToIsZero(); // 0x6a1a6afe
    error RouteDisabled(); // 0x17d0b6db
    error SendLostGasToIsZero(); // 0x9c76a9df
}

File 16 of 18 : IMessageEscrowEvents.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import { IMessageEscrowStructs } from "./IMessageEscrowStructs.sol";

interface IMessageEscrowEvents {
    // Important notice for relayers. The implementations (sourceImplementation and destinationImplementation),
    // when indexed in events, the hash is in the topic not the actual implementation.
    event BountyPlaced(
        bytes indexed destinationImplementation, 
        bytes32 chainIdentifier,
        bytes32 indexed messageIdentifier,
        IMessageEscrowStructs.IncentiveDescription incentive
    );
    event MessageDelivered(bytes indexed sourceImplementation, bytes32 chainIdentifier, bytes32 indexed messageIdentifier);
    event MessageAcked(bytes destinationImplementation, bytes32 chainIdentifier, bytes32 messageIdentifier); // Not indexed since relayers can sort by BountyClaimed.
    event TimeoutInitiated(bytes sourceImplementation, bytes32 chainIdentifier, bytes32 messageIdentifier);
    event MessageTimedOut(bytes destinationImplementation, bytes32 chainIdentifier, bytes32 messageIdentifier); // Not indexed since relayers can sort by BountyClaimed.
    event BountyClaimed(
        bytes indexed destinationImplementation,
        bytes32 chainIdentifier,
        bytes32 indexed messageIdentifier,
        uint64 gasSpentOnDestination,
        uint64 gasSpentOnSource,
        uint128 destinationRelayerReward,
        uint128 sourceRelayerReward
    );

    // To save gas, this event does not emit the full incentive scheme.
    // Instead, the new gas prices are emitted. As a result, the relayer can collect all bountyIncreased
    // and then use the maximum. (since the  maxmimum is enforced in the smart contract)
    event BountyIncreased(
        bytes32 indexed messageIdentifier,
        uint96 newDeliveryGasPrice,
        uint96 newAckGasPrice 
    );


    event RemoteImplementationSet(address application, bytes32 chainIdentifier, bytes32 implementationAddressHash, bytes implementationAddress);
}

File 17 of 18 : Getters.sol
// contracts/Getters.sol
// SPDX-License-Identifier: Apache 2

pragma solidity ^0.8.0;

import "./State.sol";

contract Getters is State {
    function getGuardianSet(uint32 index) public view returns (Structs.GuardianSet memory) {
        return _state.guardianSets[index];
    }

    function getCurrentGuardianSetIndex() public view returns (uint32) {
        return _state.guardianSetIndex;
    }

    function getGuardianSetExpiry() public view returns (uint32) {
        return _state.guardianSetExpiry;
    }

    function governanceActionIsConsumed(bytes32 hash) public view returns (bool) {
        return _state.consumedGovernanceActions[hash];
    }

    function isInitialized(address impl) public view returns (bool) {
        return _state.initializedImplementations[impl];
    }

    function chainId() public view returns (uint16) {
        return _state.provider.chainId;
    }

    function evmChainId() public view returns (uint256) {
        return _state.evmChainId;
    }

    function isFork() public view returns (bool) {
        return evmChainId() != block.chainid;
    }

    function governanceChainId() public view returns (uint16){
        return _state.provider.governanceChainId;
    }

    function governanceContract() public view returns (bytes32){
        return _state.provider.governanceContract;
    }

    function messageFee() public view returns (uint256) {
        return _state.messageFee;
    }

    function nextSequence(address emitter) public view returns (uint64) {
        return _state.sequences[emitter];
    }
}

File 18 of 18 : State.sol
// contracts/State.sol
// SPDX-License-Identifier: Apache 2

pragma solidity ^0.8.0;

import "./Structs.sol";

contract Events {
    event LogGuardianSetChanged(
        uint32 oldGuardianIndex,
        uint32 newGuardianIndex
    );

    event LogMessagePublished(
        address emitter_address,
        uint32 nonce,
        bytes payload
    );
}

contract Storage {
    struct WormholeState {
        Structs.Provider provider;

        // Mapping of guardian_set_index => guardian set
        mapping(uint32 => Structs.GuardianSet) guardianSets;

        // Current active guardian set index
        uint32 guardianSetIndex;

        // Period for which a guardian set stays active after it has been replaced
        uint32 guardianSetExpiry;

        // Sequence numbers per emitter
        mapping(address => uint64) sequences;

        // Mapping of consumed governance actions
        mapping(bytes32 => bool) consumedGovernanceActions;

        // Mapping of initialized implementations
        mapping(address => bool) initializedImplementations;

        uint256 messageFee;

        // EIP-155 Chain ID
        uint256 evmChainId;
    }
}

contract State {
    Storage.WormholeState _state;
}

Settings
{
  "remappings": [
    "forge-std/=lib/forge-std/src/",
    "openzeppelin/=lib/openzeppelin-contracts/contracts/",
    "vibc-core-smart-contracts/=lib/vibc-core-smart-contracts/contracts/",
    "@lazyledger/protobuf3-solidity-lib/=lib/vibc-core-smart-contracts/lib/protobuf3-solidity-lib/",
    "@openzeppelin-upgradeable/=lib/vibc-core-smart-contracts/lib/openzeppelin-contracts-upgradeable/",
    "@openzeppelin/=lib/vibc-core-smart-contracts/lib/openzeppelin-contracts/",
    "base64/=lib/vibc-core-smart-contracts/lib/base64/",
    "clones-with-immutable-args/=lib/vibc-core-smart-contracts/lib/optimism/packages/contracts-bedrock/lib/clones-with-immutable-args/src/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "openzeppelin-contracts-upgradeable/=lib/vibc-core-smart-contracts/lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "optimism/=lib/vibc-core-smart-contracts/lib/",
    "proto/=lib/vibc-core-smart-contracts/lib/proto/",
    "protobuf3-solidity-lib/=lib/vibc-core-smart-contracts/lib/protobuf3-solidity-lib/contracts/",
    "safe-contracts/=lib/vibc-core-smart-contracts/lib/optimism/packages/contracts-bedrock/lib/safe-contracts/contracts/",
    "solmate/=lib/vibc-core-smart-contracts/lib/optimism/packages/contracts-bedrock/lib/solmate/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 100000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": true,
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"sendLostGasTo","type":"address"},{"internalType":"address","name":"wormhole_","type":"address"}],"stateMutability":"payable","type":"constructor"},{"inputs":[],"name":"AckHasNotBeenExecuted","type":"error"},{"inputs":[],"name":"BadChainIdentifier","type":"error"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"CannotRetryWrongMessage","type":"error"},{"inputs":[{"internalType":"uint64","name":"blocktimestamp","type":"uint64"},{"internalType":"uint64","name":"actual","type":"uint64"}],"name":"DeadlineInPast","type":"error"},{"inputs":[{"internalType":"uint64","name":"expected","type":"uint64"},{"internalType":"uint64","name":"actual","type":"uint64"}],"name":"DeadlineNotPassed","type":"error"},{"inputs":[{"internalType":"uint64","name":"maxAllowed","type":"uint64"},{"internalType":"uint64","name":"actual","type":"uint64"}],"name":"DeadlineTooLong","type":"error"},{"inputs":[],"name":"FeeRecipientIsZero","type":"error"},{"inputs":[],"name":"GuardianIndexOutOfBounds","type":"error"},{"inputs":[{"internalType":"bytes","name":"currentImplementation","type":"bytes"}],"name":"ImplementationAddressAlreadySet","type":"error"},{"inputs":[{"internalType":"uint128","name":"expected","type":"uint128"},{"internalType":"uint128","name":"actual","type":"uint128"}],"name":"IncorrectValueProvided","type":"error"},{"inputs":[],"name":"InvalidBytes65Address","type":"error"},{"inputs":[],"name":"InvalidImplementationAddress","type":"error"},{"inputs":[],"name":"InvalidSignatory","type":"error"},{"inputs":[{"internalType":"bytes32","name":"expected","type":"bytes32"},{"internalType":"bytes32","name":"actual","type":"bytes32"}],"name":"InvalidTimeoutPackage","type":"error"},{"inputs":[],"name":"MessageAlreadyAcked","type":"error"},{"inputs":[],"name":"MessageAlreadyBountied","type":"error"},{"inputs":[],"name":"MessageAlreadyProcessed","type":"error"},{"inputs":[],"name":"MessageAlreadySpent","type":"error"},{"inputs":[],"name":"MessageDoesNotExist","type":"error"},{"inputs":[],"name":"MessageHasInvalidContext","type":"error"},{"inputs":[],"name":"NoImplementationAddressSet","type":"error"},{"inputs":[],"name":"NotEnoughGasExecution","type":"error"},{"inputs":[{"internalType":"uint128","name":"expected","type":"uint128"},{"internalType":"uint128","name":"actual","type":"uint128"}],"name":"NotEnoughGasProvided","type":"error"},{"inputs":[],"name":"NotImplementedError","type":"error"},{"inputs":[],"name":"RefundGasToIsZero","type":"error"},{"inputs":[],"name":"RouteDisabled","type":"error"},{"inputs":[],"name":"SendLostGasToIsZero","type":"error"},{"inputs":[],"name":"SignatureIndicesNotAscending","type":"error"},{"inputs":[],"name":"TooManyGuardians","type":"error"},{"inputs":[],"name":"VMVersionIncompatible","type":"error"},{"inputs":[],"name":"WormholeStateAddressZero","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes","name":"destinationImplementation","type":"bytes"},{"indexed":false,"internalType":"bytes32","name":"chainIdentifier","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"messageIdentifier","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"gasSpentOnDestination","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"gasSpentOnSource","type":"uint64"},{"indexed":false,"internalType":"uint128","name":"destinationRelayerReward","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"sourceRelayerReward","type":"uint128"}],"name":"BountyClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"messageIdentifier","type":"bytes32"},{"indexed":false,"internalType":"uint96","name":"newDeliveryGasPrice","type":"uint96"},{"indexed":false,"internalType":"uint96","name":"newAckGasPrice","type":"uint96"}],"name":"BountyIncreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes","name":"destinationImplementation","type":"bytes"},{"indexed":false,"internalType":"bytes32","name":"chainIdentifier","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"messageIdentifier","type":"bytes32"},{"components":[{"internalType":"uint48","name":"maxGasDelivery","type":"uint48"},{"internalType":"uint48","name":"maxGasAck","type":"uint48"},{"internalType":"address","name":"refundGasTo","type":"address"},{"internalType":"uint96","name":"priceOfDeliveryGas","type":"uint96"},{"internalType":"uint96","name":"priceOfAckGas","type":"uint96"},{"internalType":"uint64","name":"targetDelta","type":"uint64"}],"indexed":false,"internalType":"struct IMessageEscrowStructs.IncentiveDescription","name":"incentive","type":"tuple"}],"name":"BountyPlaced","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"destinationImplementation","type":"bytes"},{"indexed":false,"internalType":"bytes32","name":"chainIdentifier","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"messageIdentifier","type":"bytes32"}],"name":"MessageAcked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes","name":"sourceImplementation","type":"bytes"},{"indexed":false,"internalType":"bytes32","name":"chainIdentifier","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"messageIdentifier","type":"bytes32"}],"name":"MessageDelivered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"destinationImplementation","type":"bytes"},{"indexed":false,"internalType":"bytes32","name":"chainIdentifier","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"messageIdentifier","type":"bytes32"}],"name":"MessageTimedOut","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"application","type":"address"},{"indexed":false,"internalType":"bytes32","name":"chainIdentifier","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"implementationAddressHash","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"implementationAddress","type":"bytes"}],"name":"RemoteImplementationSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"sourceImplementation","type":"bytes"},{"indexed":false,"internalType":"bytes32","name":"chainIdentifier","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"messageIdentifier","type":"bytes32"}],"name":"TimeoutInitiated","type":"event"},{"inputs":[],"name":"SEND_LOST_GAS_TO","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNIQUE_SOURCE_IDENTIFIER","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WORMHOLE","outputs":[{"internalType":"contract IWormhole","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"fromApplication","type":"address"},{"internalType":"bytes32","name":"destinationIdentifier","type":"bytes32"},{"internalType":"bytes32","name":"messageIdentifier","type":"bytes32"}],"name":"bounty","outputs":[{"components":[{"internalType":"uint48","name":"maxGasDelivery","type":"uint48"},{"internalType":"uint48","name":"maxGasAck","type":"uint48"},{"internalType":"address","name":"refundGasTo","type":"address"},{"internalType":"uint96","name":"priceOfDeliveryGas","type":"uint96"},{"internalType":"uint96","name":"priceOfAckGas","type":"uint96"},{"internalType":"uint64","name":"targetDelta","type":"uint64"}],"internalType":"struct IMessageEscrowStructs.IncentiveDescription","name":"incentive","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chainId","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"evmAddress","type":"address"}],"name":"convertEVMTo65","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"estimateAdditionalCost","outputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"evmChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentGuardianSetIndex","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"index","type":"uint32"}],"name":"getGuardianSet","outputs":[{"components":[{"internalType":"address[]","name":"keys","type":"address[]"},{"internalType":"uint32","name":"expirationTime","type":"uint32"}],"internalType":"struct Structs.GuardianSet","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGuardianSetExpiry","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"governanceActionIsConsumed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governanceChainId","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governanceContract","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"implementationAddress","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"implementationAddressHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"fromApplication","type":"address"},{"internalType":"bytes32","name":"destinationIdentifier","type":"bytes32"},{"internalType":"bytes32","name":"messageIdentifier","type":"bytes32"},{"internalType":"uint96","name":"deliveryGasPriceIncrease","type":"uint96"},{"internalType":"uint96","name":"ackGasPriceIncrease","type":"uint96"}],"name":"increaseBounty","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"isFork","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"impl","type":"address"}],"name":"isInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"sourceIdentifier","type":"bytes32"},{"internalType":"bytes","name":"sourceImplementationIdentifier","type":"bytes"},{"internalType":"bytes32","name":"messageIdentifier","type":"bytes32"}],"name":"messageDelivered","outputs":[{"internalType":"bytes32","name":"hasMessageBeenExecuted","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"messageFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"emitter","type":"address"}],"name":"nextSequence","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedVM","type":"bytes"}],"name":"parseAndVerifyVM","outputs":[{"components":[{"internalType":"uint16","name":"emitterChainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"},{"internalType":"uint32","name":"guardianSetIndex","type":"uint32"}],"internalType":"struct SmallStructs.SmallVM","name":"vm","type":"tuple"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"bool","name":"valid","type":"bool"},{"internalType":"string","name":"reason","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedVM","type":"bytes"}],"name":"parseVM","outputs":[{"components":[{"internalType":"uint16","name":"emitterChainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"},{"internalType":"uint32","name":"guardianSetIndex","type":"uint32"}],"internalType":"struct SmallStructs.SmallVM","name":"vm","type":"tuple"},{"internalType":"bytes","name":"signatures","type":"bytes"},{"internalType":"bytes32","name":"bodyHash","type":"bytes32"},{"internalType":"bytes","name":"payload","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"messagingProtocolContext","type":"bytes"},{"internalType":"bytes","name":"rawMessage","type":"bytes"},{"internalType":"bytes32","name":"feeRecipient","type":"bytes32"}],"name":"processPacket","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"destinationIdentifier","type":"bytes32"}],"name":"proofValidPeriod","outputs":[{"internalType":"uint64","name":"duration","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"numGuardians","type":"uint256"}],"name":"quorum","outputs":[{"internalType":"uint256","name":"numSignaturesRequiredForQuorum","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"messagingProtocolContext","type":"bytes"},{"internalType":"bytes","name":"rawMessage","type":"bytes"}],"name":"recoverAck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"sourceIdentifier","type":"bytes32"},{"internalType":"bytes","name":"implementationIdentifier","type":"bytes"},{"internalType":"bytes","name":"receiveAckWithContext","type":"bytes"}],"name":"reemitAckMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"destinationIdentifier","type":"bytes32"},{"internalType":"bytes","name":"implementation","type":"bytes"}],"name":"setRemoteImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"destinationIdentifier","type":"bytes32"},{"internalType":"bytes","name":"destinationAddress","type":"bytes"},{"internalType":"bytes","name":"message","type":"bytes"},{"components":[{"internalType":"uint48","name":"maxGasDelivery","type":"uint48"},{"internalType":"uint48","name":"maxGasAck","type":"uint48"},{"internalType":"address","name":"refundGasTo","type":"address"},{"internalType":"uint96","name":"priceOfDeliveryGas","type":"uint96"},{"internalType":"uint96","name":"priceOfAckGas","type":"uint96"},{"internalType":"uint64","name":"targetDelta","type":"uint64"}],"internalType":"struct IMessageEscrowStructs.IncentiveDescription","name":"incentive","type":"tuple"},{"internalType":"uint64","name":"deadline","type":"uint64"}],"name":"submitMessage","outputs":[{"internalType":"uint256","name":"gasRefund","type":"uint256"},{"internalType":"bytes32","name":"messageIdentifier","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"thisBytes65","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"sourceIdentifier","type":"bytes32"},{"internalType":"bytes","name":"implementationIdentifier","type":"bytes"},{"internalType":"uint256","name":"originBlockNumber","type":"uint256"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"timeoutMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"bytes","name":"signatures","type":"bytes"},{"components":[{"internalType":"address[]","name":"keys","type":"address[]"},{"internalType":"uint32","name":"expirationTime","type":"uint32"}],"internalType":"struct Structs.GuardianSet","name":"guardianSet","type":"tuple"}],"name":"verifySignatures","outputs":[{"internalType":"bool","name":"valid","type":"bool"},{"internalType":"string","name":"reason","type":"string"}],"stateMutability":"pure","type":"function"}]

6101006040908082528181620053c480380380916200001f8285620001d5565b833981010312620001d0576200004360206200003b836200020f565b92016200020f565b6001600160a01b039180831615620001bf57608052168015620001ae5760208160049260a0528060c052835192838092634d4502c960e11b82525afa908115620001a35760009162000156575b5061ffff1660e0525161519f90816200022582396080518181816113a901528181614e4201528181614ec60152818161503d0152615116015260a0518181816106610152818161084e015281816109a901528181610f39015281816110a0015281816112380152818161159e0152818161194301528181611dd101528181611ec40152818161222a0152613fae015260c0518181816112e501528181611d3301526140f4015260e051818181610ab101528181611c42015281816129bb015261360d0152f35b6020813d6020116200019a575b816200017260209383620001d5565b810103126200019657519061ffff8216820362000193575061ffff62000090565b80fd5b5080fd5b3d915062000163565b82513d6000823e3d90fd5b81516323205fe760e01b8152600490fd5b8351639c76a9df60e01b8152600490fd5b600080fd5b601f909101601f19168101906001600160401b03821190821017620001f957604052565b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b0382168203620001d05756fe608060409080825260048036101561001657600080fd5b600091823560e01c9081631a90a21914611e53575080631cfe795114611e0b5780632c3c02a414611d5757806335e78cfe14611ce85780633a24ef3514611c655780633ccb217e14611c0c5780633fccfa0614611b985780634355866714611a515780634993ef33146119c05780634cf842b5146118be57806353391d3f1461184f5780635a640514146118155780635d758e22146115d757806364d42b171461152d57806365a686de146114425780638caa89ec146113cd5780638dedc1791461135e57806392006e73146112755780639a8a0592146111c7578063a9e1189314611112578063b172b2221461102f578063c0fd8bde14610f73578063d60b347f14610eb4578063daf1e16714610e77578063dd6487fc14610e0c578063dfe1aef914610a13578063e039f22414610938578063ea901f1a146108dc578063eb8d3f12146107dc578063f8ce560a14610796578063f951975a146106dc578063fbe3c2cd146105f0578063fd4716c8146104b65763ffbeacc71461019a57600080fd5b346104b257827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b25780359067ffffffffffffffff6024358181116104ae576101eb9036908401611efd565b9590913386526020936003855282872086885285528287205461045d5787156104365733875260028552828720868852855282872091881161040a57506102328154612090565b601f81116103c7575b5085601f88116001146103025791879187986102f195947f84cad7de2c9074e70f8d697042ecb3c00ae9e6622320cb8c48bdd4d5d709e79699916102f7575b508360011b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8560031b1c19161790555b6102b7368385612346565b8581519101209033895260038652808920878a52865281818a20558051968796338852870152850152608060608501526080840191612197565b0390a180f35b90508401353861027a565b818752848720907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08916885b8181106103b05750918993917f84cad7de2c9074e70f8d697042ecb3c00ae9e6622320cb8c48bdd4d5d709e796999a6102f197969410610378575b5050600183811b0190556102ac565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88660031b161c19908601351690553880610369565b91928760018192868a01358155019401920161032e565b818752848720601f890160051c810191868a10610400575b601f0160051c01905b8181106103f5575061023b565b8781556001016103e8565b90915081906103df565b8660416024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b82517f9f994b4b000000000000000000000000000000000000000000000000000000008152fd5b33875260028552828720868852855282872083517fdba4785000000000000000000000000000000000000000000000000000000000815291820186905281906104aa9060248301906120e3565b0390fd5b8480fd5b5080fd5b8284346104b257606090817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec5760c0929167ffffffffffffffff916104ff612007565b938180519161050d83611f76565b8083528060a0602094828682015282858201528288820152826080820152015273ffffffffffffffffffffffffffffffffffffffff80971681528083528181206024358252835281812060443582528352209282519361056c85611f76565b80549465ffffffffffff9485871698898352600186840194888a60301c16865283850199871c8a5201549788966bffffffffffffffffffffffff98899660a089880197898c16895289608082019c8c1c168c52019b8f1c8c5285519d8e525116908c015251169089015251169086015251166080840152511660a0820152f35b8280fd5b5082346105ec57827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec576020815180937ffbe3c2cd0000000000000000000000000000000000000000000000000000000082528173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9182156106d2576020939261069f575b5061ffff905191168152f35b61ffff9192506106c490843d86116106cb575b6106bc8183611fae565b810190613c85565b9190610693565b503d6106b2565b81513d85823e3d90fd5b5091903461079357602092837ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b257359163ffffffff92838116810361078e5761072a90613f43565b9281519385855260608501938151948488880152855180915287608088019601915b81811061076457505050948495015116908301520390f35b825173ffffffffffffffffffffffffffffffffffffffff168752958801959188019160010161074c565b600080fd5b80fd5b509190346107935760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261079357506107d560209235613f03565b9051908152f35b508290346105ec57827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec576020825180927feb8d3f120000000000000000000000000000000000000000000000000000000082528173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9283156108d157809361088e575b60208463ffffffff855191168152f35b9092506020833d6020116108c9575b816108aa60209383611fae565b81010312610793575063ffffffff6108c36020936121d6565b9261087e565b3d915061089d565b8251903d90823e3d90fd5b8284346104b25760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b2576109349061092161091c612007565b613e5d565b905191829160208352602083019061204d565b0390f35b5082346105ec57827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec576020815180937fe039f2240000000000000000000000000000000000000000000000000000000082528173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9182156106d257602093926109e4575b50519015158152f35b610a05919250833d8511610a0c575b6109fd8183611fae565b8101906122a1565b90836109db565b503d6109f3565b50346104b257827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b25767ffffffffffffffff908035828111610e0857610a629036908301611efd565b5050602435828111610e085790610a91610a82610a9f9336908401611efd565b90610a8b613c9f565b50613ccf565b959497938897939197614b77565b9015610dcc57506020838111610dc8577f0000000000000000000000000000000000000000000000000000000000000000853503610da0578061ffff87511696015193885195828701958652828752610af787611f2b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082018015610d7457818401357fff00000000000000000000000000000000000000000000000000000000000000167f010000000000000000000000000000000000000000000000000000000000000003610d4c5780602111610d485760218201359681606211610d4457606e83013560601c94858c528b81528c8c208b8d5281528c8c20898d5281528c8c205460601c610d1c57858c52600381528c8c20908b8d52528b8b2054908951902003610cf457609011610cf057823b15610cf0578593927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff508a8094610c3e60b0958f8e90519a8b98899788967f11cbf805000000000000000000000000000000000000000000000000000000008852019301918d8601613e1f565b03925af18015610ce657610c81575b5050506102f1907ff865f210bf9219c3ca273416db27a66557c44a930cfbc569e325afc1e809a30794955193849384613e3b565b819796929711610cba578552939450807ff865f210bf9219c3ca273416db27a66557c44a930cfbc569e325afc1e809a3076102f1610c4d565b6024826041897f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b88513d89823e3d90fd5b8880fd5b858b517fc970156c000000000000000000000000000000000000000000000000000000008152fd5b878d517f3d1553f8000000000000000000000000000000000000000000000000000000008152fd5b8a80fd5b8980fd5b858b517fd41c17e7000000000000000000000000000000000000000000000000000000008152fd5b60248a6032887f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8288517f3c1e02c0000000000000000000000000000000000000000000000000000000008152fd5b8680fd5b826104aa6020928a519384937f08c379a0000000000000000000000000000000000000000000000000000000008552840152602483019061204d565b8380fd5b8284346104b257807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b2578060209273ffffffffffffffffffffffffffffffffffffffff610e5d612007565b168152600384528181206024358252845220549051908152f35b8284346104b257817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b2576109349061092130613e5d565b5082346105ec5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec576020610eef612007565b602473ffffffffffffffffffffffffffffffffffffffff9182855196879485937fd60b347f00000000000000000000000000000000000000000000000000000000855216908301527f0000000000000000000000000000000000000000000000000000000000000000165afa9182156106d257602093926109e45750519015158152f35b5090346107935760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126107935781359067ffffffffffffffff821161079357611009610fde6109348661101a610fd2610a8236898b01611efd565b95949892909389614b77565b939094519788809863ffffffff6040809261ffff815116855260208101516020860152015116910152565b60c0606088015260c0870191612197565b911515608085015283820360a085015261204d565b5082346105ec57827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec576020815180937fb172b2220000000000000000000000000000000000000000000000000000000082528173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9182156106d25783926110da575b6020838351908152f35b9091506020813d60201161110a575b816110f660209383611fae565b810103126105ec57602092505190836110d0565b3d91506110e9565b5090346107935760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126107935781359067ffffffffffffffff8211610793576111a36111b46109348661117461116e36888a01611efd565b90613ccf565b94979290939195519889809963ffffffff6040809261ffff815116855260208101516020860152015116910152565b60c0606089015260c0880191612197565b92608086015284830360a0860152612197565b5082346105ec57827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec576020815180937f9a8a05920000000000000000000000000000000000000000000000000000000082528173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9182156106d2576020939261069f575061ffff905191168152f35b50346104b257817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b2576020835180927f1a90a2190000000000000000000000000000000000000000000000000000000082528173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa908115611354578291611322575b5082519182526020820152f35b90506020813d60201161134c575b8161133d60209383611fae565b810103126104b2575138611315565b3d9150611330565b83513d84823e3d90fd5b8284346104b257817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b2576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b5060607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b25767ffffffffffffffff90602435828111610e08576114199036908301611efd565b6044929192359384116104ae5761143661143f9436908401611efd565b93909235613bb6565b80f35b5091906101407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126107935767ffffffffffffffff906024358281116104b2576114919036908601611efd565b6044929192358481116105ec576114ab9036908801611efd565b93909260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c36011261079357610124359586168603610793575060418203611505576114f9959635613552565b82519182526020820152f35b8686517fbbcd8eb1000000000000000000000000000000000000000000000000000000008152fd5b5082346105ec57827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec576020815180937f64d42b170000000000000000000000000000000000000000000000000000000082528173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9182156106d25783926110da576020838351908152f35b508260a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec5761160b612007565b91604435926064356bffffffffffffffffffffffff928382168203610dc8576084359284841684036118115773ffffffffffffffffffffffffffffffffffffffff1687528660205284872060243588526020528487208688526020528487209081548060601c156117e9576116a5908661169e8765ffffffffffff836116938a8388166134cb565b169460301c166134cb565b16906134ee565b906fffffffffffffffffffffffffffffffff90818316340361179357505050926117847fffffffffffffffffffffffffffffffffffffffff00000000000000000000000093829360017f0f9ca48bcb4f4aea18e50df9f1df3c02df5c9c48f05e389a349c8ceb242da58198970190611730611724835492878416613512565b93868360601c16613512565b9485931696879116178155907fffffffffffffffff000000000000000000000000ffffffffffffffffffffffff77ffffffffffffffffffffffff00000000000000000000000083549260601b169116179055565b8351928352166020820152a280f35b87517f0b52a60b0000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff938416918101918252349092169290921660208301529081906040010390fd5b5085517f970e41ec000000000000000000000000000000000000000000000000000000008152fd5b8780fd5b8284346104b25760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b25751908152602090f35b5060607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b25767ffffffffffffffff8135818111610e08576118999036908401611efd565b50506024359081116105ec5761143f916118b591369101611efd565b60443591612986565b5082346105ec5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec5760206118f9612007565b602473ffffffffffffffffffffffffffffffffffffffff9182855196879485937f4cf842b500000000000000000000000000000000000000000000000000000000855216908301527f0000000000000000000000000000000000000000000000000000000000000000165afa9182156106d25760209392611987575b5067ffffffffffffffff905191168152f35b67ffffffffffffffff9192506119b290843d86116119b9575b6119aa8183611fae565b810190612966565b9190611975565b503d6119a0565b8284346104b257807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b25780611a3f611a38926109349473ffffffffffffffffffffffffffffffffffffffff611a19612007565b16815260026020528181206024358252602052208251938480926120e3565b0383611fae565b5191829160208352602083019061204d565b509034610793577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc6060813601126104b25767ffffffffffffffff92602435848111610e0857611aa49036908301611efd565b939092604435908682116105ec57879082360301126104b257865195611ac987611f2b565b818401359081116105ec578101366023820112156105ec5783810135611aee81611fef565b91611afb8a519384611fae565b8183526020916024602085019160051b83010191368311610dc857602401905b828210611b6c5750505090875250602401359063ffffffff82168203610793575091611b5293918593602061093497015235612710565b83929192519384931515845280602085015283019061204d565b813573ffffffffffffffffffffffffffffffffffffffff81168103611811578152908301908301611b1b565b5060807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b25767ffffffffffffffff90602435828111610e0857611be49036908301611efd565b916064359384116104ae57611bff61143f9436908301611efd565b93909260443592356123b9565b8284346104b257817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b257602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b508290346105ec5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec5760243567ffffffffffffffff8111610e08579282916020611cbc819636908401611efd565b923584526001825284842083865194859384378201908152030190206044358252845220549051908152f35b8284346104b257817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b2576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b5082346105ec5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec578051917f2c3c02a400000000000000000000000000000000000000000000000000000000835280359083015260208260248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9182156106d257602093926109e45750519015158152f35b8284346104b257817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b25760209063ffffffff611e4b6121e7565b915191168152f35b9184915034610e0857837ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610e0857826020917f1a90a2190000000000000000000000000000000000000000000000000000000082528173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9182156106d25783926110da576020838351908152f35b9181601f8401121561078e5782359167ffffffffffffffff831161078e576020838186019501011161078e57565b6040810190811067ffffffffffffffff821117611f4757604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60c0810190811067ffffffffffffffff821117611f4757604052565b6020810190811067ffffffffffffffff821117611f4757604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117611f4757604052565b67ffffffffffffffff8111611f475760051b60200190565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361078e57565b60005b83811061203d5750506000910152565b818101518382015260200161202d565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936120898151809281875287808801910161202a565b0116010190565b90600182811c921680156120d9575b60208310146120aa57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f169161209f565b8054600093926120f282612090565b9182825260209360019160018116908160001461215a5750600114612119575b5050505050565b90939495506000929192528360002092846000945b83861061214657505050500101903880808080612112565b80548587018301529401938590820161212e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168685015250505090151560051b010191503880808080612112565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b519063ffffffff8216820361078e57565b6040517f1cfe795100000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9081156122955760009161225e575090565b90506020813d60201161228d575b8161227960209383611fae565b8101031261078e5761228a906121d6565b90565b3d915061226c565b6040513d6000823e3d90fd5b9081602091031261078e5751801515810361078e5790565b9093929384831161078e57841161078e578101920390565b3590602081106122df575090565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060200360031b1b1690565b67ffffffffffffffff8111611f4757601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b9291926123528261230c565b916123606040519384611fae565b82948184528183011161078e578281602093846000960137010152565b9190820391821161238a57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b939492909280156126e1577fff000000000000000000000000000000000000000000000000000000000000008635166126b7578060211161078e57600186013591600091868352600160205260409788842060208a518092898b8337898201908152030190208585526020528884205461268e578160ab11610e085760a3810135928360c01c80158015612684575b6126405750826062116104ae578260b1116104ae577fffffffffffffffff00000000000000000000000000000000000000000000000097946125a99997947f4b43f0920d04b8fb5f32167b55abce15859e8d8bb1bfe84ba2909268d77de8d2946125a39894612578948e519c8d947f0200000000000000000000000000000000000000000000000000000000000000602087015288602187015260416021850181880137166082850152608a84015260b17fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f8301910160aa84013781017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff99283820152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd981018a520188611fae565b885180916060825261258e606083018688612197565b908860208401528b8301520390a13691612346565b506140db565b906fffffffffffffffffffffffffffffffff908134169183168083036125cf5750505050565b80839495929311612625575050517f030748b50000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff918216600482015291166024820152604490fd5b90935061263e925061263891503461237d565b3361428b565b565b8a517f862c57f400000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9182166004820152429091166024820152604490fd5b5042811015612448565b600489517f7b042609000000000000000000000000000000000000000000000000000000008152fd5b60046040517f3fcdbaba000000000000000000000000000000000000000000000000000000008152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90929160008351519282156126e15760f890863560f81c9560019560005b888110612755575050505050505050505060019060405161274e81611f92565b6000815290565b868810156126e15760218801978a81013580871c9789906127a88e6127886127828f6001890187856122b9565b906122d1565b9d604261279e61278260418a01809489876122b9565b97019485926122b9565b9390357fff00000000000000000000000000000000000000000000000000000000000000908181169560018110612951575b5050508960ff939d6040968751918c83528660209889951c601b011684840152888301526060820152600080525a6000916001608092fa156129465773ffffffffffffffffffffffffffffffffffffffff91826000511693841561291d578715918215612911575b5050156128e8578a878110156128bf57885190815111156126e157611fe0859260f31c16010151160361287957505060010161272e565b99509a995050505050505050507f564d207369676e617475726520696e76616c696400000000000000000000000060009351916128b583611f2b565b6014835282015290565b600486517fba5b4315000000000000000000000000000000000000000000000000000000008152fd5b600485517f4fe17a6f000000000000000000000000000000000000000000000000000000008152fd5b168c1190503880612842565b600487517fba0e0fd5000000000000000000000000000000000000000000000000000000008152fd5b84513d6000823e3d90fd5b60010360031b82901b161693503880806127da565b9081602091031261078e575167ffffffffffffffff8116810361078e5790565b915a9281156134a1576129aa9261299f91610a8b613c9f565b949692909387614b77565b901561346357508160201161078e577f0000000000000000000000000000000000000000000000000000000000000000918282350361343957602061ffff8651169501519260405193602085015260208452612a0584611f2b565b60208301926000917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084011561340c5784357fff000000000000000000000000000000000000000000000000000000000000001680612b27575050505091612a9693917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0612a9c97940191866144ad565b906140db565b6fffffffffffffffffffffffffffffffff803416908216808203612abf57505050565b808293949211612b165750506040517f030748b50000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff918216600482015291166024820152604490fd5b61263891935061263e92503461237d565b9091959692989394507f01000000000000000000000000000000000000000000000000000000000000008114600014612f745750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08301602111610dc8577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08301606211610dc857606e84013560601c87528660205260408720868852602052604087206021850135885260205260408720600181549101548160601c15612f4a57606e86013560601c89528860205260408920888a526020526040892060218701358a52602052886001604082208281550155606e86013560601c8952600360205260408920888a5260205260408920548751602089012003612f20577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08501609011610cf057888086612cdf612d0b8c6040519283918d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5060208501977f11cbf8050000000000000000000000000000000000000000000000000000000089520191602160b083019201359060248601613e1f565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282611fae565b519082606e8b013560601c65ffffffffffff8860301c16f115612edd575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08501608811610cf0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060a287013560d01c9501608211610cf0577f9f9aef021b9656e38cd2086f7d7ee0f6b6062c8078a049bfecd6356fdbeb1b3c9593612ed59360219693612e1f9373ffffffffffffffffffffffffffffffffffffffff9160a889013560c01c94838360c01c95169360828b013516928260601c926bffffffffffffffffffffffff8260601c16928a65ffffffffffff6bffffffffffffffffffffffff818560301c169516931691614f1c565b9890927ff865f210bf9219c3ca273416db27a66557c44a930cfbc569e325afc1e809a30760405180612e578c868c8c01359184613e3b565b0390a167ffffffffffffffff612e7d6fffffffffffffffffffffffffffffffff9a613532565b9980604051998a9901359c1695169316918693916080939695919660a0860197865267ffffffffffffffff80921660208701521660408501526fffffffffffffffffffffffffffffffff809216606085015216910152565b0390a3612a9c565b5a65ffffffffffff603f818560301c1604161115612d29575b60046040517f6bc33587000000000000000000000000000000000000000000000000000000008152fd5b60046040517fc970156c000000000000000000000000000000000000000000000000000000008152fd5b60046040517f8af35858000000000000000000000000000000000000000000000000000000008152fd5b91969392917f0200000000000000000000000000000000000000000000000000000000000000036133e2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0830160621161181157606e85013560601c885260036020526040882084895260205260408820548651602088012003612f20577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08301606a1161181157608285013560c01c904282108015906133da575b613397577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08401608a11610cf05790846130a992613095367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff56880160aa8b01612346565b92608a89013590606e8a013560601c614cb9565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08301602111611811576021850135810361335c5750606e84013560601c875286602052604087208388526020526040872060218501358852602052604087209560018754970154928760601c15612f4a578861317e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff568293606e8a013560601c845283602052604084208985526020526040842060218b013585526020528360016040822082815501550160aa89016143a3565b6040516131d181612cdf60208201947f11cbf8050000000000000000000000000000000000000000000000000000000086528b602484015260218d0135604484015260606064840152608483019061204d565b519082606e8a013560601c65ffffffffffff8d60301c16f11561333a575b9261327d7f9f9aef021b9656e38cd2086f7d7ee0f6b6062c8078a049bfecd6356fdbeb1b3c9593612ed59373ffffffffffffffffffffffffffffffffffffffff602197169182918b60601c916bffffffffffffffffffffffff8160601c16918d6bffffffffffffffffffffffff65ffffffffffff8260301c1693169165ffffffffffff808316921690614d63565b9890927fb40655ff3c2bb146ef446b11cb0b22131f89ccd00240340eda5ef4e010794ea1604051806132b58c858c8c01359184613e3b565b0390a165ffffffffffff67ffffffffffffffff6132e26fffffffffffffffffffffffffffffffff9b613532565b6040805194855267ffffffffffffffff9390951683166020850152941616918101919091526fffffffffffffffffffffffffffffffff92881683166060820152979096161660808701529101359390819060a0820190565b9391925a65ffffffffffff603f818a60301c16041611612ef6579291936131ef565b846044916021604051927fe020885d000000000000000000000000000000000000000000000000000000008452013560048301526024820152fd5b6040517f862c57f400000000000000000000000000000000000000000000000000000000815267ffffffffffffffff838116600483015242166024820152604490fd5b508115613031565b60046040517fd41c17e7000000000000000000000000000000000000000000000000000000008152fd5b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526032600452fd5b60046040517f3c1e02c0000000000000000000000000000000000000000000000000000000008152fd5b6104aa906040519182917f08c379a000000000000000000000000000000000000000000000000000000000835260206004840152602483019061204d565b60046040517ffc53a835000000000000000000000000000000000000000000000000000000008152fd5b9190916bffffffffffffffffffffffff8080941691160291821691820361238a57565b9190916fffffffffffffffffffffffffffffffff8080941691160191821161238a57565b9190916bffffffffffffffffffffffff8080941691160191821161238a57565b61354a9060206040519282848094519384920161202a565b810103902090565b929095949373ffffffffffffffffffffffffffffffffffffffff60a4351660a4350361078e5773ffffffffffffffffffffffffffffffffffffffff60a4351615613b8c573360005260026020526040600020846000526020526135c26135c96040600020604051928380926120e3565b0382611fae565b805115613b62578051600181149081613b2d575b50613b035767ffffffffffffffff86168015159081613af8575b50613ab55761363461360a368486612346565b867f0000000000000000000000000000000000000000000000000000000000000000438a33614cb9565b9733600052600060205260406000208660005260205260406000208960005260205260406000205460601c613a8b5765ffffffffffff606435166064350361078e5760c435926bffffffffffffffffffffffff8416840361078e576bffffffffffffffffffffffff6136b08565ffffffffffff606435166134cb565b1665ffffffffffff608435166084350361078e576bffffffffffffffffffffffff60e4351660e4350361078e57613704906bffffffffffffffffffffffff61169e60e43565ffffffffffff608435166134cb565b9733600052600060205260406000208860005260205260406000208b60005260205260406000207fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060a43560601b1665ffffffffffff606435166bffffffffffff00000000000060843560301b16171781556bffffffffffffffffffffffff86167fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060018301541617600182015561380560e43560018301907fffffffffffffffff000000000000000000000000ffffffffffffffffffffffff77ffffffffffffffffffffffff00000000000000000000000083549260601b169116179055565b67ffffffffffffffff6101043516610104350361078e57600101805477ffffffffffffffffffffffffffffffffffffffffffffffff167fffffffffffffffff0000000000000000000000000000000000000000000000006101043560c01b161790558a9582908861387533613e5d565b956040519a8b9760208901600090528b60218a01528051908160418b0191602001916138a09261202a565b8801916041830137019260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016604184015260643560d01b7fffffffffffff0000000000000000000000000000000000000000000000000000166049840152604f83013701604f81016000905203602f81018552604f016139239085611fae565b61392c90613532565b906040519085825260643565ffffffffffff16602083015260843565ffffffffffff16604083015260a43573ffffffffffffffffffffffffffffffffffffffff1660608301526bffffffffffffffffffffffff16608082015260e4356bffffffffffffffffffffffff1660a08201526101043567ffffffffffffffff1660c082015260e07f1b7379b49b96ce33cfd9daf95718231650c40a2c92da579412e588601186772791a36139dc916140db565b6139e5916134ee565b6fffffffffffffffffffffffffffffffff9081811691823410613a3a575050803411613a12575060009190565b3403613a368173ffffffffffffffffffffffffffffffffffffffff60a4351661428b565b9190565b6040517f030748b50000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff928316600482015234919091169091166024820152604490fd5b60046040517f068a62ee000000000000000000000000000000000000000000000000000000008152fd5b6040517f2d098d5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff428116600483015287166024820152604490fd5b9050421015386135f7565b60046040517f17d0b6db000000000000000000000000000000000000000000000000000000008152fd5b9050156126e1577fff0000000000000000000000000000000000000000000000000000000000000060208201511615386135dd565b60046040517f9f994b4b000000000000000000000000000000000000000000000000000000008152fd5b60046040517f6a1a6afe000000000000000000000000000000000000000000000000000000008152fd5b92919493948560211161078e578360005260016020526040600020602060405180928486833784820190815203019020600184013560005260205260406000205480158015613c6a575b613c22575094613c1a612a969392612a9c96973691612346565b503691612346565b604490613c30368987612346565b60208151910120604051917f48ce7fac00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b50613c76368886612346565b60208151910120811415613c00565b9081602091031261078e575161ffff8116810361078e5790565b604051906060820182811067ffffffffffffffff821117611f475760405260006040838281528260208201520152565b613cd7613c9f565b928260011161078e576001823560f81c03613df5578260051161078e57600182013560e01c60408501528260061161078e5760058201906042823560f81c0291826006018060051161078e57851061078e57613ddc90946001840194816039613d4f613d488360068a0181876122b9565b3691612346565b602081519101206040516020810191825260208152613d6d81611f2b565b51902096613dd0612782601083018d613d8b82600e8701898b6122b9565b7fffff00000000000000000000000000000000000000000000000000000000000091358281169160028110613de0575b5050905060f01c9052603084019086886122b9565b60208c015201916122b9565b9091565b8391925060020360031b1b1616803880613dbb565b60046040517fbcd5ac7a000000000000000000000000000000000000000000000000000000008152fd5b61228a9492606092825260208201528160408201520191612197565b613e536040929594939560608352606083019061204d565b9460208201520152565b73ffffffffffffffffffffffffffffffffffffffff604051917f1400000000000000000000000000000000000000000000000000000000000000602084015260006021840152166041820152604181526080810181811067ffffffffffffffff821117611f475760405290565b8115613ed4570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b610100811015613f19576003600191821b040190565b60046040517f9308529b000000000000000000000000000000000000000000000000000000008152fd5b6040908151613f5181611f2b565b606081526000928360208093015273ffffffffffffffffffffffffffffffffffffffff9063ffffffff8151947ff951975a0000000000000000000000000000000000000000000000000000000086521660048501528484602481857f0000000000000000000000000000000000000000000000000000000000000000165afa9485156140d0578095613fe6575b505050505090565b9091929394503d8082873e613ffb8187611fae565b850190848683031261079357855167ffffffffffffffff968782116105ec57019383858403126104b25783519661403188611f2b565b85519081116105ec5785019183601f840112156107935782519261406061405785611fef565b96519687611fae565b838652878087019460051b8201019485116104b257918780969497959301915b8383106140a6575050505061409893508552016121d6565b908201523880808080613fde565b918094965096909294965183811681036105ec578152870195879590949093909290860191614080565b9051903d90823e3d90fd5b919073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001692604080948151907f1a90a2190000000000000000000000000000000000000000000000000000000082526020948583600481855afa8015612946578693600091614224575b50906141a36fffffffffffffffffffffffffffffffff6141e6949316998a97815193849188830152614194815180928a868601910161202a565b81010386810184520182611fae565b84519586809481937fb19a437e0000000000000000000000000000000000000000000000000000000083526000600484015260606024840152606483019061204d565b600f604483015203925af190811561421a5750614201575050565b8161421792903d106119b9576119aa8183611fae565b50565b513d6000823e3d90fd5b929450509181813d8311614254575b61423d8183611fae565b8101031261078e57518692859290916141a361415a565b503d614233565b3d15614286573d9061426c8261230c565b9161427a6040519384611fae565b82523d6000602084013e565b606090565b81471061434557600080809373ffffffffffffffffffffffffffffffffffffffff8294165af16142b961425b565b50156142c157565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152fd5b602161263e91939293846040519586927ffd000000000000000000000000000000000000000000000000000000000000006020850152848401378101600083820152036001810185520183611fae565b9161263e947fffffffffffff000000000000000000000000000000000000000000000000000060b0957fffffffffffffffff000000000000000000000000000000000000000000000000939998949960416040519b8c987f010000000000000000000000000000000000000000000000000000000000000060208b015260218a01528189013760828701521660a28501521660a883015261449d815180926020868601910161202a565b8101036090810185520183611fae565b93919290948160211161078e57846000526001602052604060002060206040518092826144e08b8481519384920161202a565b8201908152030190206001850135600052602052604060002054614b4d57846000526001602052604060002060206040518092826145248b8481519384920161202a565b820190815203019020600185013560005260205260016040600020558160a31161078e57608f84013560601c8260621161078e578060005260036020526040600020866000526020526040600020548751602089012003614a40578260ab1161078e5760a385013560c01c8015159081614a36575b506148ef578260b11161078e57600060405180927fd00689b600000000000000000000000000000000000000000000000000000000825288600483015260018801356024830152608060448301526041608483015260416021890160a48401378260e5830152610100606483015281838161463f61010482018c60b17fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f8d019101612197565b039260ab8b013560d01cf16000918161486c575b50614812575061466161425b565b505a65ffffffffffff603f60ab87013560d01c041611612ef6576148046147bf6001927f6025efc987827001c12f1f5c8b7831a6439083c88f60686671451fe479ec6e32957fffffffffffff000000000000000000000000000000000000000000000000000061478760209761477e604051917fff000000000000000000000000000000000000000000000000000000000000008b8401528c60b17fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f8301910160218501378201827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7091600083820152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff50810184520182611fae565b935b5a9061237d565b60d01b167fffffffffffffffff0000000000000000000000000000000000000000000000004260c01b169160218a01878b01356143f3565b9687518489012087600052838552604060002085604051809285516147e78184868a0161202a565b820190815203019020848801356000528552604060002055613532565b93604051958652013593a390565b602092506147bf6001927f6025efc987827001c12f1f5c8b7831a6439083c88f60686671451fe479ec6e32957fffffffffffff00000000000000000000000000000000000000000000000000006147876148049593614780565b9091503d806000833e61487f8183611fae565b81019060208183031261078e5780519067ffffffffffffffff821161078e5782601f83830101121561078e5781810151906148b98261230c565b936148c76040519586611fae565b82855260208385840101011161078e5760206148e89381860192010161202a565b9038614653565b50508060b19592951161078e5760016148047f6025efc987827001c12f1f5c8b7831a6439083c88f60686671451fe479ec6e32936149547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f6020950160b188016143a3565b97614a1160b0604051809b888201947f01000000000000000000000000000000000000000000000000000000000000008652888c01356021840152604160218d018185013760828301527f800000000000000000000000000000000000000000000000000000000000000060a28301527fffffffffffffffff0000000000000000000000000000000000000000000000004260c01b1660a8830152614a01815180928b868601910161202a565b810103609081018c52018a611fae565b8851902087600052838552604060002085604051809285516147e78184868a0161202a565b9050421138614599565b50908060b11161078e576148046147bf6001927f6025efc987827001c12f1f5c8b7831a6439083c88f60686671451fe479ec6e32957fffffffffffff0000000000000000000000000000000000000000000000000000614787602097614780604051957ffe000000000000000000000000000000000000000000000000000000000000008b8801528c60b17fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f8301910160218901378601867fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7091600083820152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff50810188520186611fae565b60046040517fe954aba2000000000000000000000000000000000000000000000000000000008152fd5b604090929192019163ffffffff614b9081855116613f43565b9384515115614c7757816020860151164211614c1e575b5050614bb4835151613f03565b8210614bde57614bc393612710565b9015614bd9575060019060405161274e81611f92565b600091565b50505050600090604051614bf181611f2b565b600981527f6e6f2071756f72756d0000000000000000000000000000000000000000000000602082015290565b51811690614c2a6121e7565b1603614c37573880614ba7565b50505050600090604051614c4a81611f2b565b601881527f677561726469616e207365742068617320657870697265640000000000000000602082015290565b505050505050600090604051614c8c81611f2b565b601481527f696e76616c696420677561726469616e20736574000000000000000000000000602082015290565b9460b0929194614d5d947fffffffffffffffffffffffffffffffffffffffff000000000000000000000000937fffffffffffffffff000000000000000000000000000000000000000000000000604051988996602088019b813060601b168d5260601b16603488015260c01b166048860152605085015260708401526090830152614d4d815180926020868601910161202a565b8101036090810184520182611fae565b51902090565b929788929997959496919965ffffffffffff809b81831692828216841115614f14575b506bffffffffffffffffffffffff9b8c9283921602169b8c965a900399169489861115614f0b575b8188168a029b8c9889890197021692021601918383039060008080808573ffffffffffffffffffffffffffffffffffffffff98898b8492149788614f01575b1690f115614eaf575b5050811694811691828614614e855750600080808086819681159788614e7c575bf115614e2f575b505050614e2a9161428b565b929190565b600093508392839283928391614e72575b7f00000000000000000000000000000000000000000000000000000000000000001690f1156122955783853880614e1e565b6108fc9150614e40565b506108fc614e17565b9050600094858095508094508093508215614ea6575bf11561229557929190565b506108fc614e9b565b600093965083929550829182918290614ef8575b887f00000000000000000000000000000000000000000000000000000000000000001690f11561229557869288923880614df6565b506108fc614ec3565b6108fc9250614ded565b98508498614dae565b905038614d86565b939791839b9995979a939165ffffffffffff809181841693828216851115615161575b506bffffffffffffffffffffffff9e8f938492160216965a90039a16928a841115615158575b818a168b029d8e88019a8b95021692021601958187039060008080808573ffffffffffffffffffffffffffffffffffffffff9c8d8099849214978861514e575b1690f115615103575b5050809116981698888a146150e15767ffffffffffffffff8094169182156150b4574285160384169363a8c0000085116150ab575b92938493168290036000811361507f57615001935060000302613eca565b019586915b600080808086819681159788615076575bf11561502c575b5050614e2a9103809461428b565b6000809381938293839161506c575b7f00000000000000000000000000000000000000000000000000000000000000001690f1156122955784388061501e565b6108fc915061503b565b506108fc615017565b90508181101561509d576150939202613eca565b9003958691615006565b505050506000958691615006565b60009450614fe3565b5097945050968791508692600080808086819681159788614e7c57f115614e2f57505050614e2a9161428b565b9760008096925080955080945080939a508215614ea657f11561229557929190565b6000809350809281928290615145575b8a7f00000000000000000000000000000000000000000000000000000000000000001690f11561229557843880614fae565b506108fc615113565b6108fc9250614fa5565b99508299614f65565b905038614f3f56fea2646970667358221220650436a56158a64f21f64a45b35532f08d567f83e44ecf57f2389ce0c20ad58064736f6c634300081600330000000000000000000000000000000099263f0735d03bb2787ce8fb84f6ed6e000000000000000000000000ee91c335eab126df5fdb3797ea9d6ad93aec9722

Deployed Bytecode

0x608060409080825260048036101561001657600080fd5b600091823560e01c9081631a90a21914611e53575080631cfe795114611e0b5780632c3c02a414611d5757806335e78cfe14611ce85780633a24ef3514611c655780633ccb217e14611c0c5780633fccfa0614611b985780634355866714611a515780634993ef33146119c05780634cf842b5146118be57806353391d3f1461184f5780635a640514146118155780635d758e22146115d757806364d42b171461152d57806365a686de146114425780638caa89ec146113cd5780638dedc1791461135e57806392006e73146112755780639a8a0592146111c7578063a9e1189314611112578063b172b2221461102f578063c0fd8bde14610f73578063d60b347f14610eb4578063daf1e16714610e77578063dd6487fc14610e0c578063dfe1aef914610a13578063e039f22414610938578063ea901f1a146108dc578063eb8d3f12146107dc578063f8ce560a14610796578063f951975a146106dc578063fbe3c2cd146105f0578063fd4716c8146104b65763ffbeacc71461019a57600080fd5b346104b257827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b25780359067ffffffffffffffff6024358181116104ae576101eb9036908401611efd565b9590913386526020936003855282872086885285528287205461045d5787156104365733875260028552828720868852855282872091881161040a57506102328154612090565b601f81116103c7575b5085601f88116001146103025791879187986102f195947f84cad7de2c9074e70f8d697042ecb3c00ae9e6622320cb8c48bdd4d5d709e79699916102f7575b508360011b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8560031b1c19161790555b6102b7368385612346565b8581519101209033895260038652808920878a52865281818a20558051968796338852870152850152608060608501526080840191612197565b0390a180f35b90508401353861027a565b818752848720907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08916885b8181106103b05750918993917f84cad7de2c9074e70f8d697042ecb3c00ae9e6622320cb8c48bdd4d5d709e796999a6102f197969410610378575b5050600183811b0190556102ac565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88660031b161c19908601351690553880610369565b91928760018192868a01358155019401920161032e565b818752848720601f890160051c810191868a10610400575b601f0160051c01905b8181106103f5575061023b565b8781556001016103e8565b90915081906103df565b8660416024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b82517f9f994b4b000000000000000000000000000000000000000000000000000000008152fd5b33875260028552828720868852855282872083517fdba4785000000000000000000000000000000000000000000000000000000000815291820186905281906104aa9060248301906120e3565b0390fd5b8480fd5b5080fd5b8284346104b257606090817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec5760c0929167ffffffffffffffff916104ff612007565b938180519161050d83611f76565b8083528060a0602094828682015282858201528288820152826080820152015273ffffffffffffffffffffffffffffffffffffffff80971681528083528181206024358252835281812060443582528352209282519361056c85611f76565b80549465ffffffffffff9485871698898352600186840194888a60301c16865283850199871c8a5201549788966bffffffffffffffffffffffff98899660a089880197898c16895289608082019c8c1c168c52019b8f1c8c5285519d8e525116908c015251169089015251169086015251166080840152511660a0820152f35b8280fd5b5082346105ec57827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec576020815180937ffbe3c2cd0000000000000000000000000000000000000000000000000000000082528173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ee91c335eab126df5fdb3797ea9d6ad93aec9722165afa9182156106d2576020939261069f575b5061ffff905191168152f35b61ffff9192506106c490843d86116106cb575b6106bc8183611fae565b810190613c85565b9190610693565b503d6106b2565b81513d85823e3d90fd5b5091903461079357602092837ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b257359163ffffffff92838116810361078e5761072a90613f43565b9281519385855260608501938151948488880152855180915287608088019601915b81811061076457505050948495015116908301520390f35b825173ffffffffffffffffffffffffffffffffffffffff168752958801959188019160010161074c565b600080fd5b80fd5b509190346107935760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261079357506107d560209235613f03565b9051908152f35b508290346105ec57827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec576020825180927feb8d3f120000000000000000000000000000000000000000000000000000000082528173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ee91c335eab126df5fdb3797ea9d6ad93aec9722165afa9283156108d157809361088e575b60208463ffffffff855191168152f35b9092506020833d6020116108c9575b816108aa60209383611fae565b81010312610793575063ffffffff6108c36020936121d6565b9261087e565b3d915061089d565b8251903d90823e3d90fd5b8284346104b25760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b2576109349061092161091c612007565b613e5d565b905191829160208352602083019061204d565b0390f35b5082346105ec57827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec576020815180937fe039f2240000000000000000000000000000000000000000000000000000000082528173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ee91c335eab126df5fdb3797ea9d6ad93aec9722165afa9182156106d257602093926109e4575b50519015158152f35b610a05919250833d8511610a0c575b6109fd8183611fae565b8101906122a1565b90836109db565b503d6109f3565b50346104b257827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b25767ffffffffffffffff908035828111610e0857610a629036908301611efd565b5050602435828111610e085790610a91610a82610a9f9336908401611efd565b90610a8b613c9f565b50613ccf565b959497938897939197614b77565b9015610dcc57506020838111610dc8577f0000000000000000000000000000000000000000000000000000000000000018853503610da0578061ffff87511696015193885195828701958652828752610af787611f2b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082018015610d7457818401357fff00000000000000000000000000000000000000000000000000000000000000167f010000000000000000000000000000000000000000000000000000000000000003610d4c5780602111610d485760218201359681606211610d4457606e83013560601c94858c528b81528c8c208b8d5281528c8c20898d5281528c8c205460601c610d1c57858c52600381528c8c20908b8d52528b8b2054908951902003610cf457609011610cf057823b15610cf0578593927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff508a8094610c3e60b0958f8e90519a8b98899788967f11cbf805000000000000000000000000000000000000000000000000000000008852019301918d8601613e1f565b03925af18015610ce657610c81575b5050506102f1907ff865f210bf9219c3ca273416db27a66557c44a930cfbc569e325afc1e809a30794955193849384613e3b565b819796929711610cba578552939450807ff865f210bf9219c3ca273416db27a66557c44a930cfbc569e325afc1e809a3076102f1610c4d565b6024826041897f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b88513d89823e3d90fd5b8880fd5b858b517fc970156c000000000000000000000000000000000000000000000000000000008152fd5b878d517f3d1553f8000000000000000000000000000000000000000000000000000000008152fd5b8a80fd5b8980fd5b858b517fd41c17e7000000000000000000000000000000000000000000000000000000008152fd5b60248a6032887f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8288517f3c1e02c0000000000000000000000000000000000000000000000000000000008152fd5b8680fd5b826104aa6020928a519384937f08c379a0000000000000000000000000000000000000000000000000000000008552840152602483019061204d565b8380fd5b8284346104b257807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b2578060209273ffffffffffffffffffffffffffffffffffffffff610e5d612007565b168152600384528181206024358252845220549051908152f35b8284346104b257817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b2576109349061092130613e5d565b5082346105ec5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec576020610eef612007565b602473ffffffffffffffffffffffffffffffffffffffff9182855196879485937fd60b347f00000000000000000000000000000000000000000000000000000000855216908301527f000000000000000000000000ee91c335eab126df5fdb3797ea9d6ad93aec9722165afa9182156106d257602093926109e45750519015158152f35b5090346107935760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126107935781359067ffffffffffffffff821161079357611009610fde6109348661101a610fd2610a8236898b01611efd565b95949892909389614b77565b939094519788809863ffffffff6040809261ffff815116855260208101516020860152015116910152565b60c0606088015260c0870191612197565b911515608085015283820360a085015261204d565b5082346105ec57827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec576020815180937fb172b2220000000000000000000000000000000000000000000000000000000082528173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ee91c335eab126df5fdb3797ea9d6ad93aec9722165afa9182156106d25783926110da575b6020838351908152f35b9091506020813d60201161110a575b816110f660209383611fae565b810103126105ec57602092505190836110d0565b3d91506110e9565b5090346107935760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126107935781359067ffffffffffffffff8211610793576111a36111b46109348661117461116e36888a01611efd565b90613ccf565b94979290939195519889809963ffffffff6040809261ffff815116855260208101516020860152015116910152565b60c0606089015260c0880191612197565b92608086015284830360a0860152612197565b5082346105ec57827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec576020815180937f9a8a05920000000000000000000000000000000000000000000000000000000082528173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ee91c335eab126df5fdb3797ea9d6ad93aec9722165afa9182156106d2576020939261069f575061ffff905191168152f35b50346104b257817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b2576020835180927f1a90a2190000000000000000000000000000000000000000000000000000000082528173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ee91c335eab126df5fdb3797ea9d6ad93aec9722165afa908115611354578291611322575b5082519182526020820152f35b90506020813d60201161134c575b8161133d60209383611fae565b810103126104b2575138611315565b3d9150611330565b83513d84823e3d90fd5b8284346104b257817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b2576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000099263f0735d03bb2787ce8fb84f6ed6e168152f35b5060607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b25767ffffffffffffffff90602435828111610e08576114199036908301611efd565b6044929192359384116104ae5761143661143f9436908401611efd565b93909235613bb6565b80f35b5091906101407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126107935767ffffffffffffffff906024358281116104b2576114919036908601611efd565b6044929192358481116105ec576114ab9036908801611efd565b93909260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c36011261079357610124359586168603610793575060418203611505576114f9959635613552565b82519182526020820152f35b8686517fbbcd8eb1000000000000000000000000000000000000000000000000000000008152fd5b5082346105ec57827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec576020815180937f64d42b170000000000000000000000000000000000000000000000000000000082528173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ee91c335eab126df5fdb3797ea9d6ad93aec9722165afa9182156106d25783926110da576020838351908152f35b508260a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec5761160b612007565b91604435926064356bffffffffffffffffffffffff928382168203610dc8576084359284841684036118115773ffffffffffffffffffffffffffffffffffffffff1687528660205284872060243588526020528487208688526020528487209081548060601c156117e9576116a5908661169e8765ffffffffffff836116938a8388166134cb565b169460301c166134cb565b16906134ee565b906fffffffffffffffffffffffffffffffff90818316340361179357505050926117847fffffffffffffffffffffffffffffffffffffffff00000000000000000000000093829360017f0f9ca48bcb4f4aea18e50df9f1df3c02df5c9c48f05e389a349c8ceb242da58198970190611730611724835492878416613512565b93868360601c16613512565b9485931696879116178155907fffffffffffffffff000000000000000000000000ffffffffffffffffffffffff77ffffffffffffffffffffffff00000000000000000000000083549260601b169116179055565b8351928352166020820152a280f35b87517f0b52a60b0000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff938416918101918252349092169290921660208301529081906040010390fd5b5085517f970e41ec000000000000000000000000000000000000000000000000000000008152fd5b8780fd5b8284346104b25760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b25751908152602090f35b5060607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b25767ffffffffffffffff8135818111610e08576118999036908401611efd565b50506024359081116105ec5761143f916118b591369101611efd565b60443591612986565b5082346105ec5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec5760206118f9612007565b602473ffffffffffffffffffffffffffffffffffffffff9182855196879485937f4cf842b500000000000000000000000000000000000000000000000000000000855216908301527f000000000000000000000000ee91c335eab126df5fdb3797ea9d6ad93aec9722165afa9182156106d25760209392611987575b5067ffffffffffffffff905191168152f35b67ffffffffffffffff9192506119b290843d86116119b9575b6119aa8183611fae565b810190612966565b9190611975565b503d6119a0565b8284346104b257807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b25780611a3f611a38926109349473ffffffffffffffffffffffffffffffffffffffff611a19612007565b16815260026020528181206024358252602052208251938480926120e3565b0383611fae565b5191829160208352602083019061204d565b509034610793577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc6060813601126104b25767ffffffffffffffff92602435848111610e0857611aa49036908301611efd565b939092604435908682116105ec57879082360301126104b257865195611ac987611f2b565b818401359081116105ec578101366023820112156105ec5783810135611aee81611fef565b91611afb8a519384611fae565b8183526020916024602085019160051b83010191368311610dc857602401905b828210611b6c5750505090875250602401359063ffffffff82168203610793575091611b5293918593602061093497015235612710565b83929192519384931515845280602085015283019061204d565b813573ffffffffffffffffffffffffffffffffffffffff81168103611811578152908301908301611b1b565b5060807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b25767ffffffffffffffff90602435828111610e0857611be49036908301611efd565b916064359384116104ae57611bff61143f9436908301611efd565b93909260443592356123b9565b8284346104b257817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b257602090517f00000000000000000000000000000000000000000000000000000000000000188152f35b508290346105ec5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec5760243567ffffffffffffffff8111610e08579282916020611cbc819636908401611efd565b923584526001825284842083865194859384378201908152030190206044358252845220549051908152f35b8284346104b257817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b2576020905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ee91c335eab126df5fdb3797ea9d6ad93aec9722168152f35b5082346105ec5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105ec578051917f2c3c02a400000000000000000000000000000000000000000000000000000000835280359083015260208260248173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ee91c335eab126df5fdb3797ea9d6ad93aec9722165afa9182156106d257602093926109e45750519015158152f35b8284346104b257817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104b25760209063ffffffff611e4b6121e7565b915191168152f35b9184915034610e0857837ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610e0857826020917f1a90a2190000000000000000000000000000000000000000000000000000000082528173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ee91c335eab126df5fdb3797ea9d6ad93aec9722165afa9182156106d25783926110da576020838351908152f35b9181601f8401121561078e5782359167ffffffffffffffff831161078e576020838186019501011161078e57565b6040810190811067ffffffffffffffff821117611f4757604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60c0810190811067ffffffffffffffff821117611f4757604052565b6020810190811067ffffffffffffffff821117611f4757604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117611f4757604052565b67ffffffffffffffff8111611f475760051b60200190565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361078e57565b60005b83811061203d5750506000910152565b818101518382015260200161202d565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936120898151809281875287808801910161202a565b0116010190565b90600182811c921680156120d9575b60208310146120aa57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f169161209f565b8054600093926120f282612090565b9182825260209360019160018116908160001461215a5750600114612119575b5050505050565b90939495506000929192528360002092846000945b83861061214657505050500101903880808080612112565b80548587018301529401938590820161212e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168685015250505090151560051b010191503880808080612112565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b519063ffffffff8216820361078e57565b6040517f1cfe795100000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ee91c335eab126df5fdb3797ea9d6ad93aec9722165afa9081156122955760009161225e575090565b90506020813d60201161228d575b8161227960209383611fae565b8101031261078e5761228a906121d6565b90565b3d915061226c565b6040513d6000823e3d90fd5b9081602091031261078e5751801515810361078e5790565b9093929384831161078e57841161078e578101920390565b3590602081106122df575090565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060200360031b1b1690565b67ffffffffffffffff8111611f4757601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b9291926123528261230c565b916123606040519384611fae565b82948184528183011161078e578281602093846000960137010152565b9190820391821161238a57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b939492909280156126e1577fff000000000000000000000000000000000000000000000000000000000000008635166126b7578060211161078e57600186013591600091868352600160205260409788842060208a518092898b8337898201908152030190208585526020528884205461268e578160ab11610e085760a3810135928360c01c80158015612684575b6126405750826062116104ae578260b1116104ae577fffffffffffffffff00000000000000000000000000000000000000000000000097946125a99997947f4b43f0920d04b8fb5f32167b55abce15859e8d8bb1bfe84ba2909268d77de8d2946125a39894612578948e519c8d947f0200000000000000000000000000000000000000000000000000000000000000602087015288602187015260416021850181880137166082850152608a84015260b17fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f8301910160aa84013781017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff99283820152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd981018a520188611fae565b885180916060825261258e606083018688612197565b908860208401528b8301520390a13691612346565b506140db565b906fffffffffffffffffffffffffffffffff908134169183168083036125cf5750505050565b80839495929311612625575050517f030748b50000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff918216600482015291166024820152604490fd5b90935061263e925061263891503461237d565b3361428b565b565b8a517f862c57f400000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9182166004820152429091166024820152604490fd5b5042811015612448565b600489517f7b042609000000000000000000000000000000000000000000000000000000008152fd5b60046040517f3fcdbaba000000000000000000000000000000000000000000000000000000008152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90929160008351519282156126e15760f890863560f81c9560019560005b888110612755575050505050505050505060019060405161274e81611f92565b6000815290565b868810156126e15760218801978a81013580871c9789906127a88e6127886127828f6001890187856122b9565b906122d1565b9d604261279e61278260418a01809489876122b9565b97019485926122b9565b9390357fff00000000000000000000000000000000000000000000000000000000000000908181169560018110612951575b5050508960ff939d6040968751918c83528660209889951c601b011684840152888301526060820152600080525a6000916001608092fa156129465773ffffffffffffffffffffffffffffffffffffffff91826000511693841561291d578715918215612911575b5050156128e8578a878110156128bf57885190815111156126e157611fe0859260f31c16010151160361287957505060010161272e565b99509a995050505050505050507f564d207369676e617475726520696e76616c696400000000000000000000000060009351916128b583611f2b565b6014835282015290565b600486517fba5b4315000000000000000000000000000000000000000000000000000000008152fd5b600485517f4fe17a6f000000000000000000000000000000000000000000000000000000008152fd5b168c1190503880612842565b600487517fba0e0fd5000000000000000000000000000000000000000000000000000000008152fd5b84513d6000823e3d90fd5b60010360031b82901b161693503880806127da565b9081602091031261078e575167ffffffffffffffff8116810361078e5790565b915a9281156134a1576129aa9261299f91610a8b613c9f565b949692909387614b77565b901561346357508160201161078e577f0000000000000000000000000000000000000000000000000000000000000018918282350361343957602061ffff8651169501519260405193602085015260208452612a0584611f2b565b60208301926000917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084011561340c5784357fff000000000000000000000000000000000000000000000000000000000000001680612b27575050505091612a9693917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0612a9c97940191866144ad565b906140db565b6fffffffffffffffffffffffffffffffff803416908216808203612abf57505050565b808293949211612b165750506040517f030748b50000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff918216600482015291166024820152604490fd5b61263891935061263e92503461237d565b9091959692989394507f01000000000000000000000000000000000000000000000000000000000000008114600014612f745750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08301602111610dc8577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08301606211610dc857606e84013560601c87528660205260408720868852602052604087206021850135885260205260408720600181549101548160601c15612f4a57606e86013560601c89528860205260408920888a526020526040892060218701358a52602052886001604082208281550155606e86013560601c8952600360205260408920888a5260205260408920548751602089012003612f20577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08501609011610cf057888086612cdf612d0b8c6040519283918d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5060208501977f11cbf8050000000000000000000000000000000000000000000000000000000089520191602160b083019201359060248601613e1f565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282611fae565b519082606e8b013560601c65ffffffffffff8860301c16f115612edd575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08501608811610cf0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060a287013560d01c9501608211610cf0577f9f9aef021b9656e38cd2086f7d7ee0f6b6062c8078a049bfecd6356fdbeb1b3c9593612ed59360219693612e1f9373ffffffffffffffffffffffffffffffffffffffff9160a889013560c01c94838360c01c95169360828b013516928260601c926bffffffffffffffffffffffff8260601c16928a65ffffffffffff6bffffffffffffffffffffffff818560301c169516931691614f1c565b9890927ff865f210bf9219c3ca273416db27a66557c44a930cfbc569e325afc1e809a30760405180612e578c868c8c01359184613e3b565b0390a167ffffffffffffffff612e7d6fffffffffffffffffffffffffffffffff9a613532565b9980604051998a9901359c1695169316918693916080939695919660a0860197865267ffffffffffffffff80921660208701521660408501526fffffffffffffffffffffffffffffffff809216606085015216910152565b0390a3612a9c565b5a65ffffffffffff603f818560301c1604161115612d29575b60046040517f6bc33587000000000000000000000000000000000000000000000000000000008152fd5b60046040517fc970156c000000000000000000000000000000000000000000000000000000008152fd5b60046040517f8af35858000000000000000000000000000000000000000000000000000000008152fd5b91969392917f0200000000000000000000000000000000000000000000000000000000000000036133e2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0830160621161181157606e85013560601c885260036020526040882084895260205260408820548651602088012003612f20577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08301606a1161181157608285013560c01c904282108015906133da575b613397577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08401608a11610cf05790846130a992613095367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff56880160aa8b01612346565b92608a89013590606e8a013560601c614cb9565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08301602111611811576021850135810361335c5750606e84013560601c875286602052604087208388526020526040872060218501358852602052604087209560018754970154928760601c15612f4a578861317e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff568293606e8a013560601c845283602052604084208985526020526040842060218b013585526020528360016040822082815501550160aa89016143a3565b6040516131d181612cdf60208201947f11cbf8050000000000000000000000000000000000000000000000000000000086528b602484015260218d0135604484015260606064840152608483019061204d565b519082606e8a013560601c65ffffffffffff8d60301c16f11561333a575b9261327d7f9f9aef021b9656e38cd2086f7d7ee0f6b6062c8078a049bfecd6356fdbeb1b3c9593612ed59373ffffffffffffffffffffffffffffffffffffffff602197169182918b60601c916bffffffffffffffffffffffff8160601c16918d6bffffffffffffffffffffffff65ffffffffffff8260301c1693169165ffffffffffff808316921690614d63565b9890927fb40655ff3c2bb146ef446b11cb0b22131f89ccd00240340eda5ef4e010794ea1604051806132b58c858c8c01359184613e3b565b0390a165ffffffffffff67ffffffffffffffff6132e26fffffffffffffffffffffffffffffffff9b613532565b6040805194855267ffffffffffffffff9390951683166020850152941616918101919091526fffffffffffffffffffffffffffffffff92881683166060820152979096161660808701529101359390819060a0820190565b9391925a65ffffffffffff603f818a60301c16041611612ef6579291936131ef565b846044916021604051927fe020885d000000000000000000000000000000000000000000000000000000008452013560048301526024820152fd5b6040517f862c57f400000000000000000000000000000000000000000000000000000000815267ffffffffffffffff838116600483015242166024820152604490fd5b508115613031565b60046040517fd41c17e7000000000000000000000000000000000000000000000000000000008152fd5b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526032600452fd5b60046040517f3c1e02c0000000000000000000000000000000000000000000000000000000008152fd5b6104aa906040519182917f08c379a000000000000000000000000000000000000000000000000000000000835260206004840152602483019061204d565b60046040517ffc53a835000000000000000000000000000000000000000000000000000000008152fd5b9190916bffffffffffffffffffffffff8080941691160291821691820361238a57565b9190916fffffffffffffffffffffffffffffffff8080941691160191821161238a57565b9190916bffffffffffffffffffffffff8080941691160191821161238a57565b61354a9060206040519282848094519384920161202a565b810103902090565b929095949373ffffffffffffffffffffffffffffffffffffffff60a4351660a4350361078e5773ffffffffffffffffffffffffffffffffffffffff60a4351615613b8c573360005260026020526040600020846000526020526135c26135c96040600020604051928380926120e3565b0382611fae565b805115613b62578051600181149081613b2d575b50613b035767ffffffffffffffff86168015159081613af8575b50613ab55761363461360a368486612346565b867f0000000000000000000000000000000000000000000000000000000000000018438a33614cb9565b9733600052600060205260406000208660005260205260406000208960005260205260406000205460601c613a8b5765ffffffffffff606435166064350361078e5760c435926bffffffffffffffffffffffff8416840361078e576bffffffffffffffffffffffff6136b08565ffffffffffff606435166134cb565b1665ffffffffffff608435166084350361078e576bffffffffffffffffffffffff60e4351660e4350361078e57613704906bffffffffffffffffffffffff61169e60e43565ffffffffffff608435166134cb565b9733600052600060205260406000208860005260205260406000208b60005260205260406000207fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060a43560601b1665ffffffffffff606435166bffffffffffff00000000000060843560301b16171781556bffffffffffffffffffffffff86167fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060018301541617600182015561380560e43560018301907fffffffffffffffff000000000000000000000000ffffffffffffffffffffffff77ffffffffffffffffffffffff00000000000000000000000083549260601b169116179055565b67ffffffffffffffff6101043516610104350361078e57600101805477ffffffffffffffffffffffffffffffffffffffffffffffff167fffffffffffffffff0000000000000000000000000000000000000000000000006101043560c01b161790558a9582908861387533613e5d565b956040519a8b9760208901600090528b60218a01528051908160418b0191602001916138a09261202a565b8801916041830137019260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016604184015260643560d01b7fffffffffffff0000000000000000000000000000000000000000000000000000166049840152604f83013701604f81016000905203602f81018552604f016139239085611fae565b61392c90613532565b906040519085825260643565ffffffffffff16602083015260843565ffffffffffff16604083015260a43573ffffffffffffffffffffffffffffffffffffffff1660608301526bffffffffffffffffffffffff16608082015260e4356bffffffffffffffffffffffff1660a08201526101043567ffffffffffffffff1660c082015260e07f1b7379b49b96ce33cfd9daf95718231650c40a2c92da579412e588601186772791a36139dc916140db565b6139e5916134ee565b6fffffffffffffffffffffffffffffffff9081811691823410613a3a575050803411613a12575060009190565b3403613a368173ffffffffffffffffffffffffffffffffffffffff60a4351661428b565b9190565b6040517f030748b50000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff928316600482015234919091169091166024820152604490fd5b60046040517f068a62ee000000000000000000000000000000000000000000000000000000008152fd5b6040517f2d098d5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff428116600483015287166024820152604490fd5b9050421015386135f7565b60046040517f17d0b6db000000000000000000000000000000000000000000000000000000008152fd5b9050156126e1577fff0000000000000000000000000000000000000000000000000000000000000060208201511615386135dd565b60046040517f9f994b4b000000000000000000000000000000000000000000000000000000008152fd5b60046040517f6a1a6afe000000000000000000000000000000000000000000000000000000008152fd5b92919493948560211161078e578360005260016020526040600020602060405180928486833784820190815203019020600184013560005260205260406000205480158015613c6a575b613c22575094613c1a612a969392612a9c96973691612346565b503691612346565b604490613c30368987612346565b60208151910120604051917f48ce7fac00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b50613c76368886612346565b60208151910120811415613c00565b9081602091031261078e575161ffff8116810361078e5790565b604051906060820182811067ffffffffffffffff821117611f475760405260006040838281528260208201520152565b613cd7613c9f565b928260011161078e576001823560f81c03613df5578260051161078e57600182013560e01c60408501528260061161078e5760058201906042823560f81c0291826006018060051161078e57851061078e57613ddc90946001840194816039613d4f613d488360068a0181876122b9565b3691612346565b602081519101206040516020810191825260208152613d6d81611f2b565b51902096613dd0612782601083018d613d8b82600e8701898b6122b9565b7fffff00000000000000000000000000000000000000000000000000000000000091358281169160028110613de0575b5050905060f01c9052603084019086886122b9565b60208c015201916122b9565b9091565b8391925060020360031b1b1616803880613dbb565b60046040517fbcd5ac7a000000000000000000000000000000000000000000000000000000008152fd5b61228a9492606092825260208201528160408201520191612197565b613e536040929594939560608352606083019061204d565b9460208201520152565b73ffffffffffffffffffffffffffffffffffffffff604051917f1400000000000000000000000000000000000000000000000000000000000000602084015260006021840152166041820152604181526080810181811067ffffffffffffffff821117611f475760405290565b8115613ed4570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b610100811015613f19576003600191821b040190565b60046040517f9308529b000000000000000000000000000000000000000000000000000000008152fd5b6040908151613f5181611f2b565b606081526000928360208093015273ffffffffffffffffffffffffffffffffffffffff9063ffffffff8151947ff951975a0000000000000000000000000000000000000000000000000000000086521660048501528484602481857f000000000000000000000000ee91c335eab126df5fdb3797ea9d6ad93aec9722165afa9485156140d0578095613fe6575b505050505090565b9091929394503d8082873e613ffb8187611fae565b850190848683031261079357855167ffffffffffffffff968782116105ec57019383858403126104b25783519661403188611f2b565b85519081116105ec5785019183601f840112156107935782519261406061405785611fef565b96519687611fae565b838652878087019460051b8201019485116104b257918780969497959301915b8383106140a6575050505061409893508552016121d6565b908201523880808080613fde565b918094965096909294965183811681036105ec578152870195879590949093909290860191614080565b9051903d90823e3d90fd5b919073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ee91c335eab126df5fdb3797ea9d6ad93aec97221692604080948151907f1a90a2190000000000000000000000000000000000000000000000000000000082526020948583600481855afa8015612946578693600091614224575b50906141a36fffffffffffffffffffffffffffffffff6141e6949316998a97815193849188830152614194815180928a868601910161202a565b81010386810184520182611fae565b84519586809481937fb19a437e0000000000000000000000000000000000000000000000000000000083526000600484015260606024840152606483019061204d565b600f604483015203925af190811561421a5750614201575050565b8161421792903d106119b9576119aa8183611fae565b50565b513d6000823e3d90fd5b929450509181813d8311614254575b61423d8183611fae565b8101031261078e57518692859290916141a361415a565b503d614233565b3d15614286573d9061426c8261230c565b9161427a6040519384611fae565b82523d6000602084013e565b606090565b81471061434557600080809373ffffffffffffffffffffffffffffffffffffffff8294165af16142b961425b565b50156142c157565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152fd5b602161263e91939293846040519586927ffd000000000000000000000000000000000000000000000000000000000000006020850152848401378101600083820152036001810185520183611fae565b9161263e947fffffffffffff000000000000000000000000000000000000000000000000000060b0957fffffffffffffffff000000000000000000000000000000000000000000000000939998949960416040519b8c987f010000000000000000000000000000000000000000000000000000000000000060208b015260218a01528189013760828701521660a28501521660a883015261449d815180926020868601910161202a565b8101036090810185520183611fae565b93919290948160211161078e57846000526001602052604060002060206040518092826144e08b8481519384920161202a565b8201908152030190206001850135600052602052604060002054614b4d57846000526001602052604060002060206040518092826145248b8481519384920161202a565b820190815203019020600185013560005260205260016040600020558160a31161078e57608f84013560601c8260621161078e578060005260036020526040600020866000526020526040600020548751602089012003614a40578260ab1161078e5760a385013560c01c8015159081614a36575b506148ef578260b11161078e57600060405180927fd00689b600000000000000000000000000000000000000000000000000000000825288600483015260018801356024830152608060448301526041608483015260416021890160a48401378260e5830152610100606483015281838161463f61010482018c60b17fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f8d019101612197565b039260ab8b013560d01cf16000918161486c575b50614812575061466161425b565b505a65ffffffffffff603f60ab87013560d01c041611612ef6576148046147bf6001927f6025efc987827001c12f1f5c8b7831a6439083c88f60686671451fe479ec6e32957fffffffffffff000000000000000000000000000000000000000000000000000061478760209761477e604051917fff000000000000000000000000000000000000000000000000000000000000008b8401528c60b17fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f8301910160218501378201827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7091600083820152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff50810184520182611fae565b935b5a9061237d565b60d01b167fffffffffffffffff0000000000000000000000000000000000000000000000004260c01b169160218a01878b01356143f3565b9687518489012087600052838552604060002085604051809285516147e78184868a0161202a565b820190815203019020848801356000528552604060002055613532565b93604051958652013593a390565b602092506147bf6001927f6025efc987827001c12f1f5c8b7831a6439083c88f60686671451fe479ec6e32957fffffffffffff00000000000000000000000000000000000000000000000000006147876148049593614780565b9091503d806000833e61487f8183611fae565b81019060208183031261078e5780519067ffffffffffffffff821161078e5782601f83830101121561078e5781810151906148b98261230c565b936148c76040519586611fae565b82855260208385840101011161078e5760206148e89381860192010161202a565b9038614653565b50508060b19592951161078e5760016148047f6025efc987827001c12f1f5c8b7831a6439083c88f60686671451fe479ec6e32936149547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f6020950160b188016143a3565b97614a1160b0604051809b888201947f01000000000000000000000000000000000000000000000000000000000000008652888c01356021840152604160218d018185013760828301527f800000000000000000000000000000000000000000000000000000000000000060a28301527fffffffffffffffff0000000000000000000000000000000000000000000000004260c01b1660a8830152614a01815180928b868601910161202a565b810103609081018c52018a611fae565b8851902087600052838552604060002085604051809285516147e78184868a0161202a565b9050421138614599565b50908060b11161078e576148046147bf6001927f6025efc987827001c12f1f5c8b7831a6439083c88f60686671451fe479ec6e32957fffffffffffff0000000000000000000000000000000000000000000000000000614787602097614780604051957ffe000000000000000000000000000000000000000000000000000000000000008b8801528c60b17fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f8301910160218901378601867fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7091600083820152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff50810188520186611fae565b60046040517fe954aba2000000000000000000000000000000000000000000000000000000008152fd5b604090929192019163ffffffff614b9081855116613f43565b9384515115614c7757816020860151164211614c1e575b5050614bb4835151613f03565b8210614bde57614bc393612710565b9015614bd9575060019060405161274e81611f92565b600091565b50505050600090604051614bf181611f2b565b600981527f6e6f2071756f72756d0000000000000000000000000000000000000000000000602082015290565b51811690614c2a6121e7565b1603614c37573880614ba7565b50505050600090604051614c4a81611f2b565b601881527f677561726469616e207365742068617320657870697265640000000000000000602082015290565b505050505050600090604051614c8c81611f2b565b601481527f696e76616c696420677561726469616e20736574000000000000000000000000602082015290565b9460b0929194614d5d947fffffffffffffffffffffffffffffffffffffffff000000000000000000000000937fffffffffffffffff000000000000000000000000000000000000000000000000604051988996602088019b813060601b168d5260601b16603488015260c01b166048860152605085015260708401526090830152614d4d815180926020868601910161202a565b8101036090810184520182611fae565b51902090565b929788929997959496919965ffffffffffff809b81831692828216841115614f14575b506bffffffffffffffffffffffff9b8c9283921602169b8c965a900399169489861115614f0b575b8188168a029b8c9889890197021692021601918383039060008080808573ffffffffffffffffffffffffffffffffffffffff98898b8492149788614f01575b1690f115614eaf575b5050811694811691828614614e855750600080808086819681159788614e7c575bf115614e2f575b505050614e2a9161428b565b929190565b600093508392839283928391614e72575b7f0000000000000000000000000000000099263f0735d03bb2787ce8fb84f6ed6e1690f1156122955783853880614e1e565b6108fc9150614e40565b506108fc614e17565b9050600094858095508094508093508215614ea6575bf11561229557929190565b506108fc614e9b565b600093965083929550829182918290614ef8575b887f0000000000000000000000000000000099263f0735d03bb2787ce8fb84f6ed6e1690f11561229557869288923880614df6565b506108fc614ec3565b6108fc9250614ded565b98508498614dae565b905038614d86565b939791839b9995979a939165ffffffffffff809181841693828216851115615161575b506bffffffffffffffffffffffff9e8f938492160216965a90039a16928a841115615158575b818a168b029d8e88019a8b95021692021601958187039060008080808573ffffffffffffffffffffffffffffffffffffffff9c8d8099849214978861514e575b1690f115615103575b5050809116981698888a146150e15767ffffffffffffffff8094169182156150b4574285160384169363a8c0000085116150ab575b92938493168290036000811361507f57615001935060000302613eca565b019586915b600080808086819681159788615076575bf11561502c575b5050614e2a9103809461428b565b6000809381938293839161506c575b7f0000000000000000000000000000000099263f0735d03bb2787ce8fb84f6ed6e1690f1156122955784388061501e565b6108fc915061503b565b506108fc615017565b90508181101561509d576150939202613eca565b9003958691615006565b505050506000958691615006565b60009450614fe3565b5097945050968791508692600080808086819681159788614e7c57f115614e2f57505050614e2a9161428b565b9760008096925080955080945080939a508215614ea657f11561229557929190565b6000809350809281928290615145575b8a7f0000000000000000000000000000000099263f0735d03bb2787ce8fb84f6ed6e1690f11561229557843880614fae565b506108fc615113565b6108fc9250614fa5565b99508299614f65565b905038614f3f56fea2646970667358221220650436a56158a64f21f64a45b35532f08d567f83e44ecf57f2389ce0c20ad58064736f6c63430008160033

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

0000000000000000000000000000000099263f0735d03bb2787ce8fb84f6ed6e000000000000000000000000ee91c335eab126df5fdb3797ea9d6ad93aec9722

-----Decoded View---------------
Arg [0] : sendLostGasTo (address): 0x0000000099263f0735D03bB2787cE8FB84f6ED6E
Arg [1] : wormhole_ (address): 0xEe91C335eab126dF5fDB3797EA9d6aD93aeC9722

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000099263f0735d03bb2787ce8fb84f6ed6e
Arg [1] : 000000000000000000000000ee91c335eab126df5fdb3797ea9d6ad93aec9722


Deployed Bytecode Sourcemap

1304:3702:3:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1750:27:4;;1304:3702:3;1750:27:4;;;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1298:27:4;1304:3702:3;1298:27:4;;;1304:3702:3;;;;;;;;;;;;;;;;;;;;1192:24:4;1304:3702:3;1192:24:4;;;1304:3702:3;;;;;1633:35:4;1304:3702:3;1633:35:4;;;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;1400:23:4;1304:3702:3;1400:23:4;;;1304:3702:3;;;;;795:37:4;1304:3702:3;795:37:4;;;1304:3702:3;;;;;;;;;;1510:34:4;1304:3702:3;1510:34:4;;;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;13444:10:1;;;;1304:3702:3;;;;13418:25:1;1304:3702:3;;;;;;;;;;;;;;13414:198:1;;13626:26;;13622:67;;13444:10;1304:3702:3;;13700:21:1;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;13946:95:1;1304:3702:3;;;;;;;;;;;;13418:25:1;1304:3702:3;;;;;;;;2849:3:2;1304:3702:3;2849:3:2;;;:::i;:::-;1304:3702:3;;;;;13813:25:1;13444:10;;1304:3702:3;;13418:25:1;1304:3702:3;;;;;;;;;;;;;;;;;13444:10:1;;;;1304:3702:3;;;;;;;;;;;;;;;;;;:::i;:::-;13946:95:1;;;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13946:95:1;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;13418:25:1;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1304:3702:3;;;;;;;;;;;;;;13622:67:1;1304:3702:3;;13661:28:1;;;;13414:198;13444:10;1304:3702:3;;13546:21:1;1304:3702:3;;;;;;;;;;;;;;;13501:111:1;;;;;;1304:3702:3;;;;;;;;;;;;:::i;:::-;13501:111:1;;;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2670:3:2;;;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1510:34:4;1304:3702:3;;1510:34:4;;1304:3702:3;1510:34:4;;:14;1304:3702:3;1510:14:4;1304:3702:3;1510:34:4;;;;;;;;;;;;1304:3702:3;;;;;;;;;;1510:34:4;1304:3702:3;1510:34:4;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;795:37:4;1304:3702:3;;795:37:4;;1304:3702:3;795:37:4;;:14;1304:3702:3;795:14:4;1304:3702:3;795:37:4;;;;;;;;;;;1304:3702:3;795:37:4;1304:3702:3;;;;;;;;;795:37:4;;;;;;;;;;;;;;;;;;:::i;:::-;;;1304:3702:3;;;;;;;795:37:4;1304:3702:3;;:::i;:::-;795:37:4;;;;;;-1:-1:-1;795:37:4;;;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;1400:23:4;1304:3702:3;;1400:23:4;;1304:3702:3;1400:23:4;;:14;1304:3702:3;1400:14:4;1304:3702:3;1400:23:4;;;;;;;;;;;;1304:3702:3;;;;;;;;;1400:23:4;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;1069:18:6;1304:3702:3;1261:42:6;1304:3702:3;;;;;;:::i;:::-;;;;:::i;:::-;;1069:18:6;:::i;:::-;1261:42;;;;;;;;;;:::i;:::-;1304:3702:3;;;;;;1853:2:2;;;;;3734:24:3;1853:2:2;;3704:54:3;3700:87;;1304:3702;;;;;4012:17;;1304:3702;;;;;;;;;;;;;;;;;:::i;:::-;1853:2:2;;;1746:1;;;;1853:2;;;61662:10:1;1746:1:2;;;61786:36:1;1746:1:2;;1853:2;;;;;;;;;;;2126;1853;;;;;;2016;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62059:121:1;;1304:3702:3;;;62347:25:1;1304:3702:3;;;;;;;;;;;;;;;;;62465:35:1;;62424:76;62420:119;;3395:3:2;1853:2;;;62553:114:1;;;;;1304:3702:3;;;1853:2:2;1304:3702:3;;;62553:114:1;1853:2:2;1304:3702:3;;;;;62553:114:1;;;;;;;1304:3702:3;62553:114:1;;1853:2:2;;;62553:114:1;;;;;:::i;:::-;;;;;;;;;;;61782:1048;1304:3702:3;;;62686:74:1;1304:3702:3;62686:74:1;1304:3702:3;;;62686:74:1;;;;;:::i;62553:114::-;1304:3702:3;;;;;;;;;;;;-1:-1:-1;1304:3702:3;62686:74:1;;62553:114;;1304:3702:3;;;;;;;;;;62553:114:1;1304:3702:3;;;;;;;;;62553:114:1;1304:3702:3;;;62420:119:1;1304:3702:3;;;62509:30:1;;;;62059:121;1304:3702:3;;;62157:23:1;;;;1853:2:2;1304:3702:3;;;1853:2:2;1304:3702:3;;;61782:1048:1;1304:3702:3;;;62798:21:1;;;;1746:1:2;1304:3702:3;1746:1:2;;;;;;;;3700:87:3;1304:3702;;;3767:20;;;;1853:2:2;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;4115:80:1;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;918:4:17;895:29;918:4;895:29;:::i;1304:3702:3:-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;1080:34:4;;;;;1304:3702:3;1080:34:4;;1304:3702:3;1080:34:4;;;1304:3702:3;1080:14:4;1304:3702:3;1080:34:4;;;;;;;1304:3702:3;1080:34:4;;;;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1261:42:6;1304:3702:3;;;1069:18:6;1304:3702:3;;;;;;:::i;1069:18:6:-;1261:42;;;;;;;;:::i;:::-;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;1633:35:4;1304:3702:3;;1633:35:4;;1304:3702:3;1633:35:4;;:14;1304:3702:3;1633:14:4;1304:3702:3;1633:35:4;;;;;;;;;;;1304:3702:3;1633:35:4;1304:3702:3;;;;;;;1633:35:4;;;;;;;;;;;;;;;;;;:::i;:::-;;;1304:3702:3;;;;1633:35:4;1304:3702:3;;;1633:35:4;;;;;;;-1:-1:-1;1633:35:4;;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;1192:24:4;1304:3702:3;;1192:24:4;;1304:3702:3;1192:24:4;;:14;1304:3702:3;1192:14:4;1304:3702:3;1192:24:4;;;;;;;;;;;;1304:3702:3;;;;;;;;;;;;;;;;;;;;;2198:21;1304:3702;;2198:21;;1304:3702;2198:21;;:8;1304:3702;2198:8;1304:3702;2198:21;;;;;;;;;;;1304:3702;;;;;;;2198:21;1304:3702;;;;2198:21;;;;;;;;;;;;;;;;;:::i;:::-;;;1304:3702;;;;;2198:21;;;;;;-1:-1:-1;2198:21:3;;;1304:3702;;;;;;;;;;;;;;;;;;;;;;;;;;3171:41:1;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;219:30:17;247:2;219:30;;335:69;;18013:4228:1;1304:3702:3;;;18013:4228:1;:::i;:::-;1304:3702:3;;;;;;;;;;335:69:17;1304:3702:3;;;381:23:17;;;;1304:3702:3;;;;;;;;;;;;;1298:27:4;1304:3702:3;;1298:27:4;;1304:3702:3;1298:27:4;;:14;1304:3702:3;1298:14:4;1304:3702:3;1298:27:4;;;;;;;;;;;;1304:3702:3;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15109:35:1;15105:69;;15394:26;1304:3702:3;;15329:41:1;1304:3702:3;;;15248:51:1;1304:3702:3;;;;15248:51:1;:::i;:::-;1304:3702:3;;;;;15329:41:1;:::i;:::-;1304:3702:3;15394:26:1;;:::i;:::-;2849:3:2;;;;;;15482:9:1;:16;15478:76;;15596:28;;;;15831:42;1304:3702:3;15596:28:1;;;1304:3702:3;15942:121:1;15596:28;;;1304:3702:3;15687:45:1;15596:55;1304:3702:3;;;;;;15596:55:1;:::i;:::-;1304:3702:3;;;;;;15687:45:1;:::i;:::-;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;15831:42:1;1304:3702:3;;;;;;;;;;15942:121:1;1304:3702:3;;15478:76:1;1304:3702:3;;15507:47:1;;;2849:3:2;;;;15507:47:1;;;2849:3:2;;;15482:9:1;2849:3:2;;;;;;;;;;;1304:3702:3;;;2849:3:2;;13501:111:1;;;15105:69;1304:3702:3;;;15153:21:1;;;;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;1875:36:4;;;;;1304:3702:3;1875:36:4;;1304:3702:3;1875:36:4;;;1304:3702:3;1875:14:4;1304:3702:3;1875:36:4;;;;;;;1304:3702:3;1875:36:4;;;;1304:3702:3;;;;;;;;;;1875:36:4;1304:3702:3;1875:36:4;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;4035:74:1;1304:3702:3;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;1304:3702:3;;;-1:-1:-1;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;1604:49;1304:3702;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1426:35;1304:3702;;;;;;;;;;;;;;;;;;;939:47:4;1304:3702:3;939:47:4;;1304:3702:3;;939:47:4;;;1304:3702:3;;939:14:4;1304:3702:3;939:14:4;1304:3702:3;939:14:4;1304:3702:3;939:47:4;;;;;;;1304:3702:3;939:47:4;;;;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;1750:27:4;;;1304:3702:3;1750:27:4;;:14;1304:3702:3;1750:14:4;1304:3702:3;1750:27:4;;;;;;;;;;;;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;2849:3:2;1304:3702:3;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;;;;-1:-1:-1;;1304:3702:3;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;-1:-1:-1;1304:3702:3;;;;;-1:-1:-1;1304:3702:3;;;-1:-1:-1;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;1304:3702:3;;;;;;;;-1:-1:-1;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1304:3702:3;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::o;577:134:4:-;1304:3702:3;;;661:43:4;;;:14;:43;:14;1304:3702:3;661:14:4;1304:3702:3;661:43:4;;;;;;;;;;;654:50;577:134;:::o;661:43::-;;;;;;;;;;;;;;;;;:::i;:::-;;;1304:3702:3;;;;;;;:::i;:::-;577:134:4;:::o;661:43::-;;;-1:-1:-1;661:43:4;;;1304:3702:3;;;661:43:4;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;:::o;1853:2:2:-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;:::o;2849:3::-;;;;;;1304:3702:3;;;;2849:3:2;;;:::o;:::-;;;;;;;:::i;:::-;1304:3702:3;;;;;;;:::i;:::-;2849:3:2;;;;;;;;;;;;;;;;-1:-1:-1;2849:3:2;;1304:3702:3;;;;2849:3:2:o;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;66920:3792:1;;;;;;1746:1:2;;;;;67491:20:1;;1746:1:2;67487:88:1;;1853:2:2;;;;;1800:1;1853:2;;;1746:1;;1304:3702:3;;;;1800:1:2;1853:2;1304:3702:3;;;;;;1853:2:2;1304:3702:3;;;;;;;;;;;;;;;;;;;;;1853:2:2;1304:3702:3;;;;;68037:65:1;;1853:2:2;2670:3;1853:2;;;2611:3;1853:2;;2670:3;;;;;69432:13:1;;:44;;;;66920:3792;69428:109;;1853:2:2;;2126;1853;;;;2849:3;1853:2;;;2670:3;1304:3702:3;;4240:764;1304:3702;;;69998:79:1;1304:3702:3;2849:3:2;1304:3702:3;;2849:3:2;1304:3702:3;;;2849:3:2;;;1746:1;1853:2;2849:3;;;;1853:2;2849:3;;1304:3702:3;1853:2:2;;;;2849:3;;;1304:3702:3;2670:3:2;1304:3702:3;;;2849:3:2;;;;1304:3702:3;2849:3:2;1853:2;;;;;2849:3;;;1304:3702:3;;;;;;;;;2849:3:2;;;;;;;;;:::i;:::-;1304:3702:3;;2849:3:2;;;;;;;;;;;;:::i;:::-;;;1853:2;2849:3;;1304:3702:3;2849:3:2;;;1304:3702:3;69998:79:1;;;2849:3:2;;;:::i;:::-;;4240:764:3;:::i;:::-;2849:3:2;;70381:9:1;;;2849:3:2;;;;70373:26:1;;;70369:337;;66920:3792;;;;:::o;70369:337::-;70419:25;;;;;;;70415:214;;-1:-1:-1;;1304:3702:3;70649:46:1;;;2849:3:2;;;;70649:46:1;;;2849:3:2;;;;;;;;;13501:111:1;70415:214;70381:9;;;70564:25;70381:9;;70564:25;70381:9;;;70564:25;:::i;:::-;70551:10;70564:25;:::i;:::-;70608:7::o;69428:109::-;1304:3702:3;;69485:52:1;;;2670:3:2;1304:3702:3;;;69485:52:1;;;1304:3702:3;69520:15:1;1304:3702:3;;;2670:3:2;;;1304:3702:3;2670:3:2;;13501:111:1;69432:44;69461:15;;69449:27;;;69432:44;;68037:65;68077:25;1304:3702:3;;68077:25:1;;;;67487:88;67549:26;1304:3702:3;;67549:26:1;;;;1746:1:2;;;;;;;;;;4413:2233:6;;;;4603:1;4638:16;;1304:3702:3;1746:1:2;;;;;1304:3702:3;4705:13:6;;;1304:3702:3;;4730:17:6;4746:1;4782:10;4603:1;4794:14;;;;;;6612:17;;;;;;;;;;4746:1;1304:3702:3;;;;;;:::i;:::-;4603:1:6;1304:3702:3;;4413:2233:6;:::o;4810:3::-;1746:1:2;;;;;;1304:3702:3;;;;1746:1:2;;;4864:17:6;1304:3702:3;;;;1746:1:2;;5122:28:6;1746:1:2;4933:38:6;4941:29;1304:3702:3;4746:1:6;1304:3702:3;;1746:1:2;;4941:29:6;:::i;:::-;4933:38;;:::i;:::-;1304:3702:3;;5022:38:6;5030:29;1304:3702:3;;;5030:29:6;;;;;:::i;5022:38::-;1304:3702:3;;5122:28:6;;;;:::i;:::-;5115:36;;1304:3702:3;1746:1:2;;;;;1304:3702:3;4746:1:6;1304:3702:3;;;;4810:3:6;1304:3702:3;;;;;5171:10:6;1304:3702:3;;;;;;;;;4967:2:6;;1304:3702:3;;;;5155:2:6;1304:3702:3;;;;;;;;;;;;;;4603:1:6;5215:24;;;4603:1;5215:24;4746:1;1304:3702:3;5215:24:6;;;;;1304:3702:3;5215:24:6;;4603:1;5215:24;1304:3702:3;5453:23:6;;;5449:54;;5597:6;;:35;;;;;4810:3;5595:38;;;5592:80;;5686:25;6160:30;;;;6156:69;;6377:16;;1304:3702:3;;;-1:-1:-1;1304:3702:3;;;;;;;;;;;;;6364:44:6;6361:119;;4810:3;;4746:1;1304:3702:3;4782:10:6;;6361:119;6427:38;;;;;;;;;;;;;1304:3702:3;4603:1:6;1304:3702:3;;;;;;:::i;:::-;;;;;;;6427:38:6;:::o;6156:69::-;6199:26;1304:3702:3;;6199:26:6;;;;5592:80;5642:30;1304:3702:3;;5642:30:6;;;;5597:35;1304:3702:3;5607:25:6;;;-1:-1:-1;5597:35:6;;;;5449:54;5485:18;1304:3702:3;;5485:18:6;;;;5215:24;1304:3702:3;;;4603:1:6;1304:3702:3;;;;;;4746:1:6;1304:3702:3;;;1853:2:2;;;1304:3702:3;;;-1:-1:-1;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;:::o;23429:2888:1:-;;23626:9;23772:26;;;23768:59;;1261:42:6;1304:3702:3;1069:18:6;1304:3702:3;;;:::i;1069:18:6:-;1261:42;;;;;;;:::i;:::-;1304:3702:3;;;;1853:2:2;;3623::3;1853::2;;;3734:24:3;1853:2:2;;;;3704:54:3;3700:87;;3623:2;1304:3702;;;;4012:17;;1304:3702;;;;;3623:2;1304:3702;;;3623:2;1304:3702;;;;;:::i;:::-;3623:2;1853::2;;24167:16:1;-1:-1:-1;1853:2:2;;;;1746:1;;;24217:10:1;;1746:1:2;;24242:36:1;;;1853:2:2;;;;;24331:90:1;1853:2:2;;;24553:87:1;1853:2:2;;;24331:90:1;;;:::i;:::-;24553:87;;:::i;:::-;2849:3:2;25930:9:1;;2849:3:2;;;;25922:26:1;;;25918:393;;23429:2888;;;:::o;25918:393::-;25968:25;;;;;;25964:214;;-1:-1:-1;;1304:3702:3;;26254:46:1;;;2849:3:2;;;;26254:46:1;;;2849:3:2;;;;;;;;;13501:111:1;25964:214;26113:25;25930:9;;;26113:25;25930:9;;;26113:25;:::i;24238:1582::-;24661:36;;;;;;;;;1746:1:2;24661:36:1;;24657:1163;1746:1:2;;;1853:2;;;;;;;;;;;;2126;1853;;;;;;2016;1304:3702:3;;;;;3623:2;1304:3702;;;;;;;3623:2;1304:3702;;;;1853:2:2;;;;1304:3702:3;;3623:2;1304:3702;;;;1501:4:2;1304:3702:3;;36248:28:1;;1304:3702:3;;;;36586:25:1;36582:59;;1853:2:2;;;2016;1304:3702:3;;;;;3623:2;1304:3702;;;;;;;3623:2;1304:3702;;;;1853:2:2;;;;1304:3702:3;;3623:2;1304:3702;;1501:4:2;1304:3702:3;;;;;;;;1853:2:2;;;2016;1304:3702:3;;;;36921:25:1;3623:2:3;1304:3702;;;;;;;3623:2;1304:3702;;;;;;;3623:2;1304:3702;;37237:46:1;37196:87;37192:130;;1853:2:2;;;3395:3;1853:2;;;1304:3702:3;;;37602:133:1;;1304:3702:3;;;37602:133:1;;;;1853:2:2;3623::3;37602:133:1;;;;;;1853:2:2;;;;;;;;;37602:133:1;;;;;:::i;:::-;;1853:2:2;37602:133:1;;;;;;:::i;:::-;37767:775;1853:2:2;;;;;2016;1304:3702:3;;;;;;;37767:775:1;39626:8;39622:79;;24657:1163;1853:2:2;;;3216:3;1853:2;;;;;;;3216:3;;;1853:2;;3157:3;1853:2;;;41208:282:1;1304:3702:3;;41208:282:1;1304:3702:3;1853:2:2;1304:3702:3;;40588:498:1;1304:3702:3;;1853:2:2;;;;2670:3;;;;;;;;1304:3702:3;;1853:2:2;3157:3;1853:2;;;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;40588:498:1;;:::i;:::-;1304:3702:3;;;41102:91:1;1304:3702:3;;1853:2:2;41102:91:1;1853:2:2;;;;;;41102:91:1;;;:::i;:::-;;;;2670:3:2;41208:282:1;2849:3:2;41208:282:1;;:::i;:::-;1304:3702:3;;;;1853:2:2;;;;;2849:3;;;;1304:3702:3;;41208:282:1;;2510:4;;;;;;;;;;;1304:3702:3;;;;;;;2510:4:1;;;1304:3702:3;;2510:4:1;;;1304:3702:3;2849:3:2;;;;2510:4:1;;;2849:3:2;;2510:4:1;;2849:3:2;2510:4:1;41208:282;;;;24238:1582;;39622:79;39639:9;1304:3702:3;;;;;;;2510:4:1;1304:3702:3;-1:-1:-1;39636:65:1;39622:79;39636:65;;37602:133;1304:3702:3;;39678:23:1;;;;37192:130;37292:30;1304:3702:3;;37292:30:1;;;;36582:59;36620:21;1304:3702:3;;36620:21:1;;;;24657:1163;24978:38;;;;;1746:1:2;24978:38:1;1746:1:2;;1853:2;;;2126;1853;;;;;;2016;1304:3702:3;;;;48076:25:1;3623:2:3;1304:3702;;;;;;;3623:2;1304:3702;;;;;;;3623:2;1304:3702;;48355:35:1;48314:76;48310:119;;1853:2:2;;;3639:3;1853:2;;;;;;2670:3;;;48850:15:1;;48838:27;;;;:44;;;24974:846;48834:109;;1853:2:2;;;3818:3;1853:2;;;2849:3;;50098:288:1;2849:3:2;;;1853:2;;;;;;2849:3;:::i;:::-;1853:2;3818:3;1853:2;;;;;;;2016;1304:3702:3;;50098:288:1;:::i;:::-;1853:2:2;;;;;;;;;;;50625:46:1;;50621:126;;1853:2:2;;;;2016;1304:3702:3;;;;;3623:2;1304:3702;;;;;;;3623:2;1304:3702;;;;1853:2:2;;;;1304:3702:3;;3623:2;1304:3702;;;;;1501:4:2;1304:3702:3;;42679:28:1;;1304:3702:3;;;;;42961:25:1;42957:59;;1853:2:2;43710:51:1;1853:2:2;;;;;;2016;1304:3702:3;;;;;3623:2;1304:3702;;;;;;;3623:2;1304:3702;;;;1853:2:2;;;;1304:3702:3;;3623:2;1304:3702;;1501:4:2;1304:3702:3;;;;;;;;1853:2:2;;;;43710:51:1;:::i;:::-;1304:3702:3;;43607:155:1;;2510:4;3623:2:3;43607:155:1;;;;;;;;;;1304:3702:3;1853:2:2;;;;2510:4:1;;;1304:3702:3;;2510:4:1;;;;;;;;;:::i;43607:155::-;43794:807;1853:2:2;;;;;2016;1304:3702:3;;;;;;;43794:807:1;44982:8;44978:79;;24974:846;1304:3702:3;45144:463:1;45732:275;1304:3702:3;;45732:275:1;1304:3702:3;;1853:2:2;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45144:463:1;;:::i;:::-;1304:3702:3;;;45623:94:1;1304:3702:3;;1853:2:2;45623:94:1;1853:2:2;;;;;;45623:94:1;;;:::i;:::-;;;;1304:3702:3;2670:3:2;45732:275:1;2849:3:2;45732:275:1;;:::i;:::-;1304:3702:3;;;;;;;;;;;;;2510:4:1;;;1304:3702:3;;;;2510:4:1;;;1304:3702:3;;;;2849:3:2;;;;;;2510:4:1;;;2849:3:2;;;;;;2510:4:1;;;2849:3:2;1853:2;;;;1304:3702:3;;;2510:4:1;;;;;44978:79;44995:9;;;;1304:3702:3;;;;;;;2510:4:1;1304:3702:3;-1:-1:-1;44992:65:1;;44978:79;;;;;50621:126;1304:3702:3;;;1853:2:2;1304:3702:3;;50680:67:1;;;;1853:2:2;;50680:67:1;;;1304:3702:3;;;;;50680:67:1;48834:109;1304:3702:3;;48891:52:1;;;2670:3:2;1304:3702:3;;;48891:52:1;;;1304:3702:3;48850:15:1;1304:3702:3;2670:3:2;;;1304:3702:3;2670:3:2;;13501:111:1;48838:44;48869:13;;;48838:44;;24974:846;25788:21;1304:3702:3;;25788:21:1;;;;1746:1:2;;;;;;;;;;3700:87:3;3767:20;1304:3702;;3767:20;;;;1304:3702;;;;;;;;;;;;;;;;;;;;;:::i;23768:59:1:-;23807:20;1304:3702:3;;23807:20:1;;;;1304:3702:3;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;2849:3:2;;;;;;;1304:3702:3;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;:::o;2928:4:1:-;;;;1304:3702:3;;;;;;;;2928:4:1;;;;;:::i;:::-;;;;;;;:::o;18013:4228::-;;;;;;1304:3702:3;18383:21:1;1304:3702:3;;18383:21:1;1304:3702:3;;;;;18383:21:1;1304:3702:3;;18383:35:1;18379:67;;18670:10;-1:-1:-1;1304:3702:3;18648:21:1;1304:3702:3;;18383:21:1;-1:-1:-1;1304:3702:3;;-1:-1:-1;1304:3702:3;;;;;18383:21:1;-1:-1:-1;1304:3702:3;18383:21:1;1304:3702:3;;;;;;:::i;:::-;;;;:::i;:::-;;;18718:37:1;18714:78;;1304:3702:3;;18842:1:1;18806:37;;:101;;;;18013:4228;18802:129;;;1304:3702:3;;;19574:13:1;;;:44;;;;18013:4228;19570:106;;;10737:198;2849:3:2;;;;;:::i;:::-;2614:24:3;;10818:12:1;18670:10;;10737:198;:::i;:::-;18670:10;;-1:-1:-1;1304:3702:3;-1:-1:-1;1304:3702:3;;18383:21:1;-1:-1:-1;1304:3702:3;;-1:-1:-1;1304:3702:3;;;18383:21:1;-1:-1:-1;1304:3702:3;;-1:-1:-1;1304:3702:3;;;18383:21:1;-1:-1:-1;1304:3702:3;;;;60141:129:1;;1304:3702:3;;2928:4:1;1304:3702:3;;2928:4:1;;;;60370:28;1304:3702:3;;;;;;;;;;60343:55:1;2928:4;1304:3702:3;;2928:4:1;1304:3702:3;60343:55:1;:::i;:::-;1304:3702:3;;60428:19:1;2928:4;1304:3702:3;60428:19:1;2928:4;;;;1304:3702:3;60450:23:1;1304:3702:3;;60450:23:1;1304:3702:3;;;;60489:26:1;1304:3702:3;;60428:45:1;60450:23;1304:3702:3;;60428:19:1;2928:4;1304:3702:3;60428:45:1;:::i;60489:26::-;18670:10;;-1:-1:-1;1304:3702:3;-1:-1:-1;1304:3702:3;;18383:21:1;-1:-1:-1;1304:3702:3;;-1:-1:-1;1304:3702:3;;;18383:21:1;-1:-1:-1;1304:3702:3;;-1:-1:-1;1304:3702:3;;;18383:21:1;-1:-1:-1;1304:3702:3;;18383:21:1;1304:3702:3;;;;;;2928:4:1;1304:3702:3;;60428:19:1;2928:4;1304:3702:3;;;;;;;;;;;18842:1:1;1304:3702:3;;;;;18842:1:1;1304:3702:3;;;;60450:23:1;1304:3702:3;18842:1:1;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;;18842:1:1;1304:3702:3;;;;;2126:2:2;1304:3702:3;;2126:2:2;;;1304:3702:3;;;;;;;18670:10:1;20339:26;18670:10;20339:26;:::i;:::-;1304:3702:3;18383:21:1;1304:3702:3;2928:4:1;;;1304:3702:3;2928:4:1;;-1:-1:-1;2849:3:2;;2928:4:1;;;;1304:3702:3;;;2928:4:1;;;;;;1304:3702:3;2928:4:1;;;;;:::i;:::-;;;;;;;1304:3702:3;;2126:2:2;;;;;2928:4:1;1304:3702:3;;2849:3:2;1304:3702:3;2928:4:1;;;;;;;;;;;;1304:3702:3;;2928:4:1;1304:3702:3;;-1:-1:-1;1304:3702:3;;2928:4:1;;;;;;;;;;;;:::i;:::-;20837:150;;;:::i;:::-;1304:3702:3;18383:21:1;1304:3702:3;;;;;;2928:4:1;1304:3702:3;;;2928:4:1;;1304:3702:3;60428:19:1;2928:4;1304:3702:3;;18383:21:1;2928:4;;1304:3702:3;18383:21:1;1304:3702:3;;;;2928:4:1;;1304:3702:3;;;60450:23:1;2928:4;;1304:3702:3;60450:23:1;1304:3702:3;;;;2928:4:1;;1304:3702:3;;;;;2126:2:2;2928:4:1;;1304:3702:3;2928:4:1;20837:150;;;21567:36;;;:::i;:::-;;;;:::i;:::-;2849:3:2;;;;;21703:9:1;;;:15;21699:73;;21703:9;;;;21896:15;21892:294;;22205:29;-1:-1:-1;22205:29:1;18013:4228;:::o;21892:294::-;21703:9;2928:4;22097:18;1304:3702:3;;18383:21:1;1304:3702:3;;22097:18:1;:::i;:::-;22134:37;;:::o;21699:73::-;18383:21;1304:3702:3;21727:45:1;;;2849:3:2;;;;21727:45:1;;;2849:3:2;21703:9:1;2849:3:2;;;;;;;;;;;;;13501:111:1;60141:129;60246:24;18383:21;1304:3702:3;60246:24:1;;;;19570:106;18383:21;1304:3702:3;19627:49:1;;;1304:3702:3;19649:15:1;1304:3702:3;;19627:49:1;;;1304:3702:3;;;2670:3:2;;;1304:3702:3;2670:3:2;;13501:111:1;19574:44;19591:15;;;:27;;19574:44;;;18802:129;18916:15;18383:21;1304:3702:3;18916:15:1;;;;18806:101;1304:3702:3;;;;;1746:1:2;1304:3702:3;;;;1746:1:2;18847:60:1;18806:101;;;18714:78;18764:28;18383:21;1304:3702:3;18764:28:1;;;;18379:67;18427:19;18383:21;1304:3702:3;18427:19:1;;;;63632:1628;;;;;;1853:2:2;;;;;1304:3702:3;-1:-1:-1;1304:3702:3;1800:1:2;1853:2;1304:3702:3;;-1:-1:-1;1304:3702:3;1853:2:2;1304:3702:3;;;;;;;;;;;;;;;;;;1800:1:2;1853:2;;;-1:-1:-1;1304:3702:3;1853:2:2;1304:3702:3;;-1:-1:-1;1304:3702:3;;64515:27:1;;:80;;;;63632:1628;64511:165;;2849:3:2;;;;;;64737:81:1;2849:3:2;;;;;:::i;:::-;;;;;:::i;64511:165:1:-;1304:3702:3;;2849:3:2;;;;;:::i;:::-;1853:2;1304:3702:3;;;;64643:32:1;1304:3702:3;;64604:72:1;;;;;;;1304:3702:3;;;;;64604:72:1;64515:80;2849:3:2;;;;;;:::i;:::-;1853:2;1304:3702:3;;;;64563:32:1;64546:49;;;64515:80;;1304:3702:3;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;-1:-1:-1;1304:3702:3;;;;;;;;;;;;:::o;6830:2662:6:-;1304:3702:3;;:::i;:::-;1853:2:2;;7121:1:6;1853:2:2;;;7121:1:6;1304:3702:3;;;;7600:12:6;7597:47;;1853:2:2;7703:3:6;1853:2:2;;;7121:1:6;1853:2:2;;1304:3702:3;;;7655:19:6;;;1304:3702:3;1853:2:2;7823:3:6;1853:2:2;;;7703:3:6;1853:2:2;;1304:3702:3;7884:9:6;1304:3702:3;;;;;;;7823:3:6;1304:3702:3;1853:2:2;7703:3:6;1853:2:2;;;;-1:-1:-1;1853:2:2;;9458:17:6;7839:56;1853:2:2;7121:1:6;1853:2:2;;1304:3702:3;;;2849:3:2;8799:17:6;1304:3702:3;7823:3:6;1304:3702:3;;8799:17:6;;;:::i;:::-;2849:3:2;;;:::i;:::-;1304:3702:3;;;;;8860:15:6;7655:19;1304:3702:3;;;;;;;;;;;;;:::i;:::-;;8837:40:6;;1304:3702:3;9199:34:6;9207:25;1304:3702:3;;;;9122:24:6;1304:3702:3;;;;9122:24:6;;;:::i;:::-;1304:3702:3;;;;;;;9144:1:6;1304:3702:3;;;;6830:2662:6;1304:3702:3;;;;;;;;;;;9207:25:6;;;;:::i;9199:34::-;1304:3702:3;9179:17:6;;1304:3702:3;;9458:17:6;;:::i;:::-;9448:27;;6830:2662::o;1304:3702:3:-;;;;;9144:1:6;1304:3702:3;;;1853:2:2;1304:3702:3;;;;;;;7597:47:6;7621:23;1304:3702:3;;7621:23:6;;;;3395:3:2;;;;;;1304:3702:3;;3395:3:2;;;1304:3702:3;3395:3:2;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;1304:3702:3;3395:3:2;1304:3702:3;3395:3:2:o;428:387:17:-;1304:3702:3;;;;1746:1:2;1304:3702:3;;;2849:3:2;650:1:17;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;428:387:17;:::o;1304:3702:3:-;;;;;;;:::o;:::-;;;;;;;;;;9612:311:6;9822:3;9806:19;;;9802:50;;9891:1;1304:3702:3;;;;;;9612:311:6;:::o;9802:50::-;9834:18;1304:3702:3;;9834:18:6;;;;424:147:4;1304:3702:3;;;;;;;:::i;:::-;;;;-1:-1:-1;1304:3702:3;;;;;;;;;;;;528:36:4;1304:3702:3;528:36:4;;1304:3702:3;528:36:4;;;1304:3702:3;528:14:4;;1304:3702:3;528:14:4;;;1304:3702:3;528:36:4;;;;;;;;;;;424:147;521:43;;;;;424:147;:::o;528:36::-;;;;;;;;;;;;;;;;:::i;:::-;;;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;528:36:4;;;;;;;1304:3702:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;528:36:4;1304:3702:3;;;;;;;;;;4240:764;;;1304:3702;4557:8;1304:3702;;;;;;;4557:21;1304:3702;4557:21;;;;;;;;;;;;;;;;;;;;;4240:764;2849:3:2;;1304:3702:3;2849:3:2;1753:2:3;2849:3:2;;;1304:3702:3;;;;;;;;;;;;2928:4:1;1304:3702:3;;;;;;;;2928:4:1;;;:::i;:::-;;;1304:3702:3;;;;;;;;;:::i;:::-;;;4768:229;;;;;;1304:3702;4768:229;;4557:21;;4768:229;;1304:3702;1753:2;;;;;;;;;;:::i;:::-;;;;;1304:3702;4768:229;;;;;;;;;;;;4240:764;;:::o;4768:229::-;;;;;;-1:-1:-1;4768:229:3;;;;;;:::i;:::-;;4240:764::o;4768:229::-;1304:3702;;4557:21;1304:3702;;;;;4557:21;;;;;;;;;;;;;;;;;;:::i;:::-;;;1304:3702;;;;;;;;;;;;4557:21;;;;;;;1304:3702;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;-1:-1:-1;1304:3702:3;;;;:::o;:::-;;;:::o;2647:312:0:-;2736:21;;:31;1304:3702:3;;2831:33:0;1304:3702:3;;;;;;;2831:33:0;;;;:::i;:::-;;1304:3702:3;;;2647:312:0:o;1304:3702:3:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2510:4:1;;;;;;;1304:3702:3;;;2510:4:1;;;1746:1:2;2510:4:1;;;2849:3:2;2510:4:1;;;1304:3702:3;;;-1:-1:-1;1304:3702:3;;;;2510:4:1;;;;;;;;;:::i;2307:::-;;;;2928;2307;;2670:3:2;2307:4:1;;;;;1853:2:2;1304:3702:3;;2307:4:1;;;1746:1:2;2307:4:1;;;2849:3:2;2307:4:1;;;1304:3702:3;2307:4:1;;;1304:3702:3;;;;;2928:4:1;2307;;;2928;2670:3:2;2307:4:1;;;2849:3:2;2928:4:1;1304:3702:3;;2307:4:1;;;;;;2928;;;:::i;:::-;;;2307;;;;;;;;;:::i;26442:8689::-;;;;;;1853:2:2;;;;;1304:3702:3;-1:-1:-1;1304:3702:3;1800:1:2;1853:2;1304:3702:3;;-1:-1:-1;1304:3702:3;1853:2:2;1304:3702:3;;;;;2928:4:1;1304:3702:3;;;;2928:4:1;;;;;:::i;:::-;;;1304:3702:3;;;;;;;1800:1:2;1853:2;;;-1:-1:-1;1304:3702:3;1853:2:2;1304:3702:3;;-1:-1:-1;1304:3702:3;;27314:60:1;;1304:3702:3;-1:-1:-1;1304:3702:3;1800:1:2;1853:2;1304:3702:3;;-1:-1:-1;1304:3702:3;1853:2:2;1304:3702:3;;;;;2928:4:1;1304:3702:3;;;;2928:4:1;;;;;:::i;:::-;;;1304:3702:3;;;;;;;1800:1:2;1853:2;;;-1:-1:-1;1304:3702:3;1853:2:2;1304:3702:3;1800:1:2;1304:3702:3;-1:-1:-1;1304:3702:3;;1853:2:2;2611:3;1853:2;;;2436:3;1853:2;;2016;1304:3702:3;;1853:2:2;2126;1853;;;1304:3702:3;-1:-1:-1;1304:3702:3;28328:25:1;1853:2:2;1304:3702:3;;-1:-1:-1;1304:3702:3;;-1:-1:-1;1304:3702:3;1853:2:2;1304:3702:3;;-1:-1:-1;1304:3702:3;;;;1853:2:2;2928:4:1;;28695:41;28659:77;28655:1477;;1853:2:2;2670:3;1853:2;;;2611:3;1853:2;;2670:3;;;30438:13:1;;;:43;;;;26442:8689;30434:1440;;;1853:2:2;2849:3;1853:2;;;-1:-1:-1;1304:3702:3;;32665:147:1;;1304:3702:3;32665:147:1;;;;;;1304:3702:3;1800:1:2;1853:2;;;2789:3;;;1304:3702:3;2789:3:2;;;;;1853:2;2789:3;;;1304:3702:3;1853:2:2;;;;1304:3702:3;;;;;;;;;2789:3:2;;;;;1304:3702:3;;;2789:3:2;1304:3702:3;;;1853:2:2;2849:3;1853:2;;;;;2789:3;:::i;:::-;32665:147:1;1853:2:2;2670:3;1853:2;;3216:3;;;32665:147:1;-1:-1:-1;;32665:147:1;;;26442:8689;-1:-1:-1;32661:1098:1;;32895:864;;;:::i;:::-;;33299:9;3216:3:2;1304:3702:3;2670:3:2;1853:2;;3216:3;;;2510:4:1;1304:3702:3;-1:-1:-1;33296:62:1;;34936:85;33890:498;1800:1:2;1304:3702:3;34936:85:1;1304:3702:3;2928:4:1;34097:20;1853:2:2;1304:3702:3;2510:4:1;1304:3702:3;;2510:4:1;1746:1:2;2510:4:1;;;2849:3:2;1853:2;2849:3;1853:2;;;;;;2510:4:1;;1304:3702:3;;;;;;-1:-1:-1;1304:3702:3;;;;2510:4:1;;;;;;;;;:::i;:::-;32661:1098;;34108:9;34097:20;;:::i;:::-;3216:3:2;2928:4:1;;2670:3:2;34257:15:1;2670:3:2;2126:2;;1853;;;;;;;;33890:498:1;:::i;:::-;1304:3702:3;;;;;;34590:32:1;1304:3702:3;-1:-1:-1;1304:3702:3;;;;;-1:-1:-1;1304:3702:3;;;;;;;;2928:4:1;;;;;;;:::i;:::-;;;1304:3702:3;;;;;;;1853:2:2;;;;-1:-1:-1;1304:3702:3;;;;-1:-1:-1;1304:3702:3;;34936:85:1;:::i;:::-;1304:3702:3;;;;;;1853:2:2;;34936:85:1;;26442:8689;:::o;32661:1098::-;1853:2:2;32862:21:1;;33890:498;1800:1:2;32862:21:1;34936:85;32862:21;2928:4;34097:20;34936:85;32862:21;32661:1098;;;32665:147;;;;;;-1:-1:-1;32665:147:1;;;;;;:::i;:::-;;;2789:3:2;1853:2;2789:3;;;;;;;;;2670;2789;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1304:3702:3;;;;;;;:::i;:::-;2789:3:2;;;1853:2;2789:3;;;;;;;;;1853:2;2789:3;;;;;;;;;:::i;:::-;32665:147:1;;;;30434:1440;1853:2:2;;;2849:3;1853:2;;;;;;1800:1;31736:85:1;;1853:2:2;30515:108:1;1853:2:2;;;;2849:3;1853:2;;30515:108:1;:::i;:::-;1304:3702:3;2307:4:1;;1304:3702:3;;2307:4:1;;;;;2849:3:2;1746:1;2849:3;;1853:2;;;;;2307:4:1;;1304:3702:3;1853:2:2;;;;2307:4:1;;;1304:3702:3;;;;;2928:4:1;2307;;;2928;2670:3:2;31260:15:1;2670:3:2;2126:2;;2307:4:1;;;2849:3:2;2928:4:1;1304:3702:3;;2307:4:1;;;;;;2928;;;:::i;:::-;;;2307;;;;;;;;;:::i;:::-;1304:3702:3;;31609:32:1;;1304:3702:3;-1:-1:-1;1304:3702:3;;;;;-1:-1:-1;1304:3702:3;;;;;;;;2928:4:1;;;;;;;:::i;30438:43::-;30466:15;;;-1:-1:-1;30438:43:1;;;28655:1477;1853:2:2;;;2849:3;1853:2;;;29994:85:1;29106:531;1800:1:2;1304:3702:3;29994:85:1;1304:3702:3;2928:4:1;29334:20;1853:2:2;1304:3702:3;2510:4:1;1304:3702:3;;2510:4:1;1746:1:2;2510:4:1;;;2849:3:2;1853:2;2849:3;1853:2;;;;;;2510:4:1;;1304:3702:3;;;;;;-1:-1:-1;1304:3702:3;;;;2510:4:1;;;;;;;;;:::i;27314:60::-;27353:21;1304:3702:3;;27353:21:1;;;;1678:2240:6;2016:19;1678:2240;;;;2016:19;1304:3702:3;;2001:35:6;1304:3702:3;;;;2001:35:6;:::i;:::-;2500:16;;;1304:3702:3;2500:28:6;2497:95;;2718:26;;;;1304:3702:3;;2747:15:6;-1:-1:-1;2714:206:6;;1678:2240;3431:16;;3424:31;3431:16;;1304:3702:3;3424:31:6;:::i;:::-;3404:51;;3400:108;;3647:51;;;:::i;:::-;3711:16;;3708:74;;3894:17;3902:4;1304:3702:3;2016:19:6;1304:3702:3;;;;:::i;3708:74:6:-;-1:-1:-1;;3742:29:6:o;3400:108::-;3470:27;;;;-1:-1:-1;1304:3702:3;2016:19:6;1304:3702:3;;;;:::i;:::-;;;;;2718:26:6;1304:3702:3;;;3470:27:6;:::o;2714:206::-;1304:3702:3;;;;2805:28:6;;:::i;:::-;1304:3702:3;2782:51:6;2778:132;;2714:206;;;;2778:132;2853:42;;;;-1:-1:-1;1304:3702:3;2016:19:6;1304:3702:3;;;;:::i;:::-;;;;;2718:26:6;1304:3702:3;;;2853:42:6;:::o;2497:95::-;2543:38;;;;;;-1:-1:-1;1304:3702:3;2016:19:6;1304:3702:3;;;;:::i;:::-;;;;;;;;;2543:38:6;:::o;9736:598:1:-;;1304:3702:3;9736:598:1;;;1304:3702:3;9736:598:1;2016:2:2;1304:3702:3;2670:3:2;1304:3702:3;;;;;;;;10086:4:1;;;1304:3702:3;;2016:2:2;1304:3702:3;;;;;;;;;2126:2:2;;;1304:3702:3;;;2849:3:2;1304:3702:3;;;;;;;;;;;;2928:4:1;1304:3702:3;;;;;;;;2928:4:1;;;:::i;:::-;;;1304:3702:3;;;;;;;;;:::i;:::-;;10017:310:1;;9736:598;:::o;50896:8177::-;;;;;;;;;;;;1304:3702:3;;;;;;;;;;51596:39:1;;;51592:83;;50896:8177;1304:3702:3;;;;;;;;;;52086:9:1;;;;2928:4;;1304:3702:3;;52113:29:1;;;;;52109:63;;50896:8177;1304:3702:3;;;;;;;;;;;;;;;;;;2928:4:1;;;;1304:3702:3;;;;;;;53054:33:1;;;;;;;;;;50896:8177;1304:3702:3;53054:33:1;;53053:34;53050:171;;50896:8177;-1:-1:-1;;1304:3702:3;;;;;;53408:45:1;;;53404:269;;53924:50;1304:3702:3;53924:50:1;;;;;;;;;;;;50896:8177;53924:50;53923:51;53920:377;;50896:8177;54357:6;;;;;;:::i;:::-;54463:46;;50896:8177;:::o;53920:377::-;1304:3702:3;54170:47:1;;;;;;;;;;;;53920:377;54178:16;1304:3702:3;54170:47:1;;;;;53920:377;;;;;;54170:47;;;-1:-1:-1;54170:47:1;;53924:50;;;;;53404:269;53469:47;;1304:3702:3;53469:47:1;;;;;;;;;;;;;;;53404:269;53469:47;;;;53616:46;;;:::o;53469:47::-;;;;;53050:171;1304:3702:3;53103:42:1;;;;;;;;;;;;;;;53050:171;53111:16;;1304:3702:3;53103:42:1;;;;;53050:171;;;;;;;;53103:42;;;;;53054:33;;;-1:-1:-1;53054:33:1;;52109:63;52144:28;;;52109:63;;;51592:83;51637:38;;51592:83;;;50896:8177;;;;;;;;;;;;1304:3702:3;;;;;;;;;;51596:39:1;;;51592:83;;50896:8177;1304:3702:3;;;;;;;;;;52086:9:1;;2928:4;;1304:3702:3;;52113:29:1;;;;;52109:63;;50896:8177;1304:3702:3;;;;;;;;;;;;;;;;;;2928:4:1;;;;1304:3702:3;-1:-1:-1;1304:3702:3;;;;;53054:33:1;;;;;;;;;;;50896:8177;1304:3702:3;53054:33:1;;53053:34;53050:171;;50896:8177;1304:3702:3;;;;;;;53408:45:1;;;;53404:269;;1304:3702:3;;;;53756:16:1;;;53752:768;;54908:15;1304:3702:3;;;;;;55801:10:1;55785:26;;55781:49;;50896:8177;56183:43;;;;1304:3702:3;;;;-1:-1:-1;56449:34:1;;-1:-1:-1;;56893:63:1;1304:3702:3;;-1:-1:-1;1304:3702:3;;56893:63:1;:::i;:::-;1304:3702:3;56445:1706:1;;;;-1:-1:-1;58299:60:1;;;;;;;;;;;;56445:1706;58299:60;58298:61;58295:213;;56445:1706;2928:4;;58887:16;2928:4;;58887:16;;;:::i;58295:213::-;-1:-1:-1;58375:57:1;;;;;;;;;;58295:213;58383:16;1304:3702:3;58375:57:1;;;;;58295:213;;;;;58375:57;;;-1:-1:-1;58375:57:1;;58299:60;;;;;56445:1706;57232:52;-1:-1:-1;57232:52:1;;;;;;57608:66;1304:3702:3;;57608:66:1;:::i;:::-;2928:4;;57228:909;;;56445:1706;;57228:909;58093:25;;;;-1:-1:-1;57228:909:1;;;56445:1706;;55781:49;-1:-1:-1;;;55781:49:1;;53752:768;53924:50;;;;;;;;;;;-1:-1:-1;53924:50:1;;;;;;;;;;;;;53923:51;53920:377;;54357:6;;;;;;:::i;53404:269::-;53469:47;-1:-1:-1;53469:47:1;;;;;;;;;;;;;;;;;;;;;;53616:46;;;:::o;53050:171::-;-1:-1:-1;53103:42:1;;;;;;;;;;;53050:171;53111:16;;1304:3702:3;53103:42:1;;;;;53050:171;;;;;53103:42;;;;;53054:33;;;-1:-1:-1;53054:33:1;;52109:63;52144:28;;;52109:63;;;51592:83;51637:38;;51592:83;;

Swarm Source

ipfs://650436a56158a64f21f64a45b35532f08d567f83e44ecf57f2389ce0c20ad580

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ 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.