ETH Price: $2,524.72 (+0.08%)
Gas: 0.81 Gwei

Contract

0x722669cbE532F08bb4EB81127e6Ef386627E90be
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Batch Update Rem...206380672024-08-30 1:19:115 mins ago1724980751IN
0x722669cb...6627E90be
0 ETH0.000031430.7237265
Batch Update Rem...206374732024-08-29 23:19:232 hrs ago1724973563IN
0x722669cb...6627E90be
0 ETH0.000037060.8531179
Batch Update Rem...206374732024-08-29 23:19:232 hrs ago1724973563IN
0x722669cb...6627E90be
0 ETH0.000037050.8531179
Batch Update Rem...206371772024-08-29 22:19:233 hrs ago1724969963IN
0x722669cb...6627E90be
0 ETH0.000052681.21350002
Batch Update Rem...206368782024-08-29 21:19:234 hrs ago1724966363IN
0x722669cb...6627E90be
0 ETH0.000048391.11437474
Batch Update Rem...206365812024-08-29 20:19:115 hrs ago1724962751IN
0x722669cb...6627E90be
0 ETH0.000134273.09173941
Batch Update Rem...206362852024-08-29 19:19:476 hrs ago1724959187IN
0x722669cb...6627E90be
0 ETH0.00009542.1961249
Batch Update Rem...206362842024-08-29 19:19:356 hrs ago1724959175IN
0x722669cb...6627E90be
0 ETH0.000096912.2320702
Batch Update Rem...206362832024-08-29 19:19:236 hrs ago1724959163IN
0x722669cb...6627E90be
0 ETH0.000095142.19082435
Batch Update Rem...206359862024-08-29 18:19:357 hrs ago1724955575IN
0x722669cb...6627E90be
0 ETH0.00012682.91891914
Batch Update Rem...206359862024-08-29 18:19:357 hrs ago1724955575IN
0x722669cb...6627E90be
0 ETH0.00012492.87585004
Batch Update Rem...206356852024-08-29 17:19:238 hrs ago1724951963IN
0x722669cb...6627E90be
0 ETH0.000101342.33400672
Batch Update Rem...206344972024-08-29 13:20:2312 hrs ago1724937623IN
0x722669cb...6627E90be
0 ETH0.000168333.87595138
Batch Update Rem...206344922024-08-29 13:19:2312 hrs ago1724937563IN
0x722669cb...6627E90be
0 ETH0.000183724.23153574
Batch Update Rem...206333022024-08-29 9:19:2316 hrs ago1724923163IN
0x722669cb...6627E90be
0 ETH0.00004411.01516154
Batch Update Rem...206330032024-08-29 8:19:3517 hrs ago1724919575IN
0x722669cb...6627E90be
0 ETH0.000042620.98117415
Batch Update Rem...206327042024-08-29 7:19:2318 hrs ago1724915963IN
0x722669cb...6627E90be
0 ETH0.000039480.90882875
Batch Update Rem...206327042024-08-29 7:19:2318 hrs ago1724915963IN
0x722669cb...6627E90be
0 ETH0.000038310.88213642
Batch Update Rem...206324072024-08-29 6:19:3519 hrs ago1724912375IN
0x722669cb...6627E90be
0 ETH0.000035440.81617811
Batch Update Rem...206321112024-08-29 5:19:2320 hrs ago1724908763IN
0x722669cb...6627E90be
0 ETH0.000033920.78086648
Batch Update Rem...206321112024-08-29 5:19:2320 hrs ago1724908763IN
0x722669cb...6627E90be
0 ETH0.00003390.78086648
Batch Update Rem...206318162024-08-29 4:19:4721 hrs ago1724905187IN
0x722669cb...6627E90be
0 ETH0.000033830.77921293
Batch Update Rem...206318142024-08-29 4:19:2321 hrs ago1724905163IN
0x722669cb...6627E90be
0 ETH0.000036690.84460849
Batch Update Rem...206318132024-08-29 4:19:1121 hrs ago1724905151IN
0x722669cb...6627E90be
0 ETH0.000037790.87032183
Batch Update Rem...206315182024-08-29 3:19:2322 hrs ago1724901563IN
0x722669cb...6627E90be
0 ETH0.000033260.76592774
View all transactions

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
197908832024-05-03 16:49:11118 days ago1714754951  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
PaymentHelper

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
File 1 of 14 : PaymentHelper.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;

import { IPaymentHelperV2 as IPaymentHelper } from "src/interfaces/IPaymentHelperV2.sol";
import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol";
import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol";
import { ISuperformFactory } from "src/interfaces/ISuperformFactory.sol";
import { IBaseStateRegistry } from "src/interfaces/IBaseStateRegistry.sol";
import { IAmbImplementation } from "src/interfaces/IAmbImplementation.sol";
import { Error } from "src/libraries/Error.sol";
import { DataLib } from "src/libraries/DataLib.sol";
import { ProofLib } from "src/libraries/ProofLib.sol";
import { ArrayCastLib } from "src/libraries/ArrayCastLib.sol";
import {
    SingleDirectSingleVaultStateReq,
    SingleXChainSingleVaultStateReq,
    SingleDirectMultiVaultStateReq,
    SingleXChainMultiVaultStateReq,
    MultiDstSingleVaultStateReq,
    MultiDstMultiVaultStateReq,
    LiqRequest,
    AMBMessage,
    MultiVaultSFData,
    SingleVaultSFData,
    AMBExtraData,
    InitMultiVaultData,
    InitSingleVaultData,
    ReturnMultiData,
    ReturnSingleData
} from "src/types/DataTypes.sol";
import { AggregatorV3Interface } from "src/vendor/chainlink/AggregatorV3Interface.sol";

/// @dev interface to read public variable from state registry
interface ReadOnlyBaseRegistry is IBaseStateRegistry {
    function payloadsCount() external view returns (uint256);
}

/// @title PaymentHelper
/// @dev Helps estimate the cost for the entire transaction lifecycle
/// @author ZeroPoint Labs
contract PaymentHelper is IPaymentHelper {
    using DataLib for uint256;
    using ArrayCastLib for LiqRequest;
    using ArrayCastLib for bool;
    using ProofLib for bytes;
    using ProofLib for AMBMessage;

    //////////////////////////////////////////////////////////////
    //                         CONSTANTS                        //
    //////////////////////////////////////////////////////////////

    uint256 private constant PROOF_LENGTH = 160;
    uint8 private constant SUPPORTED_FEED_PRECISION = 8;
    uint32 private constant TIMELOCK_FORM_ID = 2;
    uint256 private constant MAX_UINT256 = type(uint256).max;

    ISuperRegistry public immutable superRegistry;
    uint64 public immutable CHAIN_ID;

    //////////////////////////////////////////////////////////////
    //                     STATE VARIABLES                      //
    //////////////////////////////////////////////////////////////

    /// @dev xchain params
    mapping(uint64 chainId => AggregatorV3Interface) public nativeFeedOracle;
    mapping(uint64 chainId => AggregatorV3Interface) public gasPriceOracle;
    mapping(uint64 chainId => uint256 gasForSwap) public swapGasUsed;
    mapping(uint64 chainId => uint256 gasForUpdateDeposit) public updateDepositGasUsed;
    mapping(uint64 chainId => uint256 gasForUpdateWithdraw) public updateWithdrawGasUsed;
    mapping(uint64 chainId => uint256 gasForDeposit) public depositGasUsed;
    mapping(uint64 chainId => uint256 gasForWithdraw) public withdrawGasUsed;
    mapping(uint64 chainId => uint256 defaultNativePrice) public nativePrice;
    mapping(uint64 chainId => uint256 defaultGasPrice) public gasPrice;
    mapping(uint64 chainId => uint256 gasPerByte) public gasPerByte;
    mapping(uint64 chainId => uint256 gasForAck) public ackGasCost;
    mapping(uint64 chainId => uint256 gasForTimelock) public timelockCost;
    mapping(uint64 chainId => uint256 gasForEmergency) public emergencyCost;

    /// @dev register transmuter params
    bytes public extraDataForTransmuter;

    //////////////////////////////////////////////////////////////
    //                           STRUCTS                        //
    //////////////////////////////////////////////////////////////

    struct EstimateAckCostVars {
        uint256 currPayloadId;
        uint256 payloadHeader;
        uint8 callbackType;
        bytes payloadBody;
        uint8[] ackAmbIds;
        uint8 isMulti;
        uint64 srcChainId;
        bytes message;
    }

    struct LocalEstimateVars {
        uint256 len;
        uint256 superformIdsLen;
        uint256 totalGas;
        uint256 ambFees;
        bool paused;
    }

    struct CalculateAmountsReq {
        uint256 i;
        uint64[] dstChainIds;
        uint8[] ambIds;
        MultiVaultSFData[] superformsData;
        SingleVaultSFData[] superformData;
        ISuperformFactory factory;
        bool isDeposit;
    }

    //////////////////////////////////////////////////////////////
    //                       MODIFIERS                          //
    //////////////////////////////////////////////////////////////

    modifier onlyProtocolAdmin() {
        if (!ISuperRBAC(_getAddress(keccak256("SUPER_RBAC"))).hasProtocolAdminRole(msg.sender)) {
            revert Error.NOT_PROTOCOL_ADMIN();
        }
        _;
    }

    modifier onlyPaymentAdmin() {
        if (
            !ISuperRBAC(superRegistry.getAddress(keccak256("SUPER_RBAC"))).hasRole(
                keccak256("PAYMENT_ADMIN_ROLE"), msg.sender
            )
        ) {
            revert Error.NOT_PAYMENT_ADMIN();
        }
        _;
    }

    //////////////////////////////////////////////////////////////
    //                      CONSTRUCTOR                         //
    //////////////////////////////////////////////////////////////

    constructor(address superRegistry_) {
        if (superRegistry_ == address(0)) {
            revert Error.ZERO_ADDRESS();
        }

        if (block.chainid > type(uint64).max) {
            revert Error.BLOCK_CHAIN_ID_OUT_OF_BOUNDS();
        }

        CHAIN_ID = uint64(block.chainid);
        superRegistry = ISuperRegistry(superRegistry_);
    }

    //////////////////////////////////////////////////////////////
    //              EXTERNAL VIEW FUNCTIONS                     //
    //////////////////////////////////////////////////////////////

    /// @inheritdoc IPaymentHelper
    function calculateAMBData(
        uint64 dstChainId_,
        uint8[] calldata ambIds_,
        bytes memory message_
    )
        external
        view
        override
        returns (uint256 totalFees, bytes memory extraData)
    {
        (uint256[] memory gasPerAMB, bytes[] memory extraDataPerAMB, uint256 fees) =
            _estimateAMBFeesReturnExtraData(dstChainId_, ambIds_, message_);

        extraData = abi.encode(AMBExtraData(gasPerAMB, extraDataPerAMB));
        totalFees = fees;
    }

    /// @inheritdoc IPaymentHelper
    function getRegisterTransmuterAMBData() external view override returns (bytes memory) {
        return extraDataForTransmuter;
    }

    /// @inheritdoc IPaymentHelper
    function estimateMultiDstMultiVault(
        MultiDstMultiVaultStateReq calldata req_,
        bool isDeposit_
    )
        external
        view
        override
        returns (uint256 liqAmount, uint256 srcAmount, uint256 dstAmount, uint256 totalAmount)
    {
        uint256 len = req_.dstChainIds.length;
        uint256 liqAmountIndex;
        uint256 srcAmountIndex;
        uint256 dstAmountIndex;

        ISuperformFactory factory = ISuperformFactory(_getAddress(keccak256("SUPERFORM_FACTORY")));
        SingleVaultSFData[] memory temp;

        for (uint256 i; i < len; ++i) {
            (liqAmountIndex, srcAmountIndex, dstAmountIndex) = _calculateAmounts(
                CalculateAmountsReq(i, req_.dstChainIds, req_.ambIds[i], req_.superformsData, temp, factory, isDeposit_)
            );
            liqAmount += liqAmountIndex;
            srcAmount += srcAmountIndex;
            dstAmount += dstAmountIndex;
        }

        totalAmount = srcAmount + dstAmount + liqAmount;
    }

    /// @inheritdoc IPaymentHelper
    function estimateMultiDstSingleVault(
        MultiDstSingleVaultStateReq calldata req_,
        bool isDeposit_
    )
        external
        view
        override
        returns (uint256 liqAmount, uint256 srcAmount, uint256 dstAmount, uint256 totalAmount)
    {
        uint256 len = req_.dstChainIds.length;
        uint256 liqAmountIndex;
        uint256 srcAmountIndex;
        uint256 dstAmountIndex;
        ISuperformFactory factory = ISuperformFactory(_getAddress(keccak256("SUPERFORM_FACTORY")));
        MultiVaultSFData[] memory temp;
        for (uint256 i; i < len; ++i) {
            (liqAmountIndex, srcAmountIndex, dstAmountIndex) = _calculateAmounts(
                CalculateAmountsReq(i, req_.dstChainIds, req_.ambIds[i], temp, req_.superformsData, factory, isDeposit_)
            );
            liqAmount += liqAmountIndex;
            srcAmount += srcAmountIndex;
            dstAmount += dstAmountIndex;
        }

        totalAmount = srcAmount + dstAmount + liqAmount;
    }

    /// @inheritdoc IPaymentHelper
    function estimateSingleXChainMultiVault(
        SingleXChainMultiVaultStateReq calldata req_,
        bool isDeposit_
    )
        external
        view
        override
        returns (uint256 liqAmount, uint256 srcAmount, uint256 dstAmount, uint256 totalAmount)
    {
        ISuperformFactory factory = ISuperformFactory(_getAddress(keccak256("SUPERFORM_FACTORY")));

        uint64[] memory dstChainIds = new uint64[](1);
        dstChainIds[0] = req_.dstChainId;

        SingleVaultSFData[] memory temp;

        MultiVaultSFData[] memory sfData = new MultiVaultSFData[](1);
        sfData[0] = req_.superformsData;

        (liqAmount, srcAmount, dstAmount) =
            _calculateAmounts(CalculateAmountsReq(0, dstChainIds, req_.ambIds, sfData, temp, factory, isDeposit_));

        totalAmount = srcAmount + dstAmount + liqAmount;
    }

    /// @inheritdoc IPaymentHelper
    function estimateSingleXChainSingleVault(
        SingleXChainSingleVaultStateReq calldata req_,
        bool isDeposit_
    )
        external
        view
        override
        returns (uint256 liqAmount, uint256 srcAmount, uint256 dstAmount, uint256 totalAmount)
    {
        ISuperformFactory factory = ISuperformFactory(_getAddress(keccak256("SUPERFORM_FACTORY")));

        uint64[] memory dstChainIds = new uint64[](1);
        dstChainIds[0] = req_.dstChainId;

        MultiVaultSFData[] memory temp;

        SingleVaultSFData[] memory sfData = new SingleVaultSFData[](1);
        sfData[0] = req_.superformData;

        (liqAmount, srcAmount, dstAmount) =
            _calculateAmounts(CalculateAmountsReq(0, dstChainIds, req_.ambIds, temp, sfData, factory, isDeposit_));

        totalAmount = srcAmount + dstAmount + liqAmount;
    }

    /// @inheritdoc IPaymentHelper
    function estimateSingleDirectSingleVault(
        SingleDirectSingleVaultStateReq calldata req_,
        bool isDeposit_
    )
        external
        view
        override
        returns (uint256 liqAmount, uint256 dstOrSameChainAmt, uint256 totalAmount)
    {
        ISuperformFactory factory = ISuperformFactory(_getAddress(keccak256("SUPERFORM_FACTORY")));

        uint64[] memory dstChainIds = new uint64[](1);
        dstChainIds[0] = CHAIN_ID;

        SingleVaultSFData[] memory sfData = new SingleVaultSFData[](1);
        sfData[0] = req_.superformData;

        MultiVaultSFData[] memory temp;

        uint8[] memory ambIds;

        (liqAmount,, dstOrSameChainAmt) =
            _calculateAmounts(CalculateAmountsReq(0, dstChainIds, ambIds, temp, sfData, factory, isDeposit_));

        totalAmount = liqAmount + dstOrSameChainAmt;
    }

    /// @inheritdoc IPaymentHelper
    function estimateSingleDirectMultiVault(
        SingleDirectMultiVaultStateReq calldata req_,
        bool isDeposit_
    )
        external
        view
        override
        returns (uint256 liqAmount, uint256 dstOrSameChainAmt, uint256 totalAmount)
    {
        ISuperformFactory factory = ISuperformFactory(_getAddress(keccak256("SUPERFORM_FACTORY")));

        uint64[] memory dstChainIds = new uint64[](1);
        dstChainIds[0] = CHAIN_ID;

        SingleVaultSFData[] memory temp;

        MultiVaultSFData[] memory sfData = new MultiVaultSFData[](1);
        sfData[0] = req_.superformData;

        uint8[] memory ambIds;

        (liqAmount,, dstOrSameChainAmt) =
            _calculateAmounts(CalculateAmountsReq(0, dstChainIds, ambIds, sfData, temp, factory, isDeposit_));

        totalAmount = liqAmount + dstOrSameChainAmt;
    }

    /// @inheritdoc IPaymentHelper
    function estimateAMBFees(
        uint8[] memory ambIds_,
        uint64 dstChainId_,
        bytes memory message_,
        bytes[] memory extraData_
    )
        public
        view
        override
        returns (uint256 totalFees, uint256[] memory)
    {
        uint256 len = ambIds_.length;
        uint256[] memory fees = new uint256[](len);

        /// @dev just checks the estimate for sending message from src -> dst
        if (CHAIN_ID != dstChainId_) {
            for (uint256 i; i < len; ++i) {
                fees[i] = IAmbImplementation(superRegistry.getAmbAddress(ambIds_[i])).estimateFees(
                    dstChainId_, message_, extraData_[i]
                );

                totalFees += fees[i];
            }
        }

        return (totalFees, fees);
    }

    /// @inheritdoc IPaymentHelper
    function estimateAckCost(uint256 payloadId_) external view override returns (uint256 totalFees) {
        EstimateAckCostVars memory v;
        IBaseStateRegistry coreStateRegistry = IBaseStateRegistry(_getAddress(keccak256("CORE_STATE_REGISTRY")));
        v.currPayloadId = coreStateRegistry.payloadsCount();

        if (payloadId_ > v.currPayloadId) revert Error.INVALID_PAYLOAD_ID();

        v.payloadHeader = coreStateRegistry.payloadHeader(payloadId_);
        v.payloadBody = coreStateRegistry.payloadBody(payloadId_);

        (, v.callbackType, v.isMulti,,, v.srcChainId) = DataLib.decodeTxInfo(v.payloadHeader);

        /// if callback type is return then return 0
        if (v.callbackType != 0) return 0;

        if (v.isMulti == 1) {
            InitMultiVaultData memory data = abi.decode(v.payloadBody, (InitMultiVaultData));
            v.payloadBody = abi.encode(ReturnMultiData(v.currPayloadId, data.superformIds, data.amounts));
        } else {
            InitSingleVaultData memory data = abi.decode(v.payloadBody, (InitSingleVaultData));
            v.payloadBody = abi.encode(ReturnSingleData(v.currPayloadId, data.superformId, data.amount));
        }

        v.ackAmbIds = coreStateRegistry.getMessageAMB(payloadId_);

        v.message = abi.encode(AMBMessage(coreStateRegistry.payloadHeader(payloadId_), v.payloadBody));

        return _estimateAMBFees(v.ackAmbIds, v.srcChainId, v.message);
    }

    /// @inheritdoc IPaymentHelper
    function estimateAckCostDefault(
        bool multi,
        uint8[] memory ackAmbIds,
        uint64 srcChainId
    )
        public
        view
        override
        returns (uint256 totalFees)
    {
        bytes memory payloadBody;
        if (multi) {
            uint256 vaultLimitPerDst = superRegistry.getVaultLimitPerDestination(srcChainId);
            uint256[] memory maxUints = new uint256[](vaultLimitPerDst);

            for (uint256 i; i < vaultLimitPerDst; ++i) {
                maxUints[i] = type(uint256).max;
            }
            payloadBody = abi.encode(ReturnMultiData(type(uint256).max, maxUints, maxUints));
        } else {
            payloadBody = abi.encode(ReturnSingleData(type(uint256).max, type(uint256).max, type(uint256).max));
        }

        return _estimateAMBFees(ackAmbIds, srcChainId, abi.encode(AMBMessage(type(uint256).max, payloadBody)));
    }

    /// @inheritdoc IPaymentHelper
    function estimateAckCostDefaultNativeSource(
        bool multi,
        uint8[] memory ackAmbIds,
        uint64 srcChainId
    )
        external
        view
        override
        returns (uint256)
    {
        return _convertToSrcNativeAmount(srcChainId, estimateAckCostDefault(multi, ackAmbIds, srcChainId));
    }

    //////////////////////////////////////////////////////////////
    //              EXTERNAL WRITE FUNCTIONS                    //
    //////////////////////////////////////////////////////////////

    /// @inheritdoc IPaymentHelper
    function addRemoteChain(uint64 chainId_, PaymentHelperConfig calldata config_) public override onlyProtocolAdmin {
        _addRemoteChain(chainId_, config_);
    }

    /// @inheritdoc IPaymentHelper
    function addRemoteChains(
        uint64[] calldata chainIds_,
        PaymentHelperConfig[] calldata configs_
    )
        external
        override
        onlyProtocolAdmin
    {
        uint256 len = chainIds_.length;

        if (len == 0) revert Error.ZERO_INPUT_VALUE();

        if (len != configs_.length) revert Error.ARRAY_LENGTH_MISMATCH();

        for (uint256 i; i < len; ++i) {
            _addRemoteChain(chainIds_[i], configs_[i]);
        }
    }

    /// @inheritdoc IPaymentHelper
    function updateRemoteChain(
        uint64 chainId_,
        uint256 configType_,
        bytes memory config_
    )
        external
        override
        onlyPaymentAdmin
    {
        _updateRemoteChain(chainId_, configType_, config_);
    }

    /// @inheritdoc IPaymentHelper
    function batchUpdateRemoteChain(
        uint64 chainId_,
        uint256[] calldata configTypes_,
        bytes[] calldata configs_
    )
        external
        override
        onlyPaymentAdmin
    {
        _batchUpdateRemoteChain(chainId_, configTypes_, configs_);
    }

    /// @inheritdoc IPaymentHelper
    function batchUpdateRemoteChains(
        uint64[] calldata chainIds_,
        uint256[][] calldata configTypes_,
        bytes[][] calldata configs_
    )
        external
        override
        onlyPaymentAdmin
    {
        uint256 len = chainIds_.length;

        if (len == 0) revert Error.ZERO_INPUT_VALUE();

        if (!(len == configTypes_.length && len == configs_.length)) revert Error.ARRAY_LENGTH_MISMATCH();

        for (uint256 i; i < len; ++i) {
            _batchUpdateRemoteChain(chainIds_[i], configTypes_[i], configs_[i]);
        }
    }

    /// @inheritdoc IPaymentHelper
    function updateRegisterAERC20Params(bytes memory extraDataForTransmuter_) external onlyPaymentAdmin {
        extraDataForTransmuter = extraDataForTransmuter_;
    }

    //////////////////////////////////////////////////////////////
    //                  INTERNAL FUNCTIONS                      //
    //////////////////////////////////////////////////////////////

    function _getOracleDecimals(AggregatorV3Interface oracle_) internal view returns (uint8) {
        return oracle_.decimals();
    }

    /// @dev PROTOCOL_ADMIN can perform the configuration of a remote chain for the first time
    function _addRemoteChain(uint64 chainId_, PaymentHelperConfig calldata config_) internal {
        if (config_.nativeFeedOracle != address(0)) {
            AggregatorV3Interface nativeFeedOracleContract = AggregatorV3Interface(config_.nativeFeedOracle);
            if (_getOracleDecimals(nativeFeedOracleContract) != SUPPORTED_FEED_PRECISION) {
                revert Error.CHAINLINK_UNSUPPORTED_DECIMAL();
            }

            nativeFeedOracle[chainId_] = nativeFeedOracleContract;
        }

        if (config_.gasPriceOracle != address(0)) {
            AggregatorV3Interface gasPriceOracleContract = AggregatorV3Interface(config_.gasPriceOracle);
            if (_getOracleDecimals(gasPriceOracleContract) != SUPPORTED_FEED_PRECISION) {
                revert Error.CHAINLINK_UNSUPPORTED_DECIMAL();
            }

            gasPriceOracle[chainId_] = gasPriceOracleContract;
        }

        swapGasUsed[chainId_] = config_.swapGasUsed;
        updateDepositGasUsed[chainId_] = config_.updateDepositGasUsed;
        depositGasUsed[chainId_] = config_.depositGasUsed;
        withdrawGasUsed[chainId_] = config_.withdrawGasUsed;
        nativePrice[chainId_] = config_.defaultNativePrice;
        gasPrice[chainId_] = config_.defaultGasPrice;
        gasPerByte[chainId_] = config_.dstGasPerByte;
        ackGasCost[chainId_] = config_.ackGasCost;
        timelockCost[chainId_] = config_.timelockCost;
        emergencyCost[chainId_] = config_.emergencyCost;
        updateWithdrawGasUsed[chainId_] = config_.updateWithdrawGasUsed;

        emit ChainConfigAdded(chainId_, config_);
    }

    /// @dev PAYMENT_ADMIN can update the configuration of a remote chain on a need basis
    function _updateRemoteChain(uint64 chainId_, uint256 configType_, bytes memory config_) internal {
        /// @dev Type 1: DST TOKEN PRICE FEED ORACLE
        if (configType_ == 1) {
            AggregatorV3Interface nativeFeedOracleContract = AggregatorV3Interface(abi.decode(config_, (address)));

            /// @dev allows setting price feed to address(0), equivalent for resetting native price
            if (
                address(nativeFeedOracleContract) != address(0)
                    && _getOracleDecimals(nativeFeedOracleContract) != SUPPORTED_FEED_PRECISION
            ) {
                revert Error.CHAINLINK_UNSUPPORTED_DECIMAL();
            }

            nativeFeedOracle[chainId_] = nativeFeedOracleContract;
        }

        /// @dev Type 2: DST GAS PRICE ORACLE
        if (configType_ == 2) {
            AggregatorV3Interface gasPriceOracleContract = AggregatorV3Interface(abi.decode(config_, (address)));

            /// @dev allows setting gas price to address(0), equivalent for resetting gas price
            if (
                address(gasPriceOracleContract) != address(0)
                    && _getOracleDecimals(gasPriceOracleContract) != SUPPORTED_FEED_PRECISION
            ) {
                revert Error.CHAINLINK_UNSUPPORTED_DECIMAL();
            }

            gasPriceOracle[chainId_] = gasPriceOracleContract;
        }

        /// @dev Type 3: SWAP GAS USED
        if (configType_ == 3) {
            swapGasUsed[chainId_] = abi.decode(config_, (uint256));
        }

        /// @dev Type 4: PAYLOAD UPDATE DEPOSIT GAS COST PER TX
        if (configType_ == 4) {
            updateDepositGasUsed[chainId_] = abi.decode(config_, (uint256));
        }

        /// @dev Type 5: DEPOSIT GAS COST PER TX
        if (configType_ == 5) {
            depositGasUsed[chainId_] = abi.decode(config_, (uint256));
        }

        /// @dev Type 6: WITHDRAW GAS COST PER TX
        if (configType_ == 6) {
            withdrawGasUsed[chainId_] = abi.decode(config_, (uint256));
        }

        /// @dev Type 7: DEFAULT NATIVE PRICE
        if (configType_ == 7) {
            nativePrice[chainId_] = abi.decode(config_, (uint256));
        }

        /// @dev Type 8: DEFAULT GAS PRICE
        if (configType_ == 8) {
            gasPrice[chainId_] = abi.decode(config_, (uint256));
        }

        /// @dev Type 9: GAS PRICE PER Byte of Message
        if (configType_ == 9) {
            gasPerByte[chainId_] = abi.decode(config_, (uint256));
        }

        /// @dev Type 10: ACK GAS COST
        if (configType_ == 10) {
            ackGasCost[chainId_] = abi.decode(config_, (uint256));
        }

        /// @dev Type 11: TIMELOCK PROCESSING COST
        if (configType_ == 11) {
            timelockCost[chainId_] = abi.decode(config_, (uint256));
        }

        /// @dev Type 12: EMERGENCY PROCESSING COST
        if (configType_ == 12) {
            emergencyCost[chainId_] = abi.decode(config_, (uint256));
        }

        /// @dev Type 13: PAYLOAD UPDATE WITHDRAW GAS COST PER TX
        if (configType_ == 13) {
            updateWithdrawGasUsed[chainId_] = abi.decode(config_, (uint256));
        }

        emit ChainConfigUpdated(chainId_, configType_, config_);
    }

    /// @dev batch updates the configuration of a remote chain. Performed by PAYMENT_ADMIN
    function _batchUpdateRemoteChain(
        uint64 chainId_,
        uint256[] calldata configTypes_,
        bytes[] calldata configs_
    )
        internal
    {
        uint256 len = configTypes_.length;

        if (len == 0) revert Error.ZERO_INPUT_VALUE();

        if (len != configs_.length) revert Error.ARRAY_LENGTH_MISMATCH();

        for (uint256 i; i < len; ++i) {
            _updateRemoteChain(chainId_, configTypes_[i], configs_[i]);
        }
    }

    /// @dev helps generate extra data per amb
    function _generateExtraData(
        uint64 dstChainId_,
        uint8[] memory ambIds_,
        bytes memory message_
    )
        internal
        view
        returns (bytes[] memory extraDataPerAMB)
    {
        AMBMessage memory ambIdEncodedMessage = abi.decode(message_, (AMBMessage));
        ambIdEncodedMessage.params = abi.encode(ambIds_, ambIdEncodedMessage.params);

        uint256 len = ambIds_.length;
        uint256 gasReqPerByte = gasPerByte[dstChainId_];
        uint256 totalDstGasReqInWei = abi.encode(ambIdEncodedMessage).length * gasReqPerByte;

        /// @dev proof length is always of fixed length
        uint256 totalDstGasReqInWeiForProof = PROOF_LENGTH * gasReqPerByte;

        extraDataPerAMB = new bytes[](len);

        for (uint256 i; i < len; ++i) {
            uint256 gasReq = i != 0 ? totalDstGasReqInWeiForProof : totalDstGasReqInWei;
            extraDataPerAMB[i] = IAmbImplementation(superRegistry.getAmbAddress(ambIds_[i])).generateExtraData(gasReq);
        }
    }

    /// @dev helps estimate the cross-chain message costs
    function _estimateAMBFees(
        uint8[] memory ambIds_,
        uint64 dstChainId_,
        bytes memory message_
    )
        internal
        view
        returns (uint256 totalFees)
    {
        uint256 len = ambIds_.length;

        bytes[] memory extraDataPerAMB = _generateExtraData(dstChainId_, ambIds_, message_);

        AMBMessage memory ambIdEncodedMessage = abi.decode(message_, (AMBMessage));
        ambIdEncodedMessage.params = abi.encode(ambIds_, ambIdEncodedMessage.params);

        bytes memory proof_ = abi.encode(AMBMessage(MAX_UINT256, abi.encode(keccak256(message_))));

        /// @dev just checks the estimate for sending message from src -> dst
        /// @dev only ambIds_[0] = primary amb (rest of the ambs send only the proof)
        if (CHAIN_ID != dstChainId_) {
            for (uint256 i; i < len; ++i) {
                uint256 tempFee = IAmbImplementation(superRegistry.getAmbAddress(ambIds_[i])).estimateFees(
                    dstChainId_, i != 0 ? proof_ : abi.encode(ambIdEncodedMessage), extraDataPerAMB[i]
                );

                totalFees += tempFee;
            }
        }
    }

    /// @dev helps estimate the cross-chain message costs
    function _estimateAMBFeesReturnExtraData(
        uint64 dstChainId_,
        uint8[] calldata ambIds_,
        bytes memory message_
    )
        internal
        view
        returns (uint256[] memory feeSplitUp, bytes[] memory extraDataPerAMB, uint256 totalFees)
    {
        AMBMessage memory ambIdEncodedMessage = abi.decode(message_, (AMBMessage));
        ambIdEncodedMessage.params = abi.encode(ambIds_, ambIdEncodedMessage.params);

        uint256 len = ambIds_.length;

        extraDataPerAMB = _generateExtraData(dstChainId_, ambIds_, message_);

        feeSplitUp = new uint256[](len);

        bytes memory proof_ = abi.encode(AMBMessage(MAX_UINT256, abi.encode(keccak256(message_))));

        /// @dev just checks the estimate for sending message from src -> dst
        if (CHAIN_ID != dstChainId_) {
            for (uint256 i; i < len; ++i) {
                uint256 tempFee = IAmbImplementation(superRegistry.getAmbAddress(ambIds_[i])).estimateFees(
                    dstChainId_, i != 0 ? proof_ : abi.encode(ambIdEncodedMessage), extraDataPerAMB[i]
                );

                totalFees += tempFee;
                feeSplitUp[i] = tempFee;
            }
        }
    }

    /// @dev helps estimate the liq amount involved in the tx
    function _estimateLiqAmount(LiqRequest[] memory req_) internal pure returns (uint256 liqAmount) {
        uint256 len = req_.length;
        for (uint256 i; i < len; ++i) {
            liqAmount += req_[i].nativeAmount;
        }
    }

    /// @dev helps estimate the dst chain swap gas limit (if multi-tx is involved)
    function _estimateSwapFees(
        uint64 dstChainId_,
        bool[] memory hasDstSwaps_
    )
        internal
        view
        returns (uint256 gasUsed)
    {
        uint256 totalSwaps;

        if (CHAIN_ID == dstChainId_) {
            return 0;
        }

        uint256 len = hasDstSwaps_.length;
        for (uint256 i; i < len; ++i) {
            /// @dev checks if hasDstSwap is true
            if (hasDstSwaps_[i]) {
                ++totalSwaps;
            }
        }

        if (totalSwaps == 0) {
            return 0;
        }

        return totalSwaps * swapGasUsed[dstChainId_];
    }

    /// @dev helps estimate the dst chain update payload gas limit
    function _estimateUpdateDepositCost(
        uint64 dstChainId_,
        uint256 vaultsCount_
    )
        internal
        view
        returns (uint256 gasUsed)
    {
        return vaultsCount_ * updateDepositGasUsed[dstChainId_];
    }

    /// @dev helps estimate the dst chain update payload gas limit
    function _estimateUpdateWithdrawCost(
        uint64 dstChainId_,
        LiqRequest[] memory liqRequests_
    )
        internal
        view
        returns (uint256 gasUsed)
    {
        uint256 len = liqRequests_.length;
        for (uint256 i; i < len; i++) {
            /// @dev liqRequests[i].token on withdraws is the desired token
            /// @dev if token is address(0) -> user wants settlement without any liq data
            /// @dev this means that if no txData is present and token is different than address(0) an update is
            /// required in destination
            if (liqRequests_[i].txData.length == 0 && liqRequests_[i].token != address(0)) {
                gasUsed += updateWithdrawGasUsed[dstChainId_];
            }
        }
    }

    /// @dev helps estimate the dst chain processing cost including the dst->src message cost
    /// @dev assumes that withdrawals optimisically succeed
    function _estimateDstExecutionCost(
        bool isDeposit_,
        uint64 dstChainId_,
        uint256 vaultsCount_
    )
        internal
        view
        returns (uint256 gasUsed)
    {
        uint256 executionGasPerVault = isDeposit_ ? depositGasUsed[dstChainId_] : withdrawGasUsed[dstChainId_];
        gasUsed = executionGasPerVault * vaultsCount_;
    }

    /// @dev helps estimate the src chain processing fee
    function _estimateAckProcessingCost(uint256 vaultsCount_) internal view returns (uint256 nativeFee) {
        uint256 gasCost = vaultsCount_ * ackGasCost[CHAIN_ID];

        return gasCost * _getGasPrice(CHAIN_ID);
    }

    /// @dev generates the amb message for single vault data
    function _generateSingleVaultMessage(SingleVaultSFData memory sfData_)
        internal
        view
        returns (bytes memory message_)
    {
        bytes memory ambData = abi.encode(
            InitSingleVaultData(
                _getNextPayloadId(),
                sfData_.superformId,
                sfData_.amount,
                sfData_.outputAmount,
                sfData_.maxSlippage,
                sfData_.liqRequest,
                sfData_.hasDstSwap,
                sfData_.retain4626,
                sfData_.receiverAddress,
                sfData_.extraFormData
            )
        );
        message_ = abi.encode(AMBMessage(MAX_UINT256, ambData));
    }

    /// @dev generates the amb message for multi vault data
    function _generateMultiVaultMessage(MultiVaultSFData memory sfData_)
        internal
        view
        returns (bytes memory message_)
    {
        bytes memory ambData = abi.encode(
            InitMultiVaultData(
                _getNextPayloadId(),
                sfData_.superformIds,
                sfData_.amounts,
                sfData_.outputAmounts,
                sfData_.maxSlippages,
                sfData_.liqRequests,
                sfData_.hasDstSwaps,
                sfData_.retain4626s,
                sfData_.receiverAddress,
                sfData_.extraFormData
            )
        );
        message_ = abi.encode(AMBMessage(MAX_UINT256, ambData));
    }

    /// @dev helps convert the dst gas fee into src chain native fee
    /// @dev https://docs.soliditylang.org/en/v0.8.4/units-and-global-variables.html#ether-units
    /// @dev all native tokens should be 18 decimals across all EVMs
    function _convertToNativeFee(
        uint64 dstChainId_,
        uint256 dstGas_,
        bool xChain_
    )
        internal
        view
        returns (uint256 nativeFee)
    {
        /// @dev gas fee * gas price (to get the gas amounts in dst chain's native token)
        /// @dev gas price is 9 decimal (in gwei)
        /// @dev assumption: all evm native tokens are 18 decimals
        uint256 dstNativeFee = dstGas_ * _getGasPrice(dstChainId_);

        if (dstNativeFee == 0) {
            return 0;
        }
        if (!xChain_) {
            return dstNativeFee;
        }

        /// @dev converts the gas to pay in terms of native token to usd value
        /// @dev native token price is 8 decimal
        uint256 dstUsdValue = dstNativeFee * _getNativeTokenPrice(dstChainId_); // native token price - 8 decimal

        if (dstUsdValue == 0) {
            return 0;
        }

        /// @dev converts the usd value to source chain's native token
        /// @dev native token price is 8 decimal which cancels the 8 decimal multiplied in previous step
        uint256 nativeTokenPrice = _getNativeTokenPrice(CHAIN_ID); // native token price - 8 decimal
        if (nativeTokenPrice == 0) revert Error.INVALID_NATIVE_TOKEN_PRICE();
        nativeFee = (dstUsdValue) / nativeTokenPrice;
    }

    /// @dev helps convert a native token of one chain to another
    /// @dev https://docs.soliditylang.org/en/v0.8.4/units-and-global-variables.html#ether-units
    /// @dev all native tokens should be 18 decimals across all EVMs
    function _convertToSrcNativeAmount(
        uint64 srcChainId_,
        uint256 dstAmount_
    )
        internal
        view
        returns (uint256 nativeFee)
    {
        if (dstAmount_ == 0) {
            return 0;
        }

        /// @dev converts the native token value to usd value
        /// @dev dstAmount_ is 18 decimal
        /// @dev native token price is 8 decimal
        uint256 dstUsdValue = dstAmount_ * _getNativeTokenPrice(CHAIN_ID);

        if (dstUsdValue == 0) {
            return 0;
        }

        /// @dev converts the usd value to source chain's native token
        /// @dev native token price is 8 decimal which cancels the 8 decimal multiplied in previous step
        uint256 nativeTokenPrice = _getNativeTokenPrice(srcChainId_);
        if (nativeTokenPrice == 0) revert Error.INVALID_NATIVE_TOKEN_PRICE();

        nativeFee = dstUsdValue / nativeTokenPrice;
    }

    /// @dev helps generate the new payload id
    /// @dev next payload id = current payload id + 1
    function _getNextPayloadId() internal view returns (uint256 nextPayloadId) {
        nextPayloadId = ReadOnlyBaseRegistry(_getAddress(keccak256("CORE_STATE_REGISTRY"))).payloadsCount();
        ++nextPayloadId;
    }

    /// @dev helps return the current gas price of different networks
    /// @return native token price
    function _getGasPrice(uint64 chainId_) internal view returns (uint256) {
        address oracleAddr = address(gasPriceOracle[chainId_]);
        if (oracleAddr != address(0)) {
            try AggregatorV3Interface(oracleAddr).latestRoundData() returns (
                uint80, int256 value, uint256, uint256 updatedAt, uint80
            ) {
                if (value <= 0) revert Error.CHAINLINK_MALFUNCTION();
                if (updatedAt == 0) revert Error.CHAINLINK_INCOMPLETE_ROUND();
                return uint256(value);
            } catch {
                /// @dev do nothing and return the default price at the end of the function
            }
        }

        return gasPrice[chainId_];
    }

    /// @dev helps return the dst chain token price of different networks
    /// @return native token price
    function _getNativeTokenPrice(uint64 chainId_) internal view returns (uint256) {
        address oracleAddr = address(nativeFeedOracle[chainId_]);
        if (oracleAddr != address(0)) {
            try AggregatorV3Interface(oracleAddr).latestRoundData() returns (
                uint80, int256 dstTokenPrice, uint256, uint256 updatedAt, uint80
            ) {
                if (dstTokenPrice <= 0) revert Error.CHAINLINK_MALFUNCTION();
                if (updatedAt == 0) revert Error.CHAINLINK_INCOMPLETE_ROUND();
                return uint256(dstTokenPrice);
            } catch {
                /// @dev do nothing and return the default price at the end of the function
            }
        }

        return nativePrice[chainId_];
    }

    /// @dev returns the address from super registry
    function _getAddress(bytes32 id_) internal view returns (address) {
        return superRegistry.getAddress(id_);
    }

    /// @dev calculates different cost amounts involved in the tx
    function _calculateAmounts(CalculateAmountsReq memory req_)
        internal
        view
        returns (uint256 liqAmount, uint256 srcAmount, uint256 dstOrSameChainAmt)
    {
        LocalEstimateVars memory v;

        bool xChain = req_.dstChainIds[req_.i] != CHAIN_ID;

        /// @dev in xChain this is gas on the destination chain and in !xChain this is gas on the same chain
        v.totalGas = 0;

        bool multiVaults = req_.superformsData.length > 0;
        bytes memory message = multiVaults
            ? _generateMultiVaultMessage(req_.superformsData[req_.i])
            : _generateSingleVaultMessage(req_.superformData[req_.i]);

        /// @dev step 1: estimate amb costs
        v.ambFees = xChain ? _estimateAMBFees(req_.ambIds, req_.dstChainIds[req_.i], message) : 0;

        v.superformIdsLen = multiVaults ? req_.superformsData[req_.i].superformIds.length : 1;

        srcAmount += v.ambFees;
        LiqRequest[] memory liqRequests = multiVaults
            ? req_.superformsData[req_.i].liqRequests
            : req_.superformData[req_.i].liqRequest.castLiqRequestToArray();

        if (req_.isDeposit) {
            /// @dev step 2: estimate liq amount
            liqAmount += _estimateLiqAmount(liqRequests);

            if (xChain) {
                /// @dev step 3: estimate update cost (only for deposit)
                v.totalGas += _estimateUpdateDepositCost(req_.dstChainIds[req_.i], v.superformIdsLen);

                uint256 ackLen;
                if (multiVaults) {
                    for (uint256 j; j < v.superformIdsLen; ++j) {
                        if (!req_.superformsData[req_.i].retain4626s[j]) ++ackLen;
                    }
                } else {
                    if (!req_.superformData[req_.i].retain4626) ++ackLen;
                }

                /// @dev step 4: estimation processing cost of acknowledgement on source
                srcAmount += _estimateAckProcessingCost(ackLen);
                bool[] memory hasDstSwaps = multiVaults
                    ? req_.superformsData[req_.i].hasDstSwaps
                    : req_.superformData[req_.i].hasDstSwap.castBoolToArray();
                /// @dev step 5: estimate dst swap cost if it exists
                v.totalGas += _estimateSwapFees(req_.dstChainIds[req_.i], hasDstSwaps);
            }
        } else {
            if (multiVaults) {
                /// @dev step 6: estimate if timelock form processing costs are involved
                for (uint256 j; j < v.superformIdsLen; ++j) {
                    v.totalGas += _calculateTotalDstGasTimelockEmergency(
                        req_.superformsData[req_.i].superformIds[j], req_.dstChainIds[req_.i], req_.factory
                    );
                }
            } else {
                v.totalGas += _calculateTotalDstGasTimelockEmergency(
                    req_.superformData[req_.i].superformId, req_.dstChainIds[req_.i], req_.factory
                );
            }
            if (xChain) {
                /// @dev step 7: estimate update withdraw cost if no txData is present
                v.totalGas += _estimateUpdateWithdrawCost(req_.dstChainIds[req_.i], liqRequests);
            }
        }

        /// @dev step 7: estimate execution costs in destination including sending acknowledgement to source
        /// @dev ensure that acknowledgement costs from dst to src are not double counted
        v.totalGas +=
            xChain ? _estimateDstExecutionCost(req_.isDeposit, req_.dstChainIds[req_.i], v.superformIdsLen) : 0;

        /// @dev step 8: convert all dst/same chain gas estimates to src chain estimate  (withdraw / deposit)
        dstOrSameChainAmt += _convertToNativeFee(req_.dstChainIds[req_.i], v.totalGas, xChain);
    }

    /// @dev calculates the srcAmount cost for single direct withdrawal
    function _calculateTotalDstGasTimelockEmergency(
        uint256 superformId_,
        uint64 dstChainId_,
        ISuperformFactory factory_
    )
        internal
        view
        returns (uint256 totalDstGas)
    {
        (, uint32 formId,) = superformId_.getSuperform();
        bool paused = factory_.isFormImplementationPaused(formId);

        if (!paused && formId == TIMELOCK_FORM_ID) {
            totalDstGas += timelockCost[dstChainId_];
        } else if (paused) {
            totalDstGas += emergencyCost[dstChainId_];
        }
    }
}

