ETH Price: $3,743.45 (-3.09%)

Contract

0xE5feD5b0f777F3244D8523F7FC41EF61147cDf4c

Overview

ETH Balance

0 ETH

ETH Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Transfer Ownersh...1119916032023-11-10 2:06:23396 days ago1699581983IN
0xE5feD5b0...1147cDf4c
0 ETH0.000085292430.01148282
Set Per Color Ex...1113447032023-10-26 2:43:03411 days ago1698288183IN
0xE5feD5b0...1147cDf4c
0 ETH0.0000400869210.13973069
Set Per Color Ex...1113447012023-10-26 2:42:59411 days ago1698288179IN
0xE5feD5b0...1147cDf4c
0 ETH0.0000400869210.13973069
Set Per Color Ex...1113447002023-10-26 2:42:57411 days ago1698288177IN
0xE5feD5b0...1147cDf4c
0 ETH0.0000400869210.13973069
Set Per Color Ex...1113446992023-10-26 2:42:55411 days ago1698288175IN
0xE5feD5b0...1147cDf4c
0 ETH0.0000400869210.13973069
Set Per Color Ex...1113446982023-10-26 2:42:53411 days ago1698288173IN
0xE5feD5b0...1147cDf4c
0 ETH0.0000401427690.13973069
Set Per Color Ex...1113446982023-10-26 2:42:53411 days ago1698288173IN
0xE5feD5b0...1147cDf4c
0 ETH0.0000401427690.13973069
Set Per Color Ex...1113446972023-10-26 2:42:51411 days ago1698288171IN
0xE5feD5b0...1147cDf4c
0 ETH0.000039966880.13973069
Set Per Color Ex...1113446962023-10-26 2:42:49411 days ago1698288169IN
0xE5feD5b0...1147cDf4c
0 ETH0.000039966880.13973069
Set Min Dst Gas1113446952023-10-26 2:42:47411 days ago1698288167IN
0xE5feD5b0...1147cDf4c
0 ETH0.000040152550.13973069
Set Min Dst Gas1113446932023-10-26 2:42:43411 days ago1698288163IN
0xE5feD5b0...1147cDf4c
0 ETH0.0000403284390.13973069
Set Min Dst Gas1113446922023-10-26 2:42:41411 days ago1698288161IN
0xE5feD5b0...1147cDf4c
0 ETH0.0000397757560.13973069
Set Min Dst Gas1113446912023-10-26 2:42:39411 days ago1698288159IN
0xE5feD5b0...1147cDf4c
0 ETH0.0000397757560.13973069
Set Min Dst Gas1113446912023-10-26 2:42:39411 days ago1698288159IN
0xE5feD5b0...1147cDf4c
0 ETH0.0000397757560.13973069
Set Min Dst Gas1113446892023-10-26 2:42:35411 days ago1698288155IN
0xE5feD5b0...1147cDf4c
0 ETH0.0000397757560.13973069
Set Min Dst Gas1113446892023-10-26 2:42:35411 days ago1698288155IN
0xE5feD5b0...1147cDf4c
0 ETH0.0000397757560.13973069
Set Min Dst Gas1113446872023-10-26 2:42:31411 days ago1698288151IN
0xE5feD5b0...1147cDf4c
0 ETH0.0000397757560.13973069
Set Min Dst Gas1113446862023-10-26 2:42:29411 days ago1698288149IN
0xE5feD5b0...1147cDf4c
0 ETH0.0000392386420.13973069
Set Min Dst Gas1113446852023-10-26 2:42:27411 days ago1698288147IN
0xE5feD5b0...1147cDf4c
0 ETH0.0000392386420.13973069
Set Min Dst Gas1113446842023-10-26 2:42:25411 days ago1698288145IN
0xE5feD5b0...1147cDf4c
0 ETH0.0000392386420.13973069
Set Min Dst Gas1113446842023-10-26 2:42:25411 days ago1698288145IN
0xE5feD5b0...1147cDf4c
0 ETH0.0000392386420.13973069
Set Precrime1111369162023-10-21 7:16:49416 days ago1697872609IN
0xE5feD5b0...1147cDf4c
0 ETH0.0000159599460.13263664
Set Per Color Ex...1111361802023-10-21 6:52:17416 days ago1697871137IN
0xE5feD5b0...1147cDf4c
0 ETH0.0000175274260.129665
Set Per Color Ex...1111361792023-10-21 6:52:15416 days ago1697871135IN
0xE5feD5b0...1147cDf4c
0 ETH0.0000174703810.129665
Set Per Color Ex...1111361782023-10-21 6:52:13416 days ago1697871133IN
0xE5feD5b0...1147cDf4c
0 ETH0.0000175274260.129665
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
1291043662024-12-10 5:11:496 hrs ago1733807509
0xE5feD5b0...1147cDf4c
0.000097364633221 ETH
1291043662024-12-10 5:11:496 hrs ago1733807509
0xE5feD5b0...1147cDf4c
0.000097364633221 ETH
1290868632024-12-09 19:28:2316 hrs ago1733772503
0xE5feD5b0...1147cDf4c
0.000091872451808 ETH
1290868632024-12-09 19:28:2316 hrs ago1733772503
0xE5feD5b0...1147cDf4c
0.000091872451808 ETH
1290600392024-12-09 4:34:1531 hrs ago1733718855
0xE5feD5b0...1147cDf4c
0.000091235634463 ETH
1290600392024-12-09 4:34:1531 hrs ago1733718855
0xE5feD5b0...1147cDf4c
0.000091235634463 ETH
1290308212024-12-08 12:20:1947 hrs ago1733660419
0xE5feD5b0...1147cDf4c
0.000082596287714 ETH
1290308212024-12-08 12:20:1947 hrs ago1733660419
0xE5feD5b0...1147cDf4c
0.000082596287714 ETH
1290263212024-12-08 9:50:192 days ago1733651419
0xE5feD5b0...1147cDf4c
0.000152781073816 ETH
1290263212024-12-08 9:50:192 days ago1733651419
0xE5feD5b0...1147cDf4c
0.000152781073816 ETH
1290156262024-12-08 3:53:492 days ago1733630029
0xE5feD5b0...1147cDf4c
0.000185514318261 ETH
1290156262024-12-08 3:53:492 days ago1733630029
0xE5feD5b0...1147cDf4c
0.000185514318261 ETH
1289870142024-12-07 12:00:053 days ago1733572805
0xE5feD5b0...1147cDf4c
0.000092175297808 ETH
1289870142024-12-07 12:00:053 days ago1733572805
0xE5feD5b0...1147cDf4c
0.000092175297808 ETH
1289819742024-12-07 9:12:053 days ago1733562725
0xE5feD5b0...1147cDf4c
0.000093115885808 ETH
1289819742024-12-07 9:12:053 days ago1733562725
0xE5feD5b0...1147cDf4c
0.000093115885808 ETH
1289740302024-12-07 4:47:173 days ago1733546837
0xE5feD5b0...1147cDf4c
0.000198708446159 ETH
1289740302024-12-07 4:47:173 days ago1733546837
0xE5feD5b0...1147cDf4c
0.000198708446159 ETH
1289471382024-12-06 13:50:533 days ago1733493053
0xE5feD5b0...1147cDf4c
0.000113120999104 ETH
1289471382024-12-06 13:50:533 days ago1733493053
0xE5feD5b0...1147cDf4c
0.000113120999104 ETH
1289085272024-12-05 16:23:514 days ago1733415831
0xE5feD5b0...1147cDf4c
0.000114167623405 ETH
1289085272024-12-05 16:23:514 days ago1733415831
0xE5feD5b0...1147cDf4c
0.000114167623405 ETH
1288996092024-12-05 11:26:355 days ago1733397995
0xE5feD5b0...1147cDf4c
0.000095807515405 ETH
1288996092024-12-05 11:26:355 days ago1733397995
0xE5feD5b0...1147cDf4c
0.000095807515405 ETH
1288453842024-12-04 5:19:056 days ago1733289545
0xE5feD5b0...1147cDf4c
0.000100747910605 ETH
View All Internal Transactions

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
MessagingV1

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 5000 runs

Other Settings:
paris EvmVersion, None license
File 1 of 40 : MessagingV1.sol
// SPDX-License-Identifier: LZBL-1.1
// Copyright 2023 LayerZero Labs Ltd.
// You may obtain a copy of the License at
// https://github.com/LayerZero-Labs/license/blob/main/LICENSE-LZBL-1.1

pragma solidity 0.8.19;

import "@openzeppelin/contracts/utils/math/SafeCast.sol";
import "@layerzerolabs/lz-evm-oapp-v2/contracts/standards/oft/interfaces/IOFT.sol";
import "@layerzerolabs/lz-evm-oapp-v2/contracts/standards/precrime/PreCrimeV2Simulator.sol";
import "../usdv/interfaces/IUSDV.sol";
import "../usdv/interfaces/IUSDVMain.sol";
import "./Messaging.sol";
import "./NonblockingLzApp.sol";
import "./libs/MsgCodec.sol";

contract MessagingV1 is NonblockingLzApp, Messaging, PreCrimeV2Simulator {
    using BytesLib for bytes;
    using MsgCodec for bytes;
    using SafeCast for uint32;

    constructor(
        address _endpoint,
        address _usdv,
        uint32 _mainChainEid,
        bool _isMainChain
    ) Messaging(_usdv, _mainChainEid, _isMainChain) NonblockingLzApp(_endpoint) {}

    // ======================== onlyUSDV ========================
    function send(
        SendParam calldata _param,
        bytes calldata _extraOptions,
        MessagingFee calldata /* _msgFee */,
        address payable _refundAddress,
        bytes calldata _composeMsg
    ) external payable onlyUSDV returns (MessagingReceipt memory msgReceipt) {
        require(_composeMsg.length == 0, "MessagingV1: composeMsg not supported");
        uint16 dstEid = _param.dstEid.toUint16();
        _checkGasLimit(dstEid, MsgCodec.MSG_TYPE_SEND, _extraOptions, 0);
        _lzSend(
            dstEid,
            MsgCodec.encodeSendMsg(_param.to, _param.color, _param.amount, _param.theta),
            _refundAddress,
            address(0x0),
            _extraOptions,
            msg.value
        );

        return msgReceipt;
    }

    /// @dev gas provided to sync linearly increases with num deltas
    function syncDelta(
        uint32 _dstEid,
        Delta[] calldata _deltas,
        bytes calldata _extraOptions,
        MessagingFee calldata /* _msgFee */,
        address payable _refundAddress
    ) external payable onlyUSDV returns (MessagingReceipt memory msgReceipt) {
        uint16 dstEid = _dstEid.toUint16();
        _checkGasLimit(
            dstEid,
            MsgCodec.MSG_TYPE_SYNC_DELTA,
            _extraOptions,
            perColorExtraGasLookup[_dstEid][MsgCodec.MSG_TYPE_SYNC_DELTA] * _deltas.length
        );
        _lzSend(dstEid, MsgCodec.encodeSyncDeltaMsg(_deltas), _refundAddress, address(0x0), _extraOptions, msg.value);
        return msgReceipt;
    }

    /// @dev gas provided to remint linearly increases with num deltas
    function remint(
        Delta[] calldata _deltas,
        uint32 _feeColor,
        uint64 _feeAmount,
        uint64 _feeTheta,
        bytes calldata _extraOptions,
        MessagingFee calldata /* _msgFee */,
        address payable _refundAddress
    ) external payable onlyUSDV returns (MessagingReceipt memory msgReceipt) {
        uint16 dstEid = mainChainEid.toUint16();
        _checkGasLimit(
            dstEid,
            MsgCodec.MSG_TYPE_REMINT,
            _extraOptions,
            perColorExtraGasLookup[mainChainEid][MsgCodec.MSG_TYPE_REMINT] * _deltas.length
        );
        _lzSend(
            dstEid,
            MsgCodec.encodeRemintMsg(_deltas, _feeColor, _feeAmount, _feeTheta),
            _refundAddress,
            address(0x0),
            _extraOptions,
            msg.value
        );
        return msgReceipt;
    }

    // ======================== View ========================
    function quoteSendFee(
        uint32 _dstEid,
        bytes calldata _extraOptions,
        bool /*_useLZToken*/,
        bytes calldata _composeMsg
    ) external view returns (uint nativeFee, uint lzTokenFee) {
        require(_composeMsg.length == 0, "MessagingV1: composeMsg not supported");
        uint16 dstEid = _dstEid.toUint16();
        _checkGasLimit(dstEid, MsgCodec.MSG_TYPE_SEND, _extraOptions, 0);
        return
            lzEndpoint.estimateFees(dstEid, address(this), MsgCodec.encodeSendMsg(0x0, 0, 0, 0), false, _extraOptions);
    }

    function quoteSyncDeltaFee(
        uint32 _dstEid,
        Delta[] calldata _deltas,
        bytes calldata _extraOptions,
        bool /*_useLZToken*/
    ) external view returns (uint nativeFee, uint lzTokenFee) {
        uint16 dstEid = _dstEid.toUint16();
        _checkGasLimit(
            dstEid,
            MsgCodec.MSG_TYPE_SYNC_DELTA,
            _extraOptions,
            perColorExtraGasLookup[_dstEid][MsgCodec.MSG_TYPE_SYNC_DELTA] * _deltas.length
        );
        return
            lzEndpoint.estimateFees(dstEid, address(this), MsgCodec.encodeSyncDeltaMsg(_deltas), false, _extraOptions);
    }

    function quoteRemintFee(
        Delta[] calldata _deltas,
        bytes calldata _extraOptions,
        bool /*_useLZToken*/
    ) external view returns (uint nativeFee, uint lzTokenFee) {
        uint16 dstEid = mainChainEid.toUint16();
        _checkGasLimit(
            dstEid,
            MsgCodec.MSG_TYPE_REMINT,
            _extraOptions,
            perColorExtraGasLookup[mainChainEid][MsgCodec.MSG_TYPE_REMINT] * _deltas.length
        );
        return
            lzEndpoint.estimateFees(
                dstEid,
                address(this),
                MsgCodec.encodeRemintMsg(_deltas, 0, 0, 0),
                false,
                _extraOptions
            );
    }

    function isPeer(uint32 _eid, bytes32 _peer) public view override returns (bool) {
        bytes memory path = trustedRemoteLookup[_eid.toUint16()];
        uint pathLength = path.length;
        require(pathLength > 20 && pathLength <= 52, "MessagingV1: invalid path length");

        bytes32 expectedPeer = bytes32(path.slice(0, pathLength - 20));
        unchecked {
            uint offset = 52 - path.length;
            expectedPeer = expectedPeer >> (offset * 8);
        }

        return expectedPeer == _peer;
    }

    // ======================== Internal ========================

    function _nonblockingLzReceive(
        uint16 /*_srcChainId*/,
        bytes calldata /*_srcAddress*/,
        uint64 /*_nonce*/,
        bytes calldata _message
    ) internal override {
        uint8 msgType = _message.msgType();

        if (msgType == MsgCodec.MSG_TYPE_SEND) {
            SendMsg memory message = _message.decodeSendMsg();
            IUSDV(usdv).sendAck(0x0, message.to, message.color, message.amount, message.theta);
        } else if (msgType == MsgCodec.MSG_TYPE_SYNC_DELTA) {
            SyncDeltaMsg memory message = _message.decodeSyncDeltaMsg();
            IUSDV(usdv).syncDeltaAck(message.deltas);
        } else if (msgType == MsgCodec.MSG_TYPE_REMINT) {
            if (!isMainChain) revert NotMainChain();
            RemintMsg memory message = _message.decodeRemintMsg();
            IUSDVMain(usdv).remintAck(message.deltas, message.color, message.amount, message.theta);
        } else {
            revert NotImplemented();
        }
    }

    // ======================== precrime ========================

    function _lzReceive(Origin calldata /*_origin*/, bytes32 /*_guid*/, bytes calldata _message) internal override {
        // only pass in the message
        this.nonblockingLzReceive(0x0, bytes(""), 0, _message);
    }
}

File 2 of 40 : Buffer.sol
pragma solidity ^0.8.4;

/**
* @dev A library for working with mutable byte buffers in Solidity.
*
* Byte buffers are mutable and expandable, and provide a variety of primitives
* for writing to them. At any time you can fetch a bytes object containing the
* current contents of the buffer. The bytes object should not be stored between
* operations, as it may change due to resizing of the buffer.
*/
library Buffer {
    /**
    * @dev Represents a mutable buffer. Buffers have a current value (buf) and
    *      a capacity. The capacity may be longer than the current value, in
    *      which case it can be extended without the need to allocate more memory.
    */
    struct buffer {
        bytes buf;
        uint capacity;
    }

    /**
    * @dev Initializes a buffer with an initial capacity.
    * @param buf The buffer to initialize.
    * @param capacity The number of bytes of space to allocate the buffer.
    * @return The buffer, for chaining.
    */
    function init(buffer memory buf, uint capacity) internal pure returns(buffer memory) {
        if (capacity % 32 != 0) {
            capacity += 32 - (capacity % 32);
        }
        // Allocate space for the buffer data
        buf.capacity = capacity;
        assembly {
            let ptr := mload(0x40)
            mstore(buf, ptr)
            mstore(ptr, 0)
            mstore(0x40, add(32, add(ptr, capacity)))
        }
        return buf;
    }

    /**
    * @dev Initializes a new buffer from an existing bytes object.
    *      Changes to the buffer may mutate the original value.
    * @param b The bytes object to initialize the buffer with.
    * @return A new buffer.
    */
    function fromBytes(bytes memory b) internal pure returns(buffer memory) {
        buffer memory buf;
        buf.buf = b;
        buf.capacity = b.length;
        return buf;
    }

    function resize(buffer memory buf, uint capacity) private pure {
        bytes memory oldbuf = buf.buf;
        init(buf, capacity);
        append(buf, oldbuf);
    }

    function max(uint a, uint b) private pure returns(uint) {
        if (a > b) {
            return a;
        }
        return b;
    }

    /**
    * @dev Sets buffer length to 0.
    * @param buf The buffer to truncate.
    * @return The original buffer, for chaining..
    */
    function truncate(buffer memory buf) internal pure returns (buffer memory) {
        assembly {
            let bufptr := mload(buf)
            mstore(bufptr, 0)
        }
        return buf;
    }

    /**
    * @dev Writes a byte string to a buffer. Resizes if doing so would exceed
    *      the capacity of the buffer.
    * @param buf The buffer to append to.
    * @param off The start offset to write to.
    * @param data The data to append.
    * @param len The number of bytes to copy.
    * @return The original buffer, for chaining.
    */
    function write(buffer memory buf, uint off, bytes memory data, uint len) internal pure returns(buffer memory) {
        require(len <= data.length);

        if (off + len > buf.capacity) {
            resize(buf, max(buf.capacity, len + off) * 2);
        }

        uint dest;
        uint src;
        assembly {
            // Memory address of the buffer data
            let bufptr := mload(buf)
            // Length of existing buffer data
            let buflen := mload(bufptr)
            // Start address = buffer address + offset + sizeof(buffer length)
            dest := add(add(bufptr, 32), off)
            // Update buffer length if we're extending it
            if gt(add(len, off), buflen) {
                mstore(bufptr, add(len, off))
            }
            src := add(data, 32)
        }

        // Copy word-length chunks while possible
        for (; len >= 32; len -= 32) {
            assembly {
                mstore(dest, mload(src))
            }
            dest += 32;
            src += 32;
        }

        // Copy remaining bytes
        unchecked {
            uint mask = (256 ** (32 - len)) - 1;
            assembly {
                let srcpart := and(mload(src), not(mask))
                let destpart := and(mload(dest), mask)
                mstore(dest, or(destpart, srcpart))
            }
        }

        return buf;
    }

    /**
    * @dev Appends a byte string to a buffer. Resizes if doing so would exceed
    *      the capacity of the buffer.
    * @param buf The buffer to append to.
    * @param data The data to append.
    * @param len The number of bytes to copy.
    * @return The original buffer, for chaining.
    */
    function append(buffer memory buf, bytes memory data, uint len) internal pure returns (buffer memory) {
        return write(buf, buf.buf.length, data, len);
    }

    /**
    * @dev Appends a byte string to a buffer. Resizes if doing so would exceed
    *      the capacity of the buffer.
    * @param buf The buffer to append to.
    * @param data The data to append.
    * @return The original buffer, for chaining.
    */
    function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) {
        return write(buf, buf.buf.length, data, data.length);
    }

    /**
    * @dev Writes a byte to the buffer. Resizes if doing so would exceed the
    *      capacity of the buffer.
    * @param buf The buffer to append to.
    * @param off The offset to write the byte at.
    * @param data The data to append.
    * @return The original buffer, for chaining.
    */
    function writeUint8(buffer memory buf, uint off, uint8 data) internal pure returns(buffer memory) {
        if (off >= buf.capacity) {
            resize(buf, buf.capacity * 2);
        }

        assembly {
            // Memory address of the buffer data
            let bufptr := mload(buf)
            // Length of existing buffer data
            let buflen := mload(bufptr)
            // Address = buffer address + sizeof(buffer length) + off
            let dest := add(add(bufptr, off), 32)
            mstore8(dest, data)
            // Update buffer length if we extended it
            if eq(off, buflen) {
                mstore(bufptr, add(buflen, 1))
            }
        }
        return buf;
    }

    /**
    * @dev Appends a byte to the buffer. Resizes if doing so would exceed the
    *      capacity of the buffer.
    * @param buf The buffer to append to.
    * @param data The data to append.
    * @return The original buffer, for chaining.
    */
    function appendUint8(buffer memory buf, uint8 data) internal pure returns(buffer memory) {
        return writeUint8(buf, buf.buf.length, data);
    }

    /**
    * @dev Writes up to 32 bytes to the buffer. Resizes if doing so would
    *      exceed the capacity of the buffer.
    * @param buf The buffer to append to.
    * @param off The offset to write at.
    * @param data The data to append.
    * @param len The number of bytes to write (left-aligned).
    * @return The original buffer, for chaining.
    */
    function write(buffer memory buf, uint off, bytes32 data, uint len) private pure returns(buffer memory) {
        if (len + off > buf.capacity) {
            resize(buf, (len + off) * 2);
        }

        unchecked {
            uint mask = (256 ** len) - 1;
            // Right-align data
            data = data >> (8 * (32 - len));
            assembly {
                // Memory address of the buffer data
                let bufptr := mload(buf)
                // Address = buffer address + sizeof(buffer length) + off + len
                let dest := add(add(bufptr, off), len)
                mstore(dest, or(and(mload(dest), not(mask)), data))
                // Update buffer length if we extended it
                if gt(add(off, len), mload(bufptr)) {
                    mstore(bufptr, add(off, len))
                }
            }
        }
        return buf;
    }

    /**
    * @dev Writes a bytes20 to the buffer. Resizes if doing so would exceed the
    *      capacity of the buffer.
    * @param buf The buffer to append to.
    * @param off The offset to write at.
    * @param data The data to append.
    * @return The original buffer, for chaining.
    */
    function writeBytes20(buffer memory buf, uint off, bytes20 data) internal pure returns (buffer memory) {
        return write(buf, off, bytes32(data), 20);
    }

    /**
    * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed
    *      the capacity of the buffer.
    * @param buf The buffer to append to.
    * @param data The data to append.
    * @return The original buffer, for chhaining.
    */
    function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) {
        return write(buf, buf.buf.length, bytes32(data), 20);
    }

    /**
    * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed
    *      the capacity of the buffer.
    * @param buf The buffer to append to.
    * @param data The data to append.
    * @return The original buffer, for chaining.
    */
    function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) {
        return write(buf, buf.buf.length, data, 32);
    }

    /**
    * @dev Writes an integer to the buffer. Resizes if doing so would exceed
    *      the capacity of the buffer.
    * @param buf The buffer to append to.
    * @param off The offset to write at.
    * @param data The data to append.
    * @param len The number of bytes to write (right-aligned).
    * @return The original buffer, for chaining.
    */
    function writeInt(buffer memory buf, uint off, uint data, uint len) private pure returns(buffer memory) {
        if (len + off > buf.capacity) {
            resize(buf, (len + off) * 2);
        }

        uint mask = (256 ** len) - 1;
        assembly {
            // Memory address of the buffer data
            let bufptr := mload(buf)
            // Address = buffer address + off + sizeof(buffer length) + len
            let dest := add(add(bufptr, off), len)
            mstore(dest, or(and(mload(dest), not(mask)), data))
            // Update buffer length if we extended it
            if gt(add(off, len), mload(bufptr)) {
                mstore(bufptr, add(off, len))
            }
        }
        return buf;
    }

    /**
     * @dev Appends a byte to the end of the buffer. Resizes if doing so would
     * exceed the capacity of the buffer.
     * @param buf The buffer to append to.
     * @param data The data to append.
     * @return The original buffer.
     */
    function appendInt(buffer memory buf, uint data, uint len) internal pure returns(buffer memory) {
        return writeInt(buf, buf.buf.length, data, len);
    }
}

