Contract 0xb72a7567847aba28a2819b855d7fe679d4f59846

Txn Hash Method
Block
From
To
Value [Txn Fee]
0x07ac578866df73ca2d4d2e01f8cbda7a6c28c3faac66f8d5aefd62fc818b5dae0x60a0604016866972022-04-08 19:14:36242 days 4 hrs ago0x1b9dfc56e38b0f92448659c114e2347bd803911c IN  Create: MessageBus0 MOVR0.006450142
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
MessageBus

Compiler Version
v0.8.9+commit.e5eed63a

Optimization Enabled:
Yes with 800 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 13 : MessageBus.sol
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity 0.8.9;

import "./MessageBusSender.sol";
import "./MessageBusReceiver.sol";

contract MessageBus is MessageBusSender, MessageBusReceiver {
    constructor(
        ISigsVerifier _sigsVerifier,
        address _liquidityBridge,
        address _pegBridge,
        address _pegVault,
        address _pegBridgeV2,
        address _pegVaultV2
    )
        MessageBusSender(_sigsVerifier)
        MessageBusReceiver(_liquidityBridge, _pegBridge, _pegVault, _pegBridgeV2, _pegVaultV2)
    {}

    // this is only to be called by Proxy via delegateCall as initOwner will require _owner is 0.
    // so calling init on this contract directly will guarantee to fail
    function init(
        address _liquidityBridge,
        address _pegBridge,
        address _pegVault,
        address _pegBridgeV2,
        address _pegVaultV2
    ) external {
        // MUST manually call ownable init and must only call once
        initOwner();
        // we don't need sender init as _sigsVerifier is immutable so already in the deployed code
        initReceiver(_liquidityBridge, _pegBridge, _pegVault, _pegBridgeV2, _pegVaultV2);
    }
}

File 2 of 13 : MessageBusSender.sol
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity 0.8.9;

import "../../safeguard/Ownable.sol";
import "../../interfaces/ISigsVerifier.sol";

contract MessageBusSender is Ownable {
    ISigsVerifier public immutable sigsVerifier;

    uint256 public feeBase;
    uint256 public feePerByte;
    mapping(address => uint256) public withdrawnFees;

    event Message(address indexed sender, address receiver, uint256 dstChainId, bytes message, uint256 fee);

    event MessageWithTransfer(
        address indexed sender,
        address receiver,
        uint256 dstChainId,
        address bridge,
        bytes32 srcTransferId,
        bytes message,
        uint256 fee
    );

    event FeeBaseUpdated(uint256 feeBase);
    event FeePerByteUpdated(uint256 feePerByte);

    constructor(ISigsVerifier _sigsVerifier) {
        sigsVerifier = _sigsVerifier;
    }

    /**
     * @notice Sends a message to a contract on another chain.
     * Sender needs to make sure the uniqueness of the message Id, which is computed as
     * hash(type.MessageOnly, sender, receiver, srcChainId, srcTxHash, dstChainId, message).
     * If messages with the same Id are sent, only one of them will succeed at dst chain.
     * A fee is charged in the native gas token.
     * @param _receiver The address of the destination app contract.
     * @param _dstChainId The destination chain ID.
     * @param _message Arbitrary message bytes to be decoded by the destination app contract.
     */
    function sendMessage(
        address _receiver,
        uint256 _dstChainId,
        bytes calldata _message
    ) external payable {
        require(_dstChainId != block.chainid, "Invalid chainId");
        uint256 minFee = calcFee(_message);
        require(msg.value >= minFee, "Insufficient fee");
        emit Message(msg.sender, _receiver, _dstChainId, _message, msg.value);
    }

    /**
     * @notice Sends a message associated with a transfer to a contract on another chain.
     * If messages with the same srcTransferId are sent, only one of them will succeed.
     * A fee is charged in the native token.
     * @param _receiver The address of the destination app contract.
     * @param _dstChainId The destination chain ID.
     * @param _srcBridge The bridge contract to send the transfer with.
     * @param _srcTransferId The transfer ID.
     * @param _dstChainId The destination chain ID.
     * @param _message Arbitrary message bytes to be decoded by the destination app contract.
     */
    function sendMessageWithTransfer(
        address _receiver,
        uint256 _dstChainId,
        address _srcBridge,
        bytes32 _srcTransferId,
        bytes calldata _message
    ) external payable {
        require(_dstChainId != block.chainid, "Invalid chainId");
        uint256 minFee = calcFee(_message);
        require(msg.value >= minFee, "Insufficient fee");
        // SGN needs to verify
        // 1. msg.sender matches sender of the src transfer
        // 2. dstChainId matches dstChainId of the src transfer
        // 3. bridge is either liquidity bridge, peg src vault, or peg dst bridge
        emit MessageWithTransfer(msg.sender, _receiver, _dstChainId, _srcBridge, _srcTransferId, _message, msg.value);
    }

    /**
     * @notice Withdraws message fee in the form of native gas token.
     * @param _account The address receiving the fee.
     * @param _cumulativeFee The cumulative fee credited to the account. Tracked by SGN.
     * @param _sigs The list of signatures sorted by signing addresses in ascending order. A withdrawal must be
     * signed-off by +2/3 of the sigsVerifier's current signing power to be delivered.
     * @param _signers The sorted list of signers.
     * @param _powers The signing powers of the signers.
     */
    function withdrawFee(
        address _account,
        uint256 _cumulativeFee,
        bytes[] calldata _sigs,
        address[] calldata _signers,
        uint256[] calldata _powers
    ) external {
        bytes32 domain = keccak256(abi.encodePacked(block.chainid, address(this), "withdrawFee"));
        sigsVerifier.verifySigs(abi.encodePacked(domain, _account, _cumulativeFee), _sigs, _signers, _powers);
        uint256 amount = _cumulativeFee - withdrawnFees[_account];
        require(amount > 0, "No new amount to withdraw");
        withdrawnFees[_account] = _cumulativeFee;
        (bool sent, ) = _account.call{value: amount, gas: 50000}("");
        require(sent, "failed to withdraw fee");
    }

    /**
     * @notice Calculates the required fee for the message.
     * @param _message Arbitrary message bytes to be decoded by the destination app contract.
     @ @return The required fee.
     */
    function calcFee(bytes calldata _message) public view returns (uint256) {
        return feeBase + _message.length * feePerByte;
    }

    // -------------------- Admin --------------------

    function setFeePerByte(uint256 _fee) external onlyOwner {
        feePerByte = _fee;
        emit FeePerByteUpdated(feePerByte);
    }

    function setFeeBase(uint256 _fee) external onlyOwner {
        feeBase = _fee;
        emit FeeBaseUpdated(feeBase);
    }
}

File 3 of 13 : MessageBusReceiver.sol
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity 0.8.9;

import "../libraries/MsgDataTypes.sol";
import "../interfaces/IMessageReceiverApp.sol";
import "../interfaces/IMessageBus.sol";
import "../../interfaces/IBridge.sol";
import "../../interfaces/IOriginalTokenVault.sol";
import "../../interfaces/IOriginalTokenVaultV2.sol";
import "../../interfaces/IPeggedTokenBridge.sol";
import "../../interfaces/IPeggedTokenBridgeV2.sol";
import "../../safeguard/Ownable.sol";