File 2 of 14 : IPaymentHelperV2.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;

import {
    MultiDstMultiVaultStateReq,
    MultiDstSingleVaultStateReq,
    SingleXChainMultiVaultStateReq,
    SingleXChainSingleVaultStateReq,
    SingleDirectSingleVaultStateReq,
    SingleDirectMultiVaultStateReq
} from "src/types/DataTypes.sol";

/// @title IPaymentHelper
/// @dev Interface for PaymentHelper
/// @author ZeroPoint Labs
interface IPaymentHelperV2 {
    //////////////////////////////////////////////////////////////
    //                           STRUCTS                         //
    //////////////////////////////////////////////////////////////

    /// @param nativeFeedOracle is the native price feed oracle
    /// @param gasPriceOracle is the gas price oracle
    /// @param swapGasUsed is the swap gas params
    /// @param updateDepositGasUsed is the update gas params
    /// @param depositGasUsed is the deposit per vault gas on the chain
    /// @param withdrawGasUsed is the withdraw per vault gas on the chain
    /// @param defaultNativePrice is the native price on the specified chain
    /// @param defaultGasPrice is the gas price on the specified chain
    /// @param dstGasPerByte is the gas per size of data on the specified chain
    /// @param ackGasCost is the gas cost for sending and processing from dst->src
    /// @param timelockCost is the extra cost for processing timelocked payloads
    /// @param emergencyCost is the extra cost for processing emergency payloads
    /// @param updateWithdrawGasUsed is the update gas params for withdraws
    struct PaymentHelperConfig {
        address nativeFeedOracle;
        address gasPriceOracle;
        uint256 swapGasUsed;
        uint256 updateDepositGasUsed;
        uint256 depositGasUsed;
        uint256 withdrawGasUsed;
        uint256 defaultNativePrice;
        uint256 defaultGasPrice;
        uint256 dstGasPerByte;
        uint256 ackGasCost;
        uint256 timelockCost;
        uint256 emergencyCost;
        uint256 updateWithdrawGasUsed;
    }

    //////////////////////////////////////////////////////////////
    //                          EVENTS                          //
    //////////////////////////////////////////////////////////////

    event ChainConfigUpdated(uint64 indexed chainId_, uint256 indexed configType_, bytes config_);
    event ChainConfigAdded(uint64 chainId_, PaymentHelperConfig config_);

    //////////////////////////////////////////////////////////////
    //              EXTERNAL VIEW FUNCTIONS                     //
    //////////////////////////////////////////////////////////////

    /// @dev returns the amb overrides & gas to be used
    /// @param dstChainId_ is the unique dst chain identifier
    /// @param ambIds_ is the identifiers of arbitrary message bridges to be used
    /// @param message_ is the encoded cross-chain payload
    function calculateAMBData(
        uint64 dstChainId_,
        uint8[] calldata ambIds_,
        bytes memory message_
    )
        external
        view
        returns (uint256 totalFees, bytes memory extraData);

    /// @dev returns the amb overrides & gas to be used
    /// @return extraData the amb specific override information
    function getRegisterTransmuterAMBData() external view returns (bytes memory extraData);

    /// @dev estimates the gas fees for multiple destination and multi vault operation
    /// @param req_ is the request object containing all necessary data for the actual operation on SuperRouter
    /// @param isDeposit_ indicated if the datatype will be used for a deposit
    /// @return liqAmount is the amount of liquidity to be provided in native tokens
    /// @return srcAmount is the gas expense on source chain in native tokens
    /// @return dstAmount is the gas expense on dst chain in terms of src chain's native tokens
    /// @return totalAmount is the native_tokens to be sent along the transaction
    function estimateMultiDstMultiVault(
        MultiDstMultiVaultStateReq calldata req_,
        bool isDeposit_
    )
        external
        view
        returns (uint256 liqAmount, uint256 srcAmount, uint256 dstAmount, uint256 totalAmount);

    /// @dev estimates the gas fees for multiple destination and single vault operation
    /// @param req_ is the request object containing all necessary data for the actual operation on SuperRouter
    /// @param isDeposit_ indicated if the datatype will be used for a deposit
    /// @return liqAmount is the amount of liquidity to be provided in native tokens
    /// @return srcAmount is the gas expense on source chain in native tokens
    /// @return dstAmount is the gas expense on dst chain in terms of src chain's native tokens
    /// @return totalAmount is the native_tokens to be sent along the transaction
    function estimateMultiDstSingleVault(
        MultiDstSingleVaultStateReq calldata req_,
        bool isDeposit_
    )
        external
        view
        returns (uint256 liqAmount, uint256 srcAmount, uint256 dstAmount, uint256 totalAmount);

    /// @dev estimates the gas fees for single destination and multi vault operation
    /// @param req_ is the request object containing all necessary data for the actual operation on SuperRouter
    /// @param isDeposit_ indicated if the datatype will be used for a deposit
    /// @return liqAmount is the amount of liquidity to be provided in native tokens
    /// @return srcAmount is the gas expense on source chain in native tokens
    /// @return dstAmount is the gas expense on dst chain in terms of src chain's native tokens
    /// @return totalAmount is the native_tokens to be sent along the transaction
    function estimateSingleXChainMultiVault(
        SingleXChainMultiVaultStateReq calldata req_,
        bool isDeposit_
    )
        external
        view
        returns (uint256 liqAmount, uint256 srcAmount, uint256 dstAmount, uint256 totalAmount);

    /// @dev estimates the gas fees for single destination and single vault operation
    /// @param req_ is the request object containing all necessary data for the actual operation on SuperRouter
    /// @param isDeposit_ indicated if the datatype will be used for a deposit
    /// @return liqAmount is the amount of liquidity to be provided in native tokens
    /// @return srcAmount is the gas expense on source chain in native tokens
    /// @return dstAmount is the gas expense on dst chain in terms of src chain's native tokens
    /// @return totalAmount is the native_tokens to be sent along the transaction
    function estimateSingleXChainSingleVault(
        SingleXChainSingleVaultStateReq calldata req_,
        bool isDeposit_
    )
        external
        view
        returns (uint256 liqAmount, uint256 srcAmount, uint256 dstAmount, uint256 totalAmount);

    /// @dev estimates the gas fees for same chain operation
    /// @param req_ is the request object containing all necessary data for the actual operation on SuperRouter
    /// @param isDeposit_ indicated if the datatype will be used for a deposit
    /// @return liqAmount is the amount of liquidity to be provided in native tokens
    /// @return srcAmount is the gas expense on source chain in native tokens
    /// @return totalAmount is the native_tokens to be sent along the transaction
    function estimateSingleDirectSingleVault(
        SingleDirectSingleVaultStateReq calldata req_,
        bool isDeposit_
    )
        external
        view
        returns (uint256 liqAmount, uint256 srcAmount, uint256 totalAmount);

    /// @dev estimates the gas fees for multiple same chain operation
    /// @param req_ is the request object containing all necessary data for the actual operation on SuperRouter
    /// @param isDeposit_ indicated if the datatype will be used for a deposit
    /// @return liqAmount is the amount of liquidity to be provided in native tokens
    /// @return srcAmount is the gas expense on source chain in native tokens
    /// @return totalAmount is the native_tokens to be sent along the transaction
    function estimateSingleDirectMultiVault(
        SingleDirectMultiVaultStateReq calldata req_,
        bool isDeposit_
    )
        external
        view
        returns (uint256 liqAmount, uint256 srcAmount, uint256 totalAmount);

    /// @dev returns the gas fees estimation in native tokens if we send message through a combination of AMBs
    /// @param ambIds_ is the identifier of different AMBs
    /// @param dstChainId_ is the identifier of the destination chain
    /// @param message_ is the cross-chain message
    /// @param extraData_ is any amb-specific information
    /// @return ambFees is the native_tokens to be sent along the transaction for all the ambIds_ included
    function estimateAMBFees(
        uint8[] memory ambIds_,
        uint64 dstChainId_,
        bytes memory message_,
        bytes[] memory extraData_
    )
        external
        view
        returns (uint256 ambFees, uint256[] memory);

    /// @dev helps estimate the acknowledgement costs for amb processing
    /// @param payloadId_ is the payload identifier
    /// @return totalFees is the total fees to be paid in native tokens
    function estimateAckCost(uint256 payloadId_) external view returns (uint256 totalFees);

    /// @dev helps estimate the acknowledgement costs for amb processing without relying on payloadId (using max values)
    /// @param multi is the flag indicating if the payload is multi or single
    /// @param ackAmbIds is the list of ambIds to be used for acknowledgement
    /// @param srcChainId is the source chain identifier
    /// @return totalFees is the total fees to be paid in native tokens
    function estimateAckCostDefault(
        bool multi,
        uint8[] memory ackAmbIds,
        uint64 srcChainId
    )
        external
        view
        returns (uint256 totalFees);