File 3 of 40 : LzApp.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@layerzerolabs/lz-evm-v1-0.7/contracts/interfaces/ILayerZeroReceiver.sol";
import "@layerzerolabs/lz-evm-v1-0.7/contracts/interfaces/ILayerZeroUserApplicationConfig.sol";
import "@layerzerolabs/lz-evm-v1-0.7/contracts/interfaces/ILayerZeroEndpoint.sol";
import "solidity-bytes-utils/contracts/BytesLib.sol";

/*
 * a generic LzReceiver implementation
 */
abstract contract LzApp is Ownable, ILayerZeroReceiver, ILayerZeroUserApplicationConfig {
    using BytesLib for bytes;

    ILayerZeroEndpoint public immutable lzEndpoint;
    mapping(uint16 => bytes) public trustedRemoteLookup;
    mapping(uint16 => mapping(uint16 => uint)) public minDstGasLookup;
    address public precrime;

    event SetPrecrime(address precrime);
    event SetTrustedRemote(uint16 _remoteChainId, bytes _path);
    event SetTrustedRemoteAddress(uint16 _remoteChainId, bytes _remoteAddress);
    event SetMinDstGas(uint16 _dstChainId, uint16 _type, uint _minDstGas);

    constructor(address _endpoint) {
        lzEndpoint = ILayerZeroEndpoint(_endpoint);
    }

    function lzReceive(
        uint16 _srcChainId,
        bytes calldata _srcAddress,
        uint64 _nonce,
        bytes calldata _payload
    ) public virtual override {
        // lzReceive must be called by the endpoint for security
        require(_msgSender() == address(lzEndpoint), "LzApp: invalid endpoint caller");

        bytes memory trustedRemote = trustedRemoteLookup[_srcChainId];
        // if will still block the message pathway from (srcChainId, srcAddress). should not receive message from untrusted remote.
        require(
            _srcAddress.length == trustedRemote.length &&
                trustedRemote.length > 0 &&
                keccak256(_srcAddress) == keccak256(trustedRemote),
            "LzApp: invalid source sending contract"
        );

        _blockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);
    }

    // abstract function - the default behaviour of LayerZero is blocking. See: NonblockingLzApp if you dont need to enforce ordered messaging
    function _blockingLzReceive(
        uint16 _srcChainId,
        bytes memory _srcAddress,
        uint64 _nonce,
        bytes memory _payload
    ) internal virtual;

    function _lzSend(
        uint16 _dstChainId,
        bytes memory _payload,
        address payable _refundAddress,
        address _zroPaymentAddress,
        bytes memory _adapterParams,
        uint _nativeFee
    ) internal virtual {
        bytes memory trustedRemote = trustedRemoteLookup[_dstChainId];
        require(trustedRemote.length != 0, "LzApp: destination chain is not a trusted source");
        lzEndpoint.send{value: _nativeFee}(
            _dstChainId,
            trustedRemote,
            _payload,
            _refundAddress,
            _zroPaymentAddress,
            _adapterParams
        );
    }

    function _checkGasLimit(
        uint16 _dstChainId,
        uint16 _type,
        bytes memory _adapterParams,
        uint _extraGas
    ) internal view virtual {
        uint providedGasLimit = _getGasLimit(_adapterParams);
        uint minGasLimit = minDstGasLookup[_dstChainId][_type] + _extraGas;
        require(minGasLimit > 0, "LzApp: minGasLimit not set");
        require(providedGasLimit >= minGasLimit, "LzApp: gas limit is too low");
    }

    function _getGasLimit(bytes memory _adapterParams) internal pure virtual returns (uint gasLimit) {
        require(_adapterParams.length >= 34, "LzApp: invalid adapterParams");
        assembly {
            gasLimit := mload(add(_adapterParams, 34))
        }
    }

    //---------------------------UserApplication config----------------------------------------
    function getConfig(
        uint16 _version,
        uint16 _chainId,
        address,
        uint _configType
    ) external view returns (bytes memory) {
        return lzEndpoint.getConfig(_version, _chainId, address(this), _configType);
    }

    // generic config for LayerZero user Application
    function setConfig(
        uint16 _version,
        uint16 _chainId,
        uint _configType,
        bytes calldata _config
    ) external override onlyOwner {
        lzEndpoint.setConfig(_version, _chainId, _configType, _config);
    }

    function setSendVersion(uint16 _version) external override onlyOwner {
        lzEndpoint.setSendVersion(_version);
    }

    function setReceiveVersion(uint16 _version) external override onlyOwner {
        lzEndpoint.setReceiveVersion(_version);
    }

    function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external override onlyOwner {
        lzEndpoint.forceResumeReceive(_srcChainId, _srcAddress);
    }

    // _path = abi.encodePacked(remoteAddress, localAddress)
    // this function set the trusted path for the cross-chain communication
    function setTrustedRemote(uint16 _srcChainId, bytes calldata _path) external onlyOwner {
        trustedRemoteLookup[_srcChainId] = _path;
        emit SetTrustedRemote(_srcChainId, _path);
    }

    function setTrustedRemoteAddress(uint16 _remoteChainId, bytes calldata _remoteAddress) external onlyOwner {
        trustedRemoteLookup[_remoteChainId] = abi.encodePacked(_remoteAddress, address(this));
        emit SetTrustedRemoteAddress(_remoteChainId, _remoteAddress);
    }

    function getTrustedRemoteAddress(uint16 _remoteChainId) external view returns (bytes memory) {
        bytes memory path = trustedRemoteLookup[_remoteChainId];
        require(path.length != 0, "LzApp: no trusted path record");
        return path.slice(0, path.length - 20); // the last 20 bytes should be address(this)
    }

    function setPrecrime(address _precrime) external onlyOwner {
        precrime = _precrime;
        emit SetPrecrime(_precrime);
    }

    function setMinDstGas(uint16 _dstChainId, uint16 _packetType, uint _minGas) external onlyOwner {
        require(_minGas > 0, "LzApp: invalid minGas");
        minDstGasLookup[_dstChainId][_packetType] = _minGas;
        emit SetMinDstGas(_dstChainId, _packetType, _minGas);
    }

    //--------------------------- VIEW FUNCTION ----------------------------------------
    function isTrustedRemote(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool) {
        bytes memory trustedSource = trustedRemoteLookup[_srcChainId];
        return keccak256(trustedSource) == keccak256(_srcAddress);
    }
}

File 4 of 40 : ExcessivelySafeCall.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity >=0.7.6;

library ExcessivelySafeCall {
    uint256 constant LOW_28_MASK = 0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff;

    /// @notice Use when you _really_ really _really_ don't trust the called
    /// contract. This prevents the called contract from causing reversion of
    /// the caller in as many ways as we can.
    /// @dev The main difference between this and a solidity low-level call is
    /// that we limit the number of bytes that the callee can cause to be
    /// copied to caller memory. This prevents stupid things like malicious
    /// contracts returning 10,000,000 bytes causing a local OOG when copying
    /// to memory.
    /// @param _target The address to call
    /// @param _gas The amount of gas to forward to the remote contract
    /// @param _maxCopy The maximum number of bytes of returndata to copy
    /// to memory.
    /// @param _calldata The data to send to the remote contract
    /// @return success and returndata, as `.call()`. Returndata is capped to
    /// `_maxCopy` bytes.
    function excessivelySafeCall(
        address _target,
        uint256 _gas,
        uint16 _maxCopy,
        bytes memory _calldata
    ) internal returns (bool, bytes memory) {
        // set up for assembly call
        uint256 _toCopy;
        bool _success;
        bytes memory _returnData = new bytes(_maxCopy);
        // dispatch message to recipient
        // by assembly calling "handle" function
        // we call via assembly to avoid memcopying a very large returndata
        // returned by a malicious contract
        assembly {
            _success := call(
                _gas, // gas
                _target, // recipient
                0, // ether value
                add(_calldata, 0x20), // inloc
                mload(_calldata), // inlen
                0, // outloc
                0 // outlen
            )
            // limit our copy to 256 bytes
            _toCopy := returndatasize()
            if gt(_toCopy, _maxCopy) {
                _toCopy := _maxCopy
            }
            // Store the length of the copied bytes
            mstore(_returnData, _toCopy)
            // copy the bytes from returndata[0:_toCopy]
            returndatacopy(add(_returnData, 0x20), 0, _toCopy)
        }
        return (_success, _returnData);
    }

    /// @notice Use when you _really_ really _really_ don't trust the called
    /// contract. This prevents the called contract from causing reversion of
    /// the caller in as many ways as we can.
    /// @dev The main difference between this and a solidity low-level call is
    /// that we limit the number of bytes that the callee can cause to be
    /// copied to caller memory. This prevents stupid things like malicious
    /// contracts returning 10,000,000 bytes causing a local OOG when copying
    /// to memory.
    /// @param _target The address to call
    /// @param _gas The amount of gas to forward to the remote contract
    /// @param _maxCopy The maximum number of bytes of returndata to copy
    /// to memory.
    /// @param _calldata The data to send to the remote contract
    /// @return success and returndata, as `.call()`. Returndata is capped to
    /// `_maxCopy` bytes.
    function excessivelySafeStaticCall(
        address _target,
        uint256 _gas,
        uint16 _maxCopy,
        bytes memory _calldata
    ) internal view returns (bool, bytes memory) {
        // set up for assembly call
        uint256 _toCopy;
        bool _success;
        bytes memory _returnData = new bytes(_maxCopy);
        // dispatch message to recipient
        // by assembly calling "handle" function
        // we call via assembly to avoid memcopying a very large returndata
        // returned by a malicious contract
        assembly {
            _success := staticcall(
                _gas, // gas
                _target, // recipient
                add(_calldata, 0x20), // inloc
                mload(_calldata), // inlen
                0, // outloc
                0 // outlen
            )
            // limit our copy to 256 bytes
            _toCopy := returndatasize()
            if gt(_toCopy, _maxCopy) {
                _toCopy := _maxCopy
            }
            // Store the length of the copied bytes
            mstore(_returnData, _toCopy)
            // copy the bytes from returndata[0:_toCopy]
            returndatacopy(add(_returnData, 0x20), 0, _toCopy)
        }
        return (_success, _returnData);
    }

    /**
     * @notice Swaps function selectors in encoded contract calls
     * @dev Allows reuse of encoded calldata for functions with identical
     * argument types but different names. It simply swaps out the first 4 bytes
     * for the new selector. This function modifies memory in place, and should
     * only be used with caution.
     * @param _newSelector The new 4-byte selector
     * @param _buf The encoded contract args
     */
    function swapSelector(bytes4 _newSelector, bytes memory _buf) internal pure {
        require(_buf.length >= 4);
        uint256 _mask = LOW_28_MASK;
        assembly {
            // load the first word of
            let _word := mload(add(_buf, 0x20))
            // mask out the top 4 bytes
            // /x
            _word := and(_word, _mask)
            _word := or(_newSelector, _word)
            mstore(add(_buf, 0x20), _word)
        }
    }
}

File 5 of 40 : IOFT.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity ^0.8.0;

import {MessagingFee, MessagingReceipt} from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";

// @dev unable to inherit ERC20 because the OFTAdapter needs to use this interface as well
interface IOFT {
    struct SendParam {
        bytes32 to;
        uint amountLD;
        uint minAmountLD;
        uint32 dstEid;
    }

    error LDMinusSD();
    error AmountSlippage(uint _amountLDSend, uint256 _minAmountLD);

    event SetInspector(address _inspector);
    event SendOFT(bytes32 indexed _guid, address indexed _fromAddress, uint _amountLD, bytes _composeMsg);
    event ReceiveOFT(bytes32 indexed _guid, address indexed _toAddress, uint _amountLD);

    function token() external view returns (address);

    function quoteSendFee(
        SendParam calldata _send,
        bytes calldata _options,
        bool _useLZToken,
        bytes calldata _composeMsg
    ) external view returns (uint nativeFee, uint lzTokenFee);

    function send(
        SendParam calldata _send,
        bytes calldata _options,
        MessagingFee calldata _msgFee,
        address payable _refundAddress,
        bytes calldata _composeMsg
    ) external payable returns (MessagingReceipt memory);
}

File 6 of 40 : PreCrimeV2Simulator.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity ^0.8.0;

import {Origin} from "@layerzerolabs/lz-evm-protocol-v2/contracts/MessagingStructs.sol";

import "./interfaces/IPreCrimeV2Simulator.sol";
import "./interfaces/IPreCrimeV2.sol";

abstract contract PreCrimeV2Simulator is IPreCrimeV2Simulator {
    /// @dev a generic interface for precrime simulations
    /// @dev this function reverts at the end with the simulation results
    /// @dev value is provided as a lump sum, does not restrict how much each packet can consume
    function lzReceiveAndRevert(InboundPacket[] calldata _packets) external payable virtual override {
        this._simulateLzReceive{value: msg.value}(_packets);

        // msg.sender should be the precrime contract with the buildSimulationResult() function
        revert SimulationResult(IPreCrimeV2(msg.sender).buildSimulationResult());
    }

    function _simulateLzReceive(InboundPacket[] calldata _packets) external payable virtual {
        assert(msg.sender == address(this));

        _beforeSimulation(_packets);

        for (uint i = 0; i < _packets.length; i++) {
            // skip packet from untrusted peer
            InboundPacket calldata packet = _packets[i];
            if (!isPeer(packet.origin.srcEid, packet.origin.sender)) continue;

            _lzReceive(packet.origin, packet.guid, packet.message);
        }
    }

    function _beforeSimulation(InboundPacket[] calldata _packets) internal virtual {}

    function _lzReceive(Origin calldata _origin, bytes32 _guid, bytes calldata _message) internal virtual;

    function isPeer(uint32 _eid, bytes32 _peer) public view virtual returns (bool);

    /// @dev The simulator contract is the base contract for the OApp by default.
    /// @dev If the simulator is a separate contract, override this function.
    function oapp() external view virtual returns (address) {
        return address(this);
    }
}

File 7 of 40 : IPreCrimeV2.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity >=0.8.0;

struct PreCrimePeer {
    uint32 eid;
    bytes32 precrime;
    bytes32 oapp;
}

interface IPreCrimeV2 {
    error OnlyOffChain();

    // for simulate()
    error PacketOversize(uint max, uint actual);
    error PacketUnsorted();
    error SimulationFailed(bytes reason);

    // for precrime()
    error SimulationResultNotFound(uint32 eid);
    error InvalidSimulationResult(uint32 eid, bytes reason);
    error CrimeFound(bytes crime);

    function getConfig(bytes[] calldata _packets) external returns (bytes memory);

    function simulate(bytes[] calldata _packets) external payable returns (bytes memory);

    function buildSimulationResult() external view returns (bytes memory);

    function precrime(bytes[] calldata _packets, bytes[] calldata _simulations) external;

    function version() external view returns (uint64 major, uint8 minor);
}

File 8 of 40 : IPreCrimeV2Simulator.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity >=0.8.0;

import {InboundPacket} from "../libs/Packet.sol";

interface IPreCrimeV2Simulator {
    // this error is only used to return the simulation result
    error SimulationResult(bytes result);

    function lzReceiveAndRevert(InboundPacket[] calldata _packets) external payable;

    function isPeer(uint32 _eid, bytes32 _peer) external view returns (bool);

    function oapp() external view returns (address);
}

File 9 of 40 : Packet.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity ^0.8.0;

import {Origin} from "@layerzerolabs/lz-evm-protocol-v2/contracts/MessagingStructs.sol";
import {PacketV1Codec} from "@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/PacketV1Codec.sol";

struct InboundPacket {
    Origin origin;
    uint32 dstEid;
    address receiver;
    bytes32 guid;
    bytes message;
}

library PacketDecoder {
    using PacketV1Codec for bytes;

    function decode(bytes calldata _packet) internal pure returns (InboundPacket memory packet) {
        packet.origin = Origin(_packet.srcEid(), _packet.sender(), _packet.nonce());
        packet.dstEid = _packet.dstEid();
        packet.receiver = _packet.receiverB20();
        packet.guid = _packet.guid();
        packet.message = _packet.message();
    }

    function decode(bytes[] calldata _packets) internal pure returns (InboundPacket[] memory packets) {
        packets = new InboundPacket[](_packets.length);
        for (uint i = 0; i < _packets.length; i++) {
            bytes calldata packet = _packets[i];
            packets[i] = PacketDecoder.decode(packet);
        }
    }
}

File 10 of 40 : MessagingStructs.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity >=0.8.0;

struct PacketForQuote {
    address sender;
    uint32 dstEid;
    bytes message;
}

struct Packet {
    uint64 nonce;
    uint32 srcEid;
    address sender;
    uint32 dstEid;
    bytes32 receiver;
    bytes32 guid;
    bytes message;
}

struct Origin {
    uint32 srcEid;
    bytes32 sender;
    uint64 nonce;
}

File 11 of 40 : ILayerZeroEndpointV2.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity >=0.8.0;

import "./IMessageLibManager.sol";
import "./IMessagingComposer.sol";
import "./IMessagingChannel.sol";
import "./IMessagingContext.sol";
import {Origin} from "../MessagingStructs.sol";

struct MessagingParams {
    uint32 dstEid;
    bytes32 receiver;
    bytes message;
    bytes options;
}

struct MessagingReceipt {
    bytes32 guid;
    uint64 nonce;
    MessagingFee fee;
}

struct MessagingFee {
    uint nativeFee;
    uint lzTokenFee;
}

interface ILayerZeroEndpointV2 is IMessageLibManager, IMessagingComposer, IMessagingChannel, IMessagingContext {
    event PacketSent(bytes encodedPayload, bytes options, address sendLibrary);

    event PacketDelivered(Origin origin, address receiver, bytes32 payloadHash);

    event PacketReceived(Origin origin, address receiver);

    event LzReceiveFailed(Origin origin, address receiver, bytes reason);

    event LayerZeroTokenSet(address token);

    function quote(
        address _sender,
        uint32 _dstEid,
        bytes calldata _message,
        bool _payInLzToken,
        bytes calldata _options
    ) external view returns (MessagingFee memory);

    function send(
        MessagingParams calldata _params,
        uint _lzTokenFee,
        address payable _refundAddress
    ) external payable returns (MessagingReceipt memory);

    function sendWithAlt(
        MessagingParams calldata _params,
        uint _lzTokenFee,
        uint _altTokenFee
    ) external returns (MessagingReceipt memory);

    function deliver(Origin calldata _origin, address _receiver, bytes32 _payloadHash) external;

    function deliverable(Origin calldata _origin, address _receiveLib, address _receiver) external view returns (bool);

    function lzReceive(
        Origin calldata _origin,
        address _receiver,
        bytes32 _guid,
        bytes calldata _message,
        bytes calldata _extraData
    ) external payable returns (bool, bytes memory);

    // oapp can burn messages partially by calling this function with its own business logic if messages are delivered in order
    function clear(Origin calldata _origin, bytes32 _guid, bytes calldata _message) external;

    function setLayerZeroToken(address _layerZeroToken) external;

    function layerZeroToken() external view returns (address);

    function altFeeToken() external view returns (address);
}

File 12 of 40 : IMessageLibManager.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity >=0.8.0;

struct SetConfigParam {
    uint32 configType;
    bytes config;
}

interface IMessageLibManager {
    struct Timeout {
        address lib;
        uint expiry;
    }

    event LibraryRegistered(address newLib);
    event DefaultSendLibrarySet(uint32 eid, address newLib);
    event DefaultReceiveLibrarySet(uint32 eid, address oldLib, address newLib);
    event DefaultReceiveLibraryTimeoutSet(uint32 eid, address oldLib, uint expiry);
    event SendLibrarySet(address sender, uint32 eid, address newLib);
    event ReceiveLibrarySet(address receiver, uint32 eid, address oldLib, address newLib);
    event ReceiveLibraryTimoutSet(address receiver, uint32 eid, address oldLib, uint timeout);

    function registerLibrary(address _lib) external;

    function isRegisteredLibrary(address _lib) external view returns (bool);

    function getRegisteredLibraries() external view returns (address[] memory);

    function setDefaultSendLibrary(uint32 _eid, address _newLib) external;

    function defaultSendLibrary(uint32 _eid) external view returns (address);

    function setDefaultReceiveLibrary(uint32 _eid, address _newLib, uint _timeout) external;

    function defaultReceiveLibrary(uint32 _eid) external view returns (address);

    function setDefaultReceiveLibraryTimeout(uint32 _eid, address _lib, uint _expiry) external;

    function defaultReceiveLibraryTimeout(uint32 _eid) external view returns (address lib, uint expiry);

    function defaultConfig(address _lib, uint32 _eid, uint32 _configType) external view returns (bytes memory);

    function isSupportedEid(uint32 _eid) external view returns (bool);

    /// ------------------- OApp interfaces -------------------
    function setSendLibrary(uint32 _eid, address _newLib) external;

    function getSendLibrary(address _sender, uint32 _eid) external view returns (address lib);

    function isDefaultSendLibrary(address _sender, uint32 _eid) external view returns (bool);

    function setReceiveLibrary(uint32 _eid, address _newLib, uint _gracePeriod) external;

    function getReceiveLibrary(address _receiver, uint32 _eid) external view returns (address lib, bool isDefault);

    function setReceiveLibraryTimeout(uint32 _eid, address _lib, uint _gracePeriod) external;