contract MessageBusReceiver is Ownable {
    mapping(bytes32 => MsgDataTypes.TxStatus) public executedMessages;

    address public liquidityBridge; // liquidity bridge address
    address public pegBridge; // peg bridge address
    address public pegVault; // peg original vault address
    address public pegBridgeV2; // peg bridge address
    address public pegVaultV2; // peg original vault address

    // minimum amount of gas needed by this contract before it tries to
    // deliver a message to the target contract.
    uint256 public preExecuteMessageGasUsage;

    event Executed(
        MsgDataTypes.MsgType msgType,
        bytes32 msgId,
        MsgDataTypes.TxStatus status,
        address indexed receiver,
        uint64 srcChainId,
        bytes32 srcTxHash
    );
    event NeedRetry(MsgDataTypes.MsgType msgType, bytes32 msgId, uint64 srcChainId, bytes32 srcTxHash);
    event CallReverted(string reason); // help debug

    event LiquidityBridgeUpdated(address liquidityBridge);
    event PegBridgeUpdated(address pegBridge);
    event PegVaultUpdated(address pegVault);
    event PegBridgeV2Updated(address pegBridgeV2);
    event PegVaultV2Updated(address pegVaultV2);

    constructor(
        address _liquidityBridge,
        address _pegBridge,
        address _pegVault,
        address _pegBridgeV2,
        address _pegVaultV2
    ) {
        liquidityBridge = _liquidityBridge;
        pegBridge = _pegBridge;
        pegVault = _pegVault;
        pegBridgeV2 = _pegBridgeV2;
        pegVaultV2 = _pegVaultV2;
    }

    function initReceiver(
        address _liquidityBridge,
        address _pegBridge,
        address _pegVault,
        address _pegBridgeV2,
        address _pegVaultV2
    ) internal {
        require(liquidityBridge == address(0), "liquidityBridge already set");
        liquidityBridge = _liquidityBridge;
        pegBridge = _pegBridge;
        pegVault = _pegVault;
        pegBridgeV2 = _pegBridgeV2;
        pegVaultV2 = _pegVaultV2;
    }

    // ============== functions called by executor ==============

    /**
     * @notice Execute a message with a successful transfer.
     * @param _message Arbitrary message bytes originated from and encoded by the source app contract
     * @param _transfer The transfer info.
     * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by
     * +2/3 of the sigsVerifier's current signing power to be delivered.
     * @param _signers The sorted list of signers.
     * @param _powers The signing powers of the signers.
     */
    function executeMessageWithTransfer(
        bytes calldata _message,
        MsgDataTypes.TransferInfo calldata _transfer,
        bytes[] calldata _sigs,
        address[] calldata _signers,
        uint256[] calldata _powers
    ) public payable {
        // For message with token transfer, message Id is computed through transfer info
        // in order to guarantee that each transfer can only be used once.
        bytes32 messageId = verifyTransfer(_transfer);
        require(executedMessages[messageId] == MsgDataTypes.TxStatus.Null, "transfer already executed");
        executedMessages[messageId] = MsgDataTypes.TxStatus.Pending;

        bytes32 domain = keccak256(abi.encodePacked(block.chainid, address(this), "MessageWithTransfer"));
        IBridge(liquidityBridge).verifySigs(
            abi.encodePacked(domain, messageId, _message, _transfer.srcTxHash),
            _sigs,
            _signers,
            _powers
        );
        MsgDataTypes.TxStatus status;
        IMessageReceiverApp.ExecutionStatus est = executeMessageWithTransfer(_transfer, _message);
        if (est == IMessageReceiverApp.ExecutionStatus.Success) {
            status = MsgDataTypes.TxStatus.Success;
        } else if (est == IMessageReceiverApp.ExecutionStatus.Retry) {
            executedMessages[messageId] = MsgDataTypes.TxStatus.Null;
            emit NeedRetry(
                MsgDataTypes.MsgType.MessageWithTransfer,
                messageId,
                _transfer.srcChainId,
                _transfer.srcTxHash
            );
            return;
        } else {
            est = executeMessageWithTransferFallback(_transfer, _message);
            if (est == IMessageReceiverApp.ExecutionStatus.Success) {
                status = MsgDataTypes.TxStatus.Fallback;
            } else {
                status = MsgDataTypes.TxStatus.Fail;
            }
        }
        executedMessages[messageId] = status;
        emitMessageWithTransferExecutedEvent(messageId, status, _transfer);
    }

    /**
     * @notice Execute a message with a refunded transfer.
     * @param _message Arbitrary message bytes originated from and encoded by the source app contract
     * @param _transfer The transfer info.
     * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by
     * +2/3 of the sigsVerifier's current signing power to be delivered.
     * @param _signers The sorted list of signers.
     * @param _powers The signing powers of the signers.
     */
    function executeMessageWithTransferRefund(
        bytes calldata _message, // the same message associated with the original transfer
        MsgDataTypes.TransferInfo calldata _transfer,
        bytes[] calldata _sigs,
        address[] calldata _signers,
        uint256[] calldata _powers
    ) public payable {
        // similar to executeMessageWithTransfer
        bytes32 messageId = verifyTransfer(_transfer);
        require(executedMessages[messageId] == MsgDataTypes.TxStatus.Null, "transfer already executed");
        executedMessages[messageId] = MsgDataTypes.TxStatus.Pending;

        bytes32 domain = keccak256(abi.encodePacked(block.chainid, address(this), "MessageWithTransferRefund"));
        IBridge(liquidityBridge).verifySigs(
            abi.encodePacked(domain, messageId, _message, _transfer.srcTxHash),
            _sigs,
            _signers,
            _powers
        );
        MsgDataTypes.TxStatus status;
        IMessageReceiverApp.ExecutionStatus est = executeMessageWithTransferRefund(_transfer, _message);
        if (est == IMessageReceiverApp.ExecutionStatus.Success) {
            status = MsgDataTypes.TxStatus.Success;
        } else if (est == IMessageReceiverApp.ExecutionStatus.Retry) {
            executedMessages[messageId] = MsgDataTypes.TxStatus.Null;
            emit NeedRetry(
                MsgDataTypes.MsgType.MessageWithTransfer,
                messageId,
                _transfer.srcChainId,
                _transfer.srcTxHash
            );
            return;
        } else {
            status = MsgDataTypes.TxStatus.Fail;
        }
        executedMessages[messageId] = status;
        emitMessageWithTransferExecutedEvent(messageId, status, _transfer);
    }

    /**
     * @notice Execute a message not associated with a transfer.
     * @param _message Arbitrary message bytes originated from and encoded by the source app contract
     * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by
     * +2/3 of the sigsVerifier's current signing power to be delivered.
     * @param _signers The sorted list of signers.
     * @param _powers The signing powers of the signers.
     */
    function executeMessage(
        bytes calldata _message,
        MsgDataTypes.RouteInfo calldata _route,
        bytes[] calldata _sigs,
        address[] calldata _signers,
        uint256[] calldata _powers
    ) external payable {
        // For message without associated token transfer, message Id is computed through message info,
        // in order to guarantee that each message can only be applied once
        bytes32 messageId = computeMessageOnlyId(_route, _message);
        require(executedMessages[messageId] == MsgDataTypes.TxStatus.Null, "message already executed");
        executedMessages[messageId] = MsgDataTypes.TxStatus.Pending;

        bytes32 domain = keccak256(abi.encodePacked(block.chainid, address(this), "Message"));
        IBridge(liquidityBridge).verifySigs(abi.encodePacked(domain, messageId), _sigs, _signers, _powers);
        MsgDataTypes.TxStatus status;
        IMessageReceiverApp.ExecutionStatus est = executeMessage(_route, _message);
        if (est == IMessageReceiverApp.ExecutionStatus.Success) {
            status = MsgDataTypes.TxStatus.Success;
        } else if (est == IMessageReceiverApp.ExecutionStatus.Retry) {
            executedMessages[messageId] = MsgDataTypes.TxStatus.Null;
            emit NeedRetry(MsgDataTypes.MsgType.MessageOnly, messageId, _route.srcChainId, _route.srcTxHash);
            return;
        } else {
            status = MsgDataTypes.TxStatus.Fail;
        }
        executedMessages[messageId] = status;
        emitMessageOnlyExecutedEvent(messageId, status, _route);
    }

    // ================= utils (to avoid stack too deep) =================

    function emitMessageWithTransferExecutedEvent(
        bytes32 _messageId,
        MsgDataTypes.TxStatus _status,
        MsgDataTypes.TransferInfo calldata _transfer
    ) private {
        emit Executed(
            MsgDataTypes.MsgType.MessageWithTransfer,
            _messageId,
            _status,
            _transfer.receiver,
            _transfer.srcChainId,
            _transfer.srcTxHash
        );
    }

    function emitMessageOnlyExecutedEvent(
        bytes32 _messageId,
        MsgDataTypes.TxStatus _status,
        MsgDataTypes.RouteInfo calldata _route
    ) private {
        emit Executed(
            MsgDataTypes.MsgType.MessageOnly,
            _messageId,
            _status,
            _route.receiver,
            _route.srcChainId,
            _route.srcTxHash
        );
    }

    function executeMessageWithTransfer(MsgDataTypes.TransferInfo calldata _transfer, bytes calldata _message)
        private
        returns (IMessageReceiverApp.ExecutionStatus)
    {
        uint256 gasLeftBeforeExecution = gasleft();
        (bool ok, bytes memory res) = address(_transfer.receiver).call{value: msg.value}(
            abi.encodeWithSelector(
                IMessageReceiverApp.executeMessageWithTransfer.selector,
                _transfer.sender,
                _transfer.token,
                _transfer.amount,
                _transfer.srcChainId,
                _message,
                msg.sender
            )
        );
        if (ok) {
            return abi.decode((res), (IMessageReceiverApp.ExecutionStatus));
        }
        handleExecutionRevert(gasLeftBeforeExecution, res);
        return IMessageReceiverApp.ExecutionStatus.Fail;
    }

    function executeMessageWithTransferFallback(MsgDataTypes.TransferInfo calldata _transfer, bytes calldata _message)
        private
        returns (IMessageReceiverApp.ExecutionStatus)
    {
        uint256 gasLeftBeforeExecution = gasleft();
        (bool ok, bytes memory res) = address(_transfer.receiver).call{value: msg.value}(
            abi.encodeWithSelector(
                IMessageReceiverApp.executeMessageWithTransferFallback.selector,
                _transfer.sender,
                _transfer.token,
                _transfer.amount,
                _transfer.srcChainId,
                _message,
                msg.sender
            )
        );
        if (ok) {
            return abi.decode((res), (IMessageReceiverApp.ExecutionStatus));
        }
        handleExecutionRevert(gasLeftBeforeExecution, res);
        return IMessageReceiverApp.ExecutionStatus.Fail;
    }

    function executeMessageWithTransferRefund(MsgDataTypes.TransferInfo calldata _transfer, bytes calldata _message)
        private
        returns (IMessageReceiverApp.ExecutionStatus)
    {
        uint256 gasLeftBeforeExecution = gasleft();
        (bool ok, bytes memory res) = address(_transfer.receiver).call{value: msg.value}(
            abi.encodeWithSelector(
                IMessageReceiverApp.executeMessageWithTransferRefund.selector,
                _transfer.token,
                _transfer.amount,
                _message,
                msg.sender
            )
        );
        if (ok) {
            return abi.decode((res), (IMessageReceiverApp.ExecutionStatus));
        }
        handleExecutionRevert(gasLeftBeforeExecution, res);
        return IMessageReceiverApp.ExecutionStatus.Fail;
    }

    function verifyTransfer(MsgDataTypes.TransferInfo calldata _transfer) private view returns (bytes32) {
        bytes32 transferId;
        address bridgeAddr;
        if (_transfer.t == MsgDataTypes.TransferType.LqRelay) {
            transferId = keccak256(
                abi.encodePacked(
                    _transfer.sender,
                    _transfer.receiver,
                    _transfer.token,
                    _transfer.amount,
                    _transfer.srcChainId,
                    uint64(block.chainid),
                    _transfer.refId
                )
            );
            bridgeAddr = liquidityBridge;
            require(IBridge(bridgeAddr).transfers(transferId) == true, "bridge relay not exist");
        } else if (_transfer.t == MsgDataTypes.TransferType.LqWithdraw) {
            transferId = keccak256(
                abi.encodePacked(
                    uint64(block.chainid),
                    _transfer.wdseq,
                    _transfer.receiver,
                    _transfer.token,
                    _transfer.amount
                )
            );
            bridgeAddr = liquidityBridge;
            require(IBridge(bridgeAddr).withdraws(transferId) == true, "bridge withdraw not exist");
        } else if (
            _transfer.t == MsgDataTypes.TransferType.PegMint || _transfer.t == MsgDataTypes.TransferType.PegWithdraw
        ) {
            transferId = keccak256(
                abi.encodePacked(
                    _transfer.receiver,
                    _transfer.token,
                    _transfer.amount,
                    _transfer.sender,
                    _transfer.srcChainId,
                    _transfer.refId
                )
            );
            if (_transfer.t == MsgDataTypes.TransferType.PegMint) {
                bridgeAddr = pegBridge;
                require(IPeggedTokenBridge(bridgeAddr).records(transferId) == true, "mint record not exist");
            } else {
                // _transfer.t == MsgDataTypes.TransferType.PegWithdraw
                bridgeAddr = pegVault;
                require(IOriginalTokenVault(bridgeAddr).records(transferId) == true, "withdraw record not exist");
            }
        } else if (
            _transfer.t == MsgDataTypes.TransferType.PegV2Mint || _transfer.t == MsgDataTypes.TransferType.PegV2Withdraw
        ) {
            if (_transfer.t == MsgDataTypes.TransferType.PegV2Mint) {
                bridgeAddr = pegBridgeV2;
            } else {
                // MsgDataTypes.TransferType.PegV2Withdraw
                bridgeAddr = pegVaultV2;
            }
            transferId = keccak256(
                abi.encodePacked(
                    _transfer.receiver,
                    _transfer.token,
                    _transfer.amount,
                    _transfer.sender,
                    _transfer.srcChainId,
                    _transfer.refId,
                    bridgeAddr
                )
            );
            if (_transfer.t == MsgDataTypes.TransferType.PegV2Mint) {
                require(IPeggedTokenBridgeV2(bridgeAddr).records(transferId) == true, "mint record not exist");
            } else {
                // MsgDataTypes.TransferType.PegV2Withdraw
                require(IOriginalTokenVaultV2(bridgeAddr).records(transferId) == true, "withdraw record not exist");
            }
        }
        return keccak256(abi.encodePacked(MsgDataTypes.MsgType.MessageWithTransfer, bridgeAddr, transferId));
    }

    function computeMessageOnlyId(MsgDataTypes.RouteInfo calldata _route, bytes calldata _message)
        private
        view
        returns (bytes32)
    {
        return
            keccak256(
                abi.encodePacked(
                    MsgDataTypes.MsgType.MessageOnly,
                    _route.sender,
                    _route.receiver,
                    _route.srcChainId,
                    _route.srcTxHash,
                    uint64(block.chainid),
                    _message
                )
            );
    }

    function executeMessage(MsgDataTypes.RouteInfo calldata _route, bytes calldata _message)
        private
        returns (IMessageReceiverApp.ExecutionStatus)
    {
        uint256 gasLeftBeforeExecution = gasleft();
        (bool ok, bytes memory res) = address(_route.receiver).call{value: msg.value}(
            abi.encodeWithSelector(
                IMessageReceiverApp.executeMessage.selector,
                _route.sender,
                _route.srcChainId,
                _message,
                msg.sender
            )
        );
        if (ok) {
            return abi.decode((res), (IMessageReceiverApp.ExecutionStatus));
        }
        handleExecutionRevert(gasLeftBeforeExecution, res);
        return IMessageReceiverApp.ExecutionStatus.Fail;
    }

    function handleExecutionRevert(uint256 _gasLeftBeforeExecution, bytes memory _returnData) private {
        uint256 gasLeftAfterExecution = gasleft();
        uint256 maxTargetGasLimit = block.gaslimit - preExecuteMessageGasUsage;
        if (_gasLeftBeforeExecution < maxTargetGasLimit && gasLeftAfterExecution <= _gasLeftBeforeExecution / 64) {
            // if this happens, the executor must have not provided sufficient gas limit,
            // then the tx should revert instead of recording a non-retryable failure status
            // https://github.com/wolflo/evm-opcodes/blob/main/gas.md#aa-f-gas-to-send-with-call-operations
            assembly {
                invalid()
            }
        }
        emit CallReverted(getRevertMsg(_returnData));
    }

    // https://ethereum.stackexchange.com/a/83577
    // https://github.com/Uniswap/v3-periphery/blob/v1.0.0/contracts/base/Multicall.sol
    function getRevertMsg(bytes memory _returnData) private pure returns (string memory) {
        // If the _res length is less than 68, then the transaction failed silently (without a revert message)
        if (_returnData.length < 68) return "Transaction reverted silently";
        assembly {
            // Slice the sighash.
            _returnData := add(_returnData, 0x04)
        }
        return abi.decode(_returnData, (string)); // All that remains is the revert string
    }

    // ================= helper functions =====================

    /**
     * @notice combine bridge transfer and msg execution calls into a single tx
     * @dev caller needs to get the required input params from SGN
     * @param _transferParams params to call bridge transfer
     * @param _msgParams params to execute message
     */
    function transferAndExecuteMsg(
        MsgDataTypes.BridgeTransferParams calldata _transferParams,
        MsgDataTypes.MsgWithTransferExecutionParams calldata _msgParams
    ) external {
        _bridgeTransfer(_msgParams.transfer.t, _transferParams);
        executeMessageWithTransfer(
            _msgParams.message,
            _msgParams.transfer,
            _msgParams.sigs,
            _msgParams.signers,
            _msgParams.powers
        );
    }

    /**
     * @notice combine bridge refund and msg execution calls into a single tx
     * @dev caller needs to get the required input params from SGN
     * @param _transferParams params to call bridge transfer for refund
     * @param _msgParams params to execute message for refund
     */
    function refundAndExecuteMsg(
        MsgDataTypes.BridgeTransferParams calldata _transferParams,
        MsgDataTypes.MsgWithTransferExecutionParams calldata _msgParams
    ) external {
        _bridgeTransfer(_msgParams.transfer.t, _transferParams);
        executeMessageWithTransferRefund(
            _msgParams.message,
            _msgParams.transfer,
            _msgParams.sigs,
            _msgParams.signers,
            _msgParams.powers
        );
    }

    function _bridgeTransfer(MsgDataTypes.TransferType t, MsgDataTypes.BridgeTransferParams calldata _transferParams)
        private
    {
        if (t == MsgDataTypes.TransferType.LqRelay) {
            IBridge(liquidityBridge).relay(
                _transferParams.request,
                _transferParams.sigs,
                _transferParams.signers,
                _transferParams.powers
            );
        } else if (t == MsgDataTypes.TransferType.LqWithdraw) {
            IBridge(liquidityBridge).withdraw(
                _transferParams.request,
                _transferParams.sigs,
                _transferParams.signers,
                _transferParams.powers
            );
        } else if (t == MsgDataTypes.TransferType.PegMint) {
            IPeggedTokenBridge(pegBridge).mint(
                _transferParams.request,
                _transferParams.sigs,
                _transferParams.signers,
                _transferParams.powers
            );
        } else if (t == MsgDataTypes.TransferType.PegV2Mint) {
            IPeggedTokenBridgeV2(pegBridgeV2).mint(
                _transferParams.request,
                _transferParams.sigs,
                _transferParams.signers,
                _transferParams.powers
            );
        } else if (t == MsgDataTypes.TransferType.PegWithdraw) {
            IOriginalTokenVault(pegVault).withdraw(
                _transferParams.request,
                _transferParams.sigs,
                _transferParams.signers,
                _transferParams.powers
            );
        } else if (t == MsgDataTypes.TransferType.PegV2Withdraw) {
            IOriginalTokenVaultV2(pegVaultV2).withdraw(
                _transferParams.request,
                _transferParams.sigs,
                _transferParams.signers,
                _transferParams.powers
            );
        }
    }

    // ================= contract config =================

    function setLiquidityBridge(address _addr) public onlyOwner {
        require(_addr != address(0), "invalid address");
        liquidityBridge = _addr;
        emit LiquidityBridgeUpdated(liquidityBridge);
    }

    function setPegBridge(address _addr) public onlyOwner {
        require(_addr != address(0), "invalid address");
        pegBridge = _addr;
        emit PegBridgeUpdated(pegBridge);
    }

    function setPegVault(address _addr) public onlyOwner {
        require(_addr != address(0), "invalid address");
        pegVault = _addr;
        emit PegVaultUpdated(pegVault);
    }

    function setPegBridgeV2(address _addr) public onlyOwner {
        require(_addr != address(0), "invalid address");
        pegBridgeV2 = _addr;
        emit PegBridgeV2Updated(pegBridgeV2);
    }

    function setPegVaultV2(address _addr) public onlyOwner {
        require(_addr != address(0), "invalid address");
        pegVaultV2 = _addr;
        emit PegVaultV2Updated(pegVaultV2);
    }

    function setPreExecuteMessageGasUsage(uint256 _usage) public onlyOwner {
        preExecuteMessageGasUsage = _usage;
    }
}