    /// @dev helps estimate the acknowledgement costs for amb processing without relying on payloadId (using max values)
    /// with source native amounts
    /// @param multi is the flag indicating if the payload is multi or single
    /// @param ackAmbIds is the list of ambIds to be used for acknowledgement
    /// @param srcChainId is the source chain identifier
    /// @return totalFees is the total fees to be paid in native tokens
    function estimateAckCostDefaultNativeSource(
        bool multi,
        uint8[] memory ackAmbIds,
        uint64 srcChainId
    )
        external
        view
        returns (uint256 totalFees);
    //////////////////////////////////////////////////////////////
    //              EXTERNAL WRITE FUNCTIONS                    //
    //////////////////////////////////////////////////////////////

    /// @dev admin can configure a remote chain for the first time
    /// @param chainId_ is the identifier of new chain id
    /// @param config_ is the chain config
    function addRemoteChain(uint64 chainId_, PaymentHelperConfig calldata config_) external;

    /// @dev admin can configure various remote chain for the first time in a single call
    /// @param chainIds_ is the identifier of new chain id
    /// @param configs_ is the chain config
    function addRemoteChains(uint64[] calldata chainIds_, PaymentHelperConfig[] calldata configs_) external;

    /// @dev admin can specifically configure/update certain configuration of a remote chain
    /// @param chainId_ is the remote chain's identifier
    /// @param configType_ is the type of config from 1 -> 6
    /// @param config_ is the encoded new configuration
    function updateRemoteChain(uint64 chainId_, uint256 configType_, bytes memory config_) external;

    /// @dev admin can specifically configure/update certain configurations on a single remote chain
    /// @param chainId_ are the remote chain's identifier
    /// @param configTypes_ are the type of config from 1 -> 6 for the given chain
    /// @param configs_ are the encoded new configurations for each config type for the given chain
    function batchUpdateRemoteChain(
        uint64 chainId_,
        uint256[] calldata configTypes_,
        bytes[] calldata configs_
    )
        external;

    /// @dev admin can specifically configure/update certain configurations on various remote chains at the same time
    /// @param chainIds_ are the remote chain's identifier
    /// @param configTypes_ are the type of config from 1 -> 6 for each chain
    /// @param configs_ are the encoded new configurations for each config type and chains
    function batchUpdateRemoteChains(
        uint64[] calldata chainIds_,
        uint256[][] calldata configTypes_,
        bytes[][] calldata configs_
    )
        external;

    /// @dev admin updates config for register transmuter amb params
    /// @param extraDataForTransmuter_ is the broadcast extra data
    function updateRegisterAERC20Params(bytes memory extraDataForTransmuter_) external;
}

File 3 of 14 : ISuperRBAC.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;

import { IAccessControl } from "openzeppelin-contracts/contracts/access/IAccessControl.sol";

/// @title ISuperRBAC
/// @dev Interface for SuperRBAC
/// @author Zeropoint Labs
interface ISuperRBAC is IAccessControl {

    //////////////////////////////////////////////////////////////
    //                           STRUCTS                         //
    //////////////////////////////////////////////////////////////

    struct InitialRoleSetup {
        address admin;
        address emergencyAdmin;
        address paymentAdmin;
        address csrProcessor;
        address tlProcessor;
        address brProcessor;
        address csrUpdater;
        address srcVaaRelayer;
        address dstSwapper;
        address csrRescuer;
        address csrDisputer;
    }

    //////////////////////////////////////////////////////////////
    //                          EVENTS                          //
    //////////////////////////////////////////////////////////////

    /// @dev is emitted when superRegistry is set
    event SuperRegistrySet(address indexed superRegistry);

    /// @dev is emitted when an admin is set for a role
    event RoleAdminSet(bytes32 role, bytes32 adminRole);

    //////////////////////////////////////////////////////////////
    //              EXTERNAL VIEW FUNCTIONS                     //
    //////////////////////////////////////////////////////////////

    /// @dev returns the id of the protocol admin role
    function PROTOCOL_ADMIN_ROLE() external view returns (bytes32);

    /// @dev returns the id of the emergency admin role
    function EMERGENCY_ADMIN_ROLE() external view returns (bytes32);

    /// @dev returns the id of the payment admin role
    function PAYMENT_ADMIN_ROLE() external view returns (bytes32);

    /// @dev returns the id of the broadcaster role
    function BROADCASTER_ROLE() external view returns (bytes32);

    /// @dev returns the id of the core state registry processor role
    function CORE_STATE_REGISTRY_PROCESSOR_ROLE() external view returns (bytes32);

    /// @dev returns the id of the timelock state registry processor role
    function TIMELOCK_STATE_REGISTRY_PROCESSOR_ROLE() external view returns (bytes32);

    /// @dev returns the id of the broadcast state registry processor role
    function BROADCAST_STATE_REGISTRY_PROCESSOR_ROLE() external view returns (bytes32);

    /// @dev returns the id of the core state registry updater role
    function CORE_STATE_REGISTRY_UPDATER_ROLE() external view returns (bytes32);

    /// @dev returns the id of the dst swapper role
    function DST_SWAPPER_ROLE() external view returns (bytes32);

    /// @dev returns the id of the core state registry rescuer role
    function CORE_STATE_REGISTRY_RESCUER_ROLE() external view returns (bytes32);

    /// @dev returns the id of the core state registry rescue disputer role
    function CORE_STATE_REGISTRY_DISPUTER_ROLE() external view returns (bytes32);

    /// @dev returns the id of wormhole vaa relayer role
    function WORMHOLE_VAA_RELAYER_ROLE() external view returns (bytes32);

    /// @dev returns whether the given address has the protocol admin role
    /// @param admin_ the address to check
    function hasProtocolAdminRole(address admin_) external view returns (bool);

    /// @dev returns whether the given address has the emergency admin role
    /// @param admin_ the address to check
    function hasEmergencyAdminRole(address admin_) external view returns (bool);

    //////////////////////////////////////////////////////////////
    //              EXTERNAL WRITE FUNCTIONS                    //
    //////////////////////////////////////////////////////////////

    /// @dev updates the super registry address
    function setSuperRegistry(address superRegistry_) external;

    /// @dev configures a new role in superForm
    /// @param role_ the role to set
    /// @param adminRole_ the admin role to set as admin
    function setRoleAdmin(bytes32 role_, bytes32 adminRole_) external;

    /// @dev revokes the role_ from superRegistryAddressId_ on all chains
    /// @param role_ the role to revoke
    /// @param extraData_ amb config if broadcasting is required
    /// @param superRegistryAddressId_ the super registry address id
    function revokeRoleSuperBroadcast(
        bytes32 role_,
        bytes memory extraData_,
        bytes32 superRegistryAddressId_
    )
        external
        payable;

    /// @dev allows sync of global roles from different chains using broadcast registry
    /// @notice may not work for all roles
    function stateSyncBroadcast(bytes memory data_) external;
}

File 4 of 14 : ISuperRegistry.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;

/// @title ISuperRegistry
/// @dev Interface for SuperRegistry
/// @author Zeropoint Labs
interface ISuperRegistry {
    //////////////////////////////////////////////////////////////
    //                          EVENTS                          //
    //////////////////////////////////////////////////////////////

    /// @dev emitted when permit2 is set.
    event SetPermit2(address indexed permit2);

    /// @dev is emitted when an address is set.
    event AddressUpdated(
        bytes32 indexed protocolAddressId, uint64 indexed chainId, address indexed oldAddress, address newAddress
    );

    /// @dev is emitted when a new token bridge is configured.
    event SetBridgeAddress(uint256 indexed bridgeId, address indexed bridgeAddress);

    /// @dev is emitted when a new bridge validator is configured.
    event SetBridgeValidator(uint256 indexed bridgeId, address indexed bridgeValidator);

    /// @dev is emitted when a new amb is configured.
    event SetAmbAddress(uint8 indexed ambId_, address indexed ambAddress_, bool indexed isBroadcastAMB_);

    /// @dev is emitted when a new state registry is configured.
    event SetStateRegistryAddress(uint8 indexed registryId_, address indexed registryAddress_);

    /// @dev is emitted when a new delay is configured.
    event SetDelay(uint256 indexed oldDelay_, uint256 indexed newDelay_);

    /// @dev is emitted when a new vault limit is configured
    event SetVaultLimitPerDestination(uint64 indexed chainId_, uint256 indexed vaultLimit_);

    //////////////////////////////////////////////////////////////
    //              EXTERNAL VIEW FUNCTIONS                     //
    //////////////////////////////////////////////////////////////

    /// @dev gets the deposit rescue delay
    function delay() external view returns (uint256);

    /// @dev returns the permit2 address
    function PERMIT2() external view returns (address);

    /// @dev returns the id of the superform router module
    function SUPERFORM_ROUTER() external view returns (bytes32);

    /// @dev returns the id of the superform factory module
    function SUPERFORM_FACTORY() external view returns (bytes32);

    /// @dev returns the id of the superform paymaster contract
    function PAYMASTER() external view returns (bytes32);

    /// @dev returns the id of the superform payload helper contract
    function PAYMENT_HELPER() external view returns (bytes32);

    /// @dev returns the id of the core state registry module
    function CORE_STATE_REGISTRY() external view returns (bytes32);

    /// @dev returns the id of the timelock form state registry module
    function TIMELOCK_STATE_REGISTRY() external view returns (bytes32);

    /// @dev returns the id of the broadcast state registry module
    function BROADCAST_REGISTRY() external view returns (bytes32);

    /// @dev returns the id of the super positions module
    function SUPER_POSITIONS() external view returns (bytes32);

    /// @dev returns the id of the super rbac module
    function SUPER_RBAC() external view returns (bytes32);

    /// @dev returns the id of the payload helper module
    function PAYLOAD_HELPER() external view returns (bytes32);

    /// @dev returns the id of the dst swapper keeper
    function DST_SWAPPER() external view returns (bytes32);

    /// @dev returns the id of the emergency queue
    function EMERGENCY_QUEUE() external view returns (bytes32);

    /// @dev returns the id of the superform receiver
    function SUPERFORM_RECEIVER() external view returns (bytes32);

    /// @dev returns the id of the payment admin keeper
    function PAYMENT_ADMIN() external view returns (bytes32);

    /// @dev returns the id of the core state registry processor keeper
    function CORE_REGISTRY_PROCESSOR() external view returns (bytes32);

    /// @dev returns the id of the broadcast registry processor keeper
    function BROADCAST_REGISTRY_PROCESSOR() external view returns (bytes32);

    /// @dev returns the id of the timelock form state registry processor keeper
    function TIMELOCK_REGISTRY_PROCESSOR() external view returns (bytes32);

    /// @dev returns the id of the core state registry updater keeper
    function CORE_REGISTRY_UPDATER() external view returns (bytes32);

    /// @dev returns the id of the core state registry updater keeper
    function CORE_REGISTRY_RESCUER() external view returns (bytes32);

    /// @dev returns the id of the core state registry updater keeper
    function CORE_REGISTRY_DISPUTER() external view returns (bytes32);

    /// @dev returns the id of the core state registry updater keeper
    function DST_SWAPPER_PROCESSOR() external view returns (bytes32);

    /// @dev gets the address of a contract on current chain
    /// @param id_ is the id of the contract
    function getAddress(bytes32 id_) external view returns (address);

    /// @dev gets the address of a contract on a target chain
    /// @param id_ is the id of the contract
    /// @param chainId_ is the chain id of that chain
    function getAddressByChainId(bytes32 id_, uint64 chainId_) external view returns (address);

    /// @dev gets the address of a bridge
    /// @param bridgeId_ is the id of a bridge
    /// @return bridgeAddress_ is the address of the form
    function getBridgeAddress(uint8 bridgeId_) external view returns (address bridgeAddress_);

    /// @dev gets the address of a bridge validator
    /// @param bridgeId_ is the id of a bridge
    /// @return bridgeValidator_ is the address of the form
    function getBridgeValidator(uint8 bridgeId_) external view returns (address bridgeValidator_);

    /// @dev gets the address of a amb
    /// @param ambId_ is the id of a bridge
    /// @return ambAddress_ is the address of the form
    function getAmbAddress(uint8 ambId_) external view returns (address ambAddress_);

    /// @dev gets the id of the amb
    /// @param ambAddress_ is the address of an amb
    /// @return ambId_ is the identifier of an amb
    function getAmbId(address ambAddress_) external view returns (uint8 ambId_);

    /// @dev gets the address of the registry
    /// @param registryId_ is the id of the state registry
    /// @return registryAddress_ is the address of the state registry
    function getStateRegistry(uint8 registryId_) external view returns (address registryAddress_);

    /// @dev gets the id of the registry
    /// @notice reverts if the id is not found
    /// @param registryAddress_ is the address of the state registry
    /// @return registryId_ is the id of the state registry
    function getStateRegistryId(address registryAddress_) external view returns (uint8 registryId_);

    /// @dev gets the safe vault limit
    /// @param chainId_ is the id of the remote chain
    /// @return vaultLimitPerDestination_ is the safe number of vaults to deposit
    /// without hitting out of gas error
    function getVaultLimitPerDestination(uint64 chainId_) external view returns (uint256 vaultLimitPerDestination_);

    /// @dev helps validate if an address is a valid state registry
    /// @param registryAddress_ is the address of the state registry
    /// @return valid_ a flag indicating if its valid.
    function isValidStateRegistry(address registryAddress_) external view returns (bool valid_);

    /// @dev helps validate if an address is a valid amb implementation
    /// @param ambAddress_ is the address of the amb implementation
    /// @return valid_ a flag indicating if its valid.
    function isValidAmbImpl(address ambAddress_) external view returns (bool valid_);

    /// @dev helps validate if an address is a valid broadcast amb implementation
    /// @param ambAddress_ is the address of the broadcast amb implementation
    /// @return valid_ a flag indicating if its valid.
    function isValidBroadcastAmbImpl(address ambAddress_) external view returns (bool valid_);

    //////////////////////////////////////////////////////////////
    //              EXTERNAL WRITE FUNCTIONS                    //
    //////////////////////////////////////////////////////////////

    /// @dev sets the deposit rescue delay
    /// @param delay_ the delay in seconds before the deposit rescue can be finalized
    function setDelay(uint256 delay_) external;

    /// @dev sets the permit2 address
    /// @param permit2_ the address of the permit2 contract
    function setPermit2(address permit2_) external;

    /// @dev sets the safe vault limit
    /// @param chainId_ is the remote chain identifier
    /// @param vaultLimit_ is the max limit of vaults per transaction
    function setVaultLimitPerDestination(uint64 chainId_, uint256 vaultLimit_) external;

    /// @dev sets new addresses on specific chains.
    /// @param ids_ are the identifiers of the address on that chain
    /// @param newAddresses_  are the new addresses on that chain
    /// @param chainIds_ are the chain ids of that chain
    function batchSetAddress(
        bytes32[] calldata ids_,
        address[] calldata newAddresses_,
        uint64[] calldata chainIds_
    )
        external;

    /// @dev sets a new address on a specific chain.
    /// @param id_ the identifier of the address on that chain
    /// @param newAddress_ the new address on that chain
    /// @param chainId_ the chain id of that chain
    function setAddress(bytes32 id_, address newAddress_, uint64 chainId_) external;

    /// @dev allows admin to set the bridge address for an bridge id.
    /// @notice this function operates in an APPEND-ONLY fashion.
    /// @param bridgeId_         represents the bridge unique identifier.
    /// @param bridgeAddress_    represents the bridge address.
    /// @param bridgeValidator_  represents the bridge validator address.
    function setBridgeAddresses(
        uint8[] memory bridgeId_,
        address[] memory bridgeAddress_,
        address[] memory bridgeValidator_
    )
        external;

    /// @dev allows admin to set the amb address for an amb id.
    /// @notice this function operates in an APPEND-ONLY fashion.
    /// @param ambId_         represents the bridge unique identifier.
    /// @param ambAddress_    represents the bridge address.
    /// @param isBroadcastAMB_ represents whether the amb implementation supports broadcasting
    function setAmbAddress(
        uint8[] memory ambId_,
        address[] memory ambAddress_,
        bool[] memory isBroadcastAMB_
    )
        external;

    /// @dev allows admin to set the state registry address for an state registry id.
    /// @notice this function operates in an APPEND-ONLY fashion.
    /// @param registryId_    represents the state registry's unique identifier.
    /// @param registryAddress_    represents the state registry's address.
    function setStateRegistryAddress(uint8[] memory registryId_, address[] memory registryAddress_) external;
}

File 5 of 14 : ISuperformFactory.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;

/// @title ISuperformFactory
/// @dev Interface for SuperformFactory
/// @author ZeroPoint Labs
interface ISuperformFactory {
    
    //////////////////////////////////////////////////////////////
    //                         CONSTANTS                        //
    //////////////////////////////////////////////////////////////

    enum PauseStatus {
        NON_PAUSED,
        PAUSED
    }

    //////////////////////////////////////////////////////////////
    //                          EVENTS                          //
    //////////////////////////////////////////////////////////////

    /// @dev emitted when a new formImplementation is entered into the factory
    /// @param formImplementation is the address of the new form implementation
    /// @param formImplementationId is the id of the formImplementation
    /// @param formStateRegistryId is any additional state registry id of the formImplementation
    event FormImplementationAdded(
        address indexed formImplementation, uint256 indexed formImplementationId, uint8 indexed formStateRegistryId
    );

    /// @dev emitted when a new Superform is created
    /// @param formImplementationId is the id of the form implementation
    /// @param vault is the address of the vault
    /// @param superformId is the id of the superform
    /// @param superform is the address of the superform
    event SuperformCreated(
        uint256 indexed formImplementationId, address indexed vault, uint256 indexed superformId, address superform
    );

    /// @dev emitted when a new SuperRegistry is set
    /// @param superRegistry is the address of the super registry
    event SuperRegistrySet(address indexed superRegistry);

    /// @dev emitted when a form implementation is paused
    /// @param formImplementationId is the id of the form implementation
    /// @param paused is the new paused status
    event FormImplementationPaused(uint256 indexed formImplementationId, PauseStatus indexed paused);

    //////////////////////////////////////////////////////////////
    //              EXTERNAL VIEW FUNCTIONS                     //
    //////////////////////////////////////////////////////////////

    /// @dev returns the number of forms
    /// @return forms_ is the number of forms
    function getFormCount() external view returns (uint256 forms_);

    /// @dev returns the number of superforms
    /// @return superforms_ is the number of superforms
    function getSuperformCount() external view returns (uint256 superforms_);

    /// @dev returns the address of a form implementation
    /// @param formImplementationId_ is the id of the form implementation
    /// @return formImplementation_ is the address of the form implementation
    function getFormImplementation(uint32 formImplementationId_) external view returns (address formImplementation_);

    /// @dev returns the form state registry id of a form implementation
    /// @param formImplementationId_ is the id of the form implementation
    /// @return stateRegistryId_ is the additional state registry id of the form
    function getFormStateRegistryId(uint32 formImplementationId_) external view returns (uint8 stateRegistryId_);

    /// @dev returns the paused status of form implementation
    /// @param formImplementationId_ is the id of the form implementation
    /// @return paused_ is the current paused status of the form formImplementationId_
    function isFormImplementationPaused(uint32 formImplementationId_) external view returns (bool paused_);

    /// @dev returns the address of a superform
    /// @param superformId_ is the id of the superform
    /// @return superform_ is the address of the superform
    /// @return formImplementationId_ is the id of the form implementation
    /// @return chainId_ is the chain id
    function getSuperform(uint256 superformId_)
        external
        pure
        returns (address superform_, uint32 formImplementationId_, uint64 chainId_);

    /// @dev returns if an address has been added to a Form
    /// @param superformId_ is the id of the superform
    /// @return isSuperform_ bool if it exists
    function isSuperform(uint256 superformId_) external view returns (bool isSuperform_);

    /// @dev Reverse query of getSuperform, returns all superforms for a given vault
    /// @param vault_ is the address of a vault
    /// @return superformIds_ is the id of the superform
    /// @return superforms_ is the address of the superform
    function getAllSuperformsFromVault(address vault_)
        external
        view
        returns (uint256[] memory superformIds_, address[] memory superforms_);

    //////////////////////////////////////////////////////////////
    //              EXTERNAL WRITE FUNCTIONS                    //
    //////////////////////////////////////////////////////////////

    /// @dev allows an admin to add a Form implementation to the factory
    /// @param formImplementation_ is the address of a form implementation
    /// @param formImplementationId_ is the id of the form implementation (generated off-chain and equal in all chains)
    /// @param formStateRegistryId_ is the id of any additional state registry for that form
    /// @dev formStateRegistryId_ 1 is default for all form implementations, pass in formStateRegistryId_ only if an
    /// additional state registry is required
    function addFormImplementation(
        address formImplementation_,
        uint32 formImplementationId_,
        uint8 formStateRegistryId_
    )
        external;

    /// @dev To add new vaults to Form implementations, fusing them together into Superforms
    /// @param formImplementationId_ is the form implementation we want to attach the vault to
    /// @param vault_ is the address of the vault
    /// @return superformId_ is the id of the created superform
    /// @return superform_ is the address of the created superform
    function createSuperform(
        uint32 formImplementationId_,
        address vault_
    )
        external
        returns (uint256 superformId_, address superform_);

    /// @dev to synchronize superforms added to different chains using broadcast registry
    /// @param data_ is the cross-chain superform id
    function stateSyncBroadcast(bytes memory data_) external payable;

    /// @dev allows an admin to change the status of a form
    /// @param formImplementationId_ is the id of the form implementation
    /// @param status_ is the new status
    /// @param extraData_ is optional & passed when broadcasting of status is needed
    function changeFormImplementationPauseStatus(
        uint32 formImplementationId_,
        PauseStatus status_,
        bytes memory extraData_
    )
        external
        payable;
}

File 6 of 14 : IBaseStateRegistry.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;

import { PayloadState } from "src/types/DataTypes.sol";

/// @title IBaseStateRegistry
/// @dev Interface for BaseStateRegistry
/// @author ZeroPoint Labs
interface IBaseStateRegistry {
    //////////////////////////////////////////////////////////////
    //                          EVENTS                          //
    //////////////////////////////////////////////////////////////

    /// @dev is emitted when a cross-chain payload is received in the state registry
    event PayloadReceived(uint64 indexed srcChainId, uint64 indexed dstChainId, uint256 indexed payloadId);

    /// @dev is emitted when a cross-chain proof is received in the state registry
    /// NOTE: comes handy if quorum required is more than 0
    event ProofReceived(bytes32 indexed proof);

    /// @dev is emitted when a payload id gets updated
    event PayloadUpdated(uint256 indexed payloadId);

    /// @dev is emitted when a payload id gets processed
    event PayloadProcessed(uint256 indexed payloadId);

    /// @dev is emitted when the super registry address is updated
    event SuperRegistryUpdated(address indexed superRegistry);

    //////////////////////////////////////////////////////////////
    //              EXTERNAL VIEW FUNCTIONS                     //
    //////////////////////////////////////////////////////////////

    /// @dev allows users to read the total payloads received by the registry
    function payloadsCount() external view returns (uint256);

    /// @dev allows user to read the payload state
    /// uint256 payloadId_ is the unique payload identifier allocated on the destination chain
    function payloadTracking(uint256 payloadId_) external view returns (PayloadState payloadState_);

    /// @dev allows users to read the bytes payload_ stored per payloadId_
    /// @param payloadId_ is the unique payload identifier allocated on the destination chain
    /// @return payloadBody_ the crosschain data received
    function payloadBody(uint256 payloadId_) external view returns (bytes memory payloadBody_);

    /// @dev allows users to read the uint256 payloadHeader stored per payloadId_
    /// @param payloadId_ is the unique payload identifier allocated on the destination chain
    /// @return payloadHeader_ the crosschain header received
    function payloadHeader(uint256 payloadId_) external view returns (uint256 payloadHeader_);

    /// @dev allows users to read the ambs that delivered the payload id
    /// @param payloadId_ is the unique payload identifier allocated on the destination chain
    /// @return ambIds_ is the identifier of ambs that delivered the message and proof
    function getMessageAMB(uint256 payloadId_) external view returns (uint8[] memory ambIds_);

    //////////////////////////////////////////////////////////////
    //              EXTERNAL WRITE FUNCTIONS                    //
    //////////////////////////////////////////////////////////////

    /// @dev allows core contracts to send payload to a destination chain.
    /// @param srcSender_ is the caller of the function (used for gas refunds).
    /// @param ambIds_ is the identifier of the arbitrary message bridge to be used
    /// @param dstChainId_ is the internal chainId used throughout the protocol
    /// @param message_ is the crosschain payload to be sent
    /// @param extraData_ defines all the message bridge related overrides
    /// NOTE: dstChainId_ is mapped to message bridge's destination id inside it's implementation contract
    /// NOTE: ambIds_ are superform assigned unique identifier for arbitrary message bridges
    function dispatchPayload(
        address srcSender_,
        uint8[] memory ambIds_,
        uint64 dstChainId_,
        bytes memory message_,
        bytes memory extraData_
    )
        external
        payable;

    /// @dev allows state registry to receive messages from message bridge implementations
    /// @param srcChainId_ is the superform chainId from which the payload is dispatched/sent
    /// @param message_ is the crosschain payload received
    /// NOTE: Only {IMPLEMENTATION_CONTRACT} role can call this function.
    function receivePayload(uint64 srcChainId_, bytes memory message_) external;

    /// @dev allows privileged actors to process cross-chain payloads
    /// @param payloadId_ is the identifier of the cross-chain payload
    /// NOTE: Only {CORE_STATE_REGISTRY_PROCESSOR_ROLE} role can call this function
    /// NOTE: this should handle reverting the state on source chain in-case of failure
    /// (or) can implement scenario based reverting like in coreStateRegistry
    function processPayload(uint256 payloadId_) external payable;
}

File 7 of 14 : IAmbImplementation.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;

/// @title IAmbImplementation
/// @dev Interface for arbitrary message bridge (AMB) implementations
/// @author ZeroPoint Labs
interface IAmbImplementation {
    //////////////////////////////////////////////////////////////
    //                          EVENTS                          //
    //////////////////////////////////////////////////////////////

    event ChainAdded(uint64 indexed superChainId);
    event AuthorizedImplAdded(uint64 indexed superChainId, address indexed authImpl);

    //////////////////////////////////////////////////////////////
    //              EXTERNAL VIEW FUNCTIONS                     //
    //////////////////////////////////////////////////////////////

    /// @dev returns the gas fees estimation in native tokens
    /// @notice not all AMBs will have on-chain estimation for which this function will return 0
    /// @param dstChainId_ is the identifier of the destination chain
    /// @param message_ is the cross-chain message
    /// @param extraData_ is any amb-specific information
    /// @return fees is the native_tokens to be sent along the transaction
    function estimateFees(
        uint64 dstChainId_,
        bytes memory message_,
        bytes memory extraData_
    )
        external
        view
        returns (uint256 fees);

    /// @dev returns the extra data for the given gas request
    /// @param gasLimit is the amount of gas limit in wei to override
    /// @return extraData is the bytes encoded extra data
    /// NOTE: this process is unique to the message bridge
    function generateExtraData(uint256 gasLimit) external pure returns (bytes memory extraData);

    //////////////////////////////////////////////////////////////
    //              EXTERNAL WRITE FUNCTIONS                    //
    //////////////////////////////////////////////////////////////

    /// @dev allows state registry to send message via implementation.
    /// @param srcSender_ is the caller (used for gas refunds)
    /// @param dstChainId_ is the identifier of the destination chain
    /// @param message_ is the cross-chain message to be sent
    /// @param extraData_ is message amb specific override information
    function dispatchPayload(
        address srcSender_,
        uint64 dstChainId_,
        bytes memory message_,
        bytes memory extraData_
    )
        external
        payable;