    function receiveLibraryTimeout(address _receiver, uint32 _eid) external view returns (address lib, uint expiry);

    function setConfig(address _lib, uint32 _eid, SetConfigParam[] calldata _params) external;

    function getConfig(
        address _oapp,
        address _lib,
        uint32 _eid,
        uint32 _configType
    ) external view returns (bytes memory config, bool isDefault);

    function snapshotConfig(address _lib, uint32[] calldata _eids) external;

    function resetConfig(address _lib, uint32[] calldata _eids) external;
}

File 13 of 40 : IMessagingChannel.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity >=0.8.0;

interface IMessagingChannel {
    event InboundNonceSkipped(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce);

    function eid() external view returns (uint32);

    // this is an emergency function if a message can not be delivered for some reasons
    // required to provide _nextNonce to avoid race condition
    function skip(uint32 _srcEid, bytes32 _sender, uint64 _nonce) external;

    function nextGuid(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (bytes32);

    function inboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64);

    function outboundNonce(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (uint64);

    function inboundPayloadHash(
        address _receiver,
        uint32 _srcEid,
        bytes32 _sender,
        uint64 _nonce
    ) external view returns (bytes32);

    function hasPayloadHash(
        address _receiver,
        uint32 _srcEid,
        bytes32 _sender,
        uint64 _nonce
    ) external view returns (bool);
}

File 14 of 40 : IMessagingComposer.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity >=0.8.0;

interface IMessagingComposer {
    event ComposedMessageDelivered(address receiver, address composer, bytes32 guid, bytes message);
    event ComposedMessageReceived(address receiver, address composer, bytes32 guid);
    event LzComposeFailed(address receiver, address composer, bytes32 guid, bytes reason);

    function deliverComposedMessage(address _composer, bytes32 _guid, bytes calldata _message) external;

    function lzCompose(
        address _receiver,
        address _composer,
        bytes32 _guid,
        bytes calldata _message,
        bytes calldata _extraData
    ) external payable returns (bool, bytes memory);
}

File 15 of 40 : IMessagingContext.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity >=0.8.0;

interface IMessagingContext {
    function isSendingMessage() external view returns (bool);

    function getSendContext() external view returns (uint32, address);
}

File 16 of 40 : AddressCast.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity ^0.8.0;

import "./Errors.sol";

library AddressCast {
    function toBytes32(bytes calldata _addressBytes) internal pure returns (bytes32 result) {
        require(_addressBytes.length <= 32, Errors.INVALID_SIZE);
        result = bytes32(_addressBytes);
        unchecked {
            uint offset = 32 - _addressBytes.length;
            result = result >> (offset * 8);
        }
    }

    function toBytes32(address _address) internal pure returns (bytes32 result) {
        result = bytes32(uint(uint160(_address)));
    }

    function toBytes(bytes32 _addressBytes32, uint _size) internal pure returns (bytes memory result) {
        require(_size > 0 && _size <= 32, Errors.INVALID_SIZE);
        result = new bytes(_size);
        unchecked {
            uint256 offset = 256 - _size * 8;
            assembly {
                mstore(add(result, 32), shl(offset, _addressBytes32))
            }
        }
    }

    function toAddress(bytes32 _addressBytes32) internal pure returns (address result) {
        result = address(uint160(uint(_addressBytes32)));
    }

    function toAddress(bytes calldata _addressBytes) internal pure returns (address result) {
        require(_addressBytes.length == 20, Errors.INVALID_SIZE);
        result = address(bytes20(_addressBytes));
    }
}

File 17 of 40 : Errors.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity ^0.8.0;

library Errors {
    // Invalid Argument (http: 400)
    string internal constant INVALID_ARGUMENT = "LZ10000";
    string internal constant ONLY_REGISTERED = "LZ10001";
    string internal constant ONLY_REGISTERED_OR_DEFAULT = "LZ10002";
    string internal constant INVALID_AMOUNT = "LZ10003";
    string internal constant INVALID_NONCE = "LZ10004";
    string internal constant SAME_VALUE = "LZ10005";
    string internal constant UNSORTED = "LZ10006";
    string internal constant INVALID_VERSION = "LZ10007";
    string internal constant INVALID_EID = "LZ10008";
    string internal constant INVALID_SIZE = "LZ10009";
    string internal constant ONLY_NON_DEFAULT = "LZ10010";
    string internal constant INVALID_VERIFIERS = "LZ10011";
    string internal constant INVALID_WORKER_ID = "LZ10012";
    string internal constant DUPLICATED_OPTION = "LZ10013";
    string internal constant INVALID_LEGACY_OPTION = "LZ10014";
    string internal constant INVALID_VERIFIER_OPTION = "LZ10015";
    string internal constant INVALID_WORKER_OPTIONS = "LZ10016";
    string internal constant INVALID_EXECUTOR_OPTION = "LZ10017";
    string internal constant INVALID_ADDRESS = "LZ10018";

    // Out of Range (http: 400)
    string internal constant OUT_OF_RANGE = "LZ20000";

    // Invalid State (http: 400)
    string internal constant INVALID_STATE = "LZ30000";
    string internal constant SEND_REENTRANCY = "LZ30001";
    string internal constant RECEIVE_REENTRANCY = "LZ30002";
    string internal constant COMPOSE_REENTRANCY = "LZ30003";

    // Permission Denied (http: 403)
    string internal constant PERMISSION_DENIED = "LZ50000";

    // Not Found (http: 404)
    string internal constant NOT_FOUND = "LZ60000";

    // Already Exists (http: 409)
    string internal constant ALREADY_EXISTS = "LZ80000";

    // Not Implemented (http: 501)
    string internal constant NOT_IMPLEMENTED = "LZC0000";
    string internal constant UNSUPPORTED_INTERFACE = "LZC0001";
    string internal constant UNSUPPORTED_OPTION_TYPE = "LZC0002";

    // Unavailable (http: 503)
    string internal constant UNAVAILABLE = "LZD0000";
    string internal constant NATIVE_COIN_UNAVAILABLE = "LZD0001";
    string internal constant TOKEN_UNAVAILABLE = "LZD0002";
    string internal constant DEFAULT_LIBRARY_UNAVAILABLE = "LZD0003";
    string internal constant VERIFIERS_UNAVAILABLE = "LZD0004";
}

File 18 of 40 : PacketV1Codec.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity ^0.8.0;

import "../../libs/AddressCast.sol";
import {Packet} from "../../MessagingStructs.sol";

library PacketV1Codec {
    using AddressCast for address;
    using AddressCast for bytes32;

    uint8 internal constant PACKET_VERSION = 1;

    // header (version + nonce + path)
    // version
    uint private constant PACKET_VERSION_OFFSET = 0;
    //    nonce
    uint private constant NONCE_OFFSET = 1;
    //    path
    uint private constant SRC_EID_OFFSET = 9;
    uint private constant SENDER_OFFSET = 13;
    uint private constant DST_EID_OFFSET = 45;
    uint private constant RECEIVER_OFFSET = 49;
    // payload (guid + message)
    uint private constant GUID_OFFSET = 81; // keccak256(nonce + path)
    uint private constant MESSAGE_OFFSET = 113;

    function encode(Packet memory _packet) internal pure returns (bytes memory encodedPacket) {
        encodedPacket = abi.encodePacked(
            PACKET_VERSION,
            _packet.nonce,
            _packet.srcEid,
            _packet.sender.toBytes32(),
            _packet.dstEid,
            _packet.receiver,
            _packet.guid,
            _packet.message
        );
    }

    function encodePacketHeader(Packet memory _packet) internal pure returns (bytes memory) {
        return
            abi.encodePacked(
                PACKET_VERSION,
                _packet.nonce,
                _packet.srcEid,
                _packet.sender.toBytes32(),
                _packet.dstEid,
                _packet.receiver
            );
    }

    function encodePayload(Packet memory _packet) internal pure returns (bytes memory) {
        return abi.encodePacked(_packet.guid, _packet.message);
    }

    function header(bytes calldata _packet) internal pure returns (bytes calldata) {
        return _packet[0:GUID_OFFSET];
    }

    function version(bytes calldata _packet) internal pure returns (uint8) {
        return uint8(bytes1(_packet[PACKET_VERSION_OFFSET:NONCE_OFFSET]));
    }

    function nonce(bytes calldata _packet) internal pure returns (uint64) {
        return uint64(bytes8(_packet[NONCE_OFFSET:SRC_EID_OFFSET]));
    }

    function srcEid(bytes calldata _packet) internal pure returns (uint32) {
        return uint32(bytes4(_packet[SRC_EID_OFFSET:SENDER_OFFSET]));
    }

    function sender(bytes calldata _packet) internal pure returns (bytes32) {
        return bytes32(_packet[SENDER_OFFSET:DST_EID_OFFSET]);
    }

    function senderAddressB20(bytes calldata _packet) internal pure returns (address) {
        return sender(_packet).toAddress();
    }

    function dstEid(bytes calldata _packet) internal pure returns (uint32) {
        return uint32(bytes4(_packet[DST_EID_OFFSET:RECEIVER_OFFSET]));
    }

    function receiver(bytes calldata _packet) internal pure returns (bytes32) {
        return bytes32(_packet[RECEIVER_OFFSET:GUID_OFFSET]);
    }

    function receiverB20(bytes calldata _packet) internal pure returns (address) {
        return receiver(_packet).toAddress();
    }

    function guid(bytes calldata _packet) internal pure returns (bytes32) {
        return bytes32(_packet[GUID_OFFSET:MESSAGE_OFFSET]);
    }

    function message(bytes calldata _packet) internal pure returns (bytes calldata) {
        return bytes(_packet[MESSAGE_OFFSET:]);
    }

    function payload(bytes calldata _packet) internal pure returns (bytes calldata) {
        return bytes(_packet[GUID_OFFSET:]);
    }

    function payloadHash(bytes calldata _packet) internal pure returns (bytes32) {
        return keccak256(payload(_packet));
    }
}

File 19 of 40 : ILayerZeroEndpoint.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity >=0.5.0;

import "./ILayerZeroUserApplicationConfig.sol";

interface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {
    // @notice send a LayerZero message to the specified address at a LayerZero endpoint.
    // @param _dstChainId - the destination chain identifier
    // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains
    // @param _payload - a custom bytes payload to send to the destination contract
    // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address
    // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction
    // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination
    function send(
        uint16 _dstChainId,
        bytes calldata _destination,
        bytes calldata _payload,
        address payable _refundAddress,
        address _zroPaymentAddress,
        bytes calldata _adapterParams
    ) external payable;

    // @notice used by the messaging library to publish verified payload
    // @param _srcChainId - the source chain identifier
    // @param _srcAddress - the source contract (as bytes) at the source chain
    // @param _dstAddress - the address on destination chain
    // @param _nonce - the unbound message ordering nonce
    // @param _gasLimit - the gas limit for external contract execution
    // @param _payload - verified payload to send to the destination contract
    function receivePayload(
        uint16 _srcChainId,
        bytes calldata _srcAddress,
        address _dstAddress,
        uint64 _nonce,
        uint _gasLimit,
        bytes calldata _payload
    ) external;

    // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain
    // @param _srcChainId - the source chain identifier
    // @param _srcAddress - the source chain contract address
    function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);

    // @notice get the outboundNonce from this source chain which, consequently, is always an EVM
    // @param _srcAddress - the source chain contract address
    function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);

    // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery
    // @param _dstChainId - the destination chain identifier
    // @param _userApplication - the user app address on this EVM chain
    // @param _payload - the custom message to send over LayerZero
    // @param _payInZRO - if false, user app pays the protocol fee in native token
    // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain
    function estimateFees(
        uint16 _dstChainId,
        address _userApplication,
        bytes calldata _payload,
        bool _payInZRO,
        bytes calldata _adapterParam
    ) external view returns (uint nativeFee, uint zroFee);

    // @notice get this Endpoint's immutable source identifier
    function getChainId() external view returns (uint16);

    // @notice the interface to retry failed message on this Endpoint destination
    // @param _srcChainId - the source chain identifier
    // @param _srcAddress - the source chain contract address
    // @param _payload - the payload to be retried
    function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;

    // @notice query if any STORED payload (message blocking) at the endpoint.
    // @param _srcChainId - the source chain identifier
    // @param _srcAddress - the source chain contract address
    function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);

    // @notice query if the _libraryAddress is valid for sending msgs.
    // @param _userApplication - the user app address on this EVM chain
    function getSendLibraryAddress(address _userApplication) external view returns (address);

    // @notice query if the _libraryAddress is valid for receiving msgs.
    // @param _userApplication - the user app address on this EVM chain
    function getReceiveLibraryAddress(address _userApplication) external view returns (address);

    // @notice query if the non-reentrancy guard for send() is on
    // @return true if the guard is on. false otherwise
    function isSendingPayload() external view returns (bool);

    // @notice query if the non-reentrancy guard for receive() is on
    // @return true if the guard is on. false otherwise
    function isReceivingPayload() external view returns (bool);

    // @notice get the configuration of the LayerZero messaging library of the specified version
    // @param _version - messaging library version
    // @param _chainId - the chainId for the pending config change
    // @param _userApplication - the contract address of the user application
    // @param _configType - type of configuration. every messaging library has its own convention.
    function getConfig(
        uint16 _version,
        uint16 _chainId,
        address _userApplication,
        uint _configType
    ) external view returns (bytes memory);

    // @notice get the send() LayerZero messaging library version
    // @param _userApplication - the contract address of the user application
    function getSendVersion(address _userApplication) external view returns (uint16);

    // @notice get the lzReceive() LayerZero messaging library version
    // @param _userApplication - the contract address of the user application
    function getReceiveVersion(address _userApplication) external view returns (uint16);
}

File 20 of 40 : ILayerZeroReceiver.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity >=0.5.0;

interface ILayerZeroReceiver {
    // @notice LayerZero endpoint will invoke this function to deliver the message on the destination
    // @param _srcChainId - the source endpoint identifier
    // @param _srcAddress - the source sending contract address from the source chain
    // @param _nonce - the ordered message nonce
    // @param _payload - the signed payload is the UA bytes has encoded to be sent
    function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;
}

File 21 of 40 : ILayerZeroUserApplicationConfig.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity >=0.5.0;

interface ILayerZeroUserApplicationConfig {
    // @notice set the configuration of the LayerZero messaging library of the specified version
    // @param _version - messaging library version
    // @param _chainId - the chainId for the pending config change
    // @param _configType - type of configuration. every messaging library has its own convention.
    // @param _config - configuration in the bytes. can encode arbitrary content.
    function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;

    // @notice set the send() LayerZero messaging library version to _version
    // @param _version - new messaging library version
    function setSendVersion(uint16 _version) external;

    // @notice set the lzReceive() LayerZero messaging library version to _version
    // @param _version - new messaging library version
    function setReceiveVersion(uint16 _version) external;

    // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload
    // @param _srcChainId - the chainId of the source chain
    // @param _srcAddress - the contract address of the source contract at the source chain
    function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;
}

File 22 of 40 : IERC20Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20Upgradeable {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
}

File 23 of 40 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 24 of 40 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
}

File 25 of 40 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

File 26 of 40 : IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

File 27 of 40 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
     * Revert on invalid signature.
     */
    function safePermit(
        IERC20Permit token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

        (bool success, bytes memory returndata) = address(token).call(data);
        return
            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
    }
}

File 28 of 40 : 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 29 of 40 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 30 of 40 : SafeCast.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.

pragma solidity ^0.8.0;

/**
 * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 *
 * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
 * all math on `uint256` and `int256` and then downcasting.
 */