File 4 of 13 : Ownable.sol
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity ^0.8.0;

/**
 * @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.
 *
 * This adds a normal func that setOwner if _owner is address(0). So we can't allow
 * renounceOwnership. So we can support Proxy based upgradable contract
 */
abstract contract Ownable {
    address private _owner;

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _setOwner(msg.sender);
    }

    /**
     * @dev Only to be called by inherit contracts, in their init func called by Proxy
     * we require _owner == address(0), which is only possible when it's a delegateCall
     * because constructor sets _owner in contract state.
     */
    function initOwner() internal {
        require(_owner == address(0), "owner already set");
        _setOwner(msg.sender);
    }

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

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == msg.sender, "Ownable: caller is not the owner");
        _;
    }

    /**
     * @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");
        _setOwner(newOwner);
    }

    function _setOwner(address newOwner) private {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 5 of 13 : ISigsVerifier.sol
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity >=0.8.0;

interface ISigsVerifier {
    /**
     * @notice Verifies that a message is signed by a quorum among the signers.
     * @param _msg signed message
     * @param _sigs list of signatures sorted by signer addresses in ascending order
     * @param _signers sorted list of current signers
     * @param _powers powers of current signers
     */
    function verifySigs(
        bytes memory _msg,
        bytes[] calldata _sigs,
        address[] calldata _signers,
        uint256[] calldata _powers
    ) external view;
}

File 6 of 13 : MsgDataTypes.sol
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity >=0.8.0;

library MsgDataTypes {
    // bridge operation type at the sender side (src chain)
    enum BridgeSendType {
        Null,
        Liquidity,
        PegDeposit,
        PegBurn,
        PegV2Deposit,
        PegV2Burn,
        PegV2BurnFrom
    }

    // bridge operation type at the receiver side (dst chain)
    enum TransferType {
        Null,
        LqRelay, // relay through liquidity bridge
        LqWithdraw, // withdraw from liquidity bridge
        PegMint, // mint through pegged token bridge
        PegWithdraw, // withdraw from original token vault
        PegV2Mint, // mint through pegged token bridge v2
        PegV2Withdraw // withdraw from original token vault v2
    }

    enum MsgType {
        MessageWithTransfer,
        MessageOnly
    }

    enum TxStatus {
        Null,
        Success,
        Fail,
        Fallback,
        Pending // transient state within a transaction
    }

    struct TransferInfo {
        TransferType t;
        address sender;
        address receiver;
        address token;
        uint256 amount;
        uint64 wdseq; // only needed for LqWithdraw (refund)
        uint64 srcChainId;
        bytes32 refId;
        bytes32 srcTxHash; // src chain msg tx hash
    }

    struct RouteInfo {
        address sender;
        address receiver;
        uint64 srcChainId;
        bytes32 srcTxHash; // src chain msg tx hash
    }

    struct MsgWithTransferExecutionParams {
        bytes message;
        TransferInfo transfer;
        bytes[] sigs;
        address[] signers;
        uint256[] powers;
    }

    struct BridgeTransferParams {
        bytes request;
        bytes[] sigs;
        address[] signers;
        uint256[] powers;
    }
}