    /// @dev allows for the permissionless calling of the retry mechanism for encoded data
    /// @param data_ is the encoded retry data (different per AMB implementation)
    function retryPayload(bytes memory data_) external payable;
}

File 8 of 14 : Error.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;

library Error {
    //////////////////////////////////////////////////////////////
    //                  CONFIGURATION ERRORS                    //
    //////////////////////////////////////////////////////////////
    ///@notice errors thrown in protocol setup

    /// @dev thrown if chain id exceeds max(uint64)
    error BLOCK_CHAIN_ID_OUT_OF_BOUNDS();

    /// @dev thrown if not possible to revoke a role in broadcasting
    error CANNOT_REVOKE_NON_BROADCASTABLE_ROLES();

    /// @dev thrown if not possible to revoke last admin
    error CANNOT_REVOKE_LAST_ADMIN();

    /// @dev thrown if trying to set again pseudo immutables in super registry
    error DISABLED();

    /// @dev thrown if rescue delay is not yet set for a chain
    error DELAY_NOT_SET();

    /// @dev thrown if get native token price estimate in paymentHelper is 0
    error INVALID_NATIVE_TOKEN_PRICE();

    /// @dev thrown if wormhole refund chain id is not set
    error REFUND_CHAIN_ID_NOT_SET();

    /// @dev thrown if wormhole relayer is not set
    error RELAYER_NOT_SET();

    /// @dev thrown if a role to be revoked is not assigned
    error ROLE_NOT_ASSIGNED();

    //////////////////////////////////////////////////////////////
    //                  AUTHORIZATION ERRORS                    //
    //////////////////////////////////////////////////////////////
    ///@notice errors thrown if functions cannot be called

    /// COMMON AUTHORIZATION ERRORS
    /// ---------------------------------------------------------

    /// @dev thrown if caller is not address(this), internal call
    error INVALID_INTERNAL_CALL();

    /// @dev thrown if msg.sender is not a valid amb implementation
    error NOT_AMB_IMPLEMENTATION();

    /// @dev thrown if msg.sender is not an allowed broadcaster
    error NOT_ALLOWED_BROADCASTER();

    /// @dev thrown if msg.sender is not broadcast amb implementation
    error NOT_BROADCAST_AMB_IMPLEMENTATION();

    /// @dev thrown if msg.sender is not broadcast state registry
    error NOT_BROADCAST_REGISTRY();

    /// @dev thrown if msg.sender is not core state registry
    error NOT_CORE_STATE_REGISTRY();

    /// @dev thrown if msg.sender is not emergency admin
    error NOT_EMERGENCY_ADMIN();

    /// @dev thrown if msg.sender is not emergency queue
    error NOT_EMERGENCY_QUEUE();

    /// @dev thrown if msg.sender is not minter
    error NOT_MINTER();

    /// @dev thrown if msg.sender is not minter state registry
    error NOT_MINTER_STATE_REGISTRY_ROLE();

    /// @dev thrown if msg.sender is not paymaster
    error NOT_PAYMASTER();

    /// @dev thrown if msg.sender is not payment admin
    error NOT_PAYMENT_ADMIN();

    /// @dev thrown if msg.sender is not protocol admin
    error NOT_PROTOCOL_ADMIN();

    /// @dev thrown if msg.sender is not state registry
    error NOT_STATE_REGISTRY();

    /// @dev thrown if msg.sender is not super registry
    error NOT_SUPER_REGISTRY();

    /// @dev thrown if msg.sender is not superform router
    error NOT_SUPERFORM_ROUTER();

    /// @dev thrown if msg.sender is not a superform
    error NOT_SUPERFORM();

    /// @dev thrown if msg.sender is not superform factory
    error NOT_SUPERFORM_FACTORY();

    /// @dev thrown if msg.sender is not timelock form
    error NOT_TIMELOCK_SUPERFORM();

    /// @dev thrown if msg.sender is not timelock state registry
    error NOT_TIMELOCK_STATE_REGISTRY();

    /// @dev thrown if msg.sender is not user or disputer
    error NOT_VALID_DISPUTER();

    /// @dev thrown if the msg.sender is not privileged caller
    error NOT_PRIVILEGED_CALLER(bytes32 role);

    /// STATE REGISTRY AUTHORIZATION ERRORS
    /// ---------------------------------------------------------

    /// @dev layerzero adapter specific error, thrown if caller not layerzero endpoint
    error CALLER_NOT_ENDPOINT();

    /// @dev hyperlane adapter specific error, thrown if caller not hyperlane mailbox
    error CALLER_NOT_MAILBOX();

    /// @dev wormhole relayer specific error, thrown if caller not wormhole relayer
    error CALLER_NOT_RELAYER();

    /// @dev thrown if src chain sender is not valid
    error INVALID_SRC_SENDER();

    //////////////////////////////////////////////////////////////
    //                  INPUT VALIDATION ERRORS                 //
    //////////////////////////////////////////////////////////////
    ///@notice errors thrown if input variables are not valid

    /// COMMON INPUT VALIDATION ERRORS
    /// ---------------------------------------------------------

    /// @dev thrown if there is an array length mismatch
    error ARRAY_LENGTH_MISMATCH();

    /// @dev thrown if payload id does not exist
    error INVALID_PAYLOAD_ID();

    /// @dev error thrown when msg value should be zero in certain payable functions
    error MSG_VALUE_NOT_ZERO();

    /// @dev thrown if amb ids length is 0
    error ZERO_AMB_ID_LENGTH();

    /// @dev thrown if address input is address 0
    error ZERO_ADDRESS();

    /// @dev thrown if amount input is 0
    error ZERO_AMOUNT();

    /// @dev thrown if final token is address 0
    error ZERO_FINAL_TOKEN();

    /// @dev thrown if value input is 0
    error ZERO_INPUT_VALUE();

    /// SUPERFORM ROUTER INPUT VALIDATION ERRORS
    /// ---------------------------------------------------------

    /// @dev thrown if the vaults data is invalid
    error INVALID_SUPERFORMS_DATA();

    /// @dev thrown if receiver address is not set
    error RECEIVER_ADDRESS_NOT_SET();

    /// SUPERFORM FACTORY INPUT VALIDATION ERRORS
    /// ---------------------------------------------------------

    /// @dev thrown if a form is not ERC165 compatible
    error ERC165_UNSUPPORTED();

    /// @dev thrown if a form is not form interface compatible
    error FORM_INTERFACE_UNSUPPORTED();

    /// @dev error thrown if form implementation address already exists
    error FORM_IMPLEMENTATION_ALREADY_EXISTS();

    /// @dev error thrown if form implementation id already exists
    error FORM_IMPLEMENTATION_ID_ALREADY_EXISTS();

    /// @dev thrown if a form does not exist
    error FORM_DOES_NOT_EXIST();

    /// @dev thrown if form id is larger than max uint16
    error INVALID_FORM_ID();

    /// @dev thrown if superform not on factory
    error SUPERFORM_ID_NONEXISTENT();

    /// @dev thrown if same vault and form implementation is used to create new superform
    error VAULT_FORM_IMPLEMENTATION_COMBINATION_EXISTS();

    /// FORM INPUT VALIDATION ERRORS
    /// ---------------------------------------------------------

    /// @dev thrown if in case of no txData, if liqData.token != vault.asset()
    /// in case of txData, if token output of swap != vault.asset()
    error DIFFERENT_TOKENS();

    /// @dev thrown if the amount in direct withdraw is not correct
    error DIRECT_WITHDRAW_INVALID_LIQ_REQUEST();

    /// @dev thrown if the amount in xchain withdraw is not correct
    error XCHAIN_WITHDRAW_INVALID_LIQ_REQUEST();

    /// LIQUIDITY BRIDGE INPUT VALIDATION ERRORS
    /// ---------------------------------------------------------

    /// @dev thrown if route id is blacklisted in socket
    error BLACKLISTED_ROUTE_ID();

    /// @dev thrown if route id is not blacklisted in socket
    error NOT_BLACKLISTED_ROUTE_ID();

    /// @dev error thrown when txData selector of lifi bridge is a blacklisted selector
    error BLACKLISTED_SELECTOR();

    /// @dev error thrown when txData selector of lifi bridge is not a blacklisted selector
    error NOT_BLACKLISTED_SELECTOR();

    /// @dev thrown if a certain action of the user is not allowed given the txData provided
    error INVALID_ACTION();

    /// @dev thrown if in deposits, the liqDstChainId doesn't match the stateReq dstChainId
    error INVALID_DEPOSIT_LIQ_DST_CHAIN_ID();

    /// @dev thrown if index is invalid
    error INVALID_INDEX();

    /// @dev thrown if the chain id in the txdata is invalid
    error INVALID_TXDATA_CHAIN_ID();

    /// @dev thrown if the validation of bridge txData fails due to a destination call present
    error INVALID_TXDATA_NO_DESTINATIONCALL_ALLOWED();

    /// @dev thrown if the validation of bridge txData fails due to wrong receiver
    error INVALID_TXDATA_RECEIVER();

    /// @dev thrown if the validation of bridge txData fails due to wrong token
    error INVALID_TXDATA_TOKEN();

    /// @dev thrown if txData is not present (in case of xChain actions)
    error NO_TXDATA_PRESENT();

    /// STATE REGISTRY INPUT VALIDATION ERRORS
    /// ---------------------------------------------------------

    /// @dev thrown if payload is being updated with final amounts length different than amounts length
    error DIFFERENT_PAYLOAD_UPDATE_AMOUNTS_LENGTH();

    /// @dev thrown if payload is being updated with tx data length different than liq data length
    error DIFFERENT_PAYLOAD_UPDATE_TX_DATA_LENGTH();

    /// @dev thrown if keeper update final token is different than the vault underlying
    error INVALID_UPDATE_FINAL_TOKEN();

    /// @dev thrown if broadcast finality for wormhole is invalid
    error INVALID_BROADCAST_FINALITY();

    /// @dev thrown if amb id is not valid leading to an address 0 of the implementation
    error INVALID_BRIDGE_ID();

    /// @dev thrown if chain id involved in xchain message is invalid
    error INVALID_CHAIN_ID();

    /// @dev thrown if payload update amount isn't equal to dst swapper amount
    error INVALID_DST_SWAP_AMOUNT();

    /// @dev thrown if message amb and proof amb are the same
    error INVALID_PROOF_BRIDGE_ID();

    /// @dev thrown if order of proof AMBs is incorrect, either duplicated or not incrementing
    error INVALID_PROOF_BRIDGE_IDS();

    /// @dev thrown if rescue data lengths are invalid
    error INVALID_RESCUE_DATA();

    /// @dev thrown if delay is invalid
    error INVALID_TIMELOCK_DELAY();

    /// @dev thrown if amounts being sent in update payload mean a negative slippage
    error NEGATIVE_SLIPPAGE();

    /// @dev thrown if slippage is outside of bounds
    error SLIPPAGE_OUT_OF_BOUNDS();

    /// SUPERPOSITION INPUT VALIDATION ERRORS
    /// ---------------------------------------------------------

    /// @dev thrown if src senders mismatch in state sync
    error SRC_SENDER_MISMATCH();

    /// @dev thrown if src tx types mismatch in state sync
    error SRC_TX_TYPE_MISMATCH();

    //////////////////////////////////////////////////////////////
    //                  EXECUTION ERRORS                        //
    //////////////////////////////////////////////////////////////
    ///@notice errors thrown due to function execution logic

    /// COMMON EXECUTION ERRORS
    /// ---------------------------------------------------------

    /// @dev thrown if the swap in a direct deposit resulted in insufficient tokens
    error DIRECT_DEPOSIT_SWAP_FAILED();

    /// @dev thrown if payload is not unique
    error DUPLICATE_PAYLOAD();

    /// @dev thrown if native tokens fail to be sent to superform contracts
    error FAILED_TO_SEND_NATIVE();

    /// @dev thrown if allowance is not correct to deposit
    error INSUFFICIENT_ALLOWANCE_FOR_DEPOSIT();

    /// @dev thrown if contract has insufficient balance for operations
    error INSUFFICIENT_BALANCE();

    /// @dev thrown if native amount is not at least equal to the amount in the request
    error INSUFFICIENT_NATIVE_AMOUNT();

    /// @dev thrown if payload cannot be decoded
    error INVALID_PAYLOAD();

    /// @dev thrown if payload status is invalid
    error INVALID_PAYLOAD_STATUS();

    /// @dev thrown if payload type is invalid
    error INVALID_PAYLOAD_TYPE();

    /// LIQUIDITY BRIDGE EXECUTION ERRORS
    /// ---------------------------------------------------------

    /// @dev thrown if we try to decode the final swap output token in a xChain liquidity bridging action
    error CANNOT_DECODE_FINAL_SWAP_OUTPUT_TOKEN();

    /// @dev thrown if liquidity bridge fails for erc20 or native tokens
    error FAILED_TO_EXECUTE_TXDATA(address token);

    /// @dev thrown if asset being used for deposit mismatches in multivault deposits
    error INVALID_DEPOSIT_TOKEN();

    /// STATE REGISTRY EXECUTION ERRORS
    /// ---------------------------------------------------------

    /// @dev thrown if bridge tokens haven't arrived to destination
    error BRIDGE_TOKENS_PENDING();

    /// @dev thrown if withdrawal tx data cannot be updated
    error CANNOT_UPDATE_WITHDRAW_TX_DATA();

    /// @dev thrown if rescue passed dispute deadline
    error DISPUTE_TIME_ELAPSED();

    /// @dev thrown if message failed to reach the specified level of quorum needed
    error INSUFFICIENT_QUORUM();

    /// @dev thrown if broadcast payload is invalid
    error INVALID_BROADCAST_PAYLOAD();

    /// @dev thrown if broadcast fee is invalid
    error INVALID_BROADCAST_FEE();

    /// @dev thrown if retry fees is less than required
    error INVALID_RETRY_FEE();

    /// @dev thrown if broadcast message type is wrong
    error INVALID_MESSAGE_TYPE();

    /// @dev thrown if payload hash is invalid during `retryMessage` on Layezero implementation
    error INVALID_PAYLOAD_HASH();

    /// @dev thrown if update payload function was called on a wrong payload
    error INVALID_PAYLOAD_UPDATE_REQUEST();

    /// @dev thrown if a state registry id is 0
    error INVALID_REGISTRY_ID();

    /// @dev thrown if a form state registry id is 0
    error INVALID_FORM_REGISTRY_ID();

    /// @dev thrown if trying to finalize the payload but the withdraw is still locked
    error LOCKED();

    /// @dev thrown if payload is already updated (during xChain deposits)
    error PAYLOAD_ALREADY_UPDATED();

    /// @dev thrown if payload is already processed
    error PAYLOAD_ALREADY_PROCESSED();

    /// @dev thrown if payload is not in UPDATED state
    error PAYLOAD_NOT_UPDATED();

    /// @dev thrown if rescue is still in timelocked state
    error RESCUE_LOCKED();

    /// @dev thrown if rescue is already proposed
    error RESCUE_ALREADY_PROPOSED();

    /// @dev thrown if payload hash is zero during `retryMessage` on Layezero implementation
    error ZERO_PAYLOAD_HASH();

    /// DST SWAPPER EXECUTION ERRORS
    /// ---------------------------------------------------------

    /// @dev thrown if process dst swap is tried for processed payload id
    error DST_SWAP_ALREADY_PROCESSED();

    /// @dev thrown if indices have duplicates
    error DUPLICATE_INDEX();

    /// @dev thrown if failed dst swap is already updated
    error FAILED_DST_SWAP_ALREADY_UPDATED();

    /// @dev thrown if indices are out of bounds
    error INDEX_OUT_OF_BOUNDS();

    /// @dev thrown if failed swap token amount is 0
    error INVALID_DST_SWAPPER_FAILED_SWAP();

    /// @dev thrown if failed swap token amount is not 0 and if token balance is less than amount (non zero)
    error INVALID_DST_SWAPPER_FAILED_SWAP_NO_TOKEN_BALANCE();

    /// @dev thrown if failed swap token amount is not 0 and if native amount is less than amount (non zero)
    error INVALID_DST_SWAPPER_FAILED_SWAP_NO_NATIVE_BALANCE();

    /// @dev forbid xChain deposits with destination swaps without interim token set (for user protection)
    error INVALID_INTERIM_TOKEN();

    /// @dev thrown if dst swap output is less than minimum expected
    error INVALID_SWAP_OUTPUT();

    /// FORM EXECUTION ERRORS
    /// ---------------------------------------------------------

    /// @dev thrown if try to forward 4626 share from the superform
    error CANNOT_FORWARD_4646_TOKEN();

    /// @dev thrown in KYCDAO form if no KYC token is present
    error NO_VALID_KYC_TOKEN();

    /// @dev thrown in forms where a certain functionality is not allowed or implemented
    error NOT_IMPLEMENTED();

    /// @dev thrown if form implementation is PAUSED, users cannot perform any action
    error PAUSED();

    /// @dev thrown if shares != deposit output or assets != redeem output when minting SuperPositions
    error VAULT_IMPLEMENTATION_FAILED();

    /// @dev thrown if withdrawal tx data is not updated
    error WITHDRAW_TOKEN_NOT_UPDATED();

    /// @dev thrown if withdrawal tx data is not updated
    error WITHDRAW_TX_DATA_NOT_UPDATED();

    /// @dev thrown when redeeming from vault yields zero collateral
    error WITHDRAW_ZERO_COLLATERAL();

    /// PAYMENT HELPER EXECUTION ERRORS
    /// ---------------------------------------------------------

    /// @dev thrown if chainlink is reporting an improper price
    error CHAINLINK_MALFUNCTION();

    /// @dev thrown if chainlink is reporting an incomplete round
    error CHAINLINK_INCOMPLETE_ROUND();

    /// @dev thrown if feed decimals is not 8
    error CHAINLINK_UNSUPPORTED_DECIMAL();

    /// EMERGENCY QUEUE EXECUTION ERRORS
    /// ---------------------------------------------------------

    /// @dev thrown if emergency withdraw is not queued
    error EMERGENCY_WITHDRAW_NOT_QUEUED();

    /// @dev thrown if emergency withdraw is already processed
    error EMERGENCY_WITHDRAW_PROCESSED_ALREADY();

    /// SUPERPOSITION EXECUTION ERRORS
    /// ---------------------------------------------------------

    /// @dev thrown if uri cannot be updated
    error DYNAMIC_URI_FROZEN();

    /// @dev thrown if tx history is not found while state sync
    error TX_HISTORY_NOT_FOUND();
}

File 9 of 14 : DataLib.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;

import { Error } from "src/libraries/Error.sol";

library DataLib {
    function packTxInfo(
        uint8 txType_,
        uint8 callbackType_,
        uint8 multi_,
        uint8 registryId_,
        address srcSender_,
        uint64 srcChainId_
    )
        internal
        pure
        returns (uint256 txInfo)
    {
        txInfo = uint256(txType_);
        txInfo |= uint256(callbackType_) << 8;
        txInfo |= uint256(multi_) << 16;
        txInfo |= uint256(registryId_) << 24;
        txInfo |= uint256(uint160(srcSender_)) << 32;
        txInfo |= uint256(srcChainId_) << 192;
    }

    function decodeTxInfo(uint256 txInfo_)
        internal
        pure
        returns (uint8 txType, uint8 callbackType, uint8 multi, uint8 registryId, address srcSender, uint64 srcChainId)
    {
        txType = uint8(txInfo_);
        callbackType = uint8(txInfo_ >> 8);
        multi = uint8(txInfo_ >> 16);
        registryId = uint8(txInfo_ >> 24);
        srcSender = address(uint160(txInfo_ >> 32));
        srcChainId = uint64(txInfo_ >> 192);
    }

    /// @dev returns the vault-form-chain pair of a superform
    /// @param superformId_ is the id of the superform
    /// @return superform_ is the address of the superform
    /// @return formImplementationId_ is the form id
    /// @return chainId_ is the chain id
    function getSuperform(uint256 superformId_)
        internal
        pure
        returns (address superform_, uint32 formImplementationId_, uint64 chainId_)
    {
        superform_ = address(uint160(superformId_));
        formImplementationId_ = uint32(superformId_ >> 160);
        chainId_ = uint64(superformId_ >> 192);

        if (chainId_ == 0) {
            revert Error.INVALID_CHAIN_ID();
        }
    }

    /// @dev returns the vault-form-chain pair of an array of superforms
    /// @param superformIds_  array of superforms
    /// @return superforms_ are the address of the vaults
    function getSuperforms(uint256[] memory superformIds_) internal pure returns (address[] memory superforms_) {
        uint256 len = superformIds_.length;
        superforms_ = new address[](len);

        for (uint256 i; i < len; ++i) {
            (superforms_[i],,) = getSuperform(superformIds_[i]);
        }
    }

    /// @dev returns the destination chain of a given superform
    /// @param superformId_ is the id of the superform
    /// @return chainId_ is the chain id
    function getDestinationChain(uint256 superformId_) internal pure returns (uint64 chainId_) {
        chainId_ = uint64(superformId_ >> 192);

        if (chainId_ == 0) {
            revert Error.INVALID_CHAIN_ID();
        }
    }

    /// @dev generates the superformId
    /// @param superform_ is the address of the superform
    /// @param formImplementationId_ is the type of the form
    /// @param chainId_ is the chain id on which the superform is deployed
    function packSuperform(
        address superform_,
        uint32 formImplementationId_,
        uint64 chainId_
    )
        internal
        pure
        returns (uint256 superformId_)
    {
        superformId_ = uint256(uint160(superform_));
        superformId_ |= uint256(formImplementationId_) << 160;
        superformId_ |= uint256(chainId_) << 192;
    }
}

File 10 of 14 : ProofLib.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;

import { AMBMessage } from "src/types/DataTypes.sol";

/// @dev generates proof for amb message and bytes encoded message
library ProofLib {
    function computeProof(AMBMessage memory message_) internal pure returns (bytes32) {
        return keccak256(abi.encode(message_));
    }

    function computeProofBytes(AMBMessage memory message_) internal pure returns (bytes memory) {
        return abi.encode(keccak256(abi.encode(message_)));
    }

    function computeProof(bytes memory message_) internal pure returns (bytes32) {
        return keccak256(message_);
    }

    function computeProofBytes(bytes memory message_) internal pure returns (bytes memory) {
        return abi.encode(keccak256(message_));
    }
}

File 11 of 14 : ArrayCastLib.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;

import { InitSingleVaultData, InitMultiVaultData, LiqRequest } from "src/types/DataTypes.sol";

/// @dev library to cast single values into array for streamlining helper functions
/// @notice not gas optimized, suggested for usage only in view/pure functions
library ArrayCastLib {
    function castLiqRequestToArray(LiqRequest memory value_) internal pure returns (LiqRequest[] memory values) {
        values = new LiqRequest[](1);

        values[0] = value_;
    }

    function castBoolToArray(bool value_) internal pure returns (bool[] memory values) {
        values = new bool[](1);

        values[0] = value_;
    }

    function castToMultiVaultData(InitSingleVaultData memory data_)
        internal
        pure
        returns (InitMultiVaultData memory castedData_)
    {
        uint256[] memory superformIds = new uint256[](1);
        superformIds[0] = data_.superformId;

        uint256[] memory amounts = new uint256[](1);
        amounts[0] = data_.amount;

        uint256[] memory outputAmounts = new uint256[](1);
        outputAmounts[0] = data_.outputAmount;

        uint256[] memory maxSlippage = new uint256[](1);
        maxSlippage[0] = data_.maxSlippage;

        LiqRequest[] memory liqData = new LiqRequest[](1);
        liqData[0] = data_.liqData;

        castedData_ = InitMultiVaultData(
            data_.payloadId,
            superformIds,
            amounts,
            outputAmounts,
            maxSlippage,
            liqData,
            castBoolToArray(data_.hasDstSwap),
            castBoolToArray(data_.retain4626),
            data_.receiverAddress,
            data_.extraFormData
        );
    }
}

File 12 of 14 : DataTypes.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;

/// @dev contains all the common struct and enums used for data communication between chains.

/// @dev There are two transaction types in Superform Protocol
enum TransactionType {
    DEPOSIT,
    WITHDRAW
}

/// @dev Message types can be INIT, RETURN (for successful Deposits) and FAIL (for failed withdraws)
enum CallbackType {
    INIT,
    RETURN,
    FAIL
}

/// @dev Payloads are stored, updated (deposits) or processed (finalized)
enum PayloadState {
    STORED,
    UPDATED,
    PROCESSED
}

/// @dev contains all the common struct used for interchain token transfers.
struct LiqRequest {
    /// @dev generated data
    bytes txData;
    /// @dev input token for deposits, desired output token on target liqDstChainId for withdraws. Must be set for
    /// txData to be updated on destination for withdraws
    address token;
    /// @dev intermediary token on destination. Relevant for xChain deposits where a destination swap is needed for
    /// validation purposes
    address interimToken;
    /// @dev what bridge to use to move tokens
    uint8 bridgeId;
    /// @dev dstChainId = liqDstchainId for deposits. For withdraws it is the target chain id for where the underlying
    /// is to be delivered
    uint64 liqDstChainId;
    /// @dev currently this amount is used as msg.value in the txData call.
    uint256 nativeAmount;
}

/// @dev main struct that holds required multi vault data for an action
struct MultiVaultSFData {
    // superformids must have same destination. Can have different underlyings
    uint256[] superformIds;
    uint256[] amounts; // on deposits, amount of token to deposit on dst, on withdrawals, superpositions to burn
    uint256[] outputAmounts; // on deposits, amount of shares to receive, on withdrawals, amount of assets to receive
    uint256[] maxSlippages;
    LiqRequest[] liqRequests; // if length = 1; amount = sum(amounts) | else  amounts must match the amounts being sent
    bytes permit2data;
    bool[] hasDstSwaps;
    bool[] retain4626s; // if true, we don't mint SuperPositions, and send the 4626 back to the user instead
    address receiverAddress;
    /// this address must always be an EOA otherwise funds may be lost
    address receiverAddressSP;
    /// this address can be a EOA or a contract that implements onERC1155Receiver. must always be set for deposits
    bytes extraFormData; // extraFormData
}

/// @dev main struct that holds required single vault data for an action
struct SingleVaultSFData {
    // superformids must have same destination. Can have different underlyings
    uint256 superformId;
    uint256 amount;
    uint256 outputAmount; // on deposits, amount of shares to receive, on withdrawals, amount of assets to receive
    uint256 maxSlippage;
    LiqRequest liqRequest; // if length = 1; amount = sum(amounts)| else  amounts must match the amounts being sent
    bytes permit2data;
    bool hasDstSwap;
    bool retain4626; // if true, we don't mint SuperPositions, and send the 4626 back to the user instead
    address receiverAddress;
    /// this address must always be an EOA otherwise funds may be lost
    address receiverAddressSP;
    /// this address can be a EOA or a contract that implements onERC1155Receiver. must always be set for deposits
    bytes extraFormData; // extraFormData
}

/// @dev overarching struct for multiDst requests with multi vaults
struct MultiDstMultiVaultStateReq {
    uint8[][] ambIds;
    uint64[] dstChainIds;
    MultiVaultSFData[] superformsData;
}

/// @dev overarching struct for single cross chain requests with multi vaults
struct SingleXChainMultiVaultStateReq {
    uint8[] ambIds;
    uint64 dstChainId;
    MultiVaultSFData superformsData;
}