library SafeCast {
    /**
     * @dev Returns the downcasted uint248 from uint256, reverting on
     * overflow (when the input is greater than largest uint248).
     *
     * Counterpart to Solidity's `uint248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     *
     * _Available since v4.7._
     */
    function toUint248(uint256 value) internal pure returns (uint248) {
        require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
        return uint248(value);
    }

    /**
     * @dev Returns the downcasted uint240 from uint256, reverting on
     * overflow (when the input is greater than largest uint240).
     *
     * Counterpart to Solidity's `uint240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     *
     * _Available since v4.7._
     */
    function toUint240(uint256 value) internal pure returns (uint240) {
        require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
        return uint240(value);
    }

    /**
     * @dev Returns the downcasted uint232 from uint256, reverting on
     * overflow (when the input is greater than largest uint232).
     *
     * Counterpart to Solidity's `uint232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     *
     * _Available since v4.7._
     */
    function toUint232(uint256 value) internal pure returns (uint232) {
        require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
        return uint232(value);
    }

    /**
     * @dev Returns the downcasted uint224 from uint256, reverting on
     * overflow (when the input is greater than largest uint224).
     *
     * Counterpart to Solidity's `uint224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     *
     * _Available since v4.2._
     */
    function toUint224(uint256 value) internal pure returns (uint224) {
        require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
        return uint224(value);
    }

    /**
     * @dev Returns the downcasted uint216 from uint256, reverting on
     * overflow (when the input is greater than largest uint216).
     *
     * Counterpart to Solidity's `uint216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     *
     * _Available since v4.7._
     */
    function toUint216(uint256 value) internal pure returns (uint216) {
        require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
        return uint216(value);
    }

    /**
     * @dev Returns the downcasted uint208 from uint256, reverting on
     * overflow (when the input is greater than largest uint208).
     *
     * Counterpart to Solidity's `uint208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     *
     * _Available since v4.7._
     */
    function toUint208(uint256 value) internal pure returns (uint208) {
        require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
        return uint208(value);
    }

    /**
     * @dev Returns the downcasted uint200 from uint256, reverting on
     * overflow (when the input is greater than largest uint200).
     *
     * Counterpart to Solidity's `uint200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     *
     * _Available since v4.7._
     */
    function toUint200(uint256 value) internal pure returns (uint200) {
        require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
        return uint200(value);
    }

    /**
     * @dev Returns the downcasted uint192 from uint256, reverting on
     * overflow (when the input is greater than largest uint192).
     *
     * Counterpart to Solidity's `uint192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     *
     * _Available since v4.7._
     */
    function toUint192(uint256 value) internal pure returns (uint192) {
        require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
        return uint192(value);
    }

    /**
     * @dev Returns the downcasted uint184 from uint256, reverting on
     * overflow (when the input is greater than largest uint184).
     *
     * Counterpart to Solidity's `uint184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     *
     * _Available since v4.7._
     */
    function toUint184(uint256 value) internal pure returns (uint184) {
        require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
        return uint184(value);
    }

    /**
     * @dev Returns the downcasted uint176 from uint256, reverting on
     * overflow (when the input is greater than largest uint176).
     *
     * Counterpart to Solidity's `uint176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     *
     * _Available since v4.7._
     */
    function toUint176(uint256 value) internal pure returns (uint176) {
        require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
        return uint176(value);
    }

    /**
     * @dev Returns the downcasted uint168 from uint256, reverting on
     * overflow (when the input is greater than largest uint168).
     *
     * Counterpart to Solidity's `uint168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     *
     * _Available since v4.7._
     */
    function toUint168(uint256 value) internal pure returns (uint168) {
        require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
        return uint168(value);
    }

    /**
     * @dev Returns the downcasted uint160 from uint256, reverting on
     * overflow (when the input is greater than largest uint160).
     *
     * Counterpart to Solidity's `uint160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     *
     * _Available since v4.7._
     */
    function toUint160(uint256 value) internal pure returns (uint160) {
        require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
        return uint160(value);
    }

    /**
     * @dev Returns the downcasted uint152 from uint256, reverting on
     * overflow (when the input is greater than largest uint152).
     *
     * Counterpart to Solidity's `uint152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     *
     * _Available since v4.7._
     */
    function toUint152(uint256 value) internal pure returns (uint152) {
        require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
        return uint152(value);
    }

    /**
     * @dev Returns the downcasted uint144 from uint256, reverting on
     * overflow (when the input is greater than largest uint144).
     *
     * Counterpart to Solidity's `uint144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     *
     * _Available since v4.7._
     */
    function toUint144(uint256 value) internal pure returns (uint144) {
        require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
        return uint144(value);
    }

    /**
     * @dev Returns the downcasted uint136 from uint256, reverting on
     * overflow (when the input is greater than largest uint136).
     *
     * Counterpart to Solidity's `uint136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     *
     * _Available since v4.7._
     */
    function toUint136(uint256 value) internal pure returns (uint136) {
        require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
        return uint136(value);
    }

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v2.5._
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint120 from uint256, reverting on
     * overflow (when the input is greater than largest uint120).
     *
     * Counterpart to Solidity's `uint120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     *
     * _Available since v4.7._
     */
    function toUint120(uint256 value) internal pure returns (uint120) {
        require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
        return uint120(value);
    }

    /**
     * @dev Returns the downcasted uint112 from uint256, reverting on
     * overflow (when the input is greater than largest uint112).
     *
     * Counterpart to Solidity's `uint112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     *
     * _Available since v4.7._
     */
    function toUint112(uint256 value) internal pure returns (uint112) {
        require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
        return uint112(value);
    }

    /**
     * @dev Returns the downcasted uint104 from uint256, reverting on
     * overflow (when the input is greater than largest uint104).
     *
     * Counterpart to Solidity's `uint104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     *
     * _Available since v4.7._
     */
    function toUint104(uint256 value) internal pure returns (uint104) {
        require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
        return uint104(value);
    }

    /**
     * @dev Returns the downcasted uint96 from uint256, reverting on
     * overflow (when the input is greater than largest uint96).
     *
     * Counterpart to Solidity's `uint96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     *
     * _Available since v4.2._
     */
    function toUint96(uint256 value) internal pure returns (uint96) {
        require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
        return uint96(value);
    }

    /**
     * @dev Returns the downcasted uint88 from uint256, reverting on
     * overflow (when the input is greater than largest uint88).
     *
     * Counterpart to Solidity's `uint88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     *
     * _Available since v4.7._
     */
    function toUint88(uint256 value) internal pure returns (uint88) {
        require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
        return uint88(value);
    }

    /**
     * @dev Returns the downcasted uint80 from uint256, reverting on
     * overflow (when the input is greater than largest uint80).
     *
     * Counterpart to Solidity's `uint80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     *
     * _Available since v4.7._
     */
    function toUint80(uint256 value) internal pure returns (uint80) {
        require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
        return uint80(value);
    }

    /**
     * @dev Returns the downcasted uint72 from uint256, reverting on
     * overflow (when the input is greater than largest uint72).
     *
     * Counterpart to Solidity's `uint72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     *
     * _Available since v4.7._
     */
    function toUint72(uint256 value) internal pure returns (uint72) {
        require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
        return uint72(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v2.5._
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint56 from uint256, reverting on
     * overflow (when the input is greater than largest uint56).
     *
     * Counterpart to Solidity's `uint56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     *
     * _Available since v4.7._
     */
    function toUint56(uint256 value) internal pure returns (uint56) {
        require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
        return uint56(value);
    }

    /**
     * @dev Returns the downcasted uint48 from uint256, reverting on
     * overflow (when the input is greater than largest uint48).
     *
     * Counterpart to Solidity's `uint48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     *
     * _Available since v4.7._
     */
    function toUint48(uint256 value) internal pure returns (uint48) {
        require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
        return uint48(value);
    }

    /**
     * @dev Returns the downcasted uint40 from uint256, reverting on
     * overflow (when the input is greater than largest uint40).
     *
     * Counterpart to Solidity's `uint40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     *
     * _Available since v4.7._
     */
    function toUint40(uint256 value) internal pure returns (uint40) {
        require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
        return uint40(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v2.5._
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint24 from uint256, reverting on
     * overflow (when the input is greater than largest uint24).
     *
     * Counterpart to Solidity's `uint24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     *
     * _Available since v4.7._
     */
    function toUint24(uint256 value) internal pure returns (uint24) {
        require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
        return uint24(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v2.5._
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     *
     * _Available since v2.5._
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     *
     * _Available since v3.0._
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        require(value >= 0, "SafeCast: value must be positive");
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int248 from int256, reverting on
     * overflow (when the input is less than smallest int248 or
     * greater than largest int248).
     *
     * Counterpart to Solidity's `int248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     *
     * _Available since v4.7._
     */
    function toInt248(int256 value) internal pure returns (int248 downcasted) {
        downcasted = int248(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 248 bits");
    }

    /**
     * @dev Returns the downcasted int240 from int256, reverting on
     * overflow (when the input is less than smallest int240 or
     * greater than largest int240).
     *
     * Counterpart to Solidity's `int240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     *
     * _Available since v4.7._
     */
    function toInt240(int256 value) internal pure returns (int240 downcasted) {
        downcasted = int240(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 240 bits");
    }

    /**
     * @dev Returns the downcasted int232 from int256, reverting on
     * overflow (when the input is less than smallest int232 or
     * greater than largest int232).
     *
     * Counterpart to Solidity's `int232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     *
     * _Available since v4.7._
     */
    function toInt232(int256 value) internal pure returns (int232 downcasted) {
        downcasted = int232(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 232 bits");
    }

    /**
     * @dev Returns the downcasted int224 from int256, reverting on
     * overflow (when the input is less than smallest int224 or
     * greater than largest int224).
     *
     * Counterpart to Solidity's `int224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     *
     * _Available since v4.7._
     */
    function toInt224(int256 value) internal pure returns (int224 downcasted) {
        downcasted = int224(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 224 bits");
    }

    /**
     * @dev Returns the downcasted int216 from int256, reverting on
     * overflow (when the input is less than smallest int216 or
     * greater than largest int216).
     *
     * Counterpart to Solidity's `int216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     *
     * _Available since v4.7._
     */
    function toInt216(int256 value) internal pure returns (int216 downcasted) {
        downcasted = int216(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 216 bits");
    }

    /**
     * @dev Returns the downcasted int208 from int256, reverting on
     * overflow (when the input is less than smallest int208 or
     * greater than largest int208).
     *
     * Counterpart to Solidity's `int208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     *
     * _Available since v4.7._
     */
    function toInt208(int256 value) internal pure returns (int208 downcasted) {
        downcasted = int208(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 208 bits");
    }

    /**
     * @dev Returns the downcasted int200 from int256, reverting on
     * overflow (when the input is less than smallest int200 or
     * greater than largest int200).
     *
     * Counterpart to Solidity's `int200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     *
     * _Available since v4.7._
     */
    function toInt200(int256 value) internal pure returns (int200 downcasted) {
        downcasted = int200(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 200 bits");
    }

    /**
     * @dev Returns the downcasted int192 from int256, reverting on
     * overflow (when the input is less than smallest int192 or
     * greater than largest int192).
     *
     * Counterpart to Solidity's `int192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     *
     * _Available since v4.7._
     */
    function toInt192(int256 value) internal pure returns (int192 downcasted) {
        downcasted = int192(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 192 bits");
    }

    /**
     * @dev Returns the downcasted int184 from int256, reverting on
     * overflow (when the input is less than smallest int184 or
     * greater than largest int184).
     *
     * Counterpart to Solidity's `int184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     *
     * _Available since v4.7._
     */
    function toInt184(int256 value) internal pure returns (int184 downcasted) {
        downcasted = int184(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 184 bits");
    }

    /**
     * @dev Returns the downcasted int176 from int256, reverting on
     * overflow (when the input is less than smallest int176 or
     * greater than largest int176).
     *
     * Counterpart to Solidity's `int176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     *
     * _Available since v4.7._
     */
    function toInt176(int256 value) internal pure returns (int176 downcasted) {
        downcasted = int176(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 176 bits");
    }

    /**
     * @dev Returns the downcasted int168 from int256, reverting on
     * overflow (when the input is less than smallest int168 or
     * greater than largest int168).
     *
     * Counterpart to Solidity's `int168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     *
     * _Available since v4.7._
     */
    function toInt168(int256 value) internal pure returns (int168 downcasted) {
        downcasted = int168(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 168 bits");
    }

    /**
     * @dev Returns the downcasted int160 from int256, reverting on
     * overflow (when the input is less than smallest int160 or
     * greater than largest int160).
     *
     * Counterpart to Solidity's `int160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     *
     * _Available since v4.7._
     */
    function toInt160(int256 value) internal pure returns (int160 downcasted) {
        downcasted = int160(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 160 bits");
    }

    /**
     * @dev Returns the downcasted int152 from int256, reverting on
     * overflow (when the input is less than smallest int152 or
     * greater than largest int152).
     *
     * Counterpart to Solidity's `int152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     *
     * _Available since v4.7._
     */
    function toInt152(int256 value) internal pure returns (int152 downcasted) {
        downcasted = int152(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 152 bits");
    }

    /**
     * @dev Returns the downcasted int144 from int256, reverting on
     * overflow (when the input is less than smallest int144 or
     * greater than largest int144).
     *
     * Counterpart to Solidity's `int144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     *
     * _Available since v4.7._
     */
    function toInt144(int256 value) internal pure returns (int144 downcasted) {
        downcasted = int144(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 144 bits");
    }

    /**
     * @dev Returns the downcasted int136 from int256, reverting on
     * overflow (when the input is less than smallest int136 or
     * greater than largest int136).
     *
     * Counterpart to Solidity's `int136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     *
     * _Available since v4.7._
     */
    function toInt136(int256 value) internal pure returns (int136 downcasted) {
        downcasted = int136(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 136 bits");
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v3.1._
     */
    function toInt128(int256 value) internal pure returns (int128 downcasted) {
        downcasted = int128(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 128 bits");
    }

    /**
     * @dev Returns the downcasted int120 from int256, reverting on
     * overflow (when the input is less than smallest int120 or
     * greater than largest int120).
     *
     * Counterpart to Solidity's `int120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     *
     * _Available since v4.7._
     */
    function toInt120(int256 value) internal pure returns (int120 downcasted) {
        downcasted = int120(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 120 bits");
    }

    /**
     * @dev Returns the downcasted int112 from int256, reverting on
     * overflow (when the input is less than smallest int112 or
     * greater than largest int112).
     *
     * Counterpart to Solidity's `int112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     *
     * _Available since v4.7._
     */
    function toInt112(int256 value) internal pure returns (int112 downcasted) {
        downcasted = int112(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 112 bits");
    }

    /**
     * @dev Returns the downcasted int104 from int256, reverting on
     * overflow (when the input is less than smallest int104 or
     * greater than largest int104).
     *
     * Counterpart to Solidity's `int104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     *
     * _Available since v4.7._
     */
    function toInt104(int256 value) internal pure returns (int104 downcasted) {
        downcasted = int104(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 104 bits");
    }

    /**
     * @dev Returns the downcasted int96 from int256, reverting on
     * overflow (when the input is less than smallest int96 or
     * greater than largest int96).
     *
     * Counterpart to Solidity's `int96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     *
     * _Available since v4.7._
     */
    function toInt96(int256 value) internal pure returns (int96 downcasted) {
        downcasted = int96(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 96 bits");
    }

    /**
     * @dev Returns the downcasted int88 from int256, reverting on
     * overflow (when the input is less than smallest int88 or
     * greater than largest int88).
     *
     * Counterpart to Solidity's `int88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     *
     * _Available since v4.7._
     */
    function toInt88(int256 value) internal pure returns (int88 downcasted) {
        downcasted = int88(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 88 bits");
    }

    /**
     * @dev Returns the downcasted int80 from int256, reverting on
     * overflow (when the input is less than smallest int80 or
     * greater than largest int80).
     *
     * Counterpart to Solidity's `int80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     *
     * _Available since v4.7._
     */
    function toInt80(int256 value) internal pure returns (int80 downcasted) {
        downcasted = int80(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 80 bits");
    }

    /**
     * @dev Returns the downcasted int72 from int256, reverting on
     * overflow (when the input is less than smallest int72 or
     * greater than largest int72).
     *
     * Counterpart to Solidity's `int72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     *
     * _Available since v4.7._
     */
    function toInt72(int256 value) internal pure returns (int72 downcasted) {
        downcasted = int72(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 72 bits");
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v3.1._
     */
    function toInt64(int256 value) internal pure returns (int64 downcasted) {
        downcasted = int64(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 64 bits");
    }

    /**
     * @dev Returns the downcasted int56 from int256, reverting on
     * overflow (when the input is less than smallest int56 or
     * greater than largest int56).
     *
     * Counterpart to Solidity's `int56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     *
     * _Available since v4.7._
     */
    function toInt56(int256 value) internal pure returns (int56 downcasted) {
        downcasted = int56(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 56 bits");
    }

    /**
     * @dev Returns the downcasted int48 from int256, reverting on
     * overflow (when the input is less than smallest int48 or
     * greater than largest int48).
     *
     * Counterpart to Solidity's `int48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     *
     * _Available since v4.7._
     */
    function toInt48(int256 value) internal pure returns (int48 downcasted) {
        downcasted = int48(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 48 bits");
    }

    /**
     * @dev Returns the downcasted int40 from int256, reverting on
     * overflow (when the input is less than smallest int40 or
     * greater than largest int40).
     *
     * Counterpart to Solidity's `int40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     *
     * _Available since v4.7._
     */
    function toInt40(int256 value) internal pure returns (int40 downcasted) {
        downcasted = int40(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 40 bits");
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v3.1._
     */
    function toInt32(int256 value) internal pure returns (int32 downcasted) {
        downcasted = int32(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 32 bits");
    }

    /**
     * @dev Returns the downcasted int24 from int256, reverting on
     * overflow (when the input is less than smallest int24 or
     * greater than largest int24).
     *
     * Counterpart to Solidity's `int24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     *
     * _Available since v4.7._
     */
    function toInt24(int256 value) internal pure returns (int24 downcasted) {
        downcasted = int24(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 24 bits");
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v3.1._
     */
    function toInt16(int256 value) internal pure returns (int16 downcasted) {
        downcasted = int16(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 16 bits");
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     *
     * _Available since v3.1._
     */
    function toInt8(int256 value) internal pure returns (int8 downcasted) {
        downcasted = int8(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 8 bits");
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     *
     * _Available since v3.0._
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
        require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
        return int256(value);
    }
}

File 31 of 40 : Messaging.sol
// SPDX-License-Identifier: LZBL-1.1
// Copyright 2023 LayerZero Labs Ltd.
// You may obtain a copy of the License at
// https://github.com/LayerZero-Labs/license/blob/main/LICENSE-LZBL-1.1

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/access/Ownable.sol";
import {IMessaging} from "./interfaces/IMessaging.sol";
import {IUSDV} from "../usdv/interfaces/IUSDV.sol";
import {IVaultManager} from "../vault/interfaces/IVaultManager.sol";

abstract contract Messaging is Ownable, IMessaging {
    uint32 public immutable mainChainEid;
    bool public immutable isMainChain;

    address public immutable usdv;

    mapping(uint32 dstEid => mapping(uint8 msgType => uint extraGas)) public perColorExtraGasLookup;

    constructor(address _usdv, uint32 _mainChainEid, bool _isMainChain) {
        usdv = _usdv;
        mainChainEid = _mainChainEid;
        isMainChain = _isMainChain;
    }

    modifier onlyUSDV() {
        if (msg.sender != usdv) revert NotUSDV(msg.sender);
        _;
    }

    // ======================== onlyOwner ========================
    function setPerColorExtraGas(uint32 _dstEid, uint8 _msgType, uint _extraGas) external onlyOwner {
        perColorExtraGasLookup[_dstEid][_msgType] = _extraGas;
        emit SetPerColorExtraGas(_dstEid, _msgType, _extraGas);
    }
}

File 32 of 40 : NonblockingLzApp.sol
// SPDX-License-Identifier: LZBL-1.1
// Copyright 2023 LayerZero Labs Ltd.
// You may obtain a copy of the License at
// https://github.com/LayerZero-Labs/license/blob/main/LICENSE-LZBL-1.1

pragma solidity ^0.8.0;

import "@layerzerolabs/lz-evm-oapp-v1/contracts/lzApp/LzApp.sol";
import "@layerzerolabs/lz-evm-oapp-v1/contracts/util/ExcessivelySafeCall.sol";

/*
 * COPY of https://github.com/LayerZero-Labs/solidity-examples/blob/main/contracts/lzApp/NonblockingLzApp.sol
 * Only diff is using calldata for _nonblockingLzReceive params
 * the default LayerZero messaging behaviour is blocking, i.e. any failed message will block the channel
 * this abstract class try-catch all fail messages and store locally for future retry. hence, non-blocking
 * NOTE: if the srcAddress is not configured properly, it will still block the message pathway from (srcChainId, srcAddress)
 */
abstract contract NonblockingLzApp is LzApp {
    using ExcessivelySafeCall for address;

    constructor(address _endpoint) LzApp(_endpoint) {}

    mapping(uint16 => mapping(bytes => mapping(uint64 => bytes32))) public failedMessages;

    event MessageFailed(uint16 _srcChainId, bytes _srcAddress, uint64 _nonce, bytes _payload, bytes _reason);
    event RetryMessageSuccess(uint16 _srcChainId, bytes _srcAddress, uint64 _nonce, bytes32 _payloadHash);

    // overriding the virtual function in LzReceiver
    function _blockingLzReceive(
        uint16 _srcChainId,
        bytes memory _srcAddress,
        uint64 _nonce,
        bytes memory _payload
    ) internal virtual override {
        (bool success, bytes memory reason) = address(this).excessivelySafeCall(
            gasleft(),
            150,
            abi.encodeWithSelector(this.nonblockingLzReceive.selector, _srcChainId, _srcAddress, _nonce, _payload)
        );
        // try-catch all errors/exceptions
        if (!success) {
            _storeFailedMessage(_srcChainId, _srcAddress, _nonce, _payload, reason);
        }
    }

    function _storeFailedMessage(
        uint16 _srcChainId,
        bytes memory _srcAddress,
        uint64 _nonce,
        bytes memory _payload,
        bytes memory _reason
    ) internal virtual {
        failedMessages[_srcChainId][_srcAddress][_nonce] = keccak256(_payload);
        emit MessageFailed(_srcChainId, _srcAddress, _nonce, _payload, _reason);
    }

    function nonblockingLzReceive(
        uint16 _srcChainId,
        bytes calldata _srcAddress,
        uint64 _nonce,
        bytes calldata _payload
    ) public virtual {
        // only internal transaction
        require(_msgSender() == address(this), "NonblockingLzApp: caller must be LzApp");
        _nonblockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);
    }

    //@notice override this function
    function _nonblockingLzReceive(
        uint16 _srcChainId,
        bytes calldata _srcAddress,
        uint64 _nonce,
        bytes calldata _payload
    ) internal virtual;

    function retryMessage(
        uint16 _srcChainId,
        bytes calldata _srcAddress,
        uint64 _nonce,
        bytes calldata _payload
    ) public payable virtual {
        // assert there is message to retry
        bytes32 payloadHash = failedMessages[_srcChainId][_srcAddress][_nonce];
        require(payloadHash != bytes32(0), "NonblockingLzApp: no stored message");
        require(keccak256(_payload) == payloadHash, "NonblockingLzApp: invalid payload");
        // clear the stored message
        failedMessages[_srcChainId][_srcAddress][_nonce] = bytes32(0);
        // execute the message. revert if it fails again
        _nonblockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);
        emit RetryMessageSuccess(_srcChainId, _srcAddress, _nonce, payloadHash);
    }
}

File 33 of 40 : IMessaging.sol
// SPDX-License-Identifier: LZBL-1.1
// Copyright 2023 LayerZero Labs Ltd.
// You may obtain a copy of the License at
// https://github.com/LayerZero-Labs/license/blob/main/LICENSE-LZBL-1.1

pragma solidity ^0.8.0;

import "@layerzerolabs/lz-evm-oapp-v2/contracts/standards/oft/interfaces/IOFT.sol";
import {MessagingFee, MessagingParams, MessagingReceipt} from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";
import {Delta} from "../../usdv/interfaces/IUSDV.sol";

interface IMessaging {
    error NotUSDV(address sender);
    error NotImplemented();
    error NotMainChain();

    event SetPerColorExtraGas(uint32 dstEid, uint8 msgType, uint extraGas);

    struct SendParam {
        uint32 dstEid;
        bytes32 to;
        uint32 color;
        uint64 amount;
        uint64 theta;
    }

    function send(
        SendParam calldata _pram,
        bytes calldata _extraOptions,
        MessagingFee calldata _msgFee,
        address payable _refundAddress,
        bytes calldata _composeMsg
    ) external payable returns (MessagingReceipt memory msgReceipt);

    function syncDelta(
        uint32 _dstEid,
        Delta[] calldata _deltas,
        bytes calldata _extraOptions,
        MessagingFee calldata _msgFee,
        address payable _refundAddress
    ) external payable returns (MessagingReceipt memory msgReceipt);

    function quoteSendFee(
        uint32 _dstEid,
        bytes calldata _extraOptions,
        bool _useLZToken,
        bytes calldata _composeMsg
    ) external view returns (uint nativeFee, uint lzTokenFee);

    function quoteSyncDeltaFee(
        uint32 _dstEid,
        Delta[] calldata _deltas,
        bytes calldata _extraOptions,
        bool _useLZToken
    ) external view returns (uint nativeFee, uint lzTokenFee);

    function remint(
        Delta[] calldata _deltas,
        uint32 _feeColor,
        uint64 _feeAmount,
        uint64 _feeTheta,
        bytes calldata _extraOptions,
        MessagingFee calldata _msgFee,
        address payable _refundAddress
    ) external payable returns (MessagingReceipt memory msgReceipt);

    function quoteRemintFee(
        Delta[] calldata _deltas,
        bytes calldata _extraOptions,
        bool _useLZToken
    ) external view returns (uint nativeFee, uint lzTokenFee);
}

File 34 of 40 : MsgCodec.sol
// SPDX-License-Identifier: LZBL-1.1
// Copyright 2023 LayerZero Labs Ltd.
// You may obtain a copy of the License at
// https://github.com/LayerZero-Labs/license/blob/main/LICENSE-LZBL-1.1

pragma solidity ^0.8.0;

import {Delta} from "../../usdv/interfaces/IUSDV.sol";
import "@ensdomain/buffer/contracts/Buffer.sol";

struct SendMsg {
    address to;
    uint32 color;
    uint64 amount;
    uint64 theta;
}

struct SendAndCallMsg {
    address to;
    uint32 color;
    uint64 amount;
    uint64 theta;
    bytes composeMsg;
}

struct SyncDeltaMsg {
    Delta[] deltas;
}

struct RemintMsg {
    Delta[] deltas;
    uint32 color;
    uint64 amount;
    uint64 theta;
}

library MsgCodec {
    using Buffer for Buffer.buffer;

    // message types
    uint8 internal constant MSG_TYPE_SEND = 1;
    uint8 internal constant MSG_TYPE_SEND_AND_CALL = 2;
    uint8 internal constant MSG_TYPE_SYNC_DELTA = 3;
    uint8 internal constant MSG_TYPE_REMINT = 4;

    // offsets
    uint8 internal constant MSG_TYPE_OFFSET = 0;

    // send / send and call
    uint8 internal constant TO_OFFSET = 1;
    uint8 internal constant COLOR_OFFSET = 33;
    uint8 internal constant AMOUNT_OFFSET = 37;
    uint8 internal constant THETA_OFFSET = 45;
    // send and call
    uint8 internal constant COMPOSED_MSG_OFFSET = 53;

    // sync delta
    uint8 internal constant SYNC_DELTAS_OFFSET = 1;

    // remint
    uint8 internal constant REMINT_COLOR_OFFSET = 1;
    uint8 internal constant REMINT_AMOUNT_OFFSET = 5;
    uint8 internal constant REMINT_THETA_OFFSET = 13;
    uint8 internal constant REMINT_DELTAS_OFFSET = 21;

    error InvalidSize();

    function encodeSendMsg(
        bytes32 _to,
        uint32 _color,
        uint64 _amount,
        uint64 _theta
    ) internal pure returns (bytes memory) {
        return abi.encodePacked(MSG_TYPE_SEND, _to, _color, _amount, _theta);
    }

    function decodeSendMsg(bytes calldata _message) internal pure returns (SendMsg memory) {
        if (_message.length != 53) revert InvalidSize();
        return
            SendMsg({
                to: toAddressB20(bytes32(_message[TO_OFFSET:COLOR_OFFSET])),
                color: uint32(bytes4(_message[COLOR_OFFSET:AMOUNT_OFFSET])),
                amount: uint64(bytes8(_message[AMOUNT_OFFSET:THETA_OFFSET])),
                theta: uint64(bytes8(_message[THETA_OFFSET:53]))
            });
    }

    function encodeSendAndCallMsg(
        bytes32 _to,
        uint32 _color,
        uint64 _amount,
        uint64 _theta,
        address _caller, // OFTComposeMsgCodec expects compose msg to include caller/composeFrom
        bytes memory _composeMsg // extra data
    ) internal pure returns (bytes memory) {
        return
            abi.encodePacked(
                MSG_TYPE_SEND_AND_CALL,
                _to,
                _color,
                _amount,
                _theta,
                addressToBytes32(_caller),
                _composeMsg
            );
    }

    function decodeSendAndCallMsg(bytes calldata _message) internal pure returns (SendAndCallMsg memory) {
        if (_message.length < 53) revert InvalidSize();
        return
            SendAndCallMsg({
                to: toAddressB20(bytes32(_message[TO_OFFSET:COLOR_OFFSET])),
                color: uint32(bytes4(_message[COLOR_OFFSET:AMOUNT_OFFSET])),
                amount: uint64(bytes8(_message[AMOUNT_OFFSET:THETA_OFFSET])),
                theta: uint64(bytes8(_message[THETA_OFFSET:COMPOSED_MSG_OFFSET])),
                composeMsg: _message[COMPOSED_MSG_OFFSET:]
            });
    }

    function encodeSyncDeltaMsg(Delta[] calldata _deltas) internal pure returns (bytes memory) {
        Buffer.buffer memory buf;
        buf.init(_deltas.length * 12 + 1);
        buf.appendUint8(MSG_TYPE_SYNC_DELTA);
        for (uint i = 0; i < _deltas.length; i++) {
            Delta calldata delta = _deltas[i];
            buf.appendInt(delta.color, 4);
            buf.appendInt(uint64(delta.amount), 8);
        }
        return buf.buf;
    }

    function decodeSyncDeltaMsg(bytes calldata _message) internal pure returns (SyncDeltaMsg memory) {
        if ((_message.length - SYNC_DELTAS_OFFSET) % 12 != 0) revert InvalidSize();
        uint size = (_message.length - SYNC_DELTAS_OFFSET) / 12;
        Delta[] memory deltas = new Delta[](size);
        for (uint i = 0; i < size; i++) {
            uint offset = SYNC_DELTAS_OFFSET + i * 12;
            deltas[i] = Delta({
                color: uint32(bytes4(_message[offset:offset + 4])),
                amount: int64(uint64(bytes8(_message[offset + 4:offset + 12])))
            });
        }
        return SyncDeltaMsg({deltas: deltas});
    }

    function encodeRemintMsg(
        Delta[] calldata _deltas,
        uint32 _color,
        uint64 _amount,
        uint64 _theta
    ) internal pure returns (bytes memory) {
        Buffer.buffer memory buf;
        buf.init(_deltas.length * 12 + 21); // 1 + 4 + 8 + 8
        buf.appendUint8(MSG_TYPE_REMINT);
        buf.appendInt(_color, 4);
        buf.appendInt(_amount, 8);
        buf.appendInt(_theta, 8);
        for (uint i = 0; i < _deltas.length; i++) {
            Delta calldata delta = _deltas[i];
            buf.appendInt(delta.color, 4);
            buf.appendInt(uint64(delta.amount), 8);
        }
        return buf.buf;
    }

    function decodeRemintMsg(bytes calldata _message) internal pure returns (RemintMsg memory) {
        if ((_message.length - REMINT_DELTAS_OFFSET) % 12 != 0) revert InvalidSize();
        uint size = (_message.length - REMINT_DELTAS_OFFSET) / 12;
        Delta[] memory deltas = new Delta[](size);
        for (uint i = 0; i < size; i++) {
            uint offset = REMINT_DELTAS_OFFSET + i * 12;
            deltas[i] = Delta({
                color: uint32(bytes4(_message[offset:offset + 4])),
                amount: int64(uint64(bytes8(_message[offset + 4:offset + 12])))
            });
        }
        return
            RemintMsg({
                color: uint32(bytes4(_message[REMINT_COLOR_OFFSET:REMINT_AMOUNT_OFFSET])),
                amount: uint64(bytes8(_message[REMINT_AMOUNT_OFFSET:REMINT_THETA_OFFSET])),
                theta: uint64(bytes8(_message[REMINT_THETA_OFFSET:REMINT_DELTAS_OFFSET])),
                deltas: deltas
            });
    }

    function msgType(bytes calldata _message) internal pure returns (uint8) {
        return uint8(bytes1(_message[MSG_TYPE_OFFSET:1]));
    }

    function toAddressB20(bytes32 _addr) internal pure returns (address) {
        return bytes32ToAddress(_addr);
    }

    function addressToBytes32(address _addr) internal pure returns (bytes32) {
        return bytes32(uint256(uint160(_addr)));
    }

    function bytes32ToAddress(bytes32 _b) internal pure returns (address) {
        return address(uint160(uint256(_b)));
    }
}

File 35 of 40 : IUSDV.sol
// SPDX-License-Identifier: LZBL-1.1
// Copyright 2023 LayerZero Labs Ltd.
// You may obtain a copy of the License at
// https://github.com/LayerZero-Labs/license/blob/main/LICENSE-LZBL-1.1

pragma solidity ^0.8.0;

import "@layerzerolabs/lz-evm-oapp-v2/contracts/standards/oft/interfaces/IOFT.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";

struct Delta {
    uint32 color;
    int64 amount;
}

struct State {
    uint32 color;
    uint64 balance;
    // config
    bool blacklisted;
    uint32 defaultColor;
}

enum Role {
    OWNER,
    OPERATOR,
    VAULT,
    MESSAGING,
    FOUNDATION
}

interface IUSDV is IOFT, IERC20Upgradeable {
    error Unauthorized();
    error InvalidUser();
    error InvalidArgument();
    error NotImplemented();
    error InsufficientBalance();
    error Paused();
    error Blacklisted();
    error FeeTooHigh();

    // role assigment
    event SetRole(Role role, address addr);
    event SetColorer(address indexed caller, address indexed user, address colorer);
    event SetDefaultColor(address indexed caller, address indexed user, uint32 defaultColor);
    // governance state
    event SetBlacklist(address indexed user, bool isBlacklisted);
    event SetPause(bool paused);
    // cross-chain events
    event Synced(bytes32 guid, Delta[] deltas);

    function mint(address _receiver, uint64 _amount, uint32 _color) external;

    function burn(address _from, uint64 _amount, uint32[] calldata _delta) external returns (Delta[] memory deltas);

    /// -------- coloring interfaces --------
    function setColorer(address _user, address _colorer) external;

    function setDefaultColor(address _user, uint32 _defaultColor) external;

    /// -------- governance interfaces --------
    function setPause(bool _pause) external;

    function setRole(Role _role, address _addr) external;

    /// -------- cross-chain interfaces (non-OFT) --------
    function sendAck(bytes32 _guid, address _receiver, uint32 _color, uint64 _amount, uint64 _theta) external;

    function syncDelta(
        uint32 _dstEid,
        uint64 _theta,
        uint32[] calldata _deficits,
        uint64 _feeCap,
        bytes calldata _extraOptions,
        MessagingFee calldata _msgFee,
        address payable _refundAddress
    ) external payable returns (MessagingReceipt memory msgReceipt);

    function syncDeltaAck(Delta[] calldata _deltas) external;

    function quoteSyncDeltaFee(
        uint32 _dstEid,
        uint32 _numDeficits,
        bytes calldata _extraOptions,
        bool _useLzToken
    ) external view returns (uint nativeFee, uint lzTokenFee);

    function userStates(
        address _user
    ) external view returns (uint32 color, uint64 balance, bool blacklisted, uint32 defaultColor);
}

File 36 of 40 : IUSDVMain.sol
// SPDX-License-Identifier: LZBL-1.1
// Copyright 2023 LayerZero Labs Ltd.
// You may obtain a copy of the License at
// https://github.com/LayerZero-Labs/license/blob/main/LICENSE-LZBL-1.1

pragma solidity ^0.8.0;
import "./IUSDV.sol";

interface IUSDVMain is IUSDV {
    event Reminted(Delta[] deltas, uint64 remintFee);

    function remint(uint32 _surplusColor, uint64 _surplusAmount, uint32[] calldata _deficits, uint64 _feeCap) external;

    function remintAck(Delta[] calldata _deltas, uint32 _feeColor, uint64 _feeAmount, uint64 _feeTheta) external;
}

File 37 of 40 : IVaultManager.sol
// SPDX-License-Identifier: LZBL-1.1
// Copyright 2023 LayerZero Labs Ltd.
// You may obtain a copy of the License at
// https://github.com/LayerZero-Labs/license/blob/main/LICENSE-LZBL-1.1

pragma solidity ^0.8.0;

import {Delta} from "../../usdv/interfaces/IUSDV.sol";
import "../libs/Asset.sol";

enum Role {
    OWNER,
    OPERATOR,
    FOUNDATION,
    LIQUIDITY_PROVIDER,
    DONOR
}

interface IVaultManager {
    error InvalidAmount();
    error NotDeltaZero();
    error WrongSign();
    error InvalidArgument();
    error InvalidColor(uint32 color);
    error ColorPaused();
    error Unauthorized();

    event DistributedReward(address[] token, uint[] amounts);
    event Minted(address indexed receiver, uint32 indexed color, uint64 amount, bytes32 memo);
    event Redeemed(address indexed redeemer, uint64 amount);
    event PendingRemint(Delta[] deltas);
    event WithdrewReward(address caller, address receiver, uint32 color, uint64 rewards);
    event WithdrewFees(address caller, address receiver, uint64 fees);
    event RegisteredAsset(address asset);
    event EnabledAsset(bool enabled);
    event SetRole(Role role, address addr);
    event SetFeeBpsCap(Role role, uint16 cap);
    event SetFeeBps(Role role, uint16 bps);
    event SetRateLimiter(address limiter);
    event PausedColor(uint32 color, bool paused);
    event SetMinter(address minter, uint32 color);

    function assetInfoOf(
        address _token
    ) external view returns (bool enabled, uint usdvToTokenRate, uint collateralized);

    function mint(address _token, address _receiver, uint64 _amount, uint32 _color, bytes32 _memo) external;

    function remint(Delta[] calldata _deltas, uint64 _remintFee) external;

    function redeem(
        address _token,
        address _receiver,
        uint64 _amount,
        uint64 _minAmount,
        uint32[] calldata _deficits
    ) external returns (uint amountAfterFee);

    function redeemOut(address _token, uint64 _amount) external view returns (uint);
}

File 38 of 40 : Asset.sol
// SPDX-License-Identifier: LZBL-1.1
// Copyright 2023 LayerZero Labs Ltd.
// You may obtain a copy of the License at
// https://github.com/LayerZero-Labs/license/blob/main/LICENSE-LZBL-1.1

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {Governance} from "./Governance.sol";

library Asset {
    using SafeERC20 for IERC20;
    using Governance for Governance.Info;

    struct Info {
        IERC20 token;
        bool registered;
        bool enabled; // to allow minting
        uint usdvToTokenRate;
        // all the following values are in token amount
        uint collateralized;
    }

    error TokenDecimalInvalid(uint provided, uint min);
    error Disabled();
    error AlreadyRegistered();
    error SlippageTooHigh();
    error NotRegistered();

    modifier onlyRegistered(Info storage _self) {
        if (!_self.registered) revert NotRegistered();
        _;
    }

    function initialize(Info storage _self, address _token, uint8 _shareDecimals) internal {
        if (_self.registered) revert AlreadyRegistered();

        // set token
        _self.token = IERC20(_token);
        _self.enabled = true;
        _self.registered = true;

        // set conversion rate
        uint8 tokenDecimals = IERC20Metadata(_token).decimals();
        if (_shareDecimals > tokenDecimals) {
            revert TokenDecimalInvalid(tokenDecimals, _shareDecimals);
        }
        _self.usdvToTokenRate = 10 ** (tokenDecimals - _shareDecimals);
    }

    // @dev if _newFund is true, _from must approve the token transfer
    // @dev if internal mint such as turning yield into collateral, _newFund should be false
    function credit(Info storage _self, address _from, uint64 _usdvAmount, bool _newFund) internal {
        // assert the asset is enabled
        if (!_self.enabled) revert Disabled();

        uint tokenAmount = _usdv2Token(_self, _usdvAmount);
        _self.collateralized += tokenAmount;

        if (_newFund) {
            _self.token.safeTransferFrom(_from, address(this), tokenAmount);
        }
    }

    function redeem(
        Info storage _self,
        Governance.Info storage _govInfo,
        address _receiver,
        uint64 _usdvAmount,
        uint64 _minUsdvAmount
    ) internal onlyRegistered(_self) returns (uint amountAfterFee) {
        uint tokenAmount = _usdv2Token(_self, _usdvAmount);
        _self.collateralized -= tokenAmount;
        // pay redemption fee
        amountAfterFee = _govInfo.payRedemptionFee(_self.token, tokenAmount);
        if (amountAfterFee < _usdv2Token(_self, _minUsdvAmount)) revert SlippageTooHigh();

        // transfer collateral to receiver
        _self.token.safeTransfer(_receiver, amountAfterFee);
    }

    function setEnabled(Info storage _self, bool _enabled) internal onlyRegistered(_self) {
        _self.enabled = _enabled;
    }

    // ========================= View =========================
    /// @return reward in usdv
    function distributable(Info storage _self) internal view returns (uint) {
        uint rebasedFunds = _self.token.balanceOf(address(this)) - _self.collateralized;
        return rebasedFunds / _self.usdvToTokenRate;
    }

    function redeemOutput(
        Info storage _self,
        Governance.Info storage _govInfo,
        uint64 _shares
    ) internal view returns (uint) {
        uint tokenAmount = _usdv2Token(_self, _shares);
        return tokenAmount - _govInfo.getRedemptionFee(tokenAmount);
    }

    // ========================= Internal =========================
    function _usdv2Token(Info storage _self, uint64 _shares) private view returns (uint) {
        return _shares * _self.usdvToTokenRate;
    }
}

File 39 of 40 : Governance.sol
// SPDX-License-Identifier: LZBL-1.1
// Copyright 2023 LayerZero Labs Ltd.
// You may obtain a copy of the License at
// https://github.com/LayerZero-Labs/license/blob/main/LICENSE-LZBL-1.1

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {Role} from "../interfaces/IVaultManager.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

library Governance {
    using SafeERC20 for IERC20;

    uint16 internal constant ONE_HUNDRED_PERCENT = 10000; // 100%
    uint16 internal constant RESERVE_FEE_BPS_CAP = 300; // 3%
    // A % fee is applicable on yield distribution for the vault service.
    uint16 internal constant REDEMPTION_FEE_BPS_CAP_MIN = 10; //0.1%

    struct Fee {
        uint16 bps;
        uint16 cap;
    }

    struct Info {
        mapping(Role => Fee) fees;
        mapping(Role => address) roles;
        uint operatorLastPing; // timestamp
    }

    event PaidRedemptionFee(address indexed to, uint amount);

    // ========================= Operator =========================
    function ping(Info storage _self) internal {
        _self.operatorLastPing = block.timestamp;
    }

    // ========================= Fees =========================
    function getRedemptionFee(Info storage _self, uint _amount) internal view returns (uint fee) {
        return (_amount * _self.fees[Role.FOUNDATION].bps) / ONE_HUNDRED_PERCENT;
    }

    function payRedemptionFee(Info storage _self, IERC20 _token, uint _amount) internal returns (uint) {
        uint fee = getRedemptionFee(_self, _amount);
        // pay redemption fee to operator
        address _to = _self.roles[Role.OPERATOR];
        _token.safeTransfer(_to, fee);
        emit PaidRedemptionFee(_to, fee);

        return _amount - fee;
    }
}

File 40 of 40 : 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;
    }
}

Settings
{
  "evmVersion": "paris",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs",
    "useLiteralContent": true
  },
  "optimizer": {
    "enabled": true,
    "runs": 5000
  },
  "remappings": [],
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_endpoint","type":"address"},{"internalType":"address","name":"_usdv","type":"address"},{"internalType":"uint32","name":"_mainChainEid","type":"uint32"},{"internalType":"bool","name":"_isMainChain","type":"bool"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidSize","type":"error"},{"inputs":[],"name":"NotImplemented","type":"error"},{"inputs":[],"name":"NotMainChain","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"NotUSDV","type":"error"},{"inputs":[{"internalType":"bytes","name":"result","type":"bytes"}],"name":"SimulationResult","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"_nonce","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"_payload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"_reason","type":"bytes"}],"name":"MessageFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"_nonce","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"_payloadHash","type":"bytes32"}],"name":"RetryMessageSuccess","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"_type","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"_minDstGas","type":"uint256"}],"name":"SetMinDstGas","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"dstEid","type":"uint32"},{"indexed":false,"internalType":"uint8","name":"msgType","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"extraGas","type":"uint256"}],"name":"SetPerColorExtraGas","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"precrime","type":"address"}],"name":"SetPrecrime","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_remoteChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_path","type":"bytes"}],"name":"SetTrustedRemote","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_remoteChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_remoteAddress","type":"bytes"}],"name":"SetTrustedRemoteAddress","type":"event"},{"inputs":[{"components":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"origin","type":"tuple"},{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"bytes32","name":"guid","type":"bytes32"},{"internalType":"bytes","name":"message","type":"bytes"}],"internalType":"struct InboundPacket[]","name":"_packets","type":"tuple[]"}],"name":"_simulateLzReceive","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"failedMessages","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"}],"name":"forceResumeReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"},{"internalType":"uint16","name":"_chainId","type":"uint16"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"_configType","type":"uint256"}],"name":"getConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_remoteChainId","type":"uint16"}],"name":"getTrustedRemoteAddress","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isMainChain","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"bytes32","name":"_peer","type":"bytes32"}],"name":"isPeer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"}],"name":"isTrustedRemote","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lzEndpoint","outputs":[{"internalType":"contract ILayerZeroEndpoint","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"lzReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"origin","type":"tuple"},{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"bytes32","name":"guid","type":"bytes32"},{"internalType":"bytes","name":"message","type":"bytes"}],"internalType":"struct InboundPacket[]","name":"_packets","type":"tuple[]"}],"name":"lzReceiveAndRevert","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mainChainEid","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"uint16","name":"","type":"uint16"}],"name":"minDstGasLookup","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"nonblockingLzReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"oapp","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"uint8","name":"msgType","type":"uint8"}],"name":"perColorExtraGasLookup","outputs":[{"internalType":"uint256","name":"extraGas","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"precrime","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"color","type":"uint32"},{"internalType":"int64","name":"amount","type":"int64"}],"internalType":"struct Delta[]","name":"_deltas","type":"tuple[]"},{"internalType":"bytes","name":"_extraOptions","type":"bytes"},{"internalType":"bool","name":"","type":"bool"}],"name":"quoteRemintFee","outputs":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dstEid","type":"uint32"},{"internalType":"bytes","name":"_extraOptions","type":"bytes"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"bytes","name":"_composeMsg","type":"bytes"}],"name":"quoteSendFee","outputs":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dstEid","type":"uint32"},{"components":[{"internalType":"uint32","name":"color","type":"uint32"},{"internalType":"int64","name":"amount","type":"int64"}],"internalType":"struct Delta[]","name":"_deltas","type":"tuple[]"},{"internalType":"bytes","name":"_extraOptions","type":"bytes"},{"internalType":"bool","name":"","type":"bool"}],"name":"quoteSyncDeltaFee","outputs":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"color","type":"uint32"},{"internalType":"int64","name":"amount","type":"int64"}],"internalType":"struct Delta[]","name":"_deltas","type":"tuple[]"},{"internalType":"uint32","name":"_feeColor","type":"uint32"},{"internalType":"uint64","name":"_feeAmount","type":"uint64"},{"internalType":"uint64","name":"_feeTheta","type":"uint64"},{"internalType":"bytes","name":"_extraOptions","type":"bytes"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"","type":"tuple"},{"internalType":"address payable","name":"_refundAddress","type":"address"}],"name":"remint","outputs":[{"components":[{"internalType":"bytes32","name":"guid","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"fee","type":"tuple"}],"internalType":"struct MessagingReceipt","name":"msgReceipt","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"retryMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint32","name":"color","type":"uint32"},{"internalType":"uint64","name":"amount","type":"uint64"},{"internalType":"uint64","name":"theta","type":"uint64"}],"internalType":"struct IMessaging.SendParam","name":"_param","type":"tuple"},{"internalType":"bytes","name":"_extraOptions","type":"bytes"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"","type":"tuple"},{"internalType":"address payable","name":"_refundAddress","type":"address"},{"internalType":"bytes","name":"_composeMsg","type":"bytes"}],"name":"send","outputs":[{"components":[{"internalType":"bytes32","name":"guid","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"fee","type":"tuple"}],"internalType":"struct MessagingReceipt","name":"msgReceipt","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"},{"internalType":"uint16","name":"_chainId","type":"uint16"},{"internalType":"uint256","name":"_configType","type":"uint256"},{"internalType":"bytes","name":"_config","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"uint16","name":"_packetType","type":"uint16"},{"internalType":"uint256","name":"_minGas","type":"uint256"}],"name":"setMinDstGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dstEid","type":"uint32"},{"internalType":"uint8","name":"_msgType","type":"uint8"},{"internalType":"uint256","name":"_extraGas","type":"uint256"}],"name":"setPerColorExtraGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_precrime","type":"address"}],"name":"setPrecrime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"}],"name":"setReceiveVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"}],"name":"setSendVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_path","type":"bytes"}],"name":"setTrustedRemote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_remoteChainId","type":"uint16"},{"internalType":"bytes","name":"_remoteAddress","type":"bytes"}],"name":"setTrustedRemoteAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dstEid","type":"uint32"},{"components":[{"internalType":"uint32","name":"color","type":"uint32"},{"internalType":"int64","name":"amount","type":"int64"}],"internalType":"struct Delta[]","name":"_deltas","type":"tuple[]"},{"internalType":"bytes","name":"_extraOptions","type":"bytes"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"","type":"tuple"},{"internalType":"address payable","name":"_refundAddress","type":"address"}],"name":"syncDelta","outputs":[{"components":[{"internalType":"bytes32","name":"guid","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"fee","type":"tuple"}],"internalType":"struct MessagingReceipt","name":"msgReceipt","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"trustedRemoteLookup","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"usdv","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

6101006040523480156200001257600080fd5b5060405162004e6c38038062004e6c8339810160408190526200003591620000e3565b8282828680620000453362000076565b6001600160a01b039081166080529390931660e05263ffffffff90911660a052151560c05250620001519350505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b0381168114620000de57600080fd5b919050565b60008060008060808587031215620000fa57600080fd5b6200010585620000c6565b93506200011560208601620000c6565b9250604085015163ffffffff811681146200012f57600080fd5b606086015190925080151581146200014657600080fd5b939692955090935050565b60805160a05160c05160e051614c4e6200021e6000396000818161064101528181610b6c015281816114c5015281816119c1015281816129e801528181612ab60152612bba0152600081816107090152612b150152600081816105e501528181611090015281816110fe01528181611a210152611aa50152600081816106d50152818161080101528181610a8001528181610b2201528181610f2c0152818161114c015281816112360152818161134901528181611d5e015281816121ab01526125cd0152614c4e6000f3fe6080604052600436106102695760003560e01c80637533d78811610153578063a6c3d165116100cb578063d1deba1f1161007f578063eb8d72b711610064578063eb8d72b71461079e578063f2fde38b146107be578063f5ecbdbc146107de57600080fd5b8063d1deba1f1461076b578063df2a5b3b1461077e57600080fd5b8063b834f6fb116100b0578063b834f6fb146106f7578063baf3292d1461072b578063cbed8b9c1461074b57600080fd5b8063a6c3d165146106a3578063b353aaa7146106c357600080fd5b80639212a76e116101225780639420069c116101075780639420069c1461062f578063950c8a74146106635780639f38369a1461068357600080fd5b80639212a76e146105d357806393284d951461061c57600080fd5b80637533d788146105305780637f3cbb891461055d5780638cfd8f5c1461057d5780638da5cb5b146105b557600080fd5b806342d65a8d116101e65780635a0dfe4d116101b557806366ad5c8a1161019a57806366ad5c8a146104e8578063715018a61461050857806374c71e0d1461051d57600080fd5b80635a0dfe4d146104795780635b8c41e61461049957600080fd5b806342d65a8d1461041357806344d9c507146104335780635011e5b314610453578063564991451461046657600080fd5b806318d6b43a1161023d578063314dfef511610222578063314dfef51461038e5780633d8b38f6146103c3578063403a8942146103f357600080fd5b806318d6b43a146102fc57806327d19a2c1461034857600080fd5b80621d35671461026e57806307e0db17146102905780630931cf88146102b057806310ddb137146102dc575b600080fd5b34801561027a57600080fd5b5061028e610289366004613731565b6107fe565b005b34801561029c57600080fd5b5061028e6102ab3660046137c5565b610a46565b3480156102bc57600080fd5b50305b6040516001600160a01b0390911681526020015b60405180910390f35b3480156102e857600080fd5b5061028e6102f73660046137c5565b610ae8565b61030f61030a366004613807565b610b59565b604080518251815260208084015167ffffffffffffffff16818301529282015180519282019290925291015160608201526080016102d3565b34801561035457600080fd5b506103806103633660046138e1565b600560209081526000928352604080842090915290825290205481565b6040519081526020016102d3565b34801561039a57600080fd5b506103ae6103a9366004613924565b610dd5565b604080519283526020830191909152016102d3565b3480156103cf57600080fd5b506103e36103de366004613983565b610fba565b60405190151581526020016102d3565b3480156103ff57600080fd5b506103ae61040e366004613a1b565b611086565b34801561041f57600080fd5b5061028e61042e366004613983565b6111fe565b34801561043f57600080fd5b506103ae61044e366004613a9c565b61129d565b61028e610461366004613b2c565b6113a7565b61030f610474366004613ba1565b6114b2565b34801561048557600080fd5b506103e3610494366004613c48565b611614565b3480156104a557600080fd5b506103806104b4366004613cfa565b6004602090815260009384526040808520845180860184018051928152908401958401959095209452929052825290205481565b3480156104f457600080fd5b5061028e610503366004613731565b611767565b34801561051457600080fd5b5061028e6117f2565b61028e61052b366004613b2c565b611806565b34801561053c57600080fd5b5061055061054b3660046137c5565b61189f565b6040516102d39190613deb565b34801561056957600080fd5b5061028e610578366004613dfe565b611939565b34801561058957600080fd5b50610380610598366004613e3a565b600260209081526000928352604080842090915290825290205481565b3480156105c157600080fd5b506000546001600160a01b03166102bf565b3480156105df57600080fd5b506106077f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff90911681526020016102d3565b61030f61062a366004613e64565b6119ae565b34801561063b57600080fd5b506102bf7f000000000000000000000000000000000000000000000000000000000000000081565b34801561066f57600080fd5b506003546102bf906001600160a01b031681565b34801561068f57600080fd5b5061055061069e3660046137c5565b611b20565b3480156106af57600080fd5b5061028e6106be366004613983565b611c36565b3480156106cf57600080fd5b506102bf7f000000000000000000000000000000000000000000000000000000000000000081565b34801561070357600080fd5b506103e37f000000000000000000000000000000000000000000000000000000000000000081565b34801561073757600080fd5b5061028e610746366004613f2f565b611cb2565b34801561075757600080fd5b5061028e610766366004613f4c565b611d26565b61028e610779366004613731565b611dd4565b34801561078a57600080fd5b5061028e610799366004613fbb565b611fbd565b3480156107aa57600080fd5b5061028e6107b9366004613983565b612077565b3480156107ca57600080fd5b5061028e6107d9366004613f2f565b6120d1565b3480156107ea57600080fd5b506105506107f9366004613fe7565b612161565b337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461087b5760405162461bcd60e51b815260206004820152601e60248201527f4c7a4170703a20696e76616c696420656e64706f696e742063616c6c6572000060448201526064015b60405180910390fd5b61ffff86166000908152600160205260408120805461089990614034565b80601f01602080910402602001604051908101604052809291908181526020018280546108c590614034565b80156109125780601f106108e757610100808354040283529160200191610912565b820191906000526020600020905b8154815290600101906020018083116108f557829003601f168201915b5050505050905080518686905014801561092d575060008151115b801561095557508051602082012060405161094b9088908890614081565b6040518091039020145b6109c75760405162461bcd60e51b815260206004820152602660248201527f4c7a4170703a20696e76616c696420736f757263652073656e64696e6720636f60448201527f6e747261637400000000000000000000000000000000000000000000000000006064820152608401610872565b610a3d8787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a018190048102820181019092528881528a93509150889088908190840183828082843760009201919091525061222b92505050565b50505050505050565b610a4e6122d1565b6040517f07e0db1700000000000000000000000000000000000000000000000000000000815261ffff821660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906307e0db17906024015b600060405180830381600087803b158015610acd57600080fd5b505af1158015610ae1573d6000803e3d6000fd5b5050505050565b610af06122d1565b6040517f10ddb13700000000000000000000000000000000000000000000000000000000815261ffff821660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906310ddb13790602401610ab3565b610b61613671565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610bc5576040517f871f077c000000000000000000000000000000000000000000000000000000008152336004820152602401610872565b8115610c395760405162461bcd60e51b815260206004820152602560248201527f4d6573736167696e6756313a20636f6d706f73654d7367206e6f74207375707060448201527f6f727465640000000000000000000000000000000000000000000000000000006064820152608401610872565b6000610c56610c4b60208b018b614091565b63ffffffff1661232b565b9050610c9d81600160ff168a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525092506123a9915050565b610dc981610d8860208c0135610cb960608e0160408f01614091565b8d6060016020810190610ccc91906140ac565b8e6080016020810190610cdf91906140ac565b604080517f01000000000000000000000000000000000000000000000000000000000000006020820152602181019590955260e09390931b7fffffffff0000000000000000000000000000000000000000000000000000000016604185015260c091821b7fffffffffffffffff0000000000000000000000000000000000000000000000009081166045860152911b16604d830152805160358184030181526055909201905290565b8760008c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250349250612488915050565b50979650505050505050565b6000808215610e4c5760405162461bcd60e51b815260206004820152602560248201527f4d6573736167696e6756313a20636f6d706f73654d7367206e6f74207375707060448201527f6f727465640000000000000000000000000000000000000000000000000000006064820152608401610872565b6000610e5d8963ffffffff1661232b565b9050610ea481600160ff168a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525092506123a9915050565b604080517f010000000000000000000000000000000000000000000000000000000000000060208201526000602182018190526041820181905260458201819052604d82018190528251603581840301815260558301938490527f40a7bb10000000000000000000000000000000000000000000000000000000009093526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016926340a7bb1092610f6a92869230929091908f908f906059016140f2565b6040805180830381865afa158015610f86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610faa9190614146565b9250925050965096945050505050565b61ffff831660009081526001602052604081208054829190610fdb90614034565b80601f016020809104026020016040519081016040528092919081815260200182805461100790614034565b80156110545780601f1061102957610100808354040283529160200191611054565b820191906000526020600020905b81548152906001019060200180831161103757829003601f168201915b50505050509050838360405161106b929190614081565b60405180910390208180519060200120149150509392505050565b60008060006110ba7f000000000000000000000000000000000000000000000000000000000000000063ffffffff1661232b565b905061114a81600460ff1688888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525063ffffffff7f00000000000000000000000000000000000000000000000000000000000000001681526005602090815260408083206004845290915290205461114593508e92509050614199565b6123a9565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166340a7bb10823061118a8c8c6000806000612649565b60008b8b6040518763ffffffff1660e01b81526004016111af969594939291906140f2565b6040805180830381865afa1580156111cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ef9190614146565b92509250509550959350505050565b6112066122d1565b6040517f42d65a8d0000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342d65a8d9061126f908690869086906004016141b0565b600060405180830381600087803b15801561128957600080fd5b505af1158015610a3d573d6000803e3d6000fd5b60008060006112b18963ffffffff1661232b565b905061134781600360ff1688888080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508b8b9050600560008f63ffffffff1663ffffffff1681526020019081526020016000206000600360ff1660ff168152602001908152602001600020546111459190614199565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166340a7bb1082306113828c8c612773565b60008b8b6040518763ffffffff1660e01b8152600401610f6a969594939291906140f2565b6040517f74c71e0d00000000000000000000000000000000000000000000000000000000815230906374c71e0d9034906113e79086908690600401614232565b6000604051808303818588803b15801561140057600080fd5b505af1158015611414573d6000803e3d6000fd5b5050505050336001600160a01b0316638e9e70996040518163ffffffff1660e01b8152600401600060405180830381865afa158015611457573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261147f919081019061436a565b6040517f8351eea70000000000000000000000000000000000000000000000000000000081526004016108729190613deb565b6114ba613671565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461151e576040517f871f077c000000000000000000000000000000000000000000000000000000008152336004820152602401610872565b600061152f8963ffffffff1661232b565b90506115c581600360ff1688888080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508b8b9050600560008f63ffffffff1663ffffffff1681526020019081526020016000206000600360ff1660ff168152602001908152602001600020546111459190614199565b610dc9816115d38a8a612773565b8560008a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250349250612488915050565b6000806001600061162a8663ffffffff1661232b565b61ffff1661ffff168152602001908152602001600020805461164b90614034565b80601f016020809104026020016040519081016040528092919081815260200182805461167790614034565b80156116c45780601f10611699576101008083540402835291602001916116c4565b820191906000526020600020905b8154815290600101906020018083116116a757829003601f168201915b50508351939450506014831191505080156116e0575060348111155b61172c5760405162461bcd60e51b815260206004820181905260248201527f4d6573736167696e6756313a20696e76616c69642070617468206c656e6774686044820152606401610872565b60006117458161173d6014856143d8565b859190612823565b61174e906143eb565b92516034036008029290921c8414925050505b92915050565b3330146117dc5760405162461bcd60e51b815260206004820152602660248201527f4e6f6e626c6f636b696e674c7a4170703a2063616c6c6572206d75737420626560448201527f204c7a41707000000000000000000000000000000000000000000000000000006064820152608401610872565b6117ea86868686868661294b565b505050505050565b6117fa6122d1565b6118046000612c24565b565b3330146118155761181561440f565b60005b8181101561189a57368383838181106118335761183361443e565b9050602002810190611845919061446d565b90506118616118576020830183614091565b6020830135611614565b61186b5750611888565b6118868160a081013561188160c08301836144ab565b612c8c565b505b8061189281614510565b915050611818565b505050565b600160205260009081526040902080546118b890614034565b80601f01602080910402602001604051908101604052809291908181526020018280546118e490614034565b80156119315780601f1061190657610100808354040283529160200191611931565b820191906000526020600020905b81548152906001019060200180831161191457829003601f168201915b505050505081565b6119416122d1565b63ffffffff8316600081815260056020908152604080832060ff87168085529083529281902085905580519384529083019190915281018290527f0564a47bb54b5af04d89fd36c310b8406fd9662464597e3af04594417ea05cf6906060015b60405180910390a1505050565b6119b6613671565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611a1a576040517f871f077c000000000000000000000000000000000000000000000000000000008152336004820152602401610872565b6000611a4b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff1661232b565b9050611b0181600460ff1688888080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508e8e9050600560007f000000000000000000000000000000000000000000000000000000000000000063ffffffff1663ffffffff1681526020019081526020016000206000600460ff1660ff168152602001908152602001600020546111459190614199565b611b12816115d38d8d8d8d8d612649565b509998505050505050505050565b61ffff8116600090815260016020526040812080546060929190611b4390614034565b80601f0160208091040260200160405190810160405280929190818152602001828054611b6f90614034565b8015611bbc5780601f10611b9157610100808354040283529160200191611bbc565b820191906000526020600020905b815481529060010190602001808311611b9f57829003601f168201915b505050505090508051600003611c145760405162461bcd60e51b815260206004820152601d60248201527f4c7a4170703a206e6f20747275737465642070617468207265636f72640000006044820152606401610872565b611c2f600060148351611c2791906143d8565b839190612823565b9392505050565b611c3e6122d1565b818130604051602001611c539392919061452a565b60408051601f1981840301815291815261ffff8516600090815260016020522090611c7e90826145a9565b507f8c0400cfe2d1199b1a725c78960bcc2a344d869b80590d0f2bd005db15a572ce8383836040516119a1939291906141b0565b611cba6122d1565b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527f5db758e995a17ec1ad84bdef7e8c3293a0bd6179bcce400dff5d4c3d87db726b9060200160405180910390a150565b611d2e6122d1565b6040517fcbed8b9c0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063cbed8b9c90611d9b9088908890889088908890600401614669565b600060405180830381600087803b158015611db557600080fd5b505af1158015611dc9573d6000803e3d6000fd5b505050505050505050565b61ffff86166000908152600460205260408082209051611df79088908890614081565b908152604080516020928190038301902067ffffffffffffffff871660009081529252902054905080611e925760405162461bcd60e51b815260206004820152602360248201527f4e6f6e626c6f636b696e674c7a4170703a206e6f2073746f726564206d65737360448201527f61676500000000000000000000000000000000000000000000000000000000006064820152608401610872565b808383604051611ea3929190614081565b604051809103902014611f1e5760405162461bcd60e51b815260206004820152602160248201527f4e6f6e626c6f636b696e674c7a4170703a20696e76616c6964207061796c6f6160448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610872565b61ffff87166000908152600460205260408082209051611f419089908990614081565b908152604080516020928190038301902067ffffffffffffffff881660009081529252902055611f7587878787878761294b565b7fc264d91f3adc5588250e1551f547752ca0cfa8f6b530d243b9f9f4cab10ea8e58787878785604051611fac9594939291906146a2565b60405180910390a150505050505050565b611fc56122d1565b600081116120155760405162461bcd60e51b815260206004820152601560248201527f4c7a4170703a20696e76616c6964206d696e47617300000000000000000000006044820152606401610872565b61ffff83811660008181526002602090815260408083209487168084529482529182902085905581519283528201929092529081018290527f9d5c7c0b934da8fefa9c7760c98383778a12dfbfc0c3b3106518f43fb9508ac0906060016119a1565b61207f6122d1565b61ffff8316600090815260016020526040902061209d8284836146de565b507ffa41487ad5d6728f0b19276fa1eddc16558578f5109fc39d2dc33c3230470dab8383836040516119a1939291906141b0565b6120d96122d1565b6001600160a01b0381166121555760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610872565b61215e81612c24565b50565b6040517ff5ecbdbc00000000000000000000000000000000000000000000000000000000815261ffff808616600483015284166024820152306044820152606481018290526060907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f5ecbdbc90608401600060405180830381865afa1580156121fa573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612222919081019061436a565b95945050505050565b6000806122bb5a60966366ad5c8a60e01b89898989604051602401612253949392919061479e565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915230929190612d12565b91509150816117ea576117ea8686868685612d9d565b6000546001600160a01b031633146118045760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610872565b600061ffff8211156123a55760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203160448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610872565b5090565b60006123b483612e3b565b61ffff8087166000908152600260209081526040808320938916835292905290812054919250906123e69084906147dd565b9050600081116124385760405162461bcd60e51b815260206004820152601a60248201527f4c7a4170703a206d696e4761734c696d6974206e6f74207365740000000000006044820152606401610872565b808210156117ea5760405162461bcd60e51b815260206004820152601b60248201527f4c7a4170703a20676173206c696d697420697320746f6f206c6f7700000000006044820152606401610872565b61ffff8616600090815260016020526040812080546124a690614034565b80601f01602080910402602001604051908101604052809291908181526020018280546124d290614034565b801561251f5780601f106124f45761010080835404028352916020019161251f565b820191906000526020600020905b81548152906001019060200180831161250257829003601f168201915b50505050509050805160000361259d5760405162461bcd60e51b815260206004820152603060248201527f4c7a4170703a2064657374696e6174696f6e20636861696e206973206e6f742060448201527f61207472757374656420736f75726365000000000000000000000000000000006064820152608401610872565b6040517fc58031000000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c580310090849061260e908b9086908c908c908c908c906004016147f0565b6000604051808303818588803b15801561262757600080fd5b505af115801561263b573d6000803e3d6000fd5b505050505050505050505050565b6060612668604051806040016040528060608152602001600081525090565b61268861267687600c614199565b6126819060156147dd565b8290612e97565b50612694816004612efc565b506126ab8163ffffffff80881690600490612f2116565b506126c28167ffffffffffffffff86166008612f21565b506126d98167ffffffffffffffff85166008612f21565b5060005b8681101561276757368888838181106126f8576126f861443e565b60400291909101915061272b90506127136020830183614091565b63ffffffff16600485612f219092919063ffffffff16565b5061275261273f604083016020840161484a565b849067ffffffffffffffff166008612f21565b5050808061275f90614510565b9150506126dd565b50519695505050505050565b6060612792604051806040016040528060608152602001600081525090565b6127ab6127a084600c614199565b6126819060016147dd565b506127b7816003612efc565b5060005b8381101561281a57368585838181106127d6576127d661443e565b6040029190910191506127f190506127136020830183614091565b5061280561273f604083016020840161484a565b5050808061281290614510565b9150506127bb565b50519392505050565b60608161283181601f6147dd565b101561287f5760405162461bcd60e51b815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610872565b61288982846147dd565b845110156128d95760405162461bcd60e51b815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610872565b6060821580156128f85760405191506000825260208201604052612942565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015612931578051835260209283019201612919565b5050858452601f01601f1916604052505b50949350505050565b60006129578383612f4f565b905060001960ff821601612a4b5760006129718484612f71565b80516020820151604080840151606085015191517f75c2f575000000000000000000000000000000000000000000000000000000008152600060048201526001600160a01b03948516602482015263ffffffff909316604484015267ffffffffffffffff90811660648401521660848201529192507f000000000000000000000000000000000000000000000000000000000000000016906375c2f5759060a4015b600060405180830381600087803b158015612a2d57600080fd5b505af1158015612a41573d6000803e3d6000fd5b5050505050610a3d565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd60ff821601612ae9576000612a818484613069565b80516040517f5ae0d1af0000000000000000000000000000000000000000000000000000000081529192506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691635ae0d1af91612a13916004016148b1565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60ff821601612bf2577f0000000000000000000000000000000000000000000000000000000000000000612b6a576040517f60dee01500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612b768484613221565b80516020820151604080840151606085015191517f698b933e0000000000000000000000000000000000000000000000000000000081529495506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169463698b933e94612a139490939092916004016148c4565b6040517fd623472500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60408051602081018252600080825291517f66ad5c8a00000000000000000000000000000000000000000000000000000000815230926366ad5c8a92612cda92829088908890600401614904565b600060405180830381600087803b158015612cf457600080fd5b505af1158015612d08573d6000803e3d6000fd5b5050505050505050565b6000606060008060008661ffff1667ffffffffffffffff811115612d3857612d38613c72565b6040519080825280601f01601f191660200182016040528015612d62576020820181803683370190505b50905060008087516020890160008d8df191503d925086831115612d84578692505b828152826000602083013e909890975095505050505050565b8180519060200120600460008761ffff1661ffff16815260200190815260200160002085604051612dce9190614950565b90815260408051918290036020908101832067ffffffffffffffff88166000908152915220919091557fe183f33de2837795525b4792ca4cd60535bd77c53b7e7030060bfcf5734d6b0c90612e2c9087908790879087908790614962565b60405180910390a15050505050565b6000602282511015612e8f5760405162461bcd60e51b815260206004820152601c60248201527f4c7a4170703a20696e76616c69642061646170746572506172616d73000000006044820152606401610872565b506022015190565b604080518082019091526060815260006020820152612eb76020836149e4565b15612edf57612ec76020836149e4565b612ed29060206143d8565b612edc90836147dd565b91505b506020828101829052604080518085526000815290920101905290565b604080518082019091526060815260006020820152611c2f838460000151518461344d565b604080518082019091526060815260006020820152612f478485600001515185856134ad565b949350505050565b6000612f5e60018284866149f8565b612f6791614a22565b60f81c9392505050565b60408051608081018252600080825260208201819052918101829052606081019190915260358214612fcf576040517f0ffd11ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516080810190915280612ffa612fec6021600187896149f8565b612ff591614a6a565b613539565b6001600160a01b031681526020016130166025602186886149f8565b61301f91614a88565b60e01c8152602001613035602d602586886149f8565b61303e91614ace565b60c01c81526020016130546035602d86886149f8565b61305d91614ace565b60c01c90529392505050565b604080516020810190915260608152600c6130856001846143d8565b61308f91906149e4565b156130c6576040517f0ffd11ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600c6130d56001856143d8565b6130df9190614b14565b905060008167ffffffffffffffff8111156130fc576130fc613c72565b60405190808252806020026020018201604052801561314157816020015b604080518082019091526000808252602082015281526020019060019003908161311a5790505b50905060005b8281101561320a57600061315c82600c614199565b6131679060016147dd565b905060405180604001604052808888849085600461318591906147dd565b92613192939291906149f8565b61319b91614a88565b60e01c815260200188886131b08560046147dd565b906131bc86600c6147dd565b926131c9939291906149f8565b6131d291614ace565b60c01d905283518490849081106131eb576131eb61443e565b602002602001018190525050808061320290614510565b915050613147565b506040805160208101909152908152949350505050565b604080516080810182526060808252600060208301819052928201839052810191909152600c6132526015846143d8565b61325c91906149e4565b15613293576040517f0ffd11ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600c6132a26015856143d8565b6132ac9190614b14565b905060008167ffffffffffffffff8111156132c9576132c9613c72565b60405190808252806020026020018201604052801561330e57816020015b60408051808201909152600080825260208201528152602001906001900390816132e75790505b50905060005b828110156133d757600061332982600c614199565b6133349060156147dd565b905060405180604001604052808888849085600461335291906147dd565b9261335f939291906149f8565b61336891614a88565b60e01c8152602001888861337d8560046147dd565b9061338986600c6147dd565b92613396939291906149f8565b61339f91614ace565b60c01d905283518490849081106133b8576133b861443e565b60200260200101819052505080806133cf90614510565b915050613314565b506040805160808101909152818152602081016133f860056001888a6149f8565b61340191614a88565b60e01c8152602001613417600d6005888a6149f8565b61342091614ace565b60c01c81526020016134366015600d888a6149f8565b61343f91614ace565b60c01c905295945050505050565b604080518082019091526060815260006020820152836020015183106134875761348784856020015160026134829190614199565b613541565b83518051602085830101848153508085036134a3576001810182525b5093949350505050565b60408051808201909152606081526000602082015260208501516134d185846147dd565b11156134f0576134f0856134e586856147dd565b613482906002614199565b6000600161350084610100614c0c565b61350a91906143d8565b905085518386820101858319825116178152508051848701111561352e5783860181525b509495945050505050565b600081611761565b815161354d8383612e97565b50613558838261355e565b50505050565b604080518082019091526060815260006020820152611c2f8384600001515184855160408051808201909152606081526000602082015282518211156135a357600080fd5b60208501516135b283866147dd565b11156135d5576135d5856134e5876020015187866135d091906147dd565b61365a565b6000808651805187602083010193508088870111156135f45787860182525b505050602084015b6020841061363457805182526136136020836147dd565b91506136206020826147dd565b905061362d6020856143d8565b93506135fc565b51815160001960208690036101000a019081169019919091161790525083949350505050565b60008183111561366b575081611761565b50919050565b604051806060016040528060008019168152602001600067ffffffffffffffff1681526020016136b4604051806040016040528060008152602001600081525090565b905290565b803561ffff811681146136cb57600080fd5b919050565b60008083601f8401126136e257600080fd5b50813567ffffffffffffffff8111156136fa57600080fd5b60208301915083602082850101111561371257600080fd5b9250929050565b803567ffffffffffffffff811681146136cb57600080fd5b6000806000806000806080878903121561374a57600080fd5b613753876136b9565b9550602087013567ffffffffffffffff8082111561377057600080fd5b61377c8a838b016136d0565b909750955085915061379060408a01613719565b945060608901359150808211156137a657600080fd5b506137b389828a016136d0565b979a9699509497509295939492505050565b6000602082840312156137d757600080fd5b611c2f826136b9565b60006040828403121561366b57600080fd5b6001600160a01b038116811461215e57600080fd5b600080600080600080600087890361014081121561382457600080fd5b60a081121561383257600080fd5b5087965060a088013567ffffffffffffffff8082111561385157600080fd5b61385d8b838c016136d0565b90985096508691506138728b60c08c016137e0565b95506101008a01359150613885826137f2565b909350610120890135908082111561389c57600080fd5b506138a98a828b016136d0565b989b979a50959850939692959293505050565b803563ffffffff811681146136cb57600080fd5b803560ff811681146136cb57600080fd5b600080604083850312156138f457600080fd5b6138fd836138bc565b915061390b602084016138d0565b90509250929050565b803580151581146136cb57600080fd5b6000806000806000806080878903121561393d57600080fd5b613946876138bc565b9550602087013567ffffffffffffffff8082111561396357600080fd5b61396f8a838b016136d0565b909750955085915061379060408a01613914565b60008060006040848603121561399857600080fd5b6139a1846136b9565b9250602084013567ffffffffffffffff8111156139bd57600080fd5b6139c9868287016136d0565b9497909650939450505050565b60008083601f8401126139e857600080fd5b50813567ffffffffffffffff811115613a0057600080fd5b6020830191508360208260061b850101111561371257600080fd5b600080600080600060608688031215613a3357600080fd5b853567ffffffffffffffff80821115613a4b57600080fd5b613a5789838a016139d6565b90975095506020880135915080821115613a7057600080fd5b50613a7d888289016136d0565b9094509250613a90905060408701613914565b90509295509295909350565b60008060008060008060808789031215613ab557600080fd5b613abe876138bc565b9550602087013567ffffffffffffffff80821115613adb57600080fd5b613ae78a838b016139d6565b90975095506040890135915080821115613b0057600080fd5b50613b0d89828a016136d0565b9094509250613b20905060608801613914565b90509295509295509295565b60008060208385031215613b3f57600080fd5b823567ffffffffffffffff80821115613b5757600080fd5b818501915085601f830112613b6b57600080fd5b813581811115613b7a57600080fd5b8660208260051b8501011115613b8f57600080fd5b60209290920196919550909350505050565b600080600080600080600060c0888a031215613bbc57600080fd5b613bc5886138bc565b9650602088013567ffffffffffffffff80821115613be257600080fd5b613bee8b838c016139d6565b909850965060408a0135915080821115613c0757600080fd5b50613c148a828b016136d0565b9095509350613c2890508960608a016137e0565b915060a0880135613c38816137f2565b8091505092959891949750929550565b60008060408385031215613c5b57600080fd5b613c64836138bc565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613cca57613cca613c72565b604052919050565b600067ffffffffffffffff821115613cec57613cec613c72565b50601f01601f191660200190565b600080600060608486031215613d0f57600080fd5b613d18846136b9565b9250602084013567ffffffffffffffff811115613d3457600080fd5b8401601f81018613613d4557600080fd5b8035613d58613d5382613cd2565b613ca1565b818152876020838501011115613d6d57600080fd5b81602084016020830137600060208383010152809450505050613d9260408501613719565b90509250925092565b60005b83811015613db6578181015183820152602001613d9e565b50506000910152565b60008151808452613dd7816020860160208601613d9b565b601f01601f19169290920160200192915050565b602081526000611c2f6020830184613dbf565b600080600060608486031215613e1357600080fd5b613e1c846138bc565b9250613e2a602085016138d0565b9150604084013590509250925092565b60008060408385031215613e4d57600080fd5b613e56836136b9565b915061390b602084016136b9565b60008060008060008060008060006101008a8c031215613e8357600080fd5b893567ffffffffffffffff80821115613e9b57600080fd5b613ea78d838e016139d6565b909b509950899150613ebb60208d016138bc565b9850613ec960408d01613719565b9750613ed760608d01613719565b965060808c0135915080821115613eed57600080fd5b50613efa8c828d016136d0565b9095509350613f0e90508b60a08c016137e0565b915060e08a0135613f1e816137f2565b809150509295985092959850929598565b600060208284031215613f4157600080fd5b8135611c2f816137f2565b600080600080600060808688031215613f6457600080fd5b613f6d866136b9565b9450613f7b602087016136b9565b935060408601359250606086013567ffffffffffffffff811115613f9e57600080fd5b613faa888289016136d0565b969995985093965092949392505050565b600080600060608486031215613fd057600080fd5b613fd9846136b9565b9250613e2a602085016136b9565b60008060008060808587031215613ffd57600080fd5b614006856136b9565b9350614014602086016136b9565b92506040850135614024816137f2565b9396929550929360600135925050565b600181811c9082168061404857607f821691505b60208210810361366b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b8183823760009101908152919050565b6000602082840312156140a357600080fd5b611c2f826138bc565b6000602082840312156140be57600080fd5b611c2f82613719565b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b61ffff871681526001600160a01b038616602082015260a06040820152600061411e60a0830187613dbf565b851515606084015282810360808401526141398185876140c7565b9998505050505050505050565b6000806040838503121561415957600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176117615761176161416a565b61ffff841681526040602082015260006122226040830184866140c7565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261420357600080fd5b830160208101925035905067ffffffffffffffff81111561422357600080fd5b80360382131561371257600080fd5b60208082528181018390526000906040808401600586901b850182018785805b8981101561435b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc089850301855282357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff218c36030181126142b2578283fd5b8b0160e063ffffffff806142c5846138bc565b168752898301358a88015267ffffffffffffffff6142e48a8501613719565b16898801526060816142f78286016138bc565b16908801525060808281013561430c816137f2565b6001600160a01b03169087015260a0828101359087015260c0614331818401846141ce565b9350828289015261434583890185836140c7565b988b019897505050938801935050600101614252565b50919998505050505050505050565b60006020828403121561437c57600080fd5b815167ffffffffffffffff81111561439357600080fd5b8201601f810184136143a457600080fd5b80516143b2613d5382613cd2565b8181528560208385010111156143c757600080fd5b612222826020830160208601613d9b565b818103818111156117615761176161416a565b8051602080830151919081101561366b5760001960209190910360031b1b16919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff218336030181126144a157600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126144e057600080fd5b83018035915067ffffffffffffffff8211156144fb57600080fd5b60200191503681900382131561371257600080fd5b600060001982036145235761452361416a565b5060010190565b8284823760609190911b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169101908152601401919050565b601f82111561189a57600081815260208120601f850160051c8101602086101561458a5750805b601f850160051c820191505b818110156117ea57828155600101614596565b815167ffffffffffffffff8111156145c3576145c3613c72565b6145d7816145d18454614034565b84614563565b602080601f83116001811461460c57600084156145f45750858301515b600019600386901b1c1916600185901b1785556117ea565b600085815260208120601f198616915b8281101561463b5788860151825594840194600190910190840161461c565b50858210156146595787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600061ffff8088168352808716602084015250846040830152608060608301526146976080830184866140c7565b979650505050505050565b61ffff861681526080602082015260006146c06080830186886140c7565b67ffffffffffffffff94909416604083015250606001529392505050565b67ffffffffffffffff8311156146f6576146f6613c72565b61470a836147048354614034565b83614563565b6000601f84116001811461473e57600085156147265750838201355b600019600387901b1c1916600186901b178355610ae1565b600083815260209020601f19861690835b8281101561476f578685013582556020948501946001909201910161474f565b508682101561478c5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b61ffff851681526080602082015260006147bb6080830186613dbf565b67ffffffffffffffff8516604084015282810360608401526146978185613dbf565b808201808211156117615761176161416a565b61ffff8716815260c06020820152600061480d60c0830188613dbf565b828103604084015261481f8188613dbf565b6001600160a01b0387811660608601528616608085015283810360a085015290506141398185613dbf565b60006020828403121561485c57600080fd5b81358060070b8114611c2f57600080fd5b600081518084526020808501945080840160005b8381101561352e578151805163ffffffff16885283015160070b8388015260409096019590820190600101614881565b602081526000611c2f602083018461486d565b6080815260006148d7608083018761486d565b63ffffffff9590951660208301525067ffffffffffffffff92831660408201529116606090910152919050565b61ffff861681526080602082015260006149216080830187613dbf565b67ffffffffffffffff8616604084015282810360608401526149448185876140c7565b98975050505050505050565b600082516144a1818460208701613d9b565b61ffff8616815260a06020820152600061497f60a0830187613dbf565b67ffffffffffffffff8616604084015282810360608401526149a18186613dbf565b905082810360808401526149448185613dbf565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826149f3576149f36149b5565b500690565b60008085851115614a0857600080fd5b83861115614a1557600080fd5b5050820193919092039150565b7fff000000000000000000000000000000000000000000000000000000000000008135818116916001851015614a625780818660010360031b1b83161692505b505092915050565b8035602083101561176157600019602084900360031b1b1692915050565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015614a625760049490940360031b84901b1690921692915050565b7fffffffffffffffff0000000000000000000000000000000000000000000000008135818116916008851015614a625760089490940360031b84901b1690921692915050565b600082614b2357614b236149b5565b500490565b600181815b80851115614b63578160001904821115614b4957614b4961416a565b80851615614b5657918102915b93841c9390800290614b2d565b509250929050565b600082614b7a57506001611761565b81614b8757506000611761565b8160018114614b9d5760028114614ba757614bc3565b6001915050611761565b60ff841115614bb857614bb861416a565b50506001821b611761565b5060208310610133831016604e8410600b8410161715614be6575081810a611761565b614bf08383614b28565b8060001904821115614c0457614c0461416a565b029392505050565b6000611c2f8383614b6b56fea264697066735822122067c06fc72b4c2b3575ccdb82bfe4a9b27765fc1231748bb5055ec71e99e9492964736f6c634300081300330000000000000000000000003c2269811836af69497e5f486a85d7316753cf62000000000000000000000000323665443cef804a3b5206103304bd4872ea425300000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x6080604052600436106102695760003560e01c80637533d78811610153578063a6c3d165116100cb578063d1deba1f1161007f578063eb8d72b711610064578063eb8d72b71461079e578063f2fde38b146107be578063f5ecbdbc146107de57600080fd5b8063d1deba1f1461076b578063df2a5b3b1461077e57600080fd5b8063b834f6fb116100b0578063b834f6fb146106f7578063baf3292d1461072b578063cbed8b9c1461074b57600080fd5b8063a6c3d165146106a3578063b353aaa7146106c357600080fd5b80639212a76e116101225780639420069c116101075780639420069c1461062f578063950c8a74146106635780639f38369a1461068357600080fd5b80639212a76e146105d357806393284d951461061c57600080fd5b80637533d788146105305780637f3cbb891461055d5780638cfd8f5c1461057d5780638da5cb5b146105b557600080fd5b806342d65a8d116101e65780635a0dfe4d116101b557806366ad5c8a1161019a57806366ad5c8a146104e8578063715018a61461050857806374c71e0d1461051d57600080fd5b80635a0dfe4d146104795780635b8c41e61461049957600080fd5b806342d65a8d1461041357806344d9c507146104335780635011e5b314610453578063564991451461046657600080fd5b806318d6b43a1161023d578063314dfef511610222578063314dfef51461038e5780633d8b38f6146103c3578063403a8942146103f357600080fd5b806318d6b43a146102fc57806327d19a2c1461034857600080fd5b80621d35671461026e57806307e0db17146102905780630931cf88146102b057806310ddb137146102dc575b600080fd5b34801561027a57600080fd5b5061028e610289366004613731565b6107fe565b005b34801561029c57600080fd5b5061028e6102ab3660046137c5565b610a46565b3480156102bc57600080fd5b50305b6040516001600160a01b0390911681526020015b60405180910390f35b3480156102e857600080fd5b5061028e6102f73660046137c5565b610ae8565b61030f61030a366004613807565b610b59565b604080518251815260208084015167ffffffffffffffff16818301529282015180519282019290925291015160608201526080016102d3565b34801561035457600080fd5b506103806103633660046138e1565b600560209081526000928352604080842090915290825290205481565b6040519081526020016102d3565b34801561039a57600080fd5b506103ae6103a9366004613924565b610dd5565b604080519283526020830191909152016102d3565b3480156103cf57600080fd5b506103e36103de366004613983565b610fba565b60405190151581526020016102d3565b3480156103ff57600080fd5b506103ae61040e366004613a1b565b611086565b34801561041f57600080fd5b5061028e61042e366004613983565b6111fe565b34801561043f57600080fd5b506103ae61044e366004613a9c565b61129d565b61028e610461366004613b2c565b6113a7565b61030f610474366004613ba1565b6114b2565b34801561048557600080fd5b506103e3610494366004613c48565b611614565b3480156104a557600080fd5b506103806104b4366004613cfa565b6004602090815260009384526040808520845180860184018051928152908401958401959095209452929052825290205481565b3480156104f457600080fd5b5061028e610503366004613731565b611767565b34801561051457600080fd5b5061028e6117f2565b61028e61052b366004613b2c565b611806565b34801561053c57600080fd5b5061055061054b3660046137c5565b61189f565b6040516102d39190613deb565b34801561056957600080fd5b5061028e610578366004613dfe565b611939565b34801561058957600080fd5b50610380610598366004613e3a565b600260209081526000928352604080842090915290825290205481565b3480156105c157600080fd5b506000546001600160a01b03166102bf565b3480156105df57600080fd5b506106077f000000000000000000000000000000000000000000000000000000000000006581565b60405163ffffffff90911681526020016102d3565b61030f61062a366004613e64565b6119ae565b34801561063b57600080fd5b506102bf7f000000000000000000000000323665443cef804a3b5206103304bd4872ea425381565b34801561066f57600080fd5b506003546102bf906001600160a01b031681565b34801561068f57600080fd5b5061055061069e3660046137c5565b611b20565b3480156106af57600080fd5b5061028e6106be366004613983565b611c36565b3480156106cf57600080fd5b506102bf7f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf6281565b34801561070357600080fd5b506103e37f000000000000000000000000000000000000000000000000000000000000000081565b34801561073757600080fd5b5061028e610746366004613f2f565b611cb2565b34801561075757600080fd5b5061028e610766366004613f4c565b611d26565b61028e610779366004613731565b611dd4565b34801561078a57600080fd5b5061028e610799366004613fbb565b611fbd565b3480156107aa57600080fd5b5061028e6107b9366004613983565b612077565b3480156107ca57600080fd5b5061028e6107d9366004613f2f565b6120d1565b3480156107ea57600080fd5b506105506107f9366004613fe7565b612161565b337f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf626001600160a01b03161461087b5760405162461bcd60e51b815260206004820152601e60248201527f4c7a4170703a20696e76616c696420656e64706f696e742063616c6c6572000060448201526064015b60405180910390fd5b61ffff86166000908152600160205260408120805461089990614034565b80601f01602080910402602001604051908101604052809291908181526020018280546108c590614034565b80156109125780601f106108e757610100808354040283529160200191610912565b820191906000526020600020905b8154815290600101906020018083116108f557829003601f168201915b5050505050905080518686905014801561092d575060008151115b801561095557508051602082012060405161094b9088908890614081565b6040518091039020145b6109c75760405162461bcd60e51b815260206004820152602660248201527f4c7a4170703a20696e76616c696420736f757263652073656e64696e6720636f60448201527f6e747261637400000000000000000000000000000000000000000000000000006064820152608401610872565b610a3d8787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a018190048102820181019092528881528a93509150889088908190840183828082843760009201919091525061222b92505050565b50505050505050565b610a4e6122d1565b6040517f07e0db1700000000000000000000000000000000000000000000000000000000815261ffff821660048201527f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf626001600160a01b0316906307e0db17906024015b600060405180830381600087803b158015610acd57600080fd5b505af1158015610ae1573d6000803e3d6000fd5b5050505050565b610af06122d1565b6040517f10ddb13700000000000000000000000000000000000000000000000000000000815261ffff821660048201527f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf626001600160a01b0316906310ddb13790602401610ab3565b610b61613671565b336001600160a01b037f000000000000000000000000323665443cef804a3b5206103304bd4872ea42531614610bc5576040517f871f077c000000000000000000000000000000000000000000000000000000008152336004820152602401610872565b8115610c395760405162461bcd60e51b815260206004820152602560248201527f4d6573736167696e6756313a20636f6d706f73654d7367206e6f74207375707060448201527f6f727465640000000000000000000000000000000000000000000000000000006064820152608401610872565b6000610c56610c4b60208b018b614091565b63ffffffff1661232b565b9050610c9d81600160ff168a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525092506123a9915050565b610dc981610d8860208c0135610cb960608e0160408f01614091565b8d6060016020810190610ccc91906140ac565b8e6080016020810190610cdf91906140ac565b604080517f01000000000000000000000000000000000000000000000000000000000000006020820152602181019590955260e09390931b7fffffffff0000000000000000000000000000000000000000000000000000000016604185015260c091821b7fffffffffffffffff0000000000000000000000000000000000000000000000009081166045860152911b16604d830152805160358184030181526055909201905290565b8760008c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250349250612488915050565b50979650505050505050565b6000808215610e4c5760405162461bcd60e51b815260206004820152602560248201527f4d6573736167696e6756313a20636f6d706f73654d7367206e6f74207375707060448201527f6f727465640000000000000000000000000000000000000000000000000000006064820152608401610872565b6000610e5d8963ffffffff1661232b565b9050610ea481600160ff168a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525092506123a9915050565b604080517f010000000000000000000000000000000000000000000000000000000000000060208201526000602182018190526041820181905260458201819052604d82018190528251603581840301815260558301938490527f40a7bb10000000000000000000000000000000000000000000000000000000009093526001600160a01b037f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf6216926340a7bb1092610f6a92869230929091908f908f906059016140f2565b6040805180830381865afa158015610f86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610faa9190614146565b9250925050965096945050505050565b61ffff831660009081526001602052604081208054829190610fdb90614034565b80601f016020809104026020016040519081016040528092919081815260200182805461100790614034565b80156110545780601f1061102957610100808354040283529160200191611054565b820191906000526020600020905b81548152906001019060200180831161103757829003601f168201915b50505050509050838360405161106b929190614081565b60405180910390208180519060200120149150509392505050565b60008060006110ba7f000000000000000000000000000000000000000000000000000000000000006563ffffffff1661232b565b905061114a81600460ff1688888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525063ffffffff7f00000000000000000000000000000000000000000000000000000000000000651681526005602090815260408083206004845290915290205461114593508e92509050614199565b6123a9565b7f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf626001600160a01b03166340a7bb10823061118a8c8c6000806000612649565b60008b8b6040518763ffffffff1660e01b81526004016111af969594939291906140f2565b6040805180830381865afa1580156111cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ef9190614146565b92509250509550959350505050565b6112066122d1565b6040517f42d65a8d0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf6216906342d65a8d9061126f908690869086906004016141b0565b600060405180830381600087803b15801561128957600080fd5b505af1158015610a3d573d6000803e3d6000fd5b60008060006112b18963ffffffff1661232b565b905061134781600360ff1688888080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508b8b9050600560008f63ffffffff1663ffffffff1681526020019081526020016000206000600360ff1660ff168152602001908152602001600020546111459190614199565b7f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf626001600160a01b03166340a7bb1082306113828c8c612773565b60008b8b6040518763ffffffff1660e01b8152600401610f6a969594939291906140f2565b6040517f74c71e0d00000000000000000000000000000000000000000000000000000000815230906374c71e0d9034906113e79086908690600401614232565b6000604051808303818588803b15801561140057600080fd5b505af1158015611414573d6000803e3d6000fd5b5050505050336001600160a01b0316638e9e70996040518163ffffffff1660e01b8152600401600060405180830381865afa158015611457573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261147f919081019061436a565b6040517f8351eea70000000000000000000000000000000000000000000000000000000081526004016108729190613deb565b6114ba613671565b336001600160a01b037f000000000000000000000000323665443cef804a3b5206103304bd4872ea4253161461151e576040517f871f077c000000000000000000000000000000000000000000000000000000008152336004820152602401610872565b600061152f8963ffffffff1661232b565b90506115c581600360ff1688888080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508b8b9050600560008f63ffffffff1663ffffffff1681526020019081526020016000206000600360ff1660ff168152602001908152602001600020546111459190614199565b610dc9816115d38a8a612773565b8560008a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250349250612488915050565b6000806001600061162a8663ffffffff1661232b565b61ffff1661ffff168152602001908152602001600020805461164b90614034565b80601f016020809104026020016040519081016040528092919081815260200182805461167790614034565b80156116c45780601f10611699576101008083540402835291602001916116c4565b820191906000526020600020905b8154815290600101906020018083116116a757829003601f168201915b50508351939450506014831191505080156116e0575060348111155b61172c5760405162461bcd60e51b815260206004820181905260248201527f4d6573736167696e6756313a20696e76616c69642070617468206c656e6774686044820152606401610872565b60006117458161173d6014856143d8565b859190612823565b61174e906143eb565b92516034036008029290921c8414925050505b92915050565b3330146117dc5760405162461bcd60e51b815260206004820152602660248201527f4e6f6e626c6f636b696e674c7a4170703a2063616c6c6572206d75737420626560448201527f204c7a41707000000000000000000000000000000000000000000000000000006064820152608401610872565b6117ea86868686868661294b565b505050505050565b6117fa6122d1565b6118046000612c24565b565b3330146118155761181561440f565b60005b8181101561189a57368383838181106118335761183361443e565b9050602002810190611845919061446d565b90506118616118576020830183614091565b6020830135611614565b61186b5750611888565b6118868160a081013561188160c08301836144ab565b612c8c565b505b8061189281614510565b915050611818565b505050565b600160205260009081526040902080546118b890614034565b80601f01602080910402602001604051908101604052809291908181526020018280546118e490614034565b80156119315780601f1061190657610100808354040283529160200191611931565b820191906000526020600020905b81548152906001019060200180831161191457829003601f168201915b505050505081565b6119416122d1565b63ffffffff8316600081815260056020908152604080832060ff87168085529083529281902085905580519384529083019190915281018290527f0564a47bb54b5af04d89fd36c310b8406fd9662464597e3af04594417ea05cf6906060015b60405180910390a1505050565b6119b6613671565b336001600160a01b037f000000000000000000000000323665443cef804a3b5206103304bd4872ea42531614611a1a576040517f871f077c000000000000000000000000000000000000000000000000000000008152336004820152602401610872565b6000611a4b7f000000000000000000000000000000000000000000000000000000000000006563ffffffff1661232b565b9050611b0181600460ff1688888080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508e8e9050600560007f000000000000000000000000000000000000000000000000000000000000006563ffffffff1663ffffffff1681526020019081526020016000206000600460ff1660ff168152602001908152602001600020546111459190614199565b611b12816115d38d8d8d8d8d612649565b509998505050505050505050565b61ffff8116600090815260016020526040812080546060929190611b4390614034565b80601f0160208091040260200160405190810160405280929190818152602001828054611b6f90614034565b8015611bbc5780601f10611b9157610100808354040283529160200191611bbc565b820191906000526020600020905b815481529060010190602001808311611b9f57829003601f168201915b505050505090508051600003611c145760405162461bcd60e51b815260206004820152601d60248201527f4c7a4170703a206e6f20747275737465642070617468207265636f72640000006044820152606401610872565b611c2f600060148351611c2791906143d8565b839190612823565b9392505050565b611c3e6122d1565b818130604051602001611c539392919061452a565b60408051601f1981840301815291815261ffff8516600090815260016020522090611c7e90826145a9565b507f8c0400cfe2d1199b1a725c78960bcc2a344d869b80590d0f2bd005db15a572ce8383836040516119a1939291906141b0565b611cba6122d1565b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527f5db758e995a17ec1ad84bdef7e8c3293a0bd6179bcce400dff5d4c3d87db726b9060200160405180910390a150565b611d2e6122d1565b6040517fcbed8b9c0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf62169063cbed8b9c90611d9b9088908890889088908890600401614669565b600060405180830381600087803b158015611db557600080fd5b505af1158015611dc9573d6000803e3d6000fd5b505050505050505050565b61ffff86166000908152600460205260408082209051611df79088908890614081565b908152604080516020928190038301902067ffffffffffffffff871660009081529252902054905080611e925760405162461bcd60e51b815260206004820152602360248201527f4e6f6e626c6f636b696e674c7a4170703a206e6f2073746f726564206d65737360448201527f61676500000000000000000000000000000000000000000000000000000000006064820152608401610872565b808383604051611ea3929190614081565b604051809103902014611f1e5760405162461bcd60e51b815260206004820152602160248201527f4e6f6e626c6f636b696e674c7a4170703a20696e76616c6964207061796c6f6160448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610872565b61ffff87166000908152600460205260408082209051611f419089908990614081565b908152604080516020928190038301902067ffffffffffffffff881660009081529252902055611f7587878787878761294b565b7fc264d91f3adc5588250e1551f547752ca0cfa8f6b530d243b9f9f4cab10ea8e58787878785604051611fac9594939291906146a2565b60405180910390a150505050505050565b611fc56122d1565b600081116120155760405162461bcd60e51b815260206004820152601560248201527f4c7a4170703a20696e76616c6964206d696e47617300000000000000000000006044820152606401610872565b61ffff83811660008181526002602090815260408083209487168084529482529182902085905581519283528201929092529081018290527f9d5c7c0b934da8fefa9c7760c98383778a12dfbfc0c3b3106518f43fb9508ac0906060016119a1565b61207f6122d1565b61ffff8316600090815260016020526040902061209d8284836146de565b507ffa41487ad5d6728f0b19276fa1eddc16558578f5109fc39d2dc33c3230470dab8383836040516119a1939291906141b0565b6120d96122d1565b6001600160a01b0381166121555760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610872565b61215e81612c24565b50565b6040517ff5ecbdbc00000000000000000000000000000000000000000000000000000000815261ffff808616600483015284166024820152306044820152606481018290526060907f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf626001600160a01b03169063f5ecbdbc90608401600060405180830381865afa1580156121fa573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612222919081019061436a565b95945050505050565b6000806122bb5a60966366ad5c8a60e01b89898989604051602401612253949392919061479e565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915230929190612d12565b91509150816117ea576117ea8686868685612d9d565b6000546001600160a01b031633146118045760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610872565b600061ffff8211156123a55760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203160448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610872565b5090565b60006123b483612e3b565b61ffff8087166000908152600260209081526040808320938916835292905290812054919250906123e69084906147dd565b9050600081116124385760405162461bcd60e51b815260206004820152601a60248201527f4c7a4170703a206d696e4761734c696d6974206e6f74207365740000000000006044820152606401610872565b808210156117ea5760405162461bcd60e51b815260206004820152601b60248201527f4c7a4170703a20676173206c696d697420697320746f6f206c6f7700000000006044820152606401610872565b61ffff8616600090815260016020526040812080546124a690614034565b80601f01602080910402602001604051908101604052809291908181526020018280546124d290614034565b801561251f5780601f106124f45761010080835404028352916020019161251f565b820191906000526020600020905b81548152906001019060200180831161250257829003601f168201915b50505050509050805160000361259d5760405162461bcd60e51b815260206004820152603060248201527f4c7a4170703a2064657374696e6174696f6e20636861696e206973206e6f742060448201527f61207472757374656420736f75726365000000000000000000000000000000006064820152608401610872565b6040517fc58031000000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf62169063c580310090849061260e908b9086908c908c908c908c906004016147f0565b6000604051808303818588803b15801561262757600080fd5b505af115801561263b573d6000803e3d6000fd5b505050505050505050505050565b6060612668604051806040016040528060608152602001600081525090565b61268861267687600c614199565b6126819060156147dd565b8290612e97565b50612694816004612efc565b506126ab8163ffffffff80881690600490612f2116565b506126c28167ffffffffffffffff86166008612f21565b506126d98167ffffffffffffffff85166008612f21565b5060005b8681101561276757368888838181106126f8576126f861443e565b60400291909101915061272b90506127136020830183614091565b63ffffffff16600485612f219092919063ffffffff16565b5061275261273f604083016020840161484a565b849067ffffffffffffffff166008612f21565b5050808061275f90614510565b9150506126dd565b50519695505050505050565b6060612792604051806040016040528060608152602001600081525090565b6127ab6127a084600c614199565b6126819060016147dd565b506127b7816003612efc565b5060005b8381101561281a57368585838181106127d6576127d661443e565b6040029190910191506127f190506127136020830183614091565b5061280561273f604083016020840161484a565b5050808061281290614510565b9150506127bb565b50519392505050565b60608161283181601f6147dd565b101561287f5760405162461bcd60e51b815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610872565b61288982846147dd565b845110156128d95760405162461bcd60e51b815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610872565b6060821580156128f85760405191506000825260208201604052612942565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015612931578051835260209283019201612919565b5050858452601f01601f1916604052505b50949350505050565b60006129578383612f4f565b905060001960ff821601612a4b5760006129718484612f71565b80516020820151604080840151606085015191517f75c2f575000000000000000000000000000000000000000000000000000000008152600060048201526001600160a01b03948516602482015263ffffffff909316604484015267ffffffffffffffff90811660648401521660848201529192507f000000000000000000000000323665443cef804a3b5206103304bd4872ea425316906375c2f5759060a4015b600060405180830381600087803b158015612a2d57600080fd5b505af1158015612a41573d6000803e3d6000fd5b5050505050610a3d565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd60ff821601612ae9576000612a818484613069565b80516040517f5ae0d1af0000000000000000000000000000000000000000000000000000000081529192506001600160a01b037f000000000000000000000000323665443cef804a3b5206103304bd4872ea42531691635ae0d1af91612a13916004016148b1565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60ff821601612bf2577f0000000000000000000000000000000000000000000000000000000000000000612b6a576040517f60dee01500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612b768484613221565b80516020820151604080840151606085015191517f698b933e0000000000000000000000000000000000000000000000000000000081529495506001600160a01b037f000000000000000000000000323665443cef804a3b5206103304bd4872ea4253169463698b933e94612a139490939092916004016148c4565b6040517fd623472500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60408051602081018252600080825291517f66ad5c8a00000000000000000000000000000000000000000000000000000000815230926366ad5c8a92612cda92829088908890600401614904565b600060405180830381600087803b158015612cf457600080fd5b505af1158015612d08573d6000803e3d6000fd5b5050505050505050565b6000606060008060008661ffff1667ffffffffffffffff811115612d3857612d38613c72565b6040519080825280601f01601f191660200182016040528015612d62576020820181803683370190505b50905060008087516020890160008d8df191503d925086831115612d84578692505b828152826000602083013e909890975095505050505050565b8180519060200120600460008761ffff1661ffff16815260200190815260200160002085604051612dce9190614950565b90815260408051918290036020908101832067ffffffffffffffff88166000908152915220919091557fe183f33de2837795525b4792ca4cd60535bd77c53b7e7030060bfcf5734d6b0c90612e2c9087908790879087908790614962565b60405180910390a15050505050565b6000602282511015612e8f5760405162461bcd60e51b815260206004820152601c60248201527f4c7a4170703a20696e76616c69642061646170746572506172616d73000000006044820152606401610872565b506022015190565b604080518082019091526060815260006020820152612eb76020836149e4565b15612edf57612ec76020836149e4565b612ed29060206143d8565b612edc90836147dd565b91505b506020828101829052604080518085526000815290920101905290565b604080518082019091526060815260006020820152611c2f838460000151518461344d565b604080518082019091526060815260006020820152612f478485600001515185856134ad565b949350505050565b6000612f5e60018284866149f8565b612f6791614a22565b60f81c9392505050565b60408051608081018252600080825260208201819052918101829052606081019190915260358214612fcf576040517f0ffd11ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516080810190915280612ffa612fec6021600187896149f8565b612ff591614a6a565b613539565b6001600160a01b031681526020016130166025602186886149f8565b61301f91614a88565b60e01c8152602001613035602d602586886149f8565b61303e91614ace565b60c01c81526020016130546035602d86886149f8565b61305d91614ace565b60c01c90529392505050565b604080516020810190915260608152600c6130856001846143d8565b61308f91906149e4565b156130c6576040517f0ffd11ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600c6130d56001856143d8565b6130df9190614b14565b905060008167ffffffffffffffff8111156130fc576130fc613c72565b60405190808252806020026020018201604052801561314157816020015b604080518082019091526000808252602082015281526020019060019003908161311a5790505b50905060005b8281101561320a57600061315c82600c614199565b6131679060016147dd565b905060405180604001604052808888849085600461318591906147dd565b92613192939291906149f8565b61319b91614a88565b60e01c815260200188886131b08560046147dd565b906131bc86600c6147dd565b926131c9939291906149f8565b6131d291614ace565b60c01d905283518490849081106131eb576131eb61443e565b602002602001018190525050808061320290614510565b915050613147565b506040805160208101909152908152949350505050565b604080516080810182526060808252600060208301819052928201839052810191909152600c6132526015846143d8565b61325c91906149e4565b15613293576040517f0ffd11ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600c6132a26015856143d8565b6132ac9190614b14565b905060008167ffffffffffffffff8111156132c9576132c9613c72565b60405190808252806020026020018201604052801561330e57816020015b60408051808201909152600080825260208201528152602001906001900390816132e75790505b50905060005b828110156133d757600061332982600c614199565b6133349060156147dd565b905060405180604001604052808888849085600461335291906147dd565b9261335f939291906149f8565b61336891614a88565b60e01c8152602001888861337d8560046147dd565b9061338986600c6147dd565b92613396939291906149f8565b61339f91614ace565b60c01d905283518490849081106133b8576133b861443e565b60200260200101819052505080806133cf90614510565b915050613314565b506040805160808101909152818152602081016133f860056001888a6149f8565b61340191614a88565b60e01c8152602001613417600d6005888a6149f8565b61342091614ace565b60c01c81526020016134366015600d888a6149f8565b61343f91614ace565b60c01c905295945050505050565b604080518082019091526060815260006020820152836020015183106134875761348784856020015160026134829190614199565b613541565b83518051602085830101848153508085036134a3576001810182525b5093949350505050565b60408051808201909152606081526000602082015260208501516134d185846147dd565b11156134f0576134f0856134e586856147dd565b613482906002614199565b6000600161350084610100614c0c565b61350a91906143d8565b905085518386820101858319825116178152508051848701111561352e5783860181525b509495945050505050565b600081611761565b815161354d8383612e97565b50613558838261355e565b50505050565b604080518082019091526060815260006020820152611c2f8384600001515184855160408051808201909152606081526000602082015282518211156135a357600080fd5b60208501516135b283866147dd565b11156135d5576135d5856134e5876020015187866135d091906147dd565b61365a565b6000808651805187602083010193508088870111156135f45787860182525b505050602084015b6020841061363457805182526136136020836147dd565b91506136206020826147dd565b905061362d6020856143d8565b93506135fc565b51815160001960208690036101000a019081169019919091161790525083949350505050565b60008183111561366b575081611761565b50919050565b604051806060016040528060008019168152602001600067ffffffffffffffff1681526020016136b4604051806040016040528060008152602001600081525090565b905290565b803561ffff811681146136cb57600080fd5b919050565b60008083601f8401126136e257600080fd5b50813567ffffffffffffffff8111156136fa57600080fd5b60208301915083602082850101111561371257600080fd5b9250929050565b803567ffffffffffffffff811681146136cb57600080fd5b6000806000806000806080878903121561374a57600080fd5b613753876136b9565b9550602087013567ffffffffffffffff8082111561377057600080fd5b61377c8a838b016136d0565b909750955085915061379060408a01613719565b945060608901359150808211156137a657600080fd5b506137b389828a016136d0565b979a9699509497509295939492505050565b6000602082840312156137d757600080fd5b611c2f826136b9565b60006040828403121561366b57600080fd5b6001600160a01b038116811461215e57600080fd5b600080600080600080600087890361014081121561382457600080fd5b60a081121561383257600080fd5b5087965060a088013567ffffffffffffffff8082111561385157600080fd5b61385d8b838c016136d0565b90985096508691506138728b60c08c016137e0565b95506101008a01359150613885826137f2565b909350610120890135908082111561389c57600080fd5b506138a98a828b016136d0565b989b979a50959850939692959293505050565b803563ffffffff811681146136cb57600080fd5b803560ff811681146136cb57600080fd5b600080604083850312156138f457600080fd5b6138fd836138bc565b915061390b602084016138d0565b90509250929050565b803580151581146136cb57600080fd5b6000806000806000806080878903121561393d57600080fd5b613946876138bc565b9550602087013567ffffffffffffffff8082111561396357600080fd5b61396f8a838b016136d0565b909750955085915061379060408a01613914565b60008060006040848603121561399857600080fd5b6139a1846136b9565b9250602084013567ffffffffffffffff8111156139bd57600080fd5b6139c9868287016136d0565b9497909650939450505050565b60008083601f8401126139e857600080fd5b50813567ffffffffffffffff811115613a0057600080fd5b6020830191508360208260061b850101111561371257600080fd5b600080600080600060608688031215613a3357600080fd5b853567ffffffffffffffff80821115613a4b57600080fd5b613a5789838a016139d6565b90975095506020880135915080821115613a7057600080fd5b50613a7d888289016136d0565b9094509250613a90905060408701613914565b90509295509295909350565b60008060008060008060808789031215613ab557600080fd5b613abe876138bc565b9550602087013567ffffffffffffffff80821115613adb57600080fd5b613ae78a838b016139d6565b90975095506040890135915080821115613b0057600080fd5b50613b0d89828a016136d0565b9094509250613b20905060608801613914565b90509295509295509295565b60008060208385031215613b3f57600080fd5b823567ffffffffffffffff80821115613b5757600080fd5b818501915085601f830112613b6b57600080fd5b813581811115613b7a57600080fd5b8660208260051b8501011115613b8f57600080fd5b60209290920196919550909350505050565b600080600080600080600060c0888a031215613bbc57600080fd5b613bc5886138bc565b9650602088013567ffffffffffffffff80821115613be257600080fd5b613bee8b838c016139d6565b909850965060408a0135915080821115613c0757600080fd5b50613c148a828b016136d0565b9095509350613c2890508960608a016137e0565b915060a0880135613c38816137f2565b8091505092959891949750929550565b60008060408385031215613c5b57600080fd5b613c64836138bc565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613cca57613cca613c72565b604052919050565b600067ffffffffffffffff821115613cec57613cec613c72565b50601f01601f191660200190565b600080600060608486031215613d0f57600080fd5b613d18846136b9565b9250602084013567ffffffffffffffff811115613d3457600080fd5b8401601f81018613613d4557600080fd5b8035613d58613d5382613cd2565b613ca1565b818152876020838501011115613d6d57600080fd5b81602084016020830137600060208383010152809450505050613d9260408501613719565b90509250925092565b60005b83811015613db6578181015183820152602001613d9e565b50506000910152565b60008151808452613dd7816020860160208601613d9b565b601f01601f19169290920160200192915050565b602081526000611c2f6020830184613dbf565b600080600060608486031215613e1357600080fd5b613e1c846138bc565b9250613e2a602085016138d0565b9150604084013590509250925092565b60008060408385031215613e4d57600080fd5b613e56836136b9565b915061390b602084016136b9565b60008060008060008060008060006101008a8c031215613e8357600080fd5b893567ffffffffffffffff80821115613e9b57600080fd5b613ea78d838e016139d6565b909b509950899150613ebb60208d016138bc565b9850613ec960408d01613719565b9750613ed760608d01613719565b965060808c0135915080821115613eed57600080fd5b50613efa8c828d016136d0565b9095509350613f0e90508b60a08c016137e0565b915060e08a0135613f1e816137f2565b809150509295985092959850929598565b600060208284031215613f4157600080fd5b8135611c2f816137f2565b600080600080600060808688031215613f6457600080fd5b613f6d866136b9565b9450613f7b602087016136b9565b935060408601359250606086013567ffffffffffffffff811115613f9e57600080fd5b613faa888289016136d0565b969995985093965092949392505050565b600080600060608486031215613fd057600080fd5b613fd9846136b9565b9250613e2a602085016136b9565b60008060008060808587031215613ffd57600080fd5b614006856136b9565b9350614014602086016136b9565b92506040850135614024816137f2565b9396929550929360600135925050565b600181811c9082168061404857607f821691505b60208210810361366b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b8183823760009101908152919050565b6000602082840312156140a357600080fd5b611c2f826138bc565b6000602082840312156140be57600080fd5b611c2f82613719565b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b61ffff871681526001600160a01b038616602082015260a06040820152600061411e60a0830187613dbf565b851515606084015282810360808401526141398185876140c7565b9998505050505050505050565b6000806040838503121561415957600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176117615761176161416a565b61ffff841681526040602082015260006122226040830184866140c7565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261420357600080fd5b830160208101925035905067ffffffffffffffff81111561422357600080fd5b80360382131561371257600080fd5b60208082528181018390526000906040808401600586901b850182018785805b8981101561435b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc089850301855282357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff218c36030181126142b2578283fd5b8b0160e063ffffffff806142c5846138bc565b168752898301358a88015267ffffffffffffffff6142e48a8501613719565b16898801526060816142f78286016138bc565b16908801525060808281013561430c816137f2565b6001600160a01b03169087015260a0828101359087015260c0614331818401846141ce565b9350828289015261434583890185836140c7565b988b019897505050938801935050600101614252565b50919998505050505050505050565b60006020828403121561437c57600080fd5b815167ffffffffffffffff81111561439357600080fd5b8201601f810184136143a457600080fd5b80516143b2613d5382613cd2565b8181528560208385010111156143c757600080fd5b612222826020830160208601613d9b565b818103818111156117615761176161416a565b8051602080830151919081101561366b5760001960209190910360031b1b16919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff218336030181126144a157600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126144e057600080fd5b83018035915067ffffffffffffffff8211156144fb57600080fd5b60200191503681900382131561371257600080fd5b600060001982036145235761452361416a565b5060010190565b8284823760609190911b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169101908152601401919050565b601f82111561189a57600081815260208120601f850160051c8101602086101561458a5750805b601f850160051c820191505b818110156117ea57828155600101614596565b815167ffffffffffffffff8111156145c3576145c3613c72565b6145d7816145d18454614034565b84614563565b602080601f83116001811461460c57600084156145f45750858301515b600019600386901b1c1916600185901b1785556117ea565b600085815260208120601f198616915b8281101561463b5788860151825594840194600190910190840161461c565b50858210156146595787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600061ffff8088168352808716602084015250846040830152608060608301526146976080830184866140c7565b979650505050505050565b61ffff861681526080602082015260006146c06080830186886140c7565b67ffffffffffffffff94909416604083015250606001529392505050565b67ffffffffffffffff8311156146f6576146f6613c72565b61470a836147048354614034565b83614563565b6000601f84116001811461473e57600085156147265750838201355b600019600387901b1c1916600186901b178355610ae1565b600083815260209020601f19861690835b8281101561476f578685013582556020948501946001909201910161474f565b508682101561478c5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b61ffff851681526080602082015260006147bb6080830186613dbf565b67ffffffffffffffff8516604084015282810360608401526146978185613dbf565b808201808211156117615761176161416a565b61ffff8716815260c06020820152600061480d60c0830188613dbf565b828103604084015261481f8188613dbf565b6001600160a01b0387811660608601528616608085015283810360a085015290506141398185613dbf565b60006020828403121561485c57600080fd5b81358060070b8114611c2f57600080fd5b600081518084526020808501945080840160005b8381101561352e578151805163ffffffff16885283015160070b8388015260409096019590820190600101614881565b602081526000611c2f602083018461486d565b6080815260006148d7608083018761486d565b63ffffffff9590951660208301525067ffffffffffffffff92831660408201529116606090910152919050565b61ffff861681526080602082015260006149216080830187613dbf565b67ffffffffffffffff8616604084015282810360608401526149448185876140c7565b98975050505050505050565b600082516144a1818460208701613d9b565b61ffff8616815260a06020820152600061497f60a0830187613dbf565b67ffffffffffffffff8616604084015282810360608401526149a18186613dbf565b905082810360808401526149448185613dbf565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826149f3576149f36149b5565b500690565b60008085851115614a0857600080fd5b83861115614a1557600080fd5b5050820193919092039150565b7fff000000000000000000000000000000000000000000000000000000000000008135818116916001851015614a625780818660010360031b1b83161692505b505092915050565b8035602083101561176157600019602084900360031b1b1692915050565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015614a625760049490940360031b84901b1690921692915050565b7fffffffffffffffff0000000000000000000000000000000000000000000000008135818116916008851015614a625760089490940360031b84901b1690921692915050565b600082614b2357614b236149b5565b500490565b600181815b80851115614b63578160001904821115614b4957614b4961416a565b80851615614b5657918102915b93841c9390800290614b2d565b509250929050565b600082614b7a57506001611761565b81614b8757506000611761565b8160018114614b9d5760028114614ba757614bc3565b6001915050611761565b60ff841115614bb857614bb861416a565b50506001821b611761565b5060208310610133831016604e8410600b8410161715614be6575081810a611761565b614bf08383614b28565b8060001904821115614c0457614c0461416a565b029392505050565b6000611c2f8383614b6b56fea264697066735822122067c06fc72b4c2b3575ccdb82bfe4a9b27765fc1231748bb5055ec71e99e9492964736f6c63430008130033

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

0000000000000000000000003c2269811836af69497e5f486a85d7316753cf62000000000000000000000000323665443cef804a3b5206103304bd4872ea425300000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _endpoint (address): 0x3c2269811836af69497E5F486A85D7316753cf62
Arg [1] : _usdv (address): 0x323665443CEf804A3b5206103304BD4872EA4253
Arg [2] : _mainChainEid (uint32): 101
Arg [3] : _isMainChain (bool): False

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000003c2269811836af69497e5f486a85d7316753cf62
Arg [1] : 000000000000000000000000323665443cef804a3b5206103304bd4872ea4253
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000065
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000


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.