File 7 of 13 : IMessageReceiverApp.sol
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity >=0.8.0;

interface IMessageReceiverApp {
    enum ExecutionStatus {
        Fail, // execution failed, finalized
        Success, // execution succeeded, finalized
        Retry // execution rejected, can retry later
    }

    /**
     * @notice Called by MessageBus (MessageBusReceiver) if the process is originated from MessageBus (MessageBusSender)'s
     *         sendMessageWithTransfer it is only called when the tokens are checked to be arrived at this contract's address.
     * @param _sender The address of the source app contract
     * @param _token The address of the token that comes out of the bridge
     * @param _amount The amount of tokens received at this contract through the cross-chain bridge.
     *        the contract that implements this contract can safely assume that the tokens will arrive before this
     *        function is called.
     * @param _srcChainId The source chain ID where the transfer is originated from
     * @param _message Arbitrary message bytes originated from and encoded by the source app contract
     * @param _executor Address who called the MessageBus execution function
     */
    function executeMessageWithTransfer(
        address _sender,
        address _token,
        uint256 _amount,
        uint64 _srcChainId,
        bytes calldata _message,
        address _executor
    ) external payable returns (ExecutionStatus);

    /**
     * @notice Only called by MessageBus (MessageBusReceiver) if
     *         1. executeMessageWithTransfer reverts, or
     *         2. executeMessageWithTransfer returns ExecutionStatus.Fail
     * @param _sender The address of the source app contract
     * @param _token The address of the token that comes out of the bridge
     * @param _amount The amount of tokens received at this contract through the cross-chain bridge.
     *        the contract that implements this contract can safely assume that the tokens will arrive before this
     *        function is called.
     * @param _srcChainId The source chain ID where the transfer is originated from
     * @param _message Arbitrary message bytes originated from and encoded by the source app contract
     * @param _executor Address who called the MessageBus execution function
     */
    function executeMessageWithTransferFallback(
        address _sender,
        address _token,
        uint256 _amount,
        uint64 _srcChainId,
        bytes calldata _message,
        address _executor
    ) external payable returns (ExecutionStatus);

    /**
     * @notice Called by MessageBus (MessageBusReceiver) to process refund of the original transfer from this contract
     * @param _token The token address of the original transfer
     * @param _amount The amount of the original transfer
     * @param _message The same message associated with the original transfer
     * @param _executor Address who called the MessageBus execution function
     */
    function executeMessageWithTransferRefund(
        address _token,
        uint256 _amount,
        bytes calldata _message,
        address _executor
    ) external payable returns (ExecutionStatus);

    /**
     * @notice Called by MessageBus (MessageBusReceiver)
     * @param _sender The address of the source app contract
     * @param _srcChainId The source chain ID where the transfer is originated from
     * @param _message Arbitrary message bytes originated from and encoded by the source app contract
     * @param _executor Address who called the MessageBus execution function
     */
    function executeMessage(
        address _sender,
        uint64 _srcChainId,
        bytes calldata _message,
        address _executor
    ) external payable returns (ExecutionStatus);
}

File 8 of 13 : IMessageBus.sol
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity >=0.8.0;

import "../libraries/MsgDataTypes.sol";

interface IMessageBus {
    function liquidityBridge() external view returns (address);

    function pegBridge() external view returns (address);

    function pegBridgeV2() external view returns (address);

    function pegVault() external view returns (address);

    function pegVaultV2() external view returns (address);

    /**
     * @notice Calculates the required fee for the message.
     * @param _message Arbitrary message bytes to be decoded by the destination app contract.
     @ @return The required fee.
     */
    function calcFee(bytes calldata _message) external view returns (uint256);

    /**
     * @notice Sends a message to a contract on another chain.
     * Sender needs to make sure the uniqueness of the message Id, which is computed as
     * hash(type.MessageOnly, sender, receiver, srcChainId, srcTxHash, dstChainId, message).
     * If messages with the same Id are sent, only one of them will succeed at dst chain..
     * A fee is charged in the native gas token.
     * @param _receiver The address of the destination app contract.
     * @param _dstChainId The destination chain ID.
     * @param _message Arbitrary message bytes to be decoded by the destination app contract.
     */
    function sendMessage(
        address _receiver,
        uint256 _dstChainId,
        bytes calldata _message
    ) external payable;

    /**
     * @notice Sends a message associated with a transfer to a contract on another chain.
     * If messages with the same srcTransferId are sent, only one of them will succeed at dst chain..
     * A fee is charged in the native token.
     * @param _receiver The address of the destination app contract.
     * @param _dstChainId The destination chain ID.
     * @param _srcBridge The bridge contract to send the transfer with.
     * @param _srcTransferId The transfer ID.
     * @param _dstChainId The destination chain ID.
     * @param _message Arbitrary message bytes to be decoded by the destination app contract.
     */
    function sendMessageWithTransfer(
        address _receiver,
        uint256 _dstChainId,
        address _srcBridge,
        bytes32 _srcTransferId,
        bytes calldata _message
    ) external payable;

    /**
     * @notice Withdraws message fee in the form of native gas token.
     * @param _account The address receiving the fee.
     * @param _cumulativeFee The cumulative fee credited to the account. Tracked by SGN.
     * @param _sigs The list of signatures sorted by signing addresses in ascending order. A withdrawal must be
     * signed-off by +2/3 of the sigsVerifier's current signing power to be delivered.
     * @param _signers The sorted list of signers.
     * @param _powers The signing powers of the signers.
     */
    function withdrawFee(
        address _account,
        uint256 _cumulativeFee,
        bytes[] calldata _sigs,
        address[] calldata _signers,
        uint256[] calldata _powers
    ) external;

    /**
     * @notice Execute a message with a successful transfer.
     * @param _message Arbitrary message bytes originated from and encoded by the source app contract
     * @param _transfer The transfer info.
     * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by
     * +2/3 of the sigsVerifier's current signing power to be delivered.
     * @param _signers The sorted list of signers.
     * @param _powers The signing powers of the signers.
     */
    function executeMessageWithTransfer(
        bytes calldata _message,
        MsgDataTypes.TransferInfo calldata _transfer,
        bytes[] calldata _sigs,
        address[] calldata _signers,
        uint256[] calldata _powers
    ) external payable;

    /**
     * @notice Execute a message with a refunded transfer.
     * @param _message Arbitrary message bytes originated from and encoded by the source app contract
     * @param _transfer The transfer info.
     * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by
     * +2/3 of the sigsVerifier's current signing power to be delivered.
     * @param _signers The sorted list of signers.
     * @param _powers The signing powers of the signers.
     */
    function executeMessageWithTransferRefund(
        bytes calldata _message, // the same message associated with the original transfer
        MsgDataTypes.TransferInfo calldata _transfer,
        bytes[] calldata _sigs,
        address[] calldata _signers,
        uint256[] calldata _powers
    ) external payable;

    /**
     * @notice Execute a message not associated with a transfer.
     * @param _message Arbitrary message bytes originated from and encoded by the source app contract
     * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by
     * +2/3 of the sigsVerifier's current signing power to be delivered.
     * @param _signers The sorted list of signers.
     * @param _powers The signing powers of the signers.
     */
    function executeMessage(
        bytes calldata _message,
        MsgDataTypes.RouteInfo calldata _route,
        bytes[] calldata _sigs,
        address[] calldata _signers,
        uint256[] calldata _powers
    ) external payable;
}

File 9 of 13 : IBridge.sol
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity >=0.8.0;

interface IBridge {
    function send(
        address _receiver,
        address _token,
        uint256 _amount,
        uint64 _dstChainId,
        uint64 _nonce,
        uint32 _maxSlippage
    ) external;

    function relay(
        bytes calldata _relayRequest,
        bytes[] calldata _sigs,
        address[] calldata _signers,
        uint256[] calldata _powers
    ) external;

    function transfers(bytes32 transferId) external view returns (bool);

    function withdraws(bytes32 withdrawId) external view returns (bool);

    function withdraw(
        bytes calldata _wdmsg,
        bytes[] calldata _sigs,
        address[] calldata _signers,
        uint256[] calldata _powers
    ) external;

    /**
     * @notice Verifies that a message is signed by a quorum among the signers.
     * @param _msg signed message
     * @param _sigs list of signatures sorted by signer addresses in ascending order
     * @param _signers sorted list of current signers
     * @param _powers powers of current signers
     */
    function verifySigs(
        bytes memory _msg,
        bytes[] calldata _sigs,
        address[] calldata _signers,
        uint256[] calldata _powers
    ) external view;
}

File 10 of 13 : IOriginalTokenVault.sol
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity >=0.8.0;

interface IOriginalTokenVault {
    /**
     * @notice Lock original tokens to trigger mint at a remote chain's PeggedTokenBridge
     * @param _token local token address
     * @param _amount locked token amount
     * @param _mintChainId destination chainId to mint tokens
     * @param _mintAccount destination account to receive minted tokens
     * @param _nonce user input to guarantee unique depositId
     */
    function deposit(
        address _token,
        uint256 _amount,
        uint64 _mintChainId,
        address _mintAccount,
        uint64 _nonce
    ) external;

    /**
     * @notice Withdraw locked original tokens triggered by a burn at a remote chain's PeggedTokenBridge.
     * @param _request The serialized Withdraw protobuf.
     * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by
     * +2/3 of the bridge's current signing power to be delivered.
     * @param _signers The sorted list of signers.
     * @param _powers The signing powers of the signers.
     */
    function withdraw(
        bytes calldata _request,
        bytes[] calldata _sigs,
        address[] calldata _signers,
        uint256[] calldata _powers
    ) external;

    function records(bytes32 recordId) external view returns (bool);
}

File 11 of 13 : IOriginalTokenVaultV2.sol
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity >=0.8.0;

interface IOriginalTokenVaultV2 {
    /**
     * @notice Lock original tokens to trigger mint at a remote chain's PeggedTokenBridge
     * @param _token local token address
     * @param _amount locked token amount
     * @param _mintChainId destination chainId to mint tokens
     * @param _mintAccount destination account to receive minted tokens
     * @param _nonce user input to guarantee unique depositId
     */
    function deposit(
        address _token,
        uint256 _amount,
        uint64 _mintChainId,
        address _mintAccount,
        uint64 _nonce
    ) external returns (bytes32);