/// @dev overarching struct for multiDst requests with single vaults
struct MultiDstSingleVaultStateReq {
    uint8[][] ambIds;
    uint64[] dstChainIds;
    SingleVaultSFData[] superformsData;
}

/// @dev overarching struct for single cross chain requests with single vaults
struct SingleXChainSingleVaultStateReq {
    uint8[] ambIds;
    uint64 dstChainId;
    SingleVaultSFData superformData;
}

/// @dev overarching struct for single direct chain requests with single vaults
struct SingleDirectSingleVaultStateReq {
    SingleVaultSFData superformData;
}

/// @dev overarching struct for single direct chain requests with multi vaults
struct SingleDirectMultiVaultStateReq {
    MultiVaultSFData superformData;
}

/// @dev struct for SuperRouter with re-arranged data for the message (contains the payloadId)
/// @dev realize that receiverAddressSP is not passed, only needed on source chain to mint
struct InitMultiVaultData {
    uint256 payloadId;
    uint256[] superformIds;
    uint256[] amounts;
    uint256[] outputAmounts;
    uint256[] maxSlippages;
    LiqRequest[] liqData;
    bool[] hasDstSwaps;
    bool[] retain4626s;
    address receiverAddress;
    bytes extraFormData;
}

/// @dev struct for SuperRouter with re-arranged data for the message (contains the payloadId)
struct InitSingleVaultData {
    uint256 payloadId;
    uint256 superformId;
    uint256 amount;
    uint256 outputAmount;
    uint256 maxSlippage;
    LiqRequest liqData;
    bool hasDstSwap;
    bool retain4626;
    address receiverAddress;
    bytes extraFormData;
}

/// @dev struct for Emergency Queue
struct QueuedWithdrawal {
    address receiverAddress;
    uint256 superformId;
    uint256 amount;
    uint256 srcPayloadId;
    bool isProcessed;
}

/// @dev all statuses of the timelock payload
enum TimelockStatus {
    UNAVAILABLE,
    PENDING,
    PROCESSED
}

/// @dev holds information about the timelock payload
struct TimelockPayload {
    uint8 isXChain;
    uint64 srcChainId;
    uint256 lockedTill;
    InitSingleVaultData data;
    TimelockStatus status;
}

/// @dev struct that contains the type of transaction, callback flags and other identification, as well as the vaults
/// data in params
struct AMBMessage {
    uint256 txInfo; // tight packing of  TransactionType txType,  CallbackType flag  if multi/single vault, registry id,
        // srcSender and srcChainId
    bytes params; // decoding txInfo will point to the right datatype of params. Refer PayloadHelper.sol
}

/// @dev struct that contains the information required for broadcasting changes
struct BroadcastMessage {
    bytes target;
    bytes32 messageType;
    bytes message;
}

/// @dev struct that contains info on returned data from destination
struct ReturnMultiData {
    uint256 payloadId;
    uint256[] superformIds;
    uint256[] amounts;
}

/// @dev struct that contains info on returned data from destination
struct ReturnSingleData {
    uint256 payloadId;
    uint256 superformId;
    uint256 amount;
}

/// @dev struct that contains the data on the fees to pay to the AMBs
struct AMBExtraData {
    uint256[] gasPerAMB;
    bytes[] extraDataPerAMB;
}

/// @dev struct that contains the data on the fees to pay to the AMBs on broadcasts
struct BroadCastAMBExtraData {
    uint256[] gasPerDst;
    bytes[] extraDataPerDst;
}

File 13 of 14 : AggregatorV3Interface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface AggregatorV3Interface {
    function decimals() external view returns (uint8);

    function description() external view returns (string memory);

    function version() external view returns (uint256);

    function getRoundData(uint80 _roundId)
        external
        view
        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);

    function latestRoundData()
        external
        view
        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
}

File 14 of 14 : IAccessControl.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)

pragma solidity ^0.8.20;

/**
 * @dev External interface of AccessControl declared to support ERC-165 detection.
 */
interface IAccessControl {
    /**
     * @dev The `account` is missing a role.
     */
    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);

    /**
     * @dev The caller of a function is not the expected one.
     *
     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
     */
    error AccessControlBadConfirmation();

    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `callerConfirmation`.
     */
    function renounceRole(bytes32 role, address callerConfirmation) external;
}

Settings
{
  "remappings": [
    "solmate/=lib/ERC1155A/lib/solmate/src/",
    "ERC1155A/=lib/ERC1155A/src/",
    "@openzeppelin/contracts/=lib/ERC1155A/lib/openzeppelin-contracts/contracts/",
    "ds-test/=lib/ds-test/src/",
    "erc4626-tests/=lib/ERC1155A/lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-contracts/=lib/ERC1155A/lib/openzeppelin-contracts/",
    "pigeon/=lib/pigeon/src/",
    "solady/=lib/pigeon/lib/solady/",
    "super-vaults/=lib/super-vaults/src/",
    "v2-core/=lib/super-vaults/lib/v2-core/contracts/",
    "v2-periphery/=lib/super-vaults/lib/v2-periphery/contracts/",
    "v3-core/=lib/super-vaults/lib/v3-core/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"superRegistry_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ARRAY_LENGTH_MISMATCH","type":"error"},{"inputs":[],"name":"BLOCK_CHAIN_ID_OUT_OF_BOUNDS","type":"error"},{"inputs":[],"name":"CHAINLINK_INCOMPLETE_ROUND","type":"error"},{"inputs":[],"name":"CHAINLINK_MALFUNCTION","type":"error"},{"inputs":[],"name":"CHAINLINK_UNSUPPORTED_DECIMAL","type":"error"},{"inputs":[],"name":"INVALID_CHAIN_ID","type":"error"},{"inputs":[],"name":"INVALID_NATIVE_TOKEN_PRICE","type":"error"},{"inputs":[],"name":"INVALID_PAYLOAD_ID","type":"error"},{"inputs":[],"name":"NOT_PAYMENT_ADMIN","type":"error"},{"inputs":[],"name":"NOT_PROTOCOL_ADMIN","type":"error"},{"inputs":[],"name":"ZERO_ADDRESS","type":"error"},{"inputs":[],"name":"ZERO_INPUT_VALUE","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"chainId_","type":"uint64"},{"components":[{"internalType":"address","name":"nativeFeedOracle","type":"address"},{"internalType":"address","name":"gasPriceOracle","type":"address"},{"internalType":"uint256","name":"swapGasUsed","type":"uint256"},{"internalType":"uint256","name":"updateDepositGasUsed","type":"uint256"},{"internalType":"uint256","name":"depositGasUsed","type":"uint256"},{"internalType":"uint256","name":"withdrawGasUsed","type":"uint256"},{"internalType":"uint256","name":"defaultNativePrice","type":"uint256"},{"internalType":"uint256","name":"defaultGasPrice","type":"uint256"},{"internalType":"uint256","name":"dstGasPerByte","type":"uint256"},{"internalType":"uint256","name":"ackGasCost","type":"uint256"},{"internalType":"uint256","name":"timelockCost","type":"uint256"},{"internalType":"uint256","name":"emergencyCost","type":"uint256"},{"internalType":"uint256","name":"updateWithdrawGasUsed","type":"uint256"}],"indexed":false,"internalType":"struct IPaymentHelperV2.PaymentHelperConfig","name":"config_","type":"tuple"}],"name":"ChainConfigAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"chainId_","type":"uint64"},{"indexed":true,"internalType":"uint256","name":"configType_","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"config_","type":"bytes"}],"name":"ChainConfigUpdated","type":"event"},{"inputs":[],"name":"CHAIN_ID","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"ackGasCost","outputs":[{"internalType":"uint256","name":"gasForAck","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId_","type":"uint64"},{"components":[{"internalType":"address","name":"nativeFeedOracle","type":"address"},{"internalType":"address","name":"gasPriceOracle","type":"address"},{"internalType":"uint256","name":"swapGasUsed","type":"uint256"},{"internalType":"uint256","name":"updateDepositGasUsed","type":"uint256"},{"internalType":"uint256","name":"depositGasUsed","type":"uint256"},{"internalType":"uint256","name":"withdrawGasUsed","type":"uint256"},{"internalType":"uint256","name":"defaultNativePrice","type":"uint256"},{"internalType":"uint256","name":"defaultGasPrice","type":"uint256"},{"internalType":"uint256","name":"dstGasPerByte","type":"uint256"},{"internalType":"uint256","name":"ackGasCost","type":"uint256"},{"internalType":"uint256","name":"timelockCost","type":"uint256"},{"internalType":"uint256","name":"emergencyCost","type":"uint256"},{"internalType":"uint256","name":"updateWithdrawGasUsed","type":"uint256"}],"internalType":"struct IPaymentHelperV2.PaymentHelperConfig","name":"config_","type":"tuple"}],"name":"addRemoteChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64[]","name":"chainIds_","type":"uint64[]"},{"components":[{"internalType":"address","name":"nativeFeedOracle","type":"address"},{"internalType":"address","name":"gasPriceOracle","type":"address"},{"internalType":"uint256","name":"swapGasUsed","type":"uint256"},{"internalType":"uint256","name":"updateDepositGasUsed","type":"uint256"},{"internalType":"uint256","name":"depositGasUsed","type":"uint256"},{"internalType":"uint256","name":"withdrawGasUsed","type":"uint256"},{"internalType":"uint256","name":"defaultNativePrice","type":"uint256"},{"internalType":"uint256","name":"defaultGasPrice","type":"uint256"},{"internalType":"uint256","name":"dstGasPerByte","type":"uint256"},{"internalType":"uint256","name":"ackGasCost","type":"uint256"},{"internalType":"uint256","name":"timelockCost","type":"uint256"},{"internalType":"uint256","name":"emergencyCost","type":"uint256"},{"internalType":"uint256","name":"updateWithdrawGasUsed","type":"uint256"}],"internalType":"struct IPaymentHelperV2.PaymentHelperConfig[]","name":"configs_","type":"tuple[]"}],"name":"addRemoteChains","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId_","type":"uint64"},{"internalType":"uint256[]","name":"configTypes_","type":"uint256[]"},{"internalType":"bytes[]","name":"configs_","type":"bytes[]"}],"name":"batchUpdateRemoteChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64[]","name":"chainIds_","type":"uint64[]"},{"internalType":"uint256[][]","name":"configTypes_","type":"uint256[][]"},{"internalType":"bytes[][]","name":"configs_","type":"bytes[][]"}],"name":"batchUpdateRemoteChains","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"dstChainId_","type":"uint64"},{"internalType":"uint8[]","name":"ambIds_","type":"uint8[]"},{"internalType":"bytes","name":"message_","type":"bytes"}],"name":"calculateAMBData","outputs":[{"internalType":"uint256","name":"totalFees","type":"uint256"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"depositGasUsed","outputs":[{"internalType":"uint256","name":"gasForDeposit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"emergencyCost","outputs":[{"internalType":"uint256","name":"gasForEmergency","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8[]","name":"ambIds_","type":"uint8[]"},{"internalType":"uint64","name":"dstChainId_","type":"uint64"},{"internalType":"bytes","name":"message_","type":"bytes"},{"internalType":"bytes[]","name":"extraData_","type":"bytes[]"}],"name":"estimateAMBFees","outputs":[{"internalType":"uint256","name":"totalFees","type":"uint256"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"payloadId_","type":"uint256"}],"name":"estimateAckCost","outputs":[{"internalType":"uint256","name":"totalFees","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"multi","type":"bool"},{"internalType":"uint8[]","name":"ackAmbIds","type":"uint8[]"},{"internalType":"uint64","name":"srcChainId","type":"uint64"}],"name":"estimateAckCostDefault","outputs":[{"internalType":"uint256","name":"totalFees","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"multi","type":"bool"},{"internalType":"uint8[]","name":"ackAmbIds","type":"uint8[]"},{"internalType":"uint64","name":"srcChainId","type":"uint64"}],"name":"estimateAckCostDefaultNativeSource","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint8[][]","name":"ambIds","type":"uint8[][]"},{"internalType":"uint64[]","name":"dstChainIds","type":"uint64[]"},{"components":[{"internalType":"uint256[]","name":"superformIds","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"outputAmounts","type":"uint256[]"},{"internalType":"uint256[]","name":"maxSlippages","type":"uint256[]"},{"components":[{"internalType":"bytes","name":"txData","type":"bytes"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"interimToken","type":"address"},{"internalType":"uint8","name":"bridgeId","type":"uint8"},{"internalType":"uint64","name":"liqDstChainId","type":"uint64"},{"internalType":"uint256","name":"nativeAmount","type":"uint256"}],"internalType":"struct LiqRequest[]","name":"liqRequests","type":"tuple[]"},{"internalType":"bytes","name":"permit2data","type":"bytes"},{"internalType":"bool[]","name":"hasDstSwaps","type":"bool[]"},{"internalType":"bool[]","name":"retain4626s","type":"bool[]"},{"internalType":"address","name":"receiverAddress","type":"address"},{"internalType":"address","name":"receiverAddressSP","type":"address"},{"internalType":"bytes","name":"extraFormData","type":"bytes"}],"internalType":"struct MultiVaultSFData[]","name":"superformsData","type":"tuple[]"}],"internalType":"struct MultiDstMultiVaultStateReq","name":"req_","type":"tuple"},{"internalType":"bool","name":"isDeposit_","type":"bool"}],"name":"estimateMultiDstMultiVault","outputs":[{"internalType":"uint256","name":"liqAmount","type":"uint256"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint256","name":"totalAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint8[][]","name":"ambIds","type":"uint8[][]"},{"internalType":"uint64[]","name":"dstChainIds","type":"uint64[]"},{"components":[{"internalType":"uint256","name":"superformId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"outputAmount","type":"uint256"},{"internalType":"uint256","name":"maxSlippage","type":"uint256"},{"components":[{"internalType":"bytes","name":"txData","type":"bytes"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"interimToken","type":"address"},{"internalType":"uint8","name":"bridgeId","type":"uint8"},{"internalType":"uint64","name":"liqDstChainId","type":"uint64"},{"internalType":"uint256","name":"nativeAmount","type":"uint256"}],"internalType":"struct LiqRequest","name":"liqRequest","type":"tuple"},{"internalType":"bytes","name":"permit2data","type":"bytes"},{"internalType":"bool","name":"hasDstSwap","type":"bool"},{"internalType":"bool","name":"retain4626","type":"bool"},{"internalType":"address","name":"receiverAddress","type":"address"},{"internalType":"address","name":"receiverAddressSP","type":"address"},{"internalType":"bytes","name":"extraFormData","type":"bytes"}],"internalType":"struct SingleVaultSFData[]","name":"superformsData","type":"tuple[]"}],"internalType":"struct MultiDstSingleVaultStateReq","name":"req_","type":"tuple"},{"internalType":"bool","name":"isDeposit_","type":"bool"}],"name":"estimateMultiDstSingleVault","outputs":[{"internalType":"uint256","name":"liqAmount","type":"uint256"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint256","name":"totalAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"uint256[]","name":"superformIds","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"outputAmounts","type":"uint256[]"},{"internalType":"uint256[]","name":"maxSlippages","type":"uint256[]"},{"components":[{"internalType":"bytes","name":"txData","type":"bytes"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"interimToken","type":"address"},{"internalType":"uint8","name":"bridgeId","type":"uint8"},{"internalType":"uint64","name":"liqDstChainId","type":"uint64"},{"internalType":"uint256","name":"nativeAmount","type":"uint256"}],"internalType":"struct LiqRequest[]","name":"liqRequests","type":"tuple[]"},{"internalType":"bytes","name":"permit2data","type":"bytes"},{"internalType":"bool[]","name":"hasDstSwaps","type":"bool[]"},{"internalType":"bool[]","name":"retain4626s","type":"bool[]"},{"internalType":"address","name":"receiverAddress","type":"address"},{"internalType":"address","name":"receiverAddressSP","type":"address"},{"internalType":"bytes","name":"extraFormData","type":"bytes"}],"internalType":"struct MultiVaultSFData","name":"superformData","type":"tuple"}],"internalType":"struct SingleDirectMultiVaultStateReq","name":"req_","type":"tuple"},{"internalType":"bool","name":"isDeposit_","type":"bool"}],"name":"estimateSingleDirectMultiVault","outputs":[{"internalType":"uint256","name":"liqAmount","type":"uint256"},{"internalType":"uint256","name":"dstOrSameChainAmt","type":"uint256"},{"internalType":"uint256","name":"totalAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"uint256","name":"superformId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"outputAmount","type":"uint256"},{"internalType":"uint256","name":"maxSlippage","type":"uint256"},{"components":[{"internalType":"bytes","name":"txData","type":"bytes"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"interimToken","type":"address"},{"internalType":"uint8","name":"bridgeId","type":"uint8"},{"internalType":"uint64","name":"liqDstChainId","type":"uint64"},{"internalType":"uint256","name":"nativeAmount","type":"uint256"}],"internalType":"struct LiqRequest","name":"liqRequest","type":"tuple"},{"internalType":"bytes","name":"permit2data","type":"bytes"},{"internalType":"bool","name":"hasDstSwap","type":"bool"},{"internalType":"bool","name":"retain4626","type":"bool"},{"internalType":"address","name":"receiverAddress","type":"address"},{"internalType":"address","name":"receiverAddressSP","type":"address"},{"internalType":"bytes","name":"extraFormData","type":"bytes"}],"internalType":"struct SingleVaultSFData","name":"superformData","type":"tuple"}],"internalType":"struct SingleDirectSingleVaultStateReq","name":"req_","type":"tuple"},{"internalType":"bool","name":"isDeposit_","type":"bool"}],"name":"estimateSingleDirectSingleVault","outputs":[{"internalType":"uint256","name":"liqAmount","type":"uint256"},{"internalType":"uint256","name":"dstOrSameChainAmt","type":"uint256"},{"internalType":"uint256","name":"totalAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint8[]","name":"ambIds","type":"uint8[]"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"components":[{"internalType":"uint256[]","name":"superformIds","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"outputAmounts","type":"uint256[]"},{"internalType":"uint256[]","name":"maxSlippages","type":"uint256[]"},{"components":[{"internalType":"bytes","name":"txData","type":"bytes"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"interimToken","type":"address"},{"internalType":"uint8","name":"bridgeId","type":"uint8"},{"internalType":"uint64","name":"liqDstChainId","type":"uint64"},{"internalType":"uint256","name":"nativeAmount","type":"uint256"}],"internalType":"struct LiqRequest[]","name":"liqRequests","type":"tuple[]"},{"internalType":"bytes","name":"permit2data","type":"bytes"},{"internalType":"bool[]","name":"hasDstSwaps","type":"bool[]"},{"internalType":"bool[]","name":"retain4626s","type":"bool[]"},{"internalType":"address","name":"receiverAddress","type":"address"},{"internalType":"address","name":"receiverAddressSP","type":"address"},{"internalType":"bytes","name":"extraFormData","type":"bytes"}],"internalType":"struct MultiVaultSFData","name":"superformsData","type":"tuple"}],"internalType":"struct SingleXChainMultiVaultStateReq","name":"req_","type":"tuple"},{"internalType":"bool","name":"isDeposit_","type":"bool"}],"name":"estimateSingleXChainMultiVault","outputs":[{"internalType":"uint256","name":"liqAmount","type":"uint256"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint256","name":"totalAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint8[]","name":"ambIds","type":"uint8[]"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"components":[{"internalType":"uint256","name":"superformId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"outputAmount","type":"uint256"},{"internalType":"uint256","name":"maxSlippage","type":"uint256"},{"components":[{"internalType":"bytes","name":"txData","type":"bytes"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"interimToken","type":"address"},{"internalType":"uint8","name":"bridgeId","type":"uint8"},{"internalType":"uint64","name":"liqDstChainId","type":"uint64"},{"internalType":"uint256","name":"nativeAmount","type":"uint256"}],"internalType":"struct LiqRequest","name":"liqRequest","type":"tuple"},{"internalType":"bytes","name":"permit2data","type":"bytes"},{"internalType":"bool","name":"hasDstSwap","type":"bool"},{"internalType":"bool","name":"retain4626","type":"bool"},{"internalType":"address","name":"receiverAddress","type":"address"},{"internalType":"address","name":"receiverAddressSP","type":"address"},{"internalType":"bytes","name":"extraFormData","type":"bytes"}],"internalType":"struct SingleVaultSFData","name":"superformData","type":"tuple"}],"internalType":"struct SingleXChainSingleVaultStateReq","name":"req_","type":"tuple"},{"internalType":"bool","name":"isDeposit_","type":"bool"}],"name":"estimateSingleXChainSingleVault","outputs":[{"internalType":"uint256","name":"liqAmount","type":"uint256"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint256","name":"totalAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"extraDataForTransmuter","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"gasPerByte","outputs":[{"internalType":"uint256","name":"gasPerByte","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"gasPrice","outputs":[{"internalType":"uint256","name":"defaultGasPrice","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"gasPriceOracle","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRegisterTransmuterAMBData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"nativeFeedOracle","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"nativePrice","outputs":[{"internalType":"uint256","name":"defaultNativePrice","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"superRegistry","outputs":[{"internalType":"contract ISuperRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"swapGasUsed","outputs":[{"internalType":"uint256","name":"gasForSwap","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"timelockCost","outputs":[{"internalType":"uint256","name":"gasForTimelock","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"updateDepositGasUsed","outputs":[{"internalType":"uint256","name":"gasForUpdateDeposit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"extraDataForTransmuter_","type":"bytes"}],"name":"updateRegisterAERC20Params","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId_","type":"uint64"},{"internalType":"uint256","name":"configType_","type":"uint256"},{"internalType":"bytes","name":"config_","type":"bytes"}],"name":"updateRemoteChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"updateWithdrawGasUsed","outputs":[{"internalType":"uint256","name":"gasForUpdateWithdraw","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"}],"name":"withdrawGasUsed","outputs":[{"internalType":"uint256","name":"gasForWithdraw","type":"uint256"}],"stateMutability":"view","type":"function"}]

60c06040523480156200001157600080fd5b5060405162005f6f38038062005f6f8339810160408190526200003491620000a4565b6001600160a01b0381166200005c5760405163538ba4f960e01b815260040160405180910390fd5b6001600160401b034611156200008557604051637ecdf93360e01b815260040160405180910390fd5b6001600160401b03461660a0526001600160a01b0316608052620000d6565b600060208284031215620000b757600080fd5b81516001600160a01b0381168114620000cf57600080fd5b9392505050565b60805160a051615de06200018f600039600081816104a7015281816106600152818161110c01528181611f98015281816121cf015281816124810152818161271401528181613282015281816138a2015281816138e40152818161396c0152613c710152600081816102e50152818161069a015281816108b50152818161124901528181611590015281816116cd01528181611bcf0152818161220b015281816124bd0152818161265e01526134f00152615de06000f3fe608060405234801561001057600080fd5b50600436106102065760003560e01c80637abae2511161011a578063b9694b52116100ad578063d8bb4f4e1161007c578063d8bb4f4e146105a6578063da163637146105c6578063ea7a8392146105ce578063f3afdd88146105e1578063f3d80846146105f457600080fd5b8063b9694b521461055a578063c2085f461461056d578063c97c55b014610580578063d70139741461059357600080fd5b80639d57d64e116100e95780639d57d64e14610501578063a8a0838914610514578063a9ce464814610527578063b1752d591461054757600080fd5b80637abae2511461046d5780637f7aecb51461048257806385e1f4d0146104a2578063904b1a28146104e157600080fd5b80634545fc311161019d57806353d69edc1161016c57806353d69edc146103c4578063596703e7146103d957806361d26cae146103ec5780637504988b1461041f578063786c69f31461044d57600080fd5b80634545fc311461033b5780634786b4241461035b57806349c3af451461037b5780634c75c0d8146103a457600080fd5b80631f864be3116101d95780631f864be3146102bf57806324c73dda146102e05780633283166a1461030757806336c7fe1d1461032857600080fd5b80630292540b1461020b57806310c5fbe41461023e57806312c4da861461025e5780631f5ae58f1461029f575b600080fd5b61022b6102193660046140cb565b600c6020526000908152604090205481565b6040519081526020015b60405180910390f35b61022b61024c3660046140cb565b60046020526000908152604090205481565b61028761026c3660046140cb565b6000602081905290815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610235565b61022b6102ad3660046140cb565b600b6020526000908152604090205481565b6102d26102cd3660046142be565b610607565b6040516102359291906143c6565b6102877f000000000000000000000000000000000000000000000000000000000000000081565b61031a610315366004614461565b61082b565b60405161023592919061452c565b61022b610336366004614563565b61088a565b61022b6103493660046140cb565b60076020526000908152604090205481565b61022b6103693660046140cb565b60086020526000908152604090205481565b6102876103893660046140cb565b6001602052600090815260409020546001600160a01b031681565b61022b6103b23660046140cb565b60056020526000908152604090205481565b6103cc610a7b565b60405161023591906145c6565b61022b6103e73660046145d9565b610b0d565b6103ff6103fa36600461460a565b610f28565b604080519485526020850193909352918301526060820152608001610235565b61043261042d36600461466d565b6110c7565b60408051938452602084019290925290820152606001610235565b61022b61045b3660046140cb565b60036020526000908152604090205481565b61048061047b3660046146a2565b611226565b005b61022b6104903660046140cb565b60066020526000908152604090205481565b6104c97f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160401b039091168152602001610235565b61022b6104ef3660046140cb565b60096020526000908152604090205481565b61048061050f3660046146fa565b611367565b610480610522366004614794565b6114ab565b61022b6105353660046140cb565b60026020526000908152604090205481565b61022b610555366004614563565b611557565b6104806105683660046147d7565b61156d565b61048061057b36600461480b565b6116aa565b6103ff61058e36600461460a565b6117ef565b6103ff6105a136600461460a565b611963565b61022b6105b43660046140cb565b600a6020526000908152604090205481565b6103cc611b1e565b6104806105dc36600461488d565b611bac565b6103ff6105ef36600461460a565b611dbf565b61043261060236600461466d565b611f53565b835160009060609082816001600160401b03811115610628576106286140e8565b604051908082528060200260200182016040528015610651578160200160208202803683370190505b509050866001600160401b03167f00000000000000000000000000000000000000000000000000000000000000006001600160401b03161461081f5760005b8281101561081d577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630eff125d8a83815181106106d9576106d9614926565b60200260200101516040518263ffffffff1660e01b8152600401610706919060ff91909116815260200190565b602060405180830381865afa158015610723573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610747919061495c565b6001600160a01b031663ea98b147898989858151811061076957610769614926565b60200260200101516040518463ffffffff1660e01b815260040161078f93929190614979565b602060405180830381865afa1580156107ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d091906149b7565b8282815181106107e2576107e2614926565b60200260200101818152505081818151811061080057610800614926565b60200260200101518561081391906149e6565b9450600101610690565b505b91505094509492505050565b60006060600080600061084089898989612092565b92509250925060405180604001604052808481526020018381525060405160200161086b9190614a35565b60408051601f1981840301815291905290999098509650505050505050565b6000606084156109e95760405163bffc1e1360e01b81526001600160401b03841660048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063bffc1e1390602401602060405180830381865afa158015610904573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061092891906149b7565b90506000816001600160401b03811115610944576109446140e8565b60405190808252806020026020018201604052801561096d578160200160208202803683370190505b50905060005b828110156109a35760001982828151811061099057610990614926565b6020908102919091010152600101610973565b5060405180606001604052806000198152602001828152602001828152506040516020016109d19190614ab8565b60405160208183030381529060405292505050610a30565b506040805160608082018352600019808352602080840182815293850182815285519182019290925292518385015251828201528251808303909101815260809091019091525b610a7084846040518060400160405280600019815260200185815250604051602001610a5c9190614afb565b6040516020818303038152906040526123bc565b9150505b9392505050565b6060600d8054610a8a90614b20565b80601f0160208091040260200160405190810160405280929190818152602001828054610ab690614b20565b8015610b035780601f10610ad857610100808354040283529160200191610b03565b820191906000526020600020905b815481529060010190602001808311610ae657829003601f168201915b5050505050905090565b604080516101008101825260008082526020820181905291810182905260608082018190526080820181905260a0820183905260c0820183905260e08201526000610b777f55b101fc856aff484166c46ad33bc74831c135693c159b0092bb3b72254ffb6b612645565b9050806001600160a01b03166313c02a596040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bdb91906149b7565b808352841115610bfe576040516355da2ca360e11b815260040160405180910390fd5b6040516336445ffd60e01b8152600481018590526001600160a01b038216906336445ffd90602401602060405180830381865afa158015610c43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6791906149b7565b602083015260405163361ad42b60e01b8152600481018590526001600160a01b0382169063361ad42b90602401600060405180830381865afa158015610cb1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cd99190810190614b99565b6060830152602082015160c081811c9084015260ff601082901c811660a085015260089190911c166040830181905215610d17575060009392505050565b8160a0015160ff16600103610d8c5760008260600151806020019051810190610d409190614dbd565b60408051606081018252855181526020808401518183015282840151828401529151929350610d7192909101614ab8565b60408051601f19818403018152919052606084015250610df7565b60008260600151806020019051810190610da69190614f46565b60408051606080820183528651808352602085810151818501908152958501519385019384528451908101919091529351848401529051838201528151808403820181526080909301909152840152505b604051636c181b2760e11b8152600481018590526001600160a01b0382169063d830364e90602401600060405180830381865afa158015610e3c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610e64919081019061500c565b608083015260408051808201918290526336445ffd60e01b90915260448101859052806001600160a01b0383166336445ffd60648301602060405180830381865afa158015610eb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610edb91906149b7565b81526060840151602091820152604051610ef6929101614afb565b60408051601f1981840301815291905260e08301819052608083015160c0840151610f20926123bc565b949350505050565b6000806000806000610f47600080516020615d8b833981519152612645565b6040805160018082528183019092529192506000919060208083019080368337019050509050610f7d6040890160208a016140cb565b81600081518110610f9057610f90614926565b6001600160401b03929092166020928302919091018201526040805160018082528183019092526060926000929082015b610fc9613fb8565b815260200190600190039081610fc1579050509050610feb60408b018b61509a565b610ff49061526d565b8160008151811061100757611007614926565b602002602001018190525061109c6040518060e00160405280600081526020018581526020018c806000019061103d9190615279565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509082525060208101859052604081018490526001600160a01b03871660608201528b15156080909101526126d7565b91995097509550876110ae87896149e6565b6110b891906149e6565b94505050505092959194509250565b6000806000806110e4600080516020615d8b833981519152612645565b60408051600180825281830190925291925060009190602080830190803683370190505090507f00000000000000000000000000000000000000000000000000000000000000008160008151811061113e5761113e614926565b6001600160401b03929092166020928302919091018201526040805160018082528183019092526060926000929082015b611177614047565b81526020019060019003908161116f579050509050611196898061509a565b61119f90615548565b816000815181106111b2576111b2614926565b602002602001018190525060606112066040518060e0016040528060008152602001868152602001838152602001848152602001858152602001876001600160a01b031681526020018b15158152506126d7565b919950909750611218905087896149e6565b955050505050509250925092565b6040516321f8a72160e01b8152600080516020615d4b83398151915260048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa158015611298573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112bc919061495c565b604051632474521560e21b8152600080516020615d6b83398151915260048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015611316573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133a9190615554565b61135757604051633108430360e11b815260040160405180910390fd5b611362838383612c86565b505050565b61137e600080516020615d4b833981519152612645565b6040516369ac88f960e11b81523360048201526001600160a01b03919091169063d35911f290602401602060405180830381865afa1580156113c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113e89190615554565b61140557604051633721555560e21b815260040160405180910390fd5b8260008190036114285760405163021b4ea160e01b815260040160405180910390fd5b80821461144857604051634456f5e960e11b815260040160405180910390fd5b60005b818110156114a35761149b86868381811061146857611468614926565b905060200201602081019061147d91906140cb565b85858481811061148f5761148f614926565b90506101a00201613051565b60010161144b565b505050505050565b6114c2600080516020615d4b833981519152612645565b6040516369ac88f960e11b81523360048201526001600160a01b03919091169063d35911f290602401602060405180830381865afa158015611508573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061152c9190615554565b61154957604051633721555560e21b815260040160405180910390fd5b6115538282613051565b5050565b6000610f208261156886868661088a565b613269565b6040516321f8a72160e01b8152600080516020615d4b83398151915260048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa1580156115df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611603919061495c565b604051632474521560e21b8152600080516020615d6b83398151915260048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa15801561165d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116819190615554565b61169e57604051633108430360e11b815260040160405180910390fd5b600d61155382826155b9565b6040516321f8a72160e01b8152600080516020615d4b83398151915260048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa15801561171c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611740919061495c565b604051632474521560e21b8152600080516020615d6b83398151915260048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa15801561179a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117be9190615554565b6117db57604051633108430360e11b815260040160405180910390fd5b6117e88585858585613305565b5050505050565b600080600080600061180e600080516020615d8b833981519152612645565b60408051600180825281830190925291925060009190602080830190803683370190505090506118446040890160208a016140cb565b8160008151811061185757611857614926565b6001600160401b03929092166020928302919091018201526040805160018082528183019092526060926000929082015b611890614047565b8152602001906001900390816118885790505090506118b260408b018b61509a565b6118bb90615548565b816000815181106118ce576118ce614926565b602002602001018190525061109c6040518060e00160405280600081526020018581526020018c80600001906119049190615279565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509082525060208101849052604081018590526001600160a01b03871660608201528b15156080909101526126d7565b6000808080806119766020880188615279565b90509050600080600080611997600080516020615d8b833981519152612645565b9050606060005b86811015611af757611ac46040518060e001604052808381526020018f80602001906119ca9190615279565b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505081526020018f8060000190611a1f9190615279565b85818110611a2f57611a2f614926565b9050602002810190611a419190615279565b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505081526020018481526020018f8060400190611a9c9190615279565b611aa591615678565b8152602001856001600160a01b031681526020018e15158152506126d7565b91975095509350611ad5868c6149e6565b9a50611ae1858b6149e6565b9950611aed848a6149e6565b985060010161199e565b5089611b03898b6149e6565b611b0d91906149e6565b965050505050505092959194509250565b600d8054611b2b90614b20565b80601f0160208091040260200160405190810160405280929190818152602001828054611b5790614b20565b8015611ba45780601f10611b7957610100808354040283529160200191611ba4565b820191906000526020600020905b815481529060010190602001808311611b8757829003601f168201915b505050505081565b6040516321f8a72160e01b8152600080516020615d4b83398151915260048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa158015611c1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c42919061495c565b604051632474521560e21b8152600080516020615d6b83398151915260048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015611c9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cc09190615554565b611cdd57604051633108430360e11b815260040160405180910390fd5b846000819003611d005760405163021b4ea160e01b815260040160405180910390fd5b8084148015611d0e57508082145b611d2b57604051634456f5e960e11b815260040160405180910390fd5b60005b81811015611db557611dad888883818110611d4b57611d4b614926565b9050602002016020810190611d6091906140cb565b878784818110611d7257611d72614926565b9050602002810190611d849190615279565b878786818110611d9657611d96614926565b9050602002810190611da89190615279565b613305565b600101611d2e565b5050505050505050565b600080808080611dd26020880188615279565b90509050600080600080611df3600080516020615d8b833981519152612645565b9050606060005b86811015611af757611f206040518060e001604052808381526020018f8060200190611e269190615279565b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505081526020018f8060000190611e7b9190615279565b85818110611e8b57611e8b614926565b9050602002810190611e9d9190615279565b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505081526020018f8060400190611ef29190615279565b611efb916156df565b8152602001848152602001856001600160a01b031681526020018e15158152506126d7565b91975095509350611f31868c6149e6565b9a50611f3d858b6149e6565b9950611f49848a6149e6565b9850600101611dfa565b600080600080611f70600080516020615d8b833981519152612645565b60408051600180825281830190925291925060009190602080830190803683370190505090507f000000000000000000000000000000000000000000000000000000000000000081600081518110611fca57611fca614926565b6001600160401b039290921660209283029190910190910152604080516001808252818301909252600091816020015b612002613fb8565b815260200190600190039081611ffa579050509050612021888061509a565b61202a9061526d565b8160008151811061203d5761203d614926565b60200260200101819052506060806112066040518060e0016040528060008152602001868152602001838152602001848152602001858152602001876001600160a01b031681526020018b15158152506126d7565b606080600080848060200190518101906120ac9190615746565b9050868682602001516040516020016120c7939291906157d2565b60408051601f1981840301815291815260208381019290925280518883028181018401909252888152889261211d928c92918c9186918291908501908490808284376000920191909152508b92506133df915050565b9350806001600160401b03811115612137576121376140e8565b604051908082528060200260200182016040528015612160578160200160208202803683370190505b509450600060405180604001604052806000198152602001888051906020012060405160200161219291815260200190565b60408051601f198184030181529181529152516121b29190602001614afb565b6040516020818303038152906040529050896001600160401b03167f00000000000000000000000000000000000000000000000000000000000000006001600160401b0316146123af5760005b828110156123ad5760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630eff125d8c8c8581811061224a5761224a614926565b905060200201602081019061225f9190615822565b6040516001600160e01b031960e084901b16815260ff9091166004820152602401602060405180830381865afa15801561229d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122c1919061495c565b6001600160a01b031663ea98b1478d846000036122fd57876040516020016122e99190614afb565b6040516020818303038152906040526122ff565b855b8a868151811061231157612311614926565b60200260200101516040518463ffffffff1660e01b815260040161233793929190614979565b602060405180830381865afa158015612354573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061237891906149b7565b905061238481876149e6565b95508088838151811061239957612399614926565b6020908102919091010152506001016121ff565b505b5050509450945094915050565b8251600090816123cd8587866133df565b90506000848060200190518101906123e59190615746565b90508681602001516040516020016123fe92919061583f565b6040516020818303038152906040528160200181905250600060405180604001604052806000198152602001878051906020012060405160200161244491815260200190565b60408051601f198184030181529181529152516124649190602001614afb565b6040516020818303038152906040529050866001600160401b03167f00000000000000000000000000000000000000000000000000000000000000006001600160401b03161461263a5760005b848110156126385760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630eff125d8b84815181106124fc576124fc614926565b60200260200101516040518263ffffffff1660e01b8152600401612529919060ff91909116815260200190565b602060405180830381865afa158015612546573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061256a919061495c565b6001600160a01b031663ea98b1478a846000036125a657866040516020016125929190614afb565b6040516020818303038152906040526125a8565b855b8886815181106125ba576125ba614926565b60200260200101516040518463ffffffff1660e01b81526004016125e093929190614979565b602060405180830381865afa1580156125fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061262191906149b7565b905061262d81886149e6565b9650506001016124b1565b505b505050509392505050565b6040516321f8a72160e01b8152600481018290526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa1580156126ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126d1919061495c565b92915050565b60008060006127106040518060a00160405280600081526020016000815260200160008152602001600081526020016000151581525090565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160401b0316866020015187600001518151811061275657612756614926565b60200260200101516001600160401b03161415905060008260400181815250506000808760600151511190506000816127b8576127b388608001518960000151815181106127a6576127a6614926565b6020026020010151613642565b6127e2565b6127e288606001518960000151815181106127d5576127d5614926565b602002602001015161371c565b9050826127f0576000612820565b612820886040015189602001518a600001518151811061281257612812614926565b6020026020010151836123bc565b606085015281612831576001612856565b606088015188518151811061284857612848614926565b602002602001015160000151515b6020850152606084015161286a90876149e6565b95506000826128a6576128a189608001518a600001518151811061289057612890614926565b6020026020010151608001516137ac565b6128ca565b60608901518951815181106128bd576128bd614926565b6020026020010151608001515b90508860c0015115612a96576128df8161382c565b6128e990896149e6565b97508315612a915761292089602001518a600001518151811061290e5761290e614926565b60200260200101518660200151613875565b8560400181815161293191906149e6565b905250600083156129a55760005b866020015181101561299f5760608b01518b518151811061296257612962614926565b602002602001015160e00151818151811061297f5761297f614926565b60200260200101516129975761299482615890565b91505b60010161293f565b506129d8565b60808a01518a51815181106129bc576129bc614926565b602002602001015160e001516129d8576129d581615890565b90505b6129e181613898565b6129eb90896149e6565b9750600084612a2957612a248b608001518c6000015181518110612a1157612a11614926565b602002602001015160c001511515613912565b612a4d565b60608b01518b5181518110612a4057612a40614926565b602002602001015160c001515b9050612a7a8b602001518c6000015181518110612a6c57612a6c614926565b60200260200101518261395d565b87604001818151612a8b91906149e6565b90525050505b612beb565b8215612b3b5760005b8560200151811015612b3557612b198a606001518b6000015181518110612ac857612ac8614926565b6020026020010151600001518281518110612ae557612ae5614926565b60200260200101518b602001518c6000015181518110612b0757612b07614926565b60200260200101518c60a00151613a1a565b86604001818151612b2a91906149e6565b905250600101612a9f565b50612ba5565b612b9089608001518a6000015181518110612b5857612b58614926565b6020026020010151600001518a602001518b6000015181518110612b7e57612b7e614926565b60200260200101518b60a00151613a1a565b85604001818151612ba191906149e6565b9052505b8315612beb57612bd689602001518a6000015181518110612bc857612bc8614926565b602002602001015182613b16565b85604001818151612be791906149e6565b9052505b83612bf7576000612c2b565b612c2b8960c001518a602001518b6000015181518110612c1957612c19614926565b60200260200101518760200151613bbe565b85604001818151612c3c91906149e6565b905250602089015189518151612c6f9291908110612c5c57612c5c614926565b6020026020010151866040015186613c0a565b612c7990876149e6565b9799969850505050505050565b81600103612d1f57600081806020019051810190612ca4919061495c565b90506001600160a01b03811615801590612cca57506008612cc482613ccd565b60ff1614155b15612ce8576040516333339aa360e11b815260040160405180910390fd5b6001600160401b038416600090815260208190526040902080546001600160a01b0319166001600160a01b03929092169190911790555b81600203612db857600081806020019051810190612d3d919061495c565b90506001600160a01b03811615801590612d6357506008612d5d82613ccd565b60ff1614155b15612d81576040516333339aa360e11b815260040160405180910390fd5b6001600160401b038416600090815260016020526040902080546001600160a01b0319166001600160a01b03929092169190911790555b81600303612dee5780806020019051810190612dd491906149b7565b6001600160401b0384166000908152600260205260409020555b81600403612e245780806020019051810190612e0a91906149b7565b6001600160401b0384166000908152600360205260409020555b81600503612e5a5780806020019051810190612e4091906149b7565b6001600160401b0384166000908152600560205260409020555b81600603612e905780806020019051810190612e7691906149b7565b6001600160401b0384166000908152600660205260409020555b81600703612ec65780806020019051810190612eac91906149b7565b6001600160401b0384166000908152600760205260409020555b81600803612efc5780806020019051810190612ee291906149b7565b6001600160401b0384166000908152600860205260409020555b81600903612f325780806020019051810190612f1891906149b7565b6001600160401b0384166000908152600960205260409020555b81600a03612f685780806020019051810190612f4e91906149b7565b6001600160401b0384166000908152600a60205260409020555b81600b03612f9e5780806020019051810190612f8491906149b7565b6001600160401b0384166000908152600b60205260409020555b81600c03612fd45780806020019051810190612fba91906149b7565b6001600160401b0384166000908152600c60205260409020555b81600d0361300a5780806020019051810190612ff091906149b7565b6001600160401b0384166000908152600460205260409020555b81836001600160401b03167fae3dadf141b0383d3b4db666b2fc32179836af27e11a3e8f07c3ef8da82e59308360405161304491906145c6565b60405180910390a3505050565b600061306060208301836158a9565b6001600160a01b0316146130e257600061307d60208301836158a9565b9050600861308a82613ccd565b60ff16146130ab576040516333339aa360e11b815260040160405180910390fd5b6001600160401b038316600090815260208190526040902080546001600160a01b0319166001600160a01b03929092169190911790555b60006130f460408301602084016158a9565b6001600160a01b03161461317957600061311460408301602084016158a9565b9050600861312182613ccd565b60ff1614613142576040516333339aa360e11b815260040160405180910390fd5b6001600160401b038316600090815260016020526040902080546001600160a01b0319166001600160a01b03929092169190911790555b6001600160401b0382166000908152600260209081526040808320818501359055600382528083206060850135905560058252808320608085013590556006825280832060a085013590556007825280832060c085013590556008825280832060e08501359055600982528083206101008501359055600a82528083206101208501359055600b82528083206101408501359055600c825280832061016085013590556004909152908190206101808301359055517fdee9f507a37f922d400f1af8b89ddcf4419171e4570e9bc6b83e49659d6a26eb9061325d90849084906158c6565b60405180910390a15050565b60008160000361327b575060006126d1565b60006132a67f0000000000000000000000000000000000000000000000000000000000000000613d31565b6132b09084615992565b9050806000036132c45760009150506126d1565b60006132cf85613d31565b9050806000036132f257604051634c8f99a760e11b815260040160405180910390fd5b6132fc81836159a9565b95945050505050565b8260008190036133285760405163021b4ea160e01b815260040160405180910390fd5b80821461334857604051634456f5e960e11b815260040160405180910390fd5b60005b818110156133d6576133ce8787878481811061336957613369614926565b9050602002013586868581811061338257613382614926565b905060200281019061339491906159cb565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612c8692505050565b60010161334b565b50505050505050565b60606000828060200190518101906133f79190615746565b905083816020015160405160200161341092919061583f565b60408051601f1981840301815291815260208381019290925285516001600160401b03881660009081526009845282812054925191939091839161345691879101614afb565b604051602081830303815290604052516134709190615992565b9050600061347f8360a0615992565b9050836001600160401b03811115613499576134996140e8565b6040519080825280602002602001820160405280156134cc57816020015b60608152602001906001900390816134b75790505b50955060005b84811015613635576000816000036134ea57836134ec565b825b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630eff125d8b848151811061352f5761352f614926565b60200260200101516040518263ffffffff1660e01b815260040161355c919060ff91909116815260200190565b602060405180830381865afa158015613579573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061359d919061495c565b6001600160a01b03166325fc6dd0826040518263ffffffff1660e01b81526004016135ca91815260200190565b600060405180830381865afa1580156135e7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261360f9190810190614b99565b88838151811061362157613621614926565b6020908102919091010152506001016134d2565b5050505050509392505050565b6060600060405180610140016040528061365a613e23565b815260200184600001518152602001846020015181526020018460400151815260200184606001518152602001846080015181526020018460c00151151581526020018460e00151151581526020018461010001516001600160a01b031681526020018461014001518152506040516020016136d69190615a7e565b60408051601f198184030181528282018252600019835260208381018290529151909350613705929101614afb565b604051602081830303815290604052915050919050565b60606000604051806101400160405280613734613e23565b815260200184600001518152602001846020015181526020018460400151815260200184606001518152602001846080015181526020018460c0015181526020018460e0015181526020018461010001516001600160a01b031681526020018461014001518152506040516020016136d69190615bb0565b604080516001808252818301909252606091816020015b6040805160c0810182526060808252600060208084018290529383018190529082018190526080820181905260a082015282526000199092019101816137c3579050509050818160008151811061381c5761381c614926565b6020026020010181905250919050565b8051600090815b8181101561386e5783818151811061384d5761384d614926565b602002602001015160a001518361386491906149e6565b9250600101613833565b5050919050565b6001600160401b038216600090815260036020526040812054610a749083615992565b6001600160401b037f0000000000000000000000000000000000000000000000000000000000000000166000908152600a602052604081205481906138dd9084615992565b90506139087f0000000000000000000000000000000000000000000000000000000000000000613ebf565b610a749082615992565b60408051600180825281830190925260609160208083019080368337019050509050818160008151811061394857613948614926565b91151560209283029190910190910152919050565b600080836001600160401b03167f00000000000000000000000000000000000000000000000000000000000000006001600160401b0316036139a35760009150506126d1565b825160005b818110156139e3578481815181106139c2576139c2614926565b6020026020010151156139db576139d883615890565b92505b6001016139a8565b50816000036139f7576000925050506126d1565b6001600160401b0385166000908152600260205260409020546132fc9083615992565b600080613a2685613f84565b5060405163596db71760e01b815263ffffffff82166004820152909250600091506001600160a01b0385169063596db71790602401602060405180830381865afa158015613a78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a9c9190615554565b905080158015613ab2575063ffffffff82166002145b15613ae1576001600160401b0385166000908152600b6020526040902054613ada90846149e6565b9250613b0d565b8015613b0d576001600160401b0385166000908152600c6020526040902054613b0a90846149e6565b92505b50509392505050565b8051600090815b81811015613bb657838181518110613b3757613b37614926565b602002602001015160000151516000148015613b83575060006001600160a01b0316848281518110613b6b57613b6b614926565b6020026020010151602001516001600160a01b031614155b15613bae576001600160401b038516600090815260046020526040902054613bab90846149e6565b92505b600101613b1d565b505092915050565b60008084613be4576001600160401b038416600090815260066020526040902054613bfe565b6001600160401b0384166000908152600560205260409020545b9050610a708382615992565b600080613c1685613ebf565b613c209085615992565b905080600003613c34576000915050610a74565b82613c40579050610a74565b6000613c4b86613d31565b613c559083615992565b905080600003613c6a57600092505050610a74565b6000613c957f0000000000000000000000000000000000000000000000000000000000000000613d31565b905080600003613cb857604051634c8f99a760e11b815260040160405180910390fd5b613cc281836159a9565b979650505050505050565b6000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613d0d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126d19190615cc3565b6001600160401b0381166000908152602081905260408120546001600160a01b03168015613e0657806001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa925050508015613db3575060408051601f3d908101601f19168201909252613db091810190615cfa565b60015b15613e065760008413613dd95760405163119d4d6b60e11b815260040160405180910390fd5b81600003613dfa576040516376685d7f60e11b815260040160405180910390fd5b50919695505050505050565b50506001600160401b031660009081526007602052604090205490565b6000613e4e7f55b101fc856aff484166c46ad33bc74831c135693c159b0092bb3b72254ffb6b612645565b6001600160a01b03166313c02a596040518163ffffffff1660e01b8152600401602060405180830381865afa158015613e8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613eaf91906149b7565b9050613eba81615890565b905090565b6001600160401b0381166000908152600160205260408120546001600160a01b03168015613f6757806001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa925050508015613f41575060408051601f3d908101601f19168201909252613f3e91810190615cfa565b60015b15613f675760008413613dd95760405163119d4d6b60e11b815260040160405180910390fd5b50506001600160401b031660009081526008602052604090205490565b8060a081901c60c082901c6000819003613fb15760405163030042b760e01b815260040160405180910390fd5b9193909250565b604051806101600160405280600081526020016000815260200160008152602001600081526020016140186040805160c081018252606080825260006020830181905292820183905281018290526080810182905260a081019190915290565b81526060602082018190526000604083018190528183018190526080830181905260a083015260c09091015290565b604051806101600160405280606081526020016060815260200160608152602001606081526020016060815260200160608152602001606081526020016060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001606081525090565b6001600160401b03811681146140c857600080fd5b50565b6000602082840312156140dd57600080fd5b8135610a74816140b3565b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b0381118282101715614120576141206140e8565b60405290565b60405161014081016001600160401b0381118282101715614120576141206140e8565b60405161016081016001600160401b0381118282101715614120576141206140e8565b604051601f8201601f191681016001600160401b0381118282101715614194576141946140e8565b604052919050565b60006001600160401b038211156141b5576141b56140e8565b5060051b60200190565b60ff811681146140c857600080fd5b600082601f8301126141df57600080fd5b813560206141f46141ef8361419c565b61416c565b8083825260208201915060208460051b87010193508684111561421657600080fd5b602086015b8481101561423b57803561422e816141bf565b835291830191830161421b565b509695505050505050565b60006001600160401b0382111561425f5761425f6140e8565b50601f01601f191660200190565b600082601f83011261427e57600080fd5b813561428c6141ef82614246565b8181528460208386010111156142a157600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080608085870312156142d457600080fd5b84356001600160401b03808211156142eb57600080fd5b6142f7888389016141ce565b9550602091508187013561430a816140b3565b945060408701358181111561431e57600080fd5b61432a89828a0161426d565b94505060608701358181111561433f57600080fd5b8701601f8101891361435057600080fd5b803561435e6141ef8261419c565b81815260059190911b8201840190848101908b83111561437d57600080fd5b8584015b838110156143b5578035868111156143995760008081fd5b6143a78e898389010161426d565b845250918601918601614381565b50989b979a50959850505050505050565b60006040820184835260206040602085015281855180845260608601915060208701935060005b81811015614409578451835293830193918301916001016143ed565b5090979650505050505050565b60008083601f84011261442857600080fd5b5081356001600160401b0381111561443f57600080fd5b6020830191508360208260051b850101111561445a57600080fd5b9250929050565b6000806000806060858703121561447757600080fd5b8435614482816140b3565b935060208501356001600160401b038082111561449e57600080fd5b6144aa88838901614416565b909550935060408701359150808211156144c357600080fd5b506144d08782880161426d565b91505092959194509250565b60005b838110156144f75781810151838201526020016144df565b50506000910152565b600081518084526145188160208601602086016144dc565b601f01601f19169290920160200192915050565b828152604060208201526000610f206040830184614500565b80151581146140c857600080fd5b803561455e81614545565b919050565b60008060006060848603121561457857600080fd5b833561458381614545565b925060208401356001600160401b0381111561459e57600080fd5b6145aa868287016141ce565b92505060408401356145bb816140b3565b809150509250925092565b602081526000610a746020830184614500565b6000602082840312156145eb57600080fd5b5035919050565b60006060828403121561460457600080fd5b50919050565b6000806040838503121561461d57600080fd5b82356001600160401b0381111561463357600080fd5b61463f858286016145f2565b925050602083013561465081614545565b809150509250929050565b60006020828403121561460457600080fd5b6000806040838503121561468057600080fd5b82356001600160401b0381111561469657600080fd5b61463f8582860161465b565b6000806000606084860312156146b757600080fd5b83356146c2816140b3565b92506020840135915060408401356001600160401b038111156146e457600080fd5b6146f08682870161426d565b9150509250925092565b6000806000806040858703121561471057600080fd5b84356001600160401b038082111561472757600080fd5b61473388838901614416565b9096509450602087013591508082111561474c57600080fd5b818701915087601f83011261476057600080fd5b81358181111561476f57600080fd5b8860206101a08302850101111561478557600080fd5b95989497505060200194505050565b6000808284036101c08112156147a957600080fd5b83356147b4816140b3565b92506101a0601f19820112156147c957600080fd5b506020830190509250929050565b6000602082840312156147e957600080fd5b81356001600160401b038111156147ff57600080fd5b610f208482850161426d565b60008060008060006060868803121561482357600080fd5b853561482e816140b3565b945060208601356001600160401b038082111561484a57600080fd5b61485689838a01614416565b9096509450604088013591508082111561486f57600080fd5b5061487c88828901614416565b969995985093965092949392505050565b600080600080600080606087890312156148a657600080fd5b86356001600160401b03808211156148bd57600080fd5b6148c98a838b01614416565b909850965060208901359150808211156148e257600080fd5b6148ee8a838b01614416565b9096509450604089013591508082111561490757600080fd5b5061491489828a01614416565b979a9699509497509295939492505050565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b03811681146140c857600080fd5b805161455e8161493c565b60006020828403121561496e57600080fd5b8151610a748161493c565b6001600160401b038416815260606020820152600061499b6060830185614500565b82810360408401526149ad8185614500565b9695505050505050565b6000602082840312156149c957600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156126d1576126d16149d0565b60008151808452602080850194506020840160005b83811015614a2a57815187529582019590820190600101614a0e565b509495945050505050565b600060208083528351604082850152614a5160608501826149f9565b82860151601f198683038101604088015281518084529293509084019183850190600581901b8501860160005b82811015614aaa5784878303018452614a98828751614500565b95880195938801939150600101614a7e565b509998505050505050505050565b60208152815160208201526000602083015160606040840152614ade60808401826149f9565b90506040840151601f198483030160608501526132fc82826149f9565b602081528151602082015260006020830151604080840152610f206060840182614500565b600181811c90821680614b3457607f821691505b60208210810361460457634e487b7160e01b600052602260045260246000fd5b600082601f830112614b6557600080fd5b8151614b736141ef82614246565b818152846020838601011115614b8857600080fd5b610f208260208301602087016144dc565b600060208284031215614bab57600080fd5b81516001600160401b03811115614bc157600080fd5b610f2084828501614b54565b600082601f830112614bde57600080fd5b81516020614bee6141ef8361419c565b8083825260208201915060208460051b870101935086841115614c1057600080fd5b602086015b8481101561423b5780518352918301918301614c15565b600060c08284031215614c3e57600080fd5b614c466140fe565b905081516001600160401b03811115614c5e57600080fd5b614c6a84828501614b54565b8252506020820151614c7b8161493c565b60208201526040820151614c8e8161493c565b60408201526060820151614ca1816141bf565b60608201526080820151614cb4816140b3565b8060808301525060a082015160a082015292915050565b600082601f830112614cdc57600080fd5b81516020614cec6141ef8361419c565b82815260059290921b84018101918181019086841115614d0b57600080fd5b8286015b8481101561423b5780516001600160401b03811115614d2e5760008081fd5b614d3c8986838b0101614c2c565b845250918301918301614d0f565b805161455e81614545565b600082601f830112614d6657600080fd5b81516020614d766141ef8361419c565b8083825260208201915060208460051b870101935086841115614d9857600080fd5b602086015b8481101561423b578051614db081614545565b8352918301918301614d9d565b600060208284031215614dcf57600080fd5b81516001600160401b0380821115614de657600080fd5b908301906101408286031215614dfb57600080fd5b614e03614126565b82518152602083015182811115614e1957600080fd5b614e2587828601614bcd565b602083015250604083015182811115614e3d57600080fd5b614e4987828601614bcd565b604083015250606083015182811115614e6157600080fd5b614e6d87828601614bcd565b606083015250608083015182811115614e8557600080fd5b614e9187828601614bcd565b60808301525060a083015182811115614ea957600080fd5b614eb587828601614ccb565b60a08301525060c083015182811115614ecd57600080fd5b614ed987828601614d55565b60c08301525060e083015182811115614ef157600080fd5b614efd87828601614d55565b60e083015250610100614f11818501614951565b908201526101208381015183811115614f2957600080fd5b614f3588828701614b54565b918301919091525095945050505050565b600060208284031215614f5857600080fd5b81516001600160401b0380821115614f6f57600080fd5b908301906101408286031215614f8457600080fd5b614f8c614126565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015182811115614fca57600080fd5b614fd687828601614c2c565b60a083015250614fe860c08401614d4a565b60c0820152614ff960e08401614d4a565b60e0820152610100614f11818501614951565b6000602080838503121561501f57600080fd5b82516001600160401b0381111561503557600080fd5b8301601f8101851361504657600080fd5b80516150546141ef8261419c565b81815260059190911b8201830190838101908783111561507357600080fd5b928401925b82841015613cc257835161508b816141bf565b82529284019290840190615078565b6000823561015e198336030181126150b157600080fd5b9190910192915050565b803561455e8161493c565b600060c082840312156150d857600080fd5b6150e06140fe565b905081356001600160401b038111156150f857600080fd5b6151048482850161426d565b82525060208201356151158161493c565b602082015260408201356151288161493c565b6040820152606082013561513b816141bf565b6060820152608082013561514e816140b3565b8060808301525060a082013560a082015292915050565b6000610160828403121561517857600080fd5b615180614149565b90508135815260208201356020820152604082013560408201526060820135606082015260808201356001600160401b03808211156151be57600080fd5b6151ca858386016150c6565b608084015260a08401359150808211156151e357600080fd5b6151ef8583860161426d565b60a084015261520060c08501614553565b60c084015261521160e08501614553565b60e084015261010091506152268285016150bb565b82840152610120915061523a8285016150bb565b828401526101409150818401358181111561525457600080fd5b6152608682870161426d565b8385015250505092915050565b60006126d13683615165565b6000808335601e1984360301811261529057600080fd5b8301803591506001600160401b038211156152aa57600080fd5b6020019150600581901b360382131561445a57600080fd5b600082601f8301126152d357600080fd5b813560206152e36141ef8361419c565b8083825260208201915060208460051b87010193508684111561530557600080fd5b602086015b8481101561423b578035835291830191830161530a565b600082601f83011261533257600080fd5b813560206153426141ef8361419c565b82815260059290921b8401810191818101908684111561536157600080fd5b8286015b8481101561423b5780356001600160401b038111156153845760008081fd5b6153928986838b01016150c6565b845250918301918301615365565b600082601f8301126153b157600080fd5b813560206153c16141ef8361419c565b8083825260208201915060208460051b8701019350868411156153e357600080fd5b602086015b8481101561423b5780356153fb81614545565b83529183019183016153e8565b6000610160828403121561541b57600080fd5b615423614149565b905081356001600160401b038082111561543c57600080fd5b615448858386016152c2565b8352602084013591508082111561545e57600080fd5b61546a858386016152c2565b6020840152604084013591508082111561548357600080fd5b61548f858386016152c2565b604084015260608401359150808211156154a857600080fd5b6154b4858386016152c2565b606084015260808401359150808211156154cd57600080fd5b6154d985838601615321565b608084015260a08401359150808211156154f257600080fd5b6154fe8583860161426d565b60a084015260c084013591508082111561551757600080fd5b615523858386016153a0565b60c084015260e084013591508082111561553c57600080fd5b615211858386016153a0565b60006126d13683615408565b60006020828403121561556657600080fd5b8151610a7481614545565b601f821115611362576000816000526020600020601f850160051c8101602086101561559a5750805b601f850160051c820191505b818110156114a3578281556001016155a6565b81516001600160401b038111156155d2576155d26140e8565b6155e6816155e08454614b20565b84615571565b602080601f83116001811461561b57600084156156035750858301515b600019600386901b1c1916600185901b1785556114a3565b600085815260208120601f198616915b8281101561564a5788860151825594840194600190910190840161562b565b50858210156156685787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006156866141ef8461419c565b80848252602080830192508560051b8501368111156156a457600080fd5b855b81811015613dfa5780356001600160401b038111156156c55760008081fd5b6156d136828a01615165565b8652509382019382016156a6565b60006156ed6141ef8461419c565b80848252602080830192508560051b85013681111561570b57600080fd5b855b81811015613dfa5780356001600160401b0381111561572c5760008081fd5b61573836828a01615408565b86525093820193820161570d565b60006020828403121561575857600080fd5b81516001600160401b038082111561576f57600080fd5b908301906040828603121561578357600080fd5b60405160408101818110838211171561579e5761579e6140e8565b604052825181526020830151828111156157b757600080fd5b6157c387828601614b54565b60208301525095945050505050565b6040808252810183905260008460608301825b8681101561580f5782356157f8816141bf565b60ff168252602092830192909101906001016157e5565b508381036020850152613cc28186614500565b60006020828403121561583457600080fd5b8135610a74816141bf565b604080825283519082018190526000906020906060840190828701845b8281101561587b57815160ff168452928401929084019060010161585c565b5050508381036020850152613b0a8186614500565b6000600182016158a2576158a26149d0565b5060010190565b6000602082840312156158bb57600080fd5b8135610a748161493c565b6001600160401b03831681526101c081016158f4602083016158e7856150bb565b6001600160a01b03169052565b615900602084016150bb565b6001600160a01b0381166040840152506040830135606083015260608301356080830152608083013560a083015260a083013560c083015260c083013560e083015261010060e0840135818401526101208185013581850152610140915080850135828501525061016081850135818501526101809150808501358285015250808401356101a0840152509392505050565b80820281158282048414176126d1576126d16149d0565b6000826159c657634e487b7160e01b600052601260045260246000fd5b500490565b6000808335601e198436030181126159e257600080fd5b8301803591506001600160401b038211156159fc57600080fd5b60200191503681900382131561445a57600080fd5b6000815160c08452615a2660c0850182614500565b9050602083015160018060a01b038082166020870152806040860151166040870152505060ff60608401511660608501526001600160401b03608084015116608085015260a083015160a08501528091505092915050565b6020815281516020820152602082015160408201526040820151606082015260608201516080820152608082015160a0820152600060a08301516101408060c0850152615acf610160850183615a11565b915060c0850151615ae460e086018215159052565b5060e0850151610100615afa8187018315159052565b8601519050610120615b16868201836001600160a01b03169052565b860151858403601f19018387015290506149ad8382614500565b60008282518085526020808601955060208260051b8401016020860160005b8481101561440957601f19868403018952615b6b838351615a11565b98840198925090830190600101615b4f565b60008151808452602080850194506020840160005b83811015614a2a578151151587529582019590820190600101615b92565b602081528151602082015260006020830151610140806040850152615bd96101608501836149f9565b91506040850151601f1980868503016060870152615bf784836149f9565b93506060870151915080868503016080870152615c1484836149f9565b935060808701519150808685030160a0870152615c3184836149f9565b935060a08701519150808685030160c0870152615c4e8483615b30565b935060c08701519150808685030160e0870152615c6b8483615b7d565b935060e08701519150610100818786030181880152615c8a8584615b7d565b945080880151925050610120615caa818801846001600160a01b03169052565b8701518685039091018387015290506149ad8382614500565b600060208284031215615cd557600080fd5b8151610a74816141bf565b805169ffffffffffffffffffff8116811461455e57600080fd5b600080600080600060a08688031215615d1257600080fd5b615d1b86615ce0565b9450602086015193506040860151925060608601519150615d3e60808701615ce0565b9050929550929590935056fe6b50fa17b77d24e42e27a04b69fe50cd6967cfb767d18de0bd5fe7e1a32aa8684a76dea3a6231aa5446f85ecde36fb499385f0f3539e800a138fb9855200db67bcc180fb907e9ae431665de4bc74305c00b7b27442aadd477980ecc4bb14c011a2646970667358221220f9bde5d8b97499d4bda470d0f2b1126f4ac099c2b82dbf857109419d6cad275664736f6c6343000817003300000000000000000000000017a332dc7b40ae701485023b219e9d6f493a2514

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102065760003560e01c80637abae2511161011a578063b9694b52116100ad578063d8bb4f4e1161007c578063d8bb4f4e146105a6578063da163637146105c6578063ea7a8392146105ce578063f3afdd88146105e1578063f3d80846146105f457600080fd5b8063b9694b521461055a578063c2085f461461056d578063c97c55b014610580578063d70139741461059357600080fd5b80639d57d64e116100e95780639d57d64e14610501578063a8a0838914610514578063a9ce464814610527578063b1752d591461054757600080fd5b80637abae2511461046d5780637f7aecb51461048257806385e1f4d0146104a2578063904b1a28146104e157600080fd5b80634545fc311161019d57806353d69edc1161016c57806353d69edc146103c4578063596703e7146103d957806361d26cae146103ec5780637504988b1461041f578063786c69f31461044d57600080fd5b80634545fc311461033b5780634786b4241461035b57806349c3af451461037b5780634c75c0d8146103a457600080fd5b80631f864be3116101d95780631f864be3146102bf57806324c73dda146102e05780633283166a1461030757806336c7fe1d1461032857600080fd5b80630292540b1461020b57806310c5fbe41461023e57806312c4da861461025e5780631f5ae58f1461029f575b600080fd5b61022b6102193660046140cb565b600c6020526000908152604090205481565b6040519081526020015b60405180910390f35b61022b61024c3660046140cb565b60046020526000908152604090205481565b61028761026c3660046140cb565b6000602081905290815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610235565b61022b6102ad3660046140cb565b600b6020526000908152604090205481565b6102d26102cd3660046142be565b610607565b6040516102359291906143c6565b6102877f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a251481565b61031a610315366004614461565b61082b565b60405161023592919061452c565b61022b610336366004614563565b61088a565b61022b6103493660046140cb565b60076020526000908152604090205481565b61022b6103693660046140cb565b60086020526000908152604090205481565b6102876103893660046140cb565b6001602052600090815260409020546001600160a01b031681565b61022b6103b23660046140cb565b60056020526000908152604090205481565b6103cc610a7b565b60405161023591906145c6565b61022b6103e73660046145d9565b610b0d565b6103ff6103fa36600461460a565b610f28565b604080519485526020850193909352918301526060820152608001610235565b61043261042d36600461466d565b6110c7565b60408051938452602084019290925290820152606001610235565b61022b61045b3660046140cb565b60036020526000908152604090205481565b61048061047b3660046146a2565b611226565b005b61022b6104903660046140cb565b60066020526000908152604090205481565b6104c97f000000000000000000000000000000000000000000000000000000000000000181565b6040516001600160401b039091168152602001610235565b61022b6104ef3660046140cb565b60096020526000908152604090205481565b61048061050f3660046146fa565b611367565b610480610522366004614794565b6114ab565b61022b6105353660046140cb565b60026020526000908152604090205481565b61022b610555366004614563565b611557565b6104806105683660046147d7565b61156d565b61048061057b36600461480b565b6116aa565b6103ff61058e36600461460a565b6117ef565b6103ff6105a136600461460a565b611963565b61022b6105b43660046140cb565b600a6020526000908152604090205481565b6103cc611b1e565b6104806105dc36600461488d565b611bac565b6103ff6105ef36600461460a565b611dbf565b61043261060236600461466d565b611f53565b835160009060609082816001600160401b03811115610628576106286140e8565b604051908082528060200260200182016040528015610651578160200160208202803683370190505b509050866001600160401b03167f00000000000000000000000000000000000000000000000000000000000000016001600160401b03161461081f5760005b8281101561081d577f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316630eff125d8a83815181106106d9576106d9614926565b60200260200101516040518263ffffffff1660e01b8152600401610706919060ff91909116815260200190565b602060405180830381865afa158015610723573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610747919061495c565b6001600160a01b031663ea98b147898989858151811061076957610769614926565b60200260200101516040518463ffffffff1660e01b815260040161078f93929190614979565b602060405180830381865afa1580156107ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d091906149b7565b8282815181106107e2576107e2614926565b60200260200101818152505081818151811061080057610800614926565b60200260200101518561081391906149e6565b9450600101610690565b505b91505094509492505050565b60006060600080600061084089898989612092565b92509250925060405180604001604052808481526020018381525060405160200161086b9190614a35565b60408051601f1981840301815291905290999098509650505050505050565b6000606084156109e95760405163bffc1e1360e01b81526001600160401b03841660048201526000907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b03169063bffc1e1390602401602060405180830381865afa158015610904573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061092891906149b7565b90506000816001600160401b03811115610944576109446140e8565b60405190808252806020026020018201604052801561096d578160200160208202803683370190505b50905060005b828110156109a35760001982828151811061099057610990614926565b6020908102919091010152600101610973565b5060405180606001604052806000198152602001828152602001828152506040516020016109d19190614ab8565b60405160208183030381529060405292505050610a30565b506040805160608082018352600019808352602080840182815293850182815285519182019290925292518385015251828201528251808303909101815260809091019091525b610a7084846040518060400160405280600019815260200185815250604051602001610a5c9190614afb565b6040516020818303038152906040526123bc565b9150505b9392505050565b6060600d8054610a8a90614b20565b80601f0160208091040260200160405190810160405280929190818152602001828054610ab690614b20565b8015610b035780601f10610ad857610100808354040283529160200191610b03565b820191906000526020600020905b815481529060010190602001808311610ae657829003601f168201915b5050505050905090565b604080516101008101825260008082526020820181905291810182905260608082018190526080820181905260a0820183905260c0820183905260e08201526000610b777f55b101fc856aff484166c46ad33bc74831c135693c159b0092bb3b72254ffb6b612645565b9050806001600160a01b03166313c02a596040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bdb91906149b7565b808352841115610bfe576040516355da2ca360e11b815260040160405180910390fd5b6040516336445ffd60e01b8152600481018590526001600160a01b038216906336445ffd90602401602060405180830381865afa158015610c43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6791906149b7565b602083015260405163361ad42b60e01b8152600481018590526001600160a01b0382169063361ad42b90602401600060405180830381865afa158015610cb1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cd99190810190614b99565b6060830152602082015160c081811c9084015260ff601082901c811660a085015260089190911c166040830181905215610d17575060009392505050565b8160a0015160ff16600103610d8c5760008260600151806020019051810190610d409190614dbd565b60408051606081018252855181526020808401518183015282840151828401529151929350610d7192909101614ab8565b60408051601f19818403018152919052606084015250610df7565b60008260600151806020019051810190610da69190614f46565b60408051606080820183528651808352602085810151818501908152958501519385019384528451908101919091529351848401529051838201528151808403820181526080909301909152840152505b604051636c181b2760e11b8152600481018590526001600160a01b0382169063d830364e90602401600060405180830381865afa158015610e3c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610e64919081019061500c565b608083015260408051808201918290526336445ffd60e01b90915260448101859052806001600160a01b0383166336445ffd60648301602060405180830381865afa158015610eb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610edb91906149b7565b81526060840151602091820152604051610ef6929101614afb565b60408051601f1981840301815291905260e08301819052608083015160c0840151610f20926123bc565b949350505050565b6000806000806000610f47600080516020615d8b833981519152612645565b6040805160018082528183019092529192506000919060208083019080368337019050509050610f7d6040890160208a016140cb565b81600081518110610f9057610f90614926565b6001600160401b03929092166020928302919091018201526040805160018082528183019092526060926000929082015b610fc9613fb8565b815260200190600190039081610fc1579050509050610feb60408b018b61509a565b610ff49061526d565b8160008151811061100757611007614926565b602002602001018190525061109c6040518060e00160405280600081526020018581526020018c806000019061103d9190615279565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509082525060208101859052604081018490526001600160a01b03871660608201528b15156080909101526126d7565b91995097509550876110ae87896149e6565b6110b891906149e6565b94505050505092959194509250565b6000806000806110e4600080516020615d8b833981519152612645565b60408051600180825281830190925291925060009190602080830190803683370190505090507f00000000000000000000000000000000000000000000000000000000000000018160008151811061113e5761113e614926565b6001600160401b03929092166020928302919091018201526040805160018082528183019092526060926000929082015b611177614047565b81526020019060019003908161116f579050509050611196898061509a565b61119f90615548565b816000815181106111b2576111b2614926565b602002602001018190525060606112066040518060e0016040528060008152602001868152602001838152602001848152602001858152602001876001600160a01b031681526020018b15158152506126d7565b919950909750611218905087896149e6565b955050505050509250925092565b6040516321f8a72160e01b8152600080516020615d4b83398151915260048201527f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa158015611298573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112bc919061495c565b604051632474521560e21b8152600080516020615d6b83398151915260048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015611316573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133a9190615554565b61135757604051633108430360e11b815260040160405180910390fd5b611362838383612c86565b505050565b61137e600080516020615d4b833981519152612645565b6040516369ac88f960e11b81523360048201526001600160a01b03919091169063d35911f290602401602060405180830381865afa1580156113c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113e89190615554565b61140557604051633721555560e21b815260040160405180910390fd5b8260008190036114285760405163021b4ea160e01b815260040160405180910390fd5b80821461144857604051634456f5e960e11b815260040160405180910390fd5b60005b818110156114a35761149b86868381811061146857611468614926565b905060200201602081019061147d91906140cb565b85858481811061148f5761148f614926565b90506101a00201613051565b60010161144b565b505050505050565b6114c2600080516020615d4b833981519152612645565b6040516369ac88f960e11b81523360048201526001600160a01b03919091169063d35911f290602401602060405180830381865afa158015611508573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061152c9190615554565b61154957604051633721555560e21b815260040160405180910390fd5b6115538282613051565b5050565b6000610f208261156886868661088a565b613269565b6040516321f8a72160e01b8152600080516020615d4b83398151915260048201527f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa1580156115df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611603919061495c565b604051632474521560e21b8152600080516020615d6b83398151915260048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa15801561165d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116819190615554565b61169e57604051633108430360e11b815260040160405180910390fd5b600d61155382826155b9565b6040516321f8a72160e01b8152600080516020615d4b83398151915260048201527f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa15801561171c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611740919061495c565b604051632474521560e21b8152600080516020615d6b83398151915260048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa15801561179a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117be9190615554565b6117db57604051633108430360e11b815260040160405180910390fd5b6117e88585858585613305565b5050505050565b600080600080600061180e600080516020615d8b833981519152612645565b60408051600180825281830190925291925060009190602080830190803683370190505090506118446040890160208a016140cb565b8160008151811061185757611857614926565b6001600160401b03929092166020928302919091018201526040805160018082528183019092526060926000929082015b611890614047565b8152602001906001900390816118885790505090506118b260408b018b61509a565b6118bb90615548565b816000815181106118ce576118ce614926565b602002602001018190525061109c6040518060e00160405280600081526020018581526020018c80600001906119049190615279565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509082525060208101849052604081018590526001600160a01b03871660608201528b15156080909101526126d7565b6000808080806119766020880188615279565b90509050600080600080611997600080516020615d8b833981519152612645565b9050606060005b86811015611af757611ac46040518060e001604052808381526020018f80602001906119ca9190615279565b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505081526020018f8060000190611a1f9190615279565b85818110611a2f57611a2f614926565b9050602002810190611a419190615279565b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505081526020018481526020018f8060400190611a9c9190615279565b611aa591615678565b8152602001856001600160a01b031681526020018e15158152506126d7565b91975095509350611ad5868c6149e6565b9a50611ae1858b6149e6565b9950611aed848a6149e6565b985060010161199e565b5089611b03898b6149e6565b611b0d91906149e6565b965050505050505092959194509250565b600d8054611b2b90614b20565b80601f0160208091040260200160405190810160405280929190818152602001828054611b5790614b20565b8015611ba45780601f10611b7957610100808354040283529160200191611ba4565b820191906000526020600020905b815481529060010190602001808311611b8757829003601f168201915b505050505081565b6040516321f8a72160e01b8152600080516020615d4b83398151915260048201527f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa158015611c1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c42919061495c565b604051632474521560e21b8152600080516020615d6b83398151915260048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015611c9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cc09190615554565b611cdd57604051633108430360e11b815260040160405180910390fd5b846000819003611d005760405163021b4ea160e01b815260040160405180910390fd5b8084148015611d0e57508082145b611d2b57604051634456f5e960e11b815260040160405180910390fd5b60005b81811015611db557611dad888883818110611d4b57611d4b614926565b9050602002016020810190611d6091906140cb565b878784818110611d7257611d72614926565b9050602002810190611d849190615279565b878786818110611d9657611d96614926565b9050602002810190611da89190615279565b613305565b600101611d2e565b5050505050505050565b600080808080611dd26020880188615279565b90509050600080600080611df3600080516020615d8b833981519152612645565b9050606060005b86811015611af757611f206040518060e001604052808381526020018f8060200190611e269190615279565b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505081526020018f8060000190611e7b9190615279565b85818110611e8b57611e8b614926565b9050602002810190611e9d9190615279565b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505081526020018f8060400190611ef29190615279565b611efb916156df565b8152602001848152602001856001600160a01b031681526020018e15158152506126d7565b91975095509350611f31868c6149e6565b9a50611f3d858b6149e6565b9950611f49848a6149e6565b9850600101611dfa565b600080600080611f70600080516020615d8b833981519152612645565b60408051600180825281830190925291925060009190602080830190803683370190505090507f000000000000000000000000000000000000000000000000000000000000000181600081518110611fca57611fca614926565b6001600160401b039290921660209283029190910190910152604080516001808252818301909252600091816020015b612002613fb8565b815260200190600190039081611ffa579050509050612021888061509a565b61202a9061526d565b8160008151811061203d5761203d614926565b60200260200101819052506060806112066040518060e0016040528060008152602001868152602001838152602001848152602001858152602001876001600160a01b031681526020018b15158152506126d7565b606080600080848060200190518101906120ac9190615746565b9050868682602001516040516020016120c7939291906157d2565b60408051601f1981840301815291815260208381019290925280518883028181018401909252888152889261211d928c92918c9186918291908501908490808284376000920191909152508b92506133df915050565b9350806001600160401b03811115612137576121376140e8565b604051908082528060200260200182016040528015612160578160200160208202803683370190505b509450600060405180604001604052806000198152602001888051906020012060405160200161219291815260200190565b60408051601f198184030181529181529152516121b29190602001614afb565b6040516020818303038152906040529050896001600160401b03167f00000000000000000000000000000000000000000000000000000000000000016001600160401b0316146123af5760005b828110156123ad5760007f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316630eff125d8c8c8581811061224a5761224a614926565b905060200201602081019061225f9190615822565b6040516001600160e01b031960e084901b16815260ff9091166004820152602401602060405180830381865afa15801561229d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122c1919061495c565b6001600160a01b031663ea98b1478d846000036122fd57876040516020016122e99190614afb565b6040516020818303038152906040526122ff565b855b8a868151811061231157612311614926565b60200260200101516040518463ffffffff1660e01b815260040161233793929190614979565b602060405180830381865afa158015612354573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061237891906149b7565b905061238481876149e6565b95508088838151811061239957612399614926565b6020908102919091010152506001016121ff565b505b5050509450945094915050565b8251600090816123cd8587866133df565b90506000848060200190518101906123e59190615746565b90508681602001516040516020016123fe92919061583f565b6040516020818303038152906040528160200181905250600060405180604001604052806000198152602001878051906020012060405160200161244491815260200190565b60408051601f198184030181529181529152516124649190602001614afb565b6040516020818303038152906040529050866001600160401b03167f00000000000000000000000000000000000000000000000000000000000000016001600160401b03161461263a5760005b848110156126385760007f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316630eff125d8b84815181106124fc576124fc614926565b60200260200101516040518263ffffffff1660e01b8152600401612529919060ff91909116815260200190565b602060405180830381865afa158015612546573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061256a919061495c565b6001600160a01b031663ea98b1478a846000036125a657866040516020016125929190614afb565b6040516020818303038152906040526125a8565b855b8886815181106125ba576125ba614926565b60200260200101516040518463ffffffff1660e01b81526004016125e093929190614979565b602060405180830381865afa1580156125fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061262191906149b7565b905061262d81886149e6565b9650506001016124b1565b505b505050509392505050565b6040516321f8a72160e01b8152600481018290526000907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa1580156126ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126d1919061495c565b92915050565b60008060006127106040518060a00160405280600081526020016000815260200160008152602001600081526020016000151581525090565b60007f00000000000000000000000000000000000000000000000000000000000000016001600160401b0316866020015187600001518151811061275657612756614926565b60200260200101516001600160401b03161415905060008260400181815250506000808760600151511190506000816127b8576127b388608001518960000151815181106127a6576127a6614926565b6020026020010151613642565b6127e2565b6127e288606001518960000151815181106127d5576127d5614926565b602002602001015161371c565b9050826127f0576000612820565b612820886040015189602001518a600001518151811061281257612812614926565b6020026020010151836123bc565b606085015281612831576001612856565b606088015188518151811061284857612848614926565b602002602001015160000151515b6020850152606084015161286a90876149e6565b95506000826128a6576128a189608001518a600001518151811061289057612890614926565b6020026020010151608001516137ac565b6128ca565b60608901518951815181106128bd576128bd614926565b6020026020010151608001515b90508860c0015115612a96576128df8161382c565b6128e990896149e6565b97508315612a915761292089602001518a600001518151811061290e5761290e614926565b60200260200101518660200151613875565b8560400181815161293191906149e6565b905250600083156129a55760005b866020015181101561299f5760608b01518b518151811061296257612962614926565b602002602001015160e00151818151811061297f5761297f614926565b60200260200101516129975761299482615890565b91505b60010161293f565b506129d8565b60808a01518a51815181106129bc576129bc614926565b602002602001015160e001516129d8576129d581615890565b90505b6129e181613898565b6129eb90896149e6565b9750600084612a2957612a248b608001518c6000015181518110612a1157612a11614926565b602002602001015160c001511515613912565b612a4d565b60608b01518b5181518110612a4057612a40614926565b602002602001015160c001515b9050612a7a8b602001518c6000015181518110612a6c57612a6c614926565b60200260200101518261395d565b87604001818151612a8b91906149e6565b90525050505b612beb565b8215612b3b5760005b8560200151811015612b3557612b198a606001518b6000015181518110612ac857612ac8614926565b6020026020010151600001518281518110612ae557612ae5614926565b60200260200101518b602001518c6000015181518110612b0757612b07614926565b60200260200101518c60a00151613a1a565b86604001818151612b2a91906149e6565b905250600101612a9f565b50612ba5565b612b9089608001518a6000015181518110612b5857612b58614926565b6020026020010151600001518a602001518b6000015181518110612b7e57612b7e614926565b60200260200101518b60a00151613a1a565b85604001818151612ba191906149e6565b9052505b8315612beb57612bd689602001518a6000015181518110612bc857612bc8614926565b602002602001015182613b16565b85604001818151612be791906149e6565b9052505b83612bf7576000612c2b565b612c2b8960c001518a602001518b6000015181518110612c1957612c19614926565b60200260200101518760200151613bbe565b85604001818151612c3c91906149e6565b905250602089015189518151612c6f9291908110612c5c57612c5c614926565b6020026020010151866040015186613c0a565b612c7990876149e6565b9799969850505050505050565b81600103612d1f57600081806020019051810190612ca4919061495c565b90506001600160a01b03811615801590612cca57506008612cc482613ccd565b60ff1614155b15612ce8576040516333339aa360e11b815260040160405180910390fd5b6001600160401b038416600090815260208190526040902080546001600160a01b0319166001600160a01b03929092169190911790555b81600203612db857600081806020019051810190612d3d919061495c565b90506001600160a01b03811615801590612d6357506008612d5d82613ccd565b60ff1614155b15612d81576040516333339aa360e11b815260040160405180910390fd5b6001600160401b038416600090815260016020526040902080546001600160a01b0319166001600160a01b03929092169190911790555b81600303612dee5780806020019051810190612dd491906149b7565b6001600160401b0384166000908152600260205260409020555b81600403612e245780806020019051810190612e0a91906149b7565b6001600160401b0384166000908152600360205260409020555b81600503612e5a5780806020019051810190612e4091906149b7565b6001600160401b0384166000908152600560205260409020555b81600603612e905780806020019051810190612e7691906149b7565b6001600160401b0384166000908152600660205260409020555b81600703612ec65780806020019051810190612eac91906149b7565b6001600160401b0384166000908152600760205260409020555b81600803612efc5780806020019051810190612ee291906149b7565b6001600160401b0384166000908152600860205260409020555b81600903612f325780806020019051810190612f1891906149b7565b6001600160401b0384166000908152600960205260409020555b81600a03612f685780806020019051810190612f4e91906149b7565b6001600160401b0384166000908152600a60205260409020555b81600b03612f9e5780806020019051810190612f8491906149b7565b6001600160401b0384166000908152600b60205260409020555b81600c03612fd45780806020019051810190612fba91906149b7565b6001600160401b0384166000908152600c60205260409020555b81600d0361300a5780806020019051810190612ff091906149b7565b6001600160401b0384166000908152600460205260409020555b81836001600160401b03167fae3dadf141b0383d3b4db666b2fc32179836af27e11a3e8f07c3ef8da82e59308360405161304491906145c6565b60405180910390a3505050565b600061306060208301836158a9565b6001600160a01b0316146130e257600061307d60208301836158a9565b9050600861308a82613ccd565b60ff16146130ab576040516333339aa360e11b815260040160405180910390fd5b6001600160401b038316600090815260208190526040902080546001600160a01b0319166001600160a01b03929092169190911790555b60006130f460408301602084016158a9565b6001600160a01b03161461317957600061311460408301602084016158a9565b9050600861312182613ccd565b60ff1614613142576040516333339aa360e11b815260040160405180910390fd5b6001600160401b038316600090815260016020526040902080546001600160a01b0319166001600160a01b03929092169190911790555b6001600160401b0382166000908152600260209081526040808320818501359055600382528083206060850135905560058252808320608085013590556006825280832060a085013590556007825280832060c085013590556008825280832060e08501359055600982528083206101008501359055600a82528083206101208501359055600b82528083206101408501359055600c825280832061016085013590556004909152908190206101808301359055517fdee9f507a37f922d400f1af8b89ddcf4419171e4570e9bc6b83e49659d6a26eb9061325d90849084906158c6565b60405180910390a15050565b60008160000361327b575060006126d1565b60006132a67f0000000000000000000000000000000000000000000000000000000000000001613d31565b6132b09084615992565b9050806000036132c45760009150506126d1565b60006132cf85613d31565b9050806000036132f257604051634c8f99a760e11b815260040160405180910390fd5b6132fc81836159a9565b95945050505050565b8260008190036133285760405163021b4ea160e01b815260040160405180910390fd5b80821461334857604051634456f5e960e11b815260040160405180910390fd5b60005b818110156133d6576133ce8787878481811061336957613369614926565b9050602002013586868581811061338257613382614926565b905060200281019061339491906159cb565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612c8692505050565b60010161334b565b50505050505050565b60606000828060200190518101906133f79190615746565b905083816020015160405160200161341092919061583f565b60408051601f1981840301815291815260208381019290925285516001600160401b03881660009081526009845282812054925191939091839161345691879101614afb565b604051602081830303815290604052516134709190615992565b9050600061347f8360a0615992565b9050836001600160401b03811115613499576134996140e8565b6040519080825280602002602001820160405280156134cc57816020015b60608152602001906001900390816134b75790505b50955060005b84811015613635576000816000036134ea57836134ec565b825b90507f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316630eff125d8b848151811061352f5761352f614926565b60200260200101516040518263ffffffff1660e01b815260040161355c919060ff91909116815260200190565b602060405180830381865afa158015613579573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061359d919061495c565b6001600160a01b03166325fc6dd0826040518263ffffffff1660e01b81526004016135ca91815260200190565b600060405180830381865afa1580156135e7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261360f9190810190614b99565b88838151811061362157613621614926565b6020908102919091010152506001016134d2565b5050505050509392505050565b6060600060405180610140016040528061365a613e23565b815260200184600001518152602001846020015181526020018460400151815260200184606001518152602001846080015181526020018460c00151151581526020018460e00151151581526020018461010001516001600160a01b031681526020018461014001518152506040516020016136d69190615a7e565b60408051601f198184030181528282018252600019835260208381018290529151909350613705929101614afb565b604051602081830303815290604052915050919050565b60606000604051806101400160405280613734613e23565b815260200184600001518152602001846020015181526020018460400151815260200184606001518152602001846080015181526020018460c0015181526020018460e0015181526020018461010001516001600160a01b031681526020018461014001518152506040516020016136d69190615bb0565b604080516001808252818301909252606091816020015b6040805160c0810182526060808252600060208084018290529383018190529082018190526080820181905260a082015282526000199092019101816137c3579050509050818160008151811061381c5761381c614926565b6020026020010181905250919050565b8051600090815b8181101561386e5783818151811061384d5761384d614926565b602002602001015160a001518361386491906149e6565b9250600101613833565b5050919050565b6001600160401b038216600090815260036020526040812054610a749083615992565b6001600160401b037f0000000000000000000000000000000000000000000000000000000000000001166000908152600a602052604081205481906138dd9084615992565b90506139087f0000000000000000000000000000000000000000000000000000000000000001613ebf565b610a749082615992565b60408051600180825281830190925260609160208083019080368337019050509050818160008151811061394857613948614926565b91151560209283029190910190910152919050565b600080836001600160401b03167f00000000000000000000000000000000000000000000000000000000000000016001600160401b0316036139a35760009150506126d1565b825160005b818110156139e3578481815181106139c2576139c2614926565b6020026020010151156139db576139d883615890565b92505b6001016139a8565b50816000036139f7576000925050506126d1565b6001600160401b0385166000908152600260205260409020546132fc9083615992565b600080613a2685613f84565b5060405163596db71760e01b815263ffffffff82166004820152909250600091506001600160a01b0385169063596db71790602401602060405180830381865afa158015613a78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a9c9190615554565b905080158015613ab2575063ffffffff82166002145b15613ae1576001600160401b0385166000908152600b6020526040902054613ada90846149e6565b9250613b0d565b8015613b0d576001600160401b0385166000908152600c6020526040902054613b0a90846149e6565b92505b50509392505050565b8051600090815b81811015613bb657838181518110613b3757613b37614926565b602002602001015160000151516000148015613b83575060006001600160a01b0316848281518110613b6b57613b6b614926565b6020026020010151602001516001600160a01b031614155b15613bae576001600160401b038516600090815260046020526040902054613bab90846149e6565b92505b600101613b1d565b505092915050565b60008084613be4576001600160401b038416600090815260066020526040902054613bfe565b6001600160401b0384166000908152600560205260409020545b9050610a708382615992565b600080613c1685613ebf565b613c209085615992565b905080600003613c34576000915050610a74565b82613c40579050610a74565b6000613c4b86613d31565b613c559083615992565b905080600003613c6a57600092505050610a74565b6000613c957f0000000000000000000000000000000000000000000000000000000000000001613d31565b905080600003613cb857604051634c8f99a760e11b815260040160405180910390fd5b613cc281836159a9565b979650505050505050565b6000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613d0d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126d19190615cc3565b6001600160401b0381166000908152602081905260408120546001600160a01b03168015613e0657806001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa925050508015613db3575060408051601f3d908101601f19168201909252613db091810190615cfa565b60015b15613e065760008413613dd95760405163119d4d6b60e11b815260040160405180910390fd5b81600003613dfa576040516376685d7f60e11b815260040160405180910390fd5b50919695505050505050565b50506001600160401b031660009081526007602052604090205490565b6000613e4e7f55b101fc856aff484166c46ad33bc74831c135693c159b0092bb3b72254ffb6b612645565b6001600160a01b03166313c02a596040518163ffffffff1660e01b8152600401602060405180830381865afa158015613e8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613eaf91906149b7565b9050613eba81615890565b905090565b6001600160401b0381166000908152600160205260408120546001600160a01b03168015613f6757806001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa925050508015613f41575060408051601f3d908101601f19168201909252613f3e91810190615cfa565b60015b15613f675760008413613dd95760405163119d4d6b60e11b815260040160405180910390fd5b50506001600160401b031660009081526008602052604090205490565b8060a081901c60c082901c6000819003613fb15760405163030042b760e01b815260040160405180910390fd5b9193909250565b604051806101600160405280600081526020016000815260200160008152602001600081526020016140186040805160c081018252606080825260006020830181905292820183905281018290526080810182905260a081019190915290565b81526060602082018190526000604083018190528183018190526080830181905260a083015260c09091015290565b604051806101600160405280606081526020016060815260200160608152602001606081526020016060815260200160608152602001606081526020016060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001606081525090565b6001600160401b03811681146140c857600080fd5b50565b6000602082840312156140dd57600080fd5b8135610a74816140b3565b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b0381118282101715614120576141206140e8565b60405290565b60405161014081016001600160401b0381118282101715614120576141206140e8565b60405161016081016001600160401b0381118282101715614120576141206140e8565b604051601f8201601f191681016001600160401b0381118282101715614194576141946140e8565b604052919050565b60006001600160401b038211156141b5576141b56140e8565b5060051b60200190565b60ff811681146140c857600080fd5b600082601f8301126141df57600080fd5b813560206141f46141ef8361419c565b61416c565b8083825260208201915060208460051b87010193508684111561421657600080fd5b602086015b8481101561423b57803561422e816141bf565b835291830191830161421b565b509695505050505050565b60006001600160401b0382111561425f5761425f6140e8565b50601f01601f191660200190565b600082601f83011261427e57600080fd5b813561428c6141ef82614246565b8181528460208386010111156142a157600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080608085870312156142d457600080fd5b84356001600160401b03808211156142eb57600080fd5b6142f7888389016141ce565b9550602091508187013561430a816140b3565b945060408701358181111561431e57600080fd5b61432a89828a0161426d565b94505060608701358181111561433f57600080fd5b8701601f8101891361435057600080fd5b803561435e6141ef8261419c565b81815260059190911b8201840190848101908b83111561437d57600080fd5b8584015b838110156143b5578035868111156143995760008081fd5b6143a78e898389010161426d565b845250918601918601614381565b50989b979a50959850505050505050565b60006040820184835260206040602085015281855180845260608601915060208701935060005b81811015614409578451835293830193918301916001016143ed565b5090979650505050505050565b60008083601f84011261442857600080fd5b5081356001600160401b0381111561443f57600080fd5b6020830191508360208260051b850101111561445a57600080fd5b9250929050565b6000806000806060858703121561447757600080fd5b8435614482816140b3565b935060208501356001600160401b038082111561449e57600080fd5b6144aa88838901614416565b909550935060408701359150808211156144c357600080fd5b506144d08782880161426d565b91505092959194509250565b60005b838110156144f75781810151838201526020016144df565b50506000910152565b600081518084526145188160208601602086016144dc565b601f01601f19169290920160200192915050565b828152604060208201526000610f206040830184614500565b80151581146140c857600080fd5b803561455e81614545565b919050565b60008060006060848603121561457857600080fd5b833561458381614545565b925060208401356001600160401b0381111561459e57600080fd5b6145aa868287016141ce565b92505060408401356145bb816140b3565b809150509250925092565b602081526000610a746020830184614500565b6000602082840312156145eb57600080fd5b5035919050565b60006060828403121561460457600080fd5b50919050565b6000806040838503121561461d57600080fd5b82356001600160401b0381111561463357600080fd5b61463f858286016145f2565b925050602083013561465081614545565b809150509250929050565b60006020828403121561460457600080fd5b6000806040838503121561468057600080fd5b82356001600160401b0381111561469657600080fd5b61463f8582860161465b565b6000806000606084860312156146b757600080fd5b83356146c2816140b3565b92506020840135915060408401356001600160401b038111156146e457600080fd5b6146f08682870161426d565b9150509250925092565b6000806000806040858703121561471057600080fd5b84356001600160401b038082111561472757600080fd5b61473388838901614416565b9096509450602087013591508082111561474c57600080fd5b818701915087601f83011261476057600080fd5b81358181111561476f57600080fd5b8860206101a08302850101111561478557600080fd5b95989497505060200194505050565b6000808284036101c08112156147a957600080fd5b83356147b4816140b3565b92506101a0601f19820112156147c957600080fd5b506020830190509250929050565b6000602082840312156147e957600080fd5b81356001600160401b038111156147ff57600080fd5b610f208482850161426d565b60008060008060006060868803121561482357600080fd5b853561482e816140b3565b945060208601356001600160401b038082111561484a57600080fd5b61485689838a01614416565b9096509450604088013591508082111561486f57600080fd5b5061487c88828901614416565b969995985093965092949392505050565b600080600080600080606087890312156148a657600080fd5b86356001600160401b03808211156148bd57600080fd5b6148c98a838b01614416565b909850965060208901359150808211156148e257600080fd5b6148ee8a838b01614416565b9096509450604089013591508082111561490757600080fd5b5061491489828a01614416565b979a9699509497509295939492505050565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b03811681146140c857600080fd5b805161455e8161493c565b60006020828403121561496e57600080fd5b8151610a748161493c565b6001600160401b038416815260606020820152600061499b6060830185614500565b82810360408401526149ad8185614500565b9695505050505050565b6000602082840312156149c957600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156126d1576126d16149d0565b60008151808452602080850194506020840160005b83811015614a2a57815187529582019590820190600101614a0e565b509495945050505050565b600060208083528351604082850152614a5160608501826149f9565b82860151601f198683038101604088015281518084529293509084019183850190600581901b8501860160005b82811015614aaa5784878303018452614a98828751614500565b95880195938801939150600101614a7e565b509998505050505050505050565b60208152815160208201526000602083015160606040840152614ade60808401826149f9565b90506040840151601f198483030160608501526132fc82826149f9565b602081528151602082015260006020830151604080840152610f206060840182614500565b600181811c90821680614b3457607f821691505b60208210810361460457634e487b7160e01b600052602260045260246000fd5b600082601f830112614b6557600080fd5b8151614b736141ef82614246565b818152846020838601011115614b8857600080fd5b610f208260208301602087016144dc565b600060208284031215614bab57600080fd5b81516001600160401b03811115614bc157600080fd5b610f2084828501614b54565b600082601f830112614bde57600080fd5b81516020614bee6141ef8361419c565b8083825260208201915060208460051b870101935086841115614c1057600080fd5b602086015b8481101561423b5780518352918301918301614c15565b600060c08284031215614c3e57600080fd5b614c466140fe565b905081516001600160401b03811115614c5e57600080fd5b614c6a84828501614b54565b8252506020820151614c7b8161493c565b60208201526040820151614c8e8161493c565b60408201526060820151614ca1816141bf565b60608201526080820151614cb4816140b3565b8060808301525060a082015160a082015292915050565b600082601f830112614cdc57600080fd5b81516020614cec6141ef8361419c565b82815260059290921b84018101918181019086841115614d0b57600080fd5b8286015b8481101561423b5780516001600160401b03811115614d2e5760008081fd5b614d3c8986838b0101614c2c565b845250918301918301614d0f565b805161455e81614545565b600082601f830112614d6657600080fd5b81516020614d766141ef8361419c565b8083825260208201915060208460051b870101935086841115614d9857600080fd5b602086015b8481101561423b578051614db081614545565b8352918301918301614d9d565b600060208284031215614dcf57600080fd5b81516001600160401b0380821115614de657600080fd5b908301906101408286031215614dfb57600080fd5b614e03614126565b82518152602083015182811115614e1957600080fd5b614e2587828601614bcd565b602083015250604083015182811115614e3d57600080fd5b614e4987828601614bcd565b604083015250606083015182811115614e6157600080fd5b614e6d87828601614bcd565b606083015250608083015182811115614e8557600080fd5b614e9187828601614bcd565b60808301525060a083015182811115614ea957600080fd5b614eb587828601614ccb565b60a08301525060c083015182811115614ecd57600080fd5b614ed987828601614d55565b60c08301525060e083015182811115614ef157600080fd5b614efd87828601614d55565b60e083015250610100614f11818501614951565b908201526101208381015183811115614f2957600080fd5b614f3588828701614b54565b918301919091525095945050505050565b600060208284031215614f5857600080fd5b81516001600160401b0380821115614f6f57600080fd5b908301906101408286031215614f8457600080fd5b614f8c614126565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015182811115614fca57600080fd5b614fd687828601614c2c565b60a083015250614fe860c08401614d4a565b60c0820152614ff960e08401614d4a565b60e0820152610100614f11818501614951565b6000602080838503121561501f57600080fd5b82516001600160401b0381111561503557600080fd5b8301601f8101851361504657600080fd5b80516150546141ef8261419c565b81815260059190911b8201830190838101908783111561507357600080fd5b928401925b82841015613cc257835161508b816141bf565b82529284019290840190615078565b6000823561015e198336030181126150b157600080fd5b9190910192915050565b803561455e8161493c565b600060c082840312156150d857600080fd5b6150e06140fe565b905081356001600160401b038111156150f857600080fd5b6151048482850161426d565b82525060208201356151158161493c565b602082015260408201356151288161493c565b6040820152606082013561513b816141bf565b6060820152608082013561514e816140b3565b8060808301525060a082013560a082015292915050565b6000610160828403121561517857600080fd5b615180614149565b90508135815260208201356020820152604082013560408201526060820135606082015260808201356001600160401b03808211156151be57600080fd5b6151ca858386016150c6565b608084015260a08401359150808211156151e357600080fd5b6151ef8583860161426d565b60a084015261520060c08501614553565b60c084015261521160e08501614553565b60e084015261010091506152268285016150bb565b82840152610120915061523a8285016150bb565b828401526101409150818401358181111561525457600080fd5b6152608682870161426d565b8385015250505092915050565b60006126d13683615165565b6000808335601e1984360301811261529057600080fd5b8301803591506001600160401b038211156152aa57600080fd5b6020019150600581901b360382131561445a57600080fd5b600082601f8301126152d357600080fd5b813560206152e36141ef8361419c565b8083825260208201915060208460051b87010193508684111561530557600080fd5b602086015b8481101561423b578035835291830191830161530a565b600082601f83011261533257600080fd5b813560206153426141ef8361419c565b82815260059290921b8401810191818101908684111561536157600080fd5b8286015b8481101561423b5780356001600160401b038111156153845760008081fd5b6153928986838b01016150c6565b845250918301918301615365565b600082601f8301126153b157600080fd5b813560206153c16141ef8361419c565b8083825260208201915060208460051b8701019350868411156153e357600080fd5b602086015b8481101561423b5780356153fb81614545565b83529183019183016153e8565b6000610160828403121561541b57600080fd5b615423614149565b905081356001600160401b038082111561543c57600080fd5b615448858386016152c2565b8352602084013591508082111561545e57600080fd5b61546a858386016152c2565b6020840152604084013591508082111561548357600080fd5b61548f858386016152c2565b604084015260608401359150808211156154a857600080fd5b6154b4858386016152c2565b606084015260808401359150808211156154cd57600080fd5b6154d985838601615321565b608084015260a08401359150808211156154f257600080fd5b6154fe8583860161426d565b60a084015260c084013591508082111561551757600080fd5b615523858386016153a0565b60c084015260e084013591508082111561553c57600080fd5b615211858386016153a0565b60006126d13683615408565b60006020828403121561556657600080fd5b8151610a7481614545565b601f821115611362576000816000526020600020601f850160051c8101602086101561559a5750805b601f850160051c820191505b818110156114a3578281556001016155a6565b81516001600160401b038111156155d2576155d26140e8565b6155e6816155e08454614b20565b84615571565b602080601f83116001811461561b57600084156156035750858301515b600019600386901b1c1916600185901b1785556114a3565b600085815260208120601f198616915b8281101561564a5788860151825594840194600190910190840161562b565b50858210156156685787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006156866141ef8461419c565b80848252602080830192508560051b8501368111156156a457600080fd5b855b81811015613dfa5780356001600160401b038111156156c55760008081fd5b6156d136828a01615165565b8652509382019382016156a6565b60006156ed6141ef8461419c565b80848252602080830192508560051b85013681111561570b57600080fd5b855b81811015613dfa5780356001600160401b0381111561572c5760008081fd5b61573836828a01615408565b86525093820193820161570d565b60006020828403121561575857600080fd5b81516001600160401b038082111561576f57600080fd5b908301906040828603121561578357600080fd5b60405160408101818110838211171561579e5761579e6140e8565b604052825181526020830151828111156157b757600080fd5b6157c387828601614b54565b60208301525095945050505050565b6040808252810183905260008460608301825b8681101561580f5782356157f8816141bf565b60ff168252602092830192909101906001016157e5565b508381036020850152613cc28186614500565b60006020828403121561583457600080fd5b8135610a74816141bf565b604080825283519082018190526000906020906060840190828701845b8281101561587b57815160ff168452928401929084019060010161585c565b5050508381036020850152613b0a8186614500565b6000600182016158a2576158a26149d0565b5060010190565b6000602082840312156158bb57600080fd5b8135610a748161493c565b6001600160401b03831681526101c081016158f4602083016158e7856150bb565b6001600160a01b03169052565b615900602084016150bb565b6001600160a01b0381166040840152506040830135606083015260608301356080830152608083013560a083015260a083013560c083015260c083013560e083015261010060e0840135818401526101208185013581850152610140915080850135828501525061016081850135818501526101809150808501358285015250808401356101a0840152509392505050565b80820281158282048414176126d1576126d16149d0565b6000826159c657634e487b7160e01b600052601260045260246000fd5b500490565b6000808335601e198436030181126159e257600080fd5b8301803591506001600160401b038211156159fc57600080fd5b60200191503681900382131561445a57600080fd5b6000815160c08452615a2660c0850182614500565b9050602083015160018060a01b038082166020870152806040860151166040870152505060ff60608401511660608501526001600160401b03608084015116608085015260a083015160a08501528091505092915050565b6020815281516020820152602082015160408201526040820151606082015260608201516080820152608082015160a0820152600060a08301516101408060c0850152615acf610160850183615a11565b915060c0850151615ae460e086018215159052565b5060e0850151610100615afa8187018315159052565b8601519050610120615b16868201836001600160a01b03169052565b860151858403601f19018387015290506149ad8382614500565b60008282518085526020808601955060208260051b8401016020860160005b8481101561440957601f19868403018952615b6b838351615a11565b98840198925090830190600101615b4f565b60008151808452602080850194506020840160005b83811015614a2a578151151587529582019590820190600101615b92565b602081528151602082015260006020830151610140806040850152615bd96101608501836149f9565b91506040850151601f1980868503016060870152615bf784836149f9565b93506060870151915080868503016080870152615c1484836149f9565b935060808701519150808685030160a0870152615c3184836149f9565b935060a08701519150808685030160c0870152615c4e8483615b30565b935060c08701519150808685030160e0870152615c6b8483615b7d565b935060e08701519150610100818786030181880152615c8a8584615b7d565b945080880151925050610120615caa818801846001600160a01b03169052565b8701518685039091018387015290506149ad8382614500565b600060208284031215615cd557600080fd5b8151610a74816141bf565b805169ffffffffffffffffffff8116811461455e57600080fd5b600080600080600060a08688031215615d1257600080fd5b615d1b86615ce0565b9450602086015193506040860151925060608601519150615d3e60808701615ce0565b9050929550929590935056fe6b50fa17b77d24e42e27a04b69fe50cd6967cfb767d18de0bd5fe7e1a32aa8684a76dea3a6231aa5446f85ecde36fb499385f0f3539e800a138fb9855200db67bcc180fb907e9ae431665de4bc74305c00b7b27442aadd477980ecc4bb14c011a2646970667358221220f9bde5d8b97499d4bda470d0f2b1126f4ac099c2b82dbf857109419d6cad275664736f6c63430008170033

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

00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a2514

-----Decoded View---------------
Arg [0] : superRegistry_ (address): 0x17A332dC7B40aE701485023b219E9D6f493a2514

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a2514


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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