    /**
     * @notice Withdraw locked original tokens triggered by a burn at a remote chain's PeggedTokenBridge.
     * @param _request The serialized Withdraw protobuf.
     * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by
     * +2/3 of the bridge's current signing power to be delivered.
     * @param _signers The sorted list of signers.
     * @param _powers The signing powers of the signers.
     */
    function withdraw(
        bytes calldata _request,
        bytes[] calldata _sigs,
        address[] calldata _signers,
        uint256[] calldata _powers
    ) external returns (bytes32);

    function records(bytes32 recordId) external view returns (bool);
}

File 12 of 13 : IPeggedTokenBridge.sol
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity >=0.8.0;

interface IPeggedTokenBridge {
    /**
     * @notice Burn tokens to trigger withdrawal at a remote chain's OriginalTokenVault
     * @param _token local token address
     * @param _amount locked token amount
     * @param _withdrawAccount account who withdraw original tokens on the remote chain
     * @param _nonce user input to guarantee unique depositId
     */
    function burn(
        address _token,
        uint256 _amount,
        address _withdrawAccount,
        uint64 _nonce
    ) external;

    /**
     * @notice Mint tokens triggered by deposit at a remote chain's OriginalTokenVault.
     * @param _request The serialized Mint protobuf.
     * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by
     * +2/3 of the sigsVerifier's current signing power to be delivered.
     * @param _signers The sorted list of signers.
     * @param _powers The signing powers of the signers.
     */
    function mint(
        bytes calldata _request,
        bytes[] calldata _sigs,
        address[] calldata _signers,
        uint256[] calldata _powers
    ) external;

    function records(bytes32 recordId) external view returns (bool);
}

File 13 of 13 : IPeggedTokenBridgeV2.sol
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity >=0.8.0;

interface IPeggedTokenBridgeV2 {
    /**
     * @notice Burn pegged tokens to trigger a cross-chain withdrawal of the original tokens at a remote chain's
     * OriginalTokenVault, or mint at another remote chain
     * @param _token The pegged token address.
     * @param _amount The amount to burn.
     * @param _toChainId If zero, withdraw from original vault; otherwise, the remote chain to mint tokens.
     * @param _toAccount The account to receive tokens on the remote chain
     * @param _nonce A number to guarantee unique depositId. Can be timestamp in practice.
     */
    function burn(
        address _token,
        uint256 _amount,
        uint64 _toChainId,
        address _toAccount,
        uint64 _nonce
    ) external returns (bytes32);

    // same with `burn` above, use openzeppelin ERC20Burnable interface
    function burnFrom(
        address _token,
        uint256 _amount,
        uint64 _toChainId,
        address _toAccount,
        uint64 _nonce
    ) external returns (bytes32);

    /**
     * @notice Mint tokens triggered by deposit at a remote chain's OriginalTokenVault.
     * @param _request The serialized Mint protobuf.
     * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by
     * +2/3 of the sigsVerifier's current signing power to be delivered.
     * @param _signers The sorted list of signers.
     * @param _powers The signing powers of the signers.
     */
    function mint(
        bytes calldata _request,
        bytes[] calldata _sigs,
        address[] calldata _signers,
        uint256[] calldata _powers
    ) external returns (bytes32);

    function records(bytes32 recordId) external view returns (bool);
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 800
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {}
}

Contract ABI

[{"inputs":[{"internalType":"contract ISigsVerifier","name":"_sigsVerifier","type":"address"},{"internalType":"address","name":"_liquidityBridge","type":"address"},{"internalType":"address","name":"_pegBridge","type":"address"},{"internalType":"address","name":"_pegVault","type":"address"},{"internalType":"address","name":"_pegBridgeV2","type":"address"},{"internalType":"address","name":"_pegVaultV2","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"reason","type":"string"}],"name":"CallReverted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum MsgDataTypes.MsgType","name":"msgType","type":"uint8"},{"indexed":false,"internalType":"bytes32","name":"msgId","type":"bytes32"},{"indexed":false,"internalType":"enum MsgDataTypes.TxStatus","name":"status","type":"uint8"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint64","name":"srcChainId","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"srcTxHash","type":"bytes32"}],"name":"Executed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"feeBase","type":"uint256"}],"name":"FeeBaseUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"feePerByte","type":"uint256"}],"name":"FeePerByteUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"liquidityBridge","type":"address"}],"name":"LiquidityBridgeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"dstChainId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"message","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"Message","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"dstChainId","type":"uint256"},{"indexed":false,"internalType":"address","name":"bridge","type":"address"},{"indexed":false,"internalType":"bytes32","name":"srcTransferId","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"message","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"MessageWithTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum MsgDataTypes.MsgType","name":"msgType","type":"uint8"},{"indexed":false,"internalType":"bytes32","name":"msgId","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"srcChainId","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"srcTxHash","type":"bytes32"}],"name":"NeedRetry","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":"address","name":"pegBridge","type":"address"}],"name":"PegBridgeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pegBridgeV2","type":"address"}],"name":"PegBridgeV2Updated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pegVault","type":"address"}],"name":"PegVaultUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pegVaultV2","type":"address"}],"name":"PegVaultV2Updated","type":"event"},{"inputs":[{"internalType":"bytes","name":"_message","type":"bytes"}],"name":"calcFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_message","type":"bytes"},{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"bytes32","name":"srcTxHash","type":"bytes32"}],"internalType":"struct MsgDataTypes.RouteInfo","name":"_route","type":"tuple"},{"internalType":"bytes[]","name":"_sigs","type":"bytes[]"},{"internalType":"address[]","name":"_signers","type":"address[]"},{"internalType":"uint256[]","name":"_powers","type":"uint256[]"}],"name":"executeMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_message","type":"bytes"},{"components":[{"internalType":"enum MsgDataTypes.TransferType","name":"t","type":"uint8"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"wdseq","type":"uint64"},{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"bytes32","name":"refId","type":"bytes32"},{"internalType":"bytes32","name":"srcTxHash","type":"bytes32"}],"internalType":"struct MsgDataTypes.TransferInfo","name":"_transfer","type":"tuple"},{"internalType":"bytes[]","name":"_sigs","type":"bytes[]"},{"internalType":"address[]","name":"_signers","type":"address[]"},{"internalType":"uint256[]","name":"_powers","type":"uint256[]"}],"name":"executeMessageWithTransfer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_message","type":"bytes"},{"components":[{"internalType":"enum MsgDataTypes.TransferType","name":"t","type":"uint8"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"wdseq","type":"uint64"},{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"bytes32","name":"refId","type":"bytes32"},{"internalType":"bytes32","name":"srcTxHash","type":"bytes32"}],"internalType":"struct MsgDataTypes.TransferInfo","name":"_transfer","type":"tuple"},{"internalType":"bytes[]","name":"_sigs","type":"bytes[]"},{"internalType":"address[]","name":"_signers","type":"address[]"},{"internalType":"uint256[]","name":"_powers","type":"uint256[]"}],"name":"executeMessageWithTransferRefund","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"executedMessages","outputs":[{"internalType":"enum MsgDataTypes.TxStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeBase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feePerByte","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_liquidityBridge","type":"address"},{"internalType":"address","name":"_pegBridge","type":"address"},{"internalType":"address","name":"_pegVault","type":"address"},{"internalType":"address","name":"_pegBridgeV2","type":"address"},{"internalType":"address","name":"_pegVaultV2","type":"address"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"liquidityBridge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pegBridge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pegBridgeV2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pegVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pegVaultV2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"preExecuteMessageGasUsage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"bytes[]","name":"sigs","type":"bytes[]"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"uint256[]","name":"powers","type":"uint256[]"}],"internalType":"struct MsgDataTypes.BridgeTransferParams","name":"_transferParams","type":"tuple"},{"components":[{"internalType":"bytes","name":"message","type":"bytes"},{"components":[{"internalType":"enum MsgDataTypes.TransferType","name":"t","type":"uint8"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"wdseq","type":"uint64"},{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"bytes32","name":"refId","type":"bytes32"},{"internalType":"bytes32","name":"srcTxHash","type":"bytes32"}],"internalType":"struct MsgDataTypes.TransferInfo","name":"transfer","type":"tuple"},{"internalType":"bytes[]","name":"sigs","type":"bytes[]"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"uint256[]","name":"powers","type":"uint256[]"}],"internalType":"struct MsgDataTypes.MsgWithTransferExecutionParams","name":"_msgParams","type":"tuple"}],"name":"refundAndExecuteMsg","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint256","name":"_dstChainId","type":"uint256"},{"internalType":"bytes","name":"_message","type":"bytes"}],"name":"sendMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint256","name":"_dstChainId","type":"uint256"},{"internalType":"address","name":"_srcBridge","type":"address"},{"internalType":"bytes32","name":"_srcTransferId","type":"bytes32"},{"internalType":"bytes","name":"_message","type":"bytes"}],"name":"sendMessageWithTransfer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"setFeeBase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"setFeePerByte","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"setLiquidityBridge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"setPegBridge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"setPegBridgeV2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"setPegVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"setPegVaultV2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_usage","type":"uint256"}],"name":"setPreExecuteMessageGasUsage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sigsVerifier","outputs":[{"internalType":"contract ISigsVerifier","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"bytes[]","name":"sigs","type":"bytes[]"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"uint256[]","name":"powers","type":"uint256[]"}],"internalType":"struct MsgDataTypes.BridgeTransferParams","name":"_transferParams","type":"tuple"},{"components":[{"internalType":"bytes","name":"message","type":"bytes"},{"components":[{"internalType":"enum MsgDataTypes.TransferType","name":"t","type":"uint8"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"wdseq","type":"uint64"},{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"bytes32","name":"refId","type":"bytes32"},{"internalType":"bytes32","name":"srcTxHash","type":"bytes32"}],"internalType":"struct MsgDataTypes.TransferInfo","name":"transfer","type":"tuple"},{"internalType":"bytes[]","name":"sigs","type":"bytes[]"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"uint256[]","name":"powers","type":"uint256[]"}],"internalType":"struct MsgDataTypes.MsgWithTransferExecutionParams","name":"_msgParams","type":"tuple"}],"name":"transferAndExecuteMsg","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_cumulativeFee","type":"uint256"},{"internalType":"bytes[]","name":"_sigs","type":"bytes[]"},{"internalType":"address[]","name":"_signers","type":"address[]"},{"internalType":"uint256[]","name":"_powers","type":"uint256[]"}],"name":"withdrawFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"withdrawnFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

60a06040523480156200001157600080fd5b50604051620039be380380620039be83398101604081905262000034916200011d565b84848484848a6200004533620000b4565b6001600160a01b03908116608052600580546001600160a01b0319908116978316979097179055600680548716958216959095179094556007805486169385169390931790925560088054851691841691909117905560098054909316911617905550620001b1945050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146200011a57600080fd5b50565b60008060008060008060c087890312156200013757600080fd5b8651620001448162000104565b6020880151909650620001578162000104565b60408801519095506200016a8162000104565b60608801519094506200017d8162000104565b6080880151909350620001908162000104565b60a0880151909250620001a38162000104565b809150509295509295509295565b6080516137ea620001d4600039600081816104b201526107f701526137ea6000f3fe6080604052600436106101d85760003560e01c806382980dc411610102578063ccf2683b11610095578063e2c1ed2511610064578063e2c1ed2514610551578063f2fde38b14610571578063f60bbe2a14610591578063f83b0fb9146105a757600080fd5b8063ccf2683b146104a0578063cd2abd66146104d4578063d8257d1714610511578063dfa2dbaf1461053157600080fd5b806395e911a8116100d157806395e911a8146104375780639b05a7751461044d5780639f3ce55a1461046d578063c66a9c5a1461048057600080fd5b806382980dc4146103a157806382efd502146103d95780638da5cb5b146103f957806395b12c271461041757600080fd5b80634586f3311161017a578063588be02b11610149578063588be02b146103215780635b3e5f5014610341578063723d0a9d1461036e5780637b80ab201461038e57600080fd5b80634586f331146102a5578063468a2d04146102c55780635335dca2146102d8578063584e45e11461030b57600080fd5b8063359ef75b116101b6578063359ef75b1461023f5780633f395aff1461025f57806340d0d026146102725780634289fbb31461029257600080fd5b806303cbfe66146101dd57806306c28bd6146101ff5780632ff4c4111461021f575b600080fd5b3480156101e957600080fd5b506101fd6101f8366004612a6b565b6105c7565b005b34801561020b57600080fd5b506101fd61021a366004612a86565b6106c0565b34801561022b57600080fd5b506101fd61023a366004612aeb565b61074c565b34801561024b57600080fd5b506101fd61025a366004612b9f565b6109a5565b6101fd61026d366004612c46565b6109c1565b34801561027e57600080fd5b506101fd61028d366004612d4f565b610cb4565b6101fd6102a0366004612dbb565b610d0c565b3480156102b157600080fd5b506101fd6102c0366004612a86565b610df5565b6101fd6102d3366004612e33565b610e51565b3480156102e457600080fd5b506102f86102f3366004612ef8565b6110cd565b6040519081526020015b60405180910390f35b34801561031757600080fd5b506102f8600a5481565b34801561032d57600080fd5b506101fd61033c366004612a6b565b6110f3565b34801561034d57600080fd5b506102f861035c366004612a6b565b60036020526000908152604090205481565b34801561037a57600080fd5b506101fd610389366004612d4f565b6111e0565b6101fd61039c366004612c46565b61122e565b3480156103ad57600080fd5b506005546103c1906001600160a01b031681565b6040516001600160a01b039091168152602001610302565b3480156103e557600080fd5b506101fd6103f4366004612a6b565b61143d565b34801561040557600080fd5b506000546001600160a01b03166103c1565b34801561042357600080fd5b506008546103c1906001600160a01b031681565b34801561044357600080fd5b506102f860015481565b34801561045957600080fd5b506101fd610468366004612a6b565b61152a565b6101fd61047b366004612f3a565b611617565b34801561048c57600080fd5b506009546103c1906001600160a01b031681565b3480156104ac57600080fd5b506103c17f000000000000000000000000000000000000000000000000000000000000000081565b3480156104e057600080fd5b506105046104ef366004612a86565b60046020526000908152604090205460ff1681565b6040516103029190612fbe565b34801561051d57600080fd5b506007546103c1906001600160a01b031681565b34801561053d57600080fd5b506006546103c1906001600160a01b031681565b34801561055d57600080fd5b506101fd61056c366004612a86565b6116fa565b34801561057d57600080fd5b506101fd61058c366004612a6b565b611786565b34801561059d57600080fd5b506102f860025481565b3480156105b357600080fd5b506101fd6105c2366004612a6b565b611865565b336105da6000546001600160a01b031690565b6001600160a01b0316146106235760405162461bcd60e51b8152602060048201819052602482015260008051602061379583398151915260448201526064015b60405180910390fd5b6001600160a01b03811661066b5760405162461bcd60e51b815260206004820152600f60248201526e696e76616c6964206164647265737360881b604482015260640161061a565b600680546001600160a01b0319166001600160a01b0383169081179091556040519081527fd60e9ceb4f54f1bfb1741a4b35fc9d806d7ed48200b523203b92248ea38fa17d906020015b60405180910390a150565b336106d36000546001600160a01b031690565b6001600160a01b0316146107175760405162461bcd60e51b81526020600482018190526024820152600080516020613795833981519152604482015260640161061a565b60018190556040518181527f892dfdc99ecd3bb4f2f2cb118dca02f0bd16640ff156d3c6459d4282e336a5f2906020016106b5565b6000463060405160200161079d92919091825260601b6001600160601b03191660208201527f77697468647261774665650000000000000000000000000000000000000000006034820152603f0190565b60408051808303601f19018152828252805160209182012090830181905260608c901b6001600160601b0319168383015260548084018c9052825180850390910181526074840192839052633416de1160e11b90925292507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169163682dbc229161083e918b908b908b908b908b908b90607801613178565b60006040518083038186803b15801561085657600080fd5b505afa15801561086a573d6000803e3d6000fd5b505050506001600160a01b038916600090815260036020526040812054610891908a6131ec565b9050600081116108e35760405162461bcd60e51b815260206004820152601960248201527f4e6f206e657720616d6f756e7420746f20776974686472617700000000000000604482015260640161061a565b6001600160a01b038a166000818152600360205260408082208c90555190919061c35090849084818181858888f193505050503d8060008114610942576040519150601f19603f3d011682016040523d82523d6000602084013e610947565b606091505b50509050806109985760405162461bcd60e51b815260206004820152601660248201527f6661696c656420746f2077697468647261772066656500000000000000000000604482015260640161061a565b5050505050505050505050565b6109ad611952565b6109ba85858585856119b6565b5050505050565b60006109cc88611a6e565b90506000808281526004602081905260409091205460ff16908111156109f4576109f4612f94565b14610a415760405162461bcd60e51b815260206004820152601960248201527f7472616e7366657220616c726561647920657865637574656400000000000000604482015260640161061a565b6000818152600460208181526040808420805460ff1916909317909255815146918101919091526001600160601b03193060601b16918101919091527f4d657373616765576974685472616e73666572000000000000000000000000006054820152606701604051602081830303815290604052805190602001209050600560009054906101000a90046001600160a01b03166001600160a01b031663682dbc2282848e8e8e6101000135604051602001610b00959493929190613203565b6040516020818303038152906040528a8a8a8a8a8a6040518863ffffffff1660e01b8152600401610b379796959493929190613178565b60006040518083038186803b158015610b4f57600080fd5b505afa158015610b63573d6000803e3d6000fd5b50505050600080610b758b8e8e612327565b90506001816002811115610b8b57610b8b612f94565b1415610b9a5760019150610c64565b6002816002811115610bae57610bae612f94565b1415610c2f576000848152600460205260408120805460ff19166001835b02179055507fe49c2c954d381d1448cf824743aeff9da7a1d82078a7c9e5817269cc359bd26c6000858d60c0016020810190610c089190613225565b8e6101000135604051610c1e949392919061325f565b60405180910390a150505050610ca9565b610c3a8b8e8e61248f565b90506001816002811115610c5057610c50612f94565b1415610c5f5760039150610c64565b600291505b60008481526004602081905260409091208054849260ff19909116906001908490811115610c9457610c94612f94565b0217905550610ca484838d6124ca565b505050505b505050505050505050565b610ccd610cc76040830160208401613292565b8361253c565b610d08610cda82806132b3565b60208401610cec6101408601866132fa565b610cfa6101608801886132fa565b61039c6101808a018a6132fa565b5050565b46851415610d4e5760405162461bcd60e51b815260206004820152600f60248201526e125b9d985b1a590818da185a5b9259608a1b604482015260640161061a565b6000610d5a83836110cd565b905080341015610d9f5760405162461bcd60e51b815260206004820152601060248201526f496e73756666696369656e742066656560801b604482015260640161061a565b336001600160a01b03167f172762498a59a3bc4fed3f2b63f94f17ea0193cffdc304fe7d3eaf4d342d2f6688888888888834604051610de49796959493929190613344565b60405180910390a250505050505050565b33610e086000546001600160a01b031690565b6001600160a01b031614610e4c5760405162461bcd60e51b81526020600482018190526024820152600080516020613795833981519152604482015260640161061a565b600a55565b6000610e5e888b8b61279b565b90506000808281526004602081905260409091205460ff1690811115610e8657610e86612f94565b14610ed35760405162461bcd60e51b815260206004820152601860248201527f6d65737361676520616c72656164792065786563757465640000000000000000604482015260640161061a565b600081815260046020818152604092839020805460ff1916909217909155815146818301523060601b6001600160601b031916818401527f4d6573736167650000000000000000000000000000000000000000000000000060548201528251603b818303018152605b820184528051920191909120600554607b8301829052609b8084018690528451808503909101815260bb840194859052633416de1160e11b90945290926001600160a01b039091169163682dbc2291610fa3918c908c908c908c908c908c9060bf01613178565b60006040518083038186803b158015610fbb57600080fd5b505afa158015610fcf573d6000803e3d6000fd5b50505050600080610fe18b8e8e61280a565b90506001816002811115610ff757610ff7612f94565b1415611006576001915061108d565b600281600281111561101a5761101a612f94565b1415611088576000848152600460205260408120805460ff191660018302179055507fe49c2c954d381d1448cf824743aeff9da7a1d82078a7c9e5817269cc359bd26c6001858d60400160208101906110739190613225565b8e60600135604051610c1e949392919061325f565b600291505b60008481526004602081905260409091208054849260ff199091169060019084908111156110bd576110bd612f94565b0217905550610ca484838d612869565b6002546000906110dd9083613391565b6001546110ea91906133b0565b90505b92915050565b336111066000546001600160a01b031690565b6001600160a01b03161461114a5760405162461bcd60e51b81526020600482018190526024820152600080516020613795833981519152604482015260640161061a565b6001600160a01b0381166111925760405162461bcd60e51b815260206004820152600f60248201526e696e76616c6964206164647265737360881b604482015260640161061a565b600580546001600160a01b0319166001600160a01b0383169081179091556040519081527fbf9977180dc6e6cff25598c8e59150cecd7f8e448e092633d38ab7ee223ae058906020016106b5565b6111f3610cc76040830160208401613292565b610d0861120082806132b3565b602084016112126101408601866132fa565b6112206101608801886132fa565b61026d6101808a018a6132fa565b600061123988611a6e565b90506000808281526004602081905260409091205460ff169081111561126157611261612f94565b146112ae5760405162461bcd60e51b815260206004820152601960248201527f7472616e7366657220616c726561647920657865637574656400000000000000604482015260640161061a565b6000818152600460208181526040808420805460ff1916909317909255815146918101919091526001600160601b03193060601b16918101919091527f4d657373616765576974685472616e73666572526566756e64000000000000006054820152606d01604051602081830303815290604052805190602001209050600560009054906101000a90046001600160a01b03166001600160a01b031663682dbc2282848e8e8e610100013560405160200161136d959493929190613203565b6040516020818303038152906040528a8a8a8a8a8a6040518863ffffffff1660e01b81526004016113a49796959493929190613178565b60006040518083038186803b1580156113bc57600080fd5b505afa1580156113d0573d6000803e3d6000fd5b505050506000806113e28b8e8e6128cd565b905060018160028111156113f8576113f8612f94565b14156114075760019150610c64565b600281600281111561141b5761141b612f94565b1415610c5f576000848152600460205260408120805460ff1916600183610bcc565b336114506000546001600160a01b031690565b6001600160a01b0316146114945760405162461bcd60e51b81526020600482018190526024820152600080516020613795833981519152604482015260640161061a565b6001600160a01b0381166114dc5760405162461bcd60e51b815260206004820152600f60248201526e696e76616c6964206164647265737360881b604482015260640161061a565b600880546001600160a01b0319166001600160a01b0383169081179091556040519081527ffb337a6c76476534518d5816caeb86263972470fedccfd047a35eb1825eaa9e8906020016106b5565b3361153d6000546001600160a01b031690565b6001600160a01b0316146115815760405162461bcd60e51b81526020600482018190526024820152600080516020613795833981519152604482015260640161061a565b6001600160a01b0381166115c95760405162461bcd60e51b815260206004820152600f60248201526e696e76616c6964206164647265737360881b604482015260640161061a565b600780546001600160a01b0319166001600160a01b0383169081179091556040519081527fa9db0c32d9c6c2f75f3b95047a9e67cc1c010eab792a4e6ca777ce918ad94aad906020016106b5565b468314156116595760405162461bcd60e51b815260206004820152600f60248201526e125b9d985b1a590818da185a5b9259608a1b604482015260640161061a565b600061166583836110cd565b9050803410156116aa5760405162461bcd60e51b815260206004820152601060248201526f496e73756666696369656e742066656560801b604482015260640161061a565b336001600160a01b03167fce3972bfffe49d317e1d128047a97a3d86b25c94f6f04409f988ef854d25e0e486868686346040516116eb9594939291906133c8565b60405180910390a25050505050565b3361170d6000546001600160a01b031690565b6001600160a01b0316146117515760405162461bcd60e51b81526020600482018190526024820152600080516020613795833981519152604482015260640161061a565b60028190556040518181527f210d4d5d2d36d571207dac98e383e2441c684684c885fb2d7c54f8d24422074c906020016106b5565b336117996000546001600160a01b031690565b6001600160a01b0316146117dd5760405162461bcd60e51b81526020600482018190526024820152600080516020613795833981519152604482015260640161061a565b6001600160a01b0381166118595760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161061a565b61186281612924565b50565b336118786000546001600160a01b031690565b6001600160a01b0316146118bc5760405162461bcd60e51b81526020600482018190526024820152600080516020613795833981519152604482015260640161061a565b6001600160a01b0381166119045760405162461bcd60e51b815260206004820152600f60248201526e696e76616c6964206164647265737360881b604482015260640161061a565b600980546001600160a01b0319166001600160a01b0383169081179091556040519081527f918a691a2a82482a10e11f43d7b627b2ba220dd08f251cb61933c42560f6fcb5906020016106b5565b6000546001600160a01b0316156119ab5760405162461bcd60e51b815260206004820152601160248201527f6f776e657220616c726561647920736574000000000000000000000000000000604482015260640161061a565b6119b433612924565b565b6005546001600160a01b031615611a0f5760405162461bcd60e51b815260206004820152601b60248201527f6c697175696469747942726964676520616c7265616479207365740000000000604482015260640161061a565b600580546001600160a01b03199081166001600160a01b03978816179091556006805482169587169590951790945560078054851693861693909317909255600880548416918516919091179055600980549092169216919091179055565b600080806001611a816020860186613292565b6006811115611a9257611a92612f94565b1415611c2d57611aa86040850160208601612a6b565b611ab86060860160408701612a6b565b611ac86080870160608801612a6b565b6080870135611add60e0890160c08a01613225565b6040516001600160601b0319606096871b8116602083015294861b851660348201529290941b9092166048820152605c8101919091526001600160c01b031960c092831b8116607c8301524690921b909116608482015260e0850135608c82015260ac0160408051808303601f19018152908290528051602090910120600554633c64f04b60e01b8352600483018290529093506001600160a01b031691508190633c64f04b9060240160206040518083038186803b158015611b9f57600080fd5b505afa158015611bb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd79190613403565b1515600114611c285760405162461bcd60e51b815260206004820152601660248201527f6272696467652072656c6179206e6f7420657869737400000000000000000000604482015260640161061a565b6122f2565b6002611c3c6020860186613292565b6006811115611c4d57611c4d612f94565b1415611dba5746611c6460c0860160a08701613225565b611c746060870160408801612a6b565b611c846080880160608901612a6b565b6040516001600160c01b031960c095861b811660208301529390941b90921660288401526001600160601b0319606091821b8116603085015291901b1660448201526080850135605882015260780160408051808303601f19018152908290528051602090910120600554631c13568560e31b8352600483018290529093506001600160a01b03169150819063e09ab4289060240160206040518083038186803b158015611d3157600080fd5b505afa158015611d45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d699190613403565b1515600114611c285760405162461bcd60e51b815260206004820152601960248201527f627269646765207769746864726177206e6f7420657869737400000000000000604482015260640161061a565b6003611dc96020860186613292565b6006811115611dda57611dda612f94565b1480611e0357506004611df06020860186613292565b6006811115611e0157611e01612f94565b145b1561208557611e186060850160408601612a6b565b611e286080860160608701612a6b565b6080860135611e3d6040880160208901612a6b565b611e4d60e0890160c08a01613225565b604051606095861b6001600160601b0319908116602083015294861b851660348201526048810193909352931b909116606882015260c09190911b6001600160c01b031916607c82015260e0850135608482015260a40160408051601f19818403018152919052805160209091012091506003611ecd6020860186613292565b6006811115611ede57611ede612f94565b1415611fb557506006546040516301e6472560e01b8152600481018390526001600160a01b039091169081906301e64725906024015b60206040518083038186803b158015611f2c57600080fd5b505afa158015611f40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f649190613403565b1515600114611c285760405162461bcd60e51b815260206004820152601560248201527f6d696e74207265636f7264206e6f742065786973740000000000000000000000604482015260640161061a565b506007546040516301e6472560e01b8152600481018390526001600160a01b039091169081906301e647259060240160206040518083038186803b158015611ffc57600080fd5b505afa158015612010573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120349190613403565b1515600114611c285760405162461bcd60e51b815260206004820152601960248201527f7769746864726177207265636f7264206e6f7420657869737400000000000000604482015260640161061a565b60056120946020860186613292565b60068111156120a5576120a5612f94565b14806120ce575060066120bb6020860186613292565b60068111156120cc576120cc612f94565b145b156122f25760056120e26020860186613292565b60068111156120f3576120f3612f94565b141561210b57506008546001600160a01b0316612119565b506009546001600160a01b03165b6121296060850160408601612a6b565b6121396080860160608701612a6b565b608086013561214e6040880160208901612a6b565b61215e60e0890160c08a01613225565b604051606095861b6001600160601b0319908116602083015294861b85166034820152604881019390935290841b8316606883015260c01b6001600160c01b031916607c82015260e087013560848201529183901b1660a482015260b80160408051601f198184030181529190528051602090910120915060056121e56020860186613292565b60068111156121f6576121f6612f94565b1415612229576040516301e6472560e01b8152600481018390526001600160a01b038216906301e6472590602401611f14565b6040516301e6472560e01b8152600481018390526001600160a01b038216906301e647259060240160206040518083038186803b15801561226957600080fd5b505afa15801561227d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a19190613403565b15156001146122f25760405162461bcd60e51b815260206004820152601960248201527f7769746864726177207265636f7264206e6f7420657869737400000000000000604482015260640161061a565b600081836040516020016123089392919061343c565b6040516020818303038152906040528051906020012092505050919050565b6000805a90506000806123406060880160408901612a6b565b6001600160a01b031634631f34afff60e21b61236260408b0160208c01612a6b565b61237260808c0160608d01612a6b565b60808c013561238760e08e0160c08f01613225565b8c8c336040516024016123a09796959493929190613468565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161240b91906134c1565b60006040518083038185875af1925050503d8060008114612448576040519150601f19603f3d011682016040523d82523d6000602084013e61244d565b606091505b50915091508115612476578080602001905181019061246c91906134dd565b9350505050612488565b6124808382612974565b600093505050505b9392505050565b6000805a90506000806124a86060880160408901612a6b565b6001600160a01b031634632d5bd7e360e11b61236260408b0160208c01612a6b565b6124da6060820160408301612a6b565b6001600160a01b03167fa635eb05143f74743822bbd96428928de4c8ee8cc578299749be9425c17bb34d6000858561251860e0870160c08801613225565b86610100013560405161252f9594939291906134fe565b60405180910390a2505050565b600182600681111561255057612550612f94565b14156125f1576005546001600160a01b031663cdd1b25d61257183806132b3565b61257e60208601866132fa565b61258b60408801886132fa565b61259860608a018a6132fa565b6040518963ffffffff1660e01b81526004016125bb98979695949392919061353c565b600060405180830381600087803b1580156125d557600080fd5b505af11580156125e9573d6000803e3d6000fd5b505050505050565b600282600681111561260557612605612f94565b1415612626576005546001600160a01b031663a21a928061257183806132b3565b600382600681111561263a5761263a612f94565b141561265b576006546001600160a01b031663f873430261257183806132b3565b600582600681111561266f5761266f612f94565b1415612731576008546001600160a01b031663f873430261269083806132b3565b61269d60208601866132fa565b6126aa60408801886132fa565b6126b760608a018a6132fa565b6040518963ffffffff1660e01b81526004016126da98979695949392919061353c565b602060405180830381600087803b1580156126f457600080fd5b505af1158015612708573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061272c919061359c565b505050565b600482600681111561274557612745612f94565b1415612766576007546001600160a01b031663a21a928061257183806132b3565b600682600681111561277a5761277a612f94565b1415610d08576009546001600160a01b031663a21a928061269083806132b3565b600060016127ac6020860186612a6b565b6127bc6040870160208801612a6b565b6127cc6060880160408901613225565b87606001354688886040516020016127eb9897969594939291906135b5565b6040516020818303038152906040528051906020012090509392505050565b6000805a90506000806128236040880160208901612a6b565b6001600160a01b031634639c649fdf60e01b61284260208b018b612a6b565b61285260608c0160408d01613225565b8a8a336040516024016123a0959493929190613629565b6128796040820160208301612a6b565b6001600160a01b03167fa635eb05143f74743822bbd96428928de4c8ee8cc578299749be9425c17bb34d600185856128b76060870160408801613225565b866060013560405161252f9594939291906134fe565b6000805a90506000806128e66060880160408901612a6b565b6001600160a01b0316346305e5a4c160e11b61290860808b0160608c01612a6b565b8a608001358a8a336040516024016123a0959493929190613672565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60005a90506000600a544561298991906131ec565b905080841080156129a457506129a060408561369c565b8211155b156129ab57fe5b7fffdd6142bbb721f3400e3908b04b86f60649b2e4d191e3f4c50c32c3e6471d2f6129d5846129f0565b6040516129e291906136be565b60405180910390a150505050565b6060604482511015612a3557505060408051808201909152601d81527f5472616e73616374696f6e2072657665727465642073696c656e746c79000000602082015290565b600482019150818060200190518101906110ed91906136e7565b80356001600160a01b0381168114612a6657600080fd5b919050565b600060208284031215612a7d57600080fd5b6110ea82612a4f565b600060208284031215612a9857600080fd5b5035919050565b60008083601f840112612ab157600080fd5b50813567ffffffffffffffff811115612ac957600080fd5b6020830191508360208260051b8501011115612ae457600080fd5b9250929050565b60008060008060008060008060a0898b031215612b0757600080fd5b612b1089612a4f565b975060208901359650604089013567ffffffffffffffff80821115612b3457600080fd5b612b408c838d01612a9f565b909850965060608b0135915080821115612b5957600080fd5b612b658c838d01612a9f565b909650945060808b0135915080821115612b7e57600080fd5b50612b8b8b828c01612a9f565b999c989b5096995094979396929594505050565b600080600080600060a08688031215612bb757600080fd5b612bc086612a4f565b9450612bce60208701612a4f565b9350612bdc60408701612a4f565b9250612bea60608701612a4f565b9150612bf860808701612a4f565b90509295509295909350565b60008083601f840112612c1657600080fd5b50813567ffffffffffffffff811115612c2e57600080fd5b602083019150836020828501011115612ae457600080fd5b6000806000806000806000806000898b036101a0811215612c6657600080fd5b8a3567ffffffffffffffff80821115612c7e57600080fd5b612c8a8e838f01612c04565b909c509a508a9150610120601f1984011215612ca557600080fd5b60208d0199506101408d0135925080831115612cc057600080fd5b612ccc8e848f01612a9f565b90995097506101608d0135925088915080831115612ce957600080fd5b612cf58e848f01612a9f565b90975095506101808d0135925086915080831115612d1257600080fd5b5050612d208c828d01612a9f565b915080935050809150509295985092959850929598565b600060808284031215612d4957600080fd5b50919050565b60008060408385031215612d6257600080fd5b823567ffffffffffffffff80821115612d7a57600080fd5b612d8686838701612d37565b93506020850135915080821115612d9c57600080fd5b5083016101a08186031215612db057600080fd5b809150509250929050565b60008060008060008060a08789031215612dd457600080fd5b612ddd87612a4f565b955060208701359450612df260408801612a4f565b935060608701359250608087013567ffffffffffffffff811115612e1557600080fd5b612e2189828a01612c04565b979a9699509497509295939492505050565b60008060008060008060008060006101008a8c031215612e5257600080fd5b893567ffffffffffffffff80821115612e6a57600080fd5b612e768d838e01612c04565b909b509950899150612e8b8d60208e01612d37565b985060a08c0135915080821115612ea157600080fd5b612ead8d838e01612a9f565b909850965060c08c0135915080821115612ec657600080fd5b612ed28d838e01612a9f565b909650945060e08c0135915080821115612eeb57600080fd5b50612d208c828d01612a9f565b60008060208385031215612f0b57600080fd5b823567ffffffffffffffff811115612f2257600080fd5b612f2e85828601612c04565b90969095509350505050565b60008060008060608587031215612f5057600080fd5b612f5985612a4f565b935060208501359250604085013567ffffffffffffffff811115612f7c57600080fd5b612f8887828801612c04565b95989497509550505050565b634e487b7160e01b600052602160045260246000fd5b60058110612fba57612fba612f94565b9052565b602081016110ed8284612faa565b60005b83811015612fe7578181015183820152602001612fcf565b83811115612ff6576000848401525b50505050565b60008151808452613014816020860160208601612fcc565b601f01601f19169290920160200192915050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b81835260006020808501808196508560051b810191508460005b878110156130d55782840389528135601e1988360301811261308c57600080fd5b8701803567ffffffffffffffff8111156130a557600080fd5b8036038913156130b457600080fd5b6130c18682898501613028565b9a87019a955050509084019060010161306b565b5091979650505050505050565b8183526000602080850194508260005b8581101561311e576001600160a01b0361310b83612a4f565b16875295820195908201906001016130f2565b509495945050505050565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561315b57600080fd5b8260051b8083602087013760009401602001938452509192915050565b60808152600061318b608083018a612ffc565b828103602084015261319e81898b613051565b905082810360408401526131b38187896130e2565b905082810360608401526131c8818587613129565b9a9950505050505050505050565b634e487b7160e01b600052601160045260246000fd5b6000828210156131fe576131fe6131d6565b500390565b8581528460208201528284604083013760409201918201526060019392505050565b60006020828403121561323757600080fd5b813567ffffffffffffffff8116811461248857600080fd5b60028110612fba57612fba612f94565b6080810161326d828761324f565b84602083015267ffffffffffffffff8416604083015282606083015295945050505050565b6000602082840312156132a457600080fd5b81356007811061248857600080fd5b6000808335601e198436030181126132ca57600080fd5b83018035915067ffffffffffffffff8211156132e557600080fd5b602001915036819003821315612ae457600080fd5b6000808335601e1984360301811261331157600080fd5b83018035915067ffffffffffffffff82111561332c57600080fd5b6020019150600581901b3603821315612ae457600080fd5b60006001600160a01b03808a16835288602084015280881660408401525085606083015260c0608083015261337d60c083018587613028565b90508260a083015298975050505050505050565b60008160001904831182151516156133ab576133ab6131d6565b500290565b600082198211156133c3576133c36131d6565b500190565b6001600160a01b03861681528460208201526080604082015260006133f1608083018587613028565b90508260608301529695505050505050565b60006020828403121561341557600080fd5b8151801515811461248857600080fd5b6002811061343557613435612f94565b60f81b9052565b6134468185613425565b60609290921b6001600160601b03191660018301526015820152603501919050565b60006001600160a01b03808a168352808916602084015287604084015267ffffffffffffffff8716606084015260c060808401526134aa60c084018688613028565b915080841660a08401525098975050505050505050565b600082516134d3818460208701612fcc565b9190910192915050565b6000602082840312156134ef57600080fd5b81516003811061248857600080fd5b60a0810161350c828861324f565b85602083015261351f6040830186612faa565b67ffffffffffffffff939093166060820152608001529392505050565b608081526000613550608083018a8c613028565b828103602084015261356381898b613051565b905082810360408401526135788187896130e2565b9050828103606084015261358d818587613129565b9b9a5050505050505050505050565b6000602082840312156135ae57600080fd5b5051919050565b6135bf818a613425565b60006bffffffffffffffffffffffff19808a60601b166001840152808960601b166015840152506001600160c01b0319808860c01b166029840152866031840152808660c01b16605184015250828460598401375060009101605901908152979650505050505050565b60006001600160a01b03808816835267ffffffffffffffff871660208401526080604084015261365d608084018688613028565b91508084166060840152509695505050505050565b60006001600160a01b0380881683528660208401526080604084015261365d608084018688613028565b6000826136b957634e487b7160e01b600052601260045260246000fd5b500490565b6020815260006110ea6020830184612ffc565b634e487b7160e01b600052604160045260246000fd5b6000602082840312156136f957600080fd5b815167ffffffffffffffff8082111561371157600080fd5b818401915084601f83011261372557600080fd5b815181811115613737576137376136d1565b604051601f8201601f19908116603f0116810190838211818310171561375f5761375f6136d1565b8160405282815287602084870101111561377857600080fd5b613789836020830160208801612fcc565b97965050505050505056fe4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572a264697066735822122090433ad1f9028c73df85259673150d737b2492dffdb7beccd4915ade0e7f7edc64736f6c63430008090033000000000000000000000000841ce48f9446c8e281d3f1444cb859b4a6d0738c000000000000000000000000841ce48f9446c8e281d3f1444cb859b4a6d0738c000000000000000000000000374b8a9f3ec5eb2d97eca84ea27aca45aa1c57ef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

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

000000000000000000000000841ce48f9446c8e281d3f1444cb859b4a6d0738c000000000000000000000000841ce48f9446c8e281d3f1444cb859b4a6d0738c000000000000000000000000374b8a9f3ec5eb2d97eca84ea27aca45aa1c57ef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _sigsVerifier (address): 0x841ce48f9446c8e281d3f1444cb859b4a6d0738c
Arg [1] : _liquidityBridge (address): 0x841ce48f9446c8e281d3f1444cb859b4a6d0738c
Arg [2] : _pegBridge (address): 0x374b8a9f3ec5eb2d97eca84ea27aca45aa1c57ef
Arg [3] : _pegVault (address): 0x0000000000000000000000000000000000000000
Arg [4] : _pegBridgeV2 (address): 0x0000000000000000000000000000000000000000
Arg [5] : _pegVaultV2 (address): 0x0000000000000000000000000000000000000000

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000841ce48f9446c8e281d3f1444cb859b4a6d0738c
Arg [1] : 000000000000000000000000841ce48f9446c8e281d3f1444cb859b4a6d0738c
Arg [2] : 000000000000000000000000374b8a9f3ec5eb2d97eca84ea27aca45aa1c57ef
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000000


Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.