VaultCrossChainManagerUpgradeable

Description:

Multi-signature wallet contract requiring multiple confirmations for transaction execution.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "contracts/VaultCrossChainManagerUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import "contract-evm/src/interface/IVault.sol";
import "contract-evm/src/library/types/VaultTypes.sol";
import "contract-evm/src/library/types/EventTypes.sol";
import "contract-evm/src/library/types/RebalanceTypes.sol";
import "contract-evm/src/library/Utils.sol";

import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

import "./interface/IVaultCrossChainManager.sol";
import "./interface/IOrderlyCrossChain.sol";
import "./utils/OrderlyCrossChainMessage.sol";

/**
 * @title Vault Cross Chain Manager
 * @notice Manages cross-chain communication between Vaults and the Orderly Ledger
 * @dev This contract is responsible for:
 * - Processing deposits from vault to ledger
 * - Handling withdrawals from ledger to vault
 * - Managing token decimal conversions
 * - Coordinating rebalancing operations (mint/burn) with ledger
 */

/// @notice Storage layout for the Vault Cross Chain Manager
/// @dev Separate contract to enforce proper storage layout with upgradeable contracts
contract VaultCrossChainManagerDatalayout {
    /// @notice Chain ID where this contract is deployed (vault chain)
    uint256 public chainId;
    /// @notice Chain ID of the ledger chain
    uint256 public ledgerChainId;
    /// @notice Interface to the vault contract
    IVault public vault;
    /// @notice Interface to the cross-chain messaging relay
    IOrderlyCrossChain public crossChainRelay;
    /// @notice Maps chain IDs to their respective ledger cross-chain manager addresses
    mapping(uint256 => address) public ledgerCrossChainManagers;
    /// @notice Flag to indicate the version of the cross-chain relay
    /// @dev 0: LayerZeroV1, 1: LayerZeroV2
    uint8 public ccRelayOption;
    /// @notice Interface to the cross-chain messaging relay v2
    IOrderlyCrossChain public crossChainRelayV2;
    /// @notice Mapping of enabled cross-chain relay addresses
    mapping(address => bool) public enabledRelays;

    /// @notice Ensures only the vault contract can call certain functions
    modifier onlyVault() {
        require(msg.sender == address(vault), "VaultCrossChainManager: only vault can call");
        _;
    }

    /// @notice Ensures only the cross-chain relay can call certain functions
    modifier onlyEnabledRelay() {
        require(enabledRelays[msg.sender], "VaultCrossChainManager: only enabled CCRelay can call");
        _;
    }

    event SetCCRelayStatus(address indexed ccRelay, bool status);
    event SetCCRelayOption(uint8 ccRelayOption);
}

/// @title VaultCrossChainManagerUpgradeable
/// @notice Main contract for managing cross-chain operations on vault chains
/// @dev Handles message routing between vault and cross-chain relay
contract VaultCrossChainManagerUpgradeable is
    IVaultCrossChainManager,
    IOrderlyCrossChainReceiver,
    OwnableUpgradeable,
    UUPSUpgradeable,
    VaultCrossChainManagerDatalayout
{
    /// @notice Initializes the contract
    /// @dev Sets up the upgradeable contract with ownership and UUPS functionality
    function initialize(address owner) public initializer {
        _transferOwnership(owner);
        __UUPSUpgradeable_init();
    }

    /// @dev Required override for UUPS proxy pattern
    function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}

    /// @notice Upgrades the implementation contract
    /// @dev Only callable by owner through proxy
    /// @param newImplementation Address of new implementation contract
    function upgradeTo(address newImplementation) public override onlyOwner onlyProxy {
        _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
    }

    // ================================ ONLY OWNER FUNCTIONS ================================
    /// @notice Sets the chain ID for this contract instance
    /// @dev Critical for cross-chain message routing
    /// @param _chainId The chain ID where this contract is deployed
    function setChainId(uint256 _chainId) public onlyOwner {
        chainId = _chainId;
    }

    /// @notice Links this contract to the vault
    /// @dev The vault contract will be the only one allowed to initiate deposits
    /// @param _vault Address of the vault contract
    function setVault(address _vault) public onlyOwner {
        vault = IVault(_vault);
    }

    /// @notice Sets the cross-chain relay contract address
    /// @dev The relay handles the actual cross-chain message transmission
    /// @param _crossChainRelay Address of the cross-chain relay contract
    function setCrossChainRelay(address _crossChainRelay) public onlyOwner {
        crossChainRelay = IOrderlyCrossChain(_crossChainRelay);
    }

    /// @notice Sets the cross-chain relay contract address
    /// @dev The relay handles the actual cross-chain message transmission
    /// @param _crossChainRelayV2 Address of the cross-chain relay contract
    function setCrossChainRelayV2(address _crossChainRelayV2) public onlyOwner {
        crossChainRelayV2 = IOrderlyCrossChain(_crossChainRelayV2);
    }

    /// @notice Sets the status of a cross-chain relay
    /// @dev Allows the owner to enable or disable a relay
    /// @param _ccRelay The address of the cross-chain relay
    /// @param _status The new status of the relay (true for enabled, false for disabled)
    function setRelayStatus(address _ccRelay, bool _status) public onlyOwner {
        enabledRelays[_ccRelay] = _status;
        emit SetCCRelayStatus(_ccRelay, _status);
    }

    /// @notice Sets the cross-chain relay option
    /// @dev Allows the owner to set the cross-chain relay option
    /// @param _ccRelayOption The new cross-chain relay option
    /// @dev 0: LayerZeroV1, 1: LayerZeroV2
    function setCCRelayOption(uint8 _ccRelayOption) public onlyOwner {
        ccRelayOption = _ccRelayOption;
        emit SetCCRelayOption(_ccRelayOption);
    }

    /// @notice Sets the ledger chain ID and its cross-chain manager address
    /// @dev Required for routing messages to the ledger
    /// @param _chainId The ledger chain ID
    /// @param _ledgerCrossChainManager Address of the ledger's cross-chain manager
    function setLedgerCrossChainManager(uint256 _chainId, address _ledgerCrossChainManager) public onlyOwner {
        ledgerChainId = _chainId;
        ledgerCrossChainManagers[_chainId] = _ledgerCrossChainManager;
    }

    // ================================ ONLY RELAY FUNCTIONS ================================
    /// @notice Handles incoming cross-chain messages from the relay
    /// @dev Routes messages based on their type and forwards to vault
    /// @param message The cross-chain message metadata
    /// @param payload The actual message data
    function receiveMessage(OrderlyCrossChainMessage.MessageV1 memory message, bytes memory payload)
        external
        override
        onlyEnabledRelay
    {
        require(message.dstChainId == chainId, "VaultCrossChainManager: dstChainId not match");
        require(message.srcChainId == ledgerChainId, "VaultCrossChainManager: invalid source chain");

        if (message.payloadDataType == uint8(OrderlyCrossChainMessage.PayloadDataType.EventTypesWithdrawData)) {
            EventTypes.WithdrawData memory data = abi.decode(payload, (EventTypes.WithdrawData));
            // Handle test token case
            if (keccak256(bytes(data.tokenSymbol)) == keccak256(bytes("CrossChainManagerTest"))) {
                _sendTestWithdrawBack();
            } else {
                VaultTypes.VaultWithdraw memory withdrawData = VaultTypes.VaultWithdraw({
                    accountId: data.accountId,
                    sender: data.sender,
                    receiver: data.receiver,
                    brokerHash: Utils.calculateStringHash(data.brokerId),
                    tokenHash: Utils.calculateStringHash(data.tokenSymbol),
                    tokenAmount: data.tokenAmount,
                    fee: data.fee,
                    withdrawNonce: data.withdrawNonce
                });
                _sendWithdrawToVault(withdrawData);
            }
        } else if (message.payloadDataType == uint8(OrderlyCrossChainMessage.PayloadDataType.EventTypesWithdraw2Contract)) {
            EventTypes.Withdraw2Contract memory data = abi.decode(payload, (EventTypes.Withdraw2Contract));
            VaultTypes.VaultWithdraw2Contract memory vaultData = VaultTypes.VaultWithdraw2Contract({
                vaultType: VaultTypes.VaultEnum(uint8(data.vaultType)),
                accountId: data.accountId,
                brokerHash: data.brokerHash,
                tokenHash: data.tokenHash,
                tokenAmount: data.tokenAmount,
                fee: data.fee,
                sender: data.sender,
                receiver: data.receiver,
                withdrawNonce: data.withdrawNonce,
                clientId: data.clientId
            });
            vault.withdraw2Contract(vaultData);
        } else if (message.payloadDataType == uint8(OrderlyCrossChainMessage.PayloadDataType.RebalanceBurnCCData)) {
            RebalanceTypes.RebalanceBurnCCData memory data = abi.decode(payload, (RebalanceTypes.RebalanceBurnCCData));
            vault.rebalanceBurn(data);
        } else if (message.payloadDataType == uint8(OrderlyCrossChainMessage.PayloadDataType.RebalanceMintCCData)) {
            RebalanceTypes.RebalanceMintCCData memory data = abi.decode(payload, (RebalanceTypes.RebalanceMintCCData));
            vault.rebalanceMint(data);
        } else if (message.payloadDataType == uint8(OrderlyCrossChainMessage.PayloadDataType.EventTypesSetBrokerData)) {
            // Handle SetBroker from ledger
            EventTypes.SetBrokerData memory data = abi.decode(payload, (EventTypes.SetBrokerData));
            
            // Validate destination chain ID from both message envelope and payload data
            require(data.dstChainId == chainId, "VaultCrossChainManager: dstChainId not match");
                    
            vault.setBrokerFromLedger(data);
        } else {
            revert("VaultCrossChainManager: payloadDataType not match");
        }
    }

    /// @notice Triggers a withdrawal from the ledger.
    /// @param data Struct containing withdrawal data.
    function _sendWithdrawToVault(VaultTypes.VaultWithdraw memory data) internal {
        vault.withdraw(data);
    }


    // ================================ ONLY VAULT FUNCTIONS ================================
    /// @notice Fetches the deposit fee based on deposit data.
    /// @param data Struct containing deposit data.
    function getDepositFee(VaultTypes.VaultDeposit memory data) public view override returns (uint256) {
        OrderlyCrossChainMessage.MessageV1 memory message = OrderlyCrossChainMessage.MessageV1({
            method: uint8(OrderlyCrossChainMessage.CrossChainMethod.Deposit),
            option: ccRelayOption,
            payloadDataType: uint8(OrderlyCrossChainMessage.PayloadDataType.VaultTypesVaultDeposit),
            srcCrossChainManager: address(this),
            dstCrossChainManager: ledgerCrossChainManagers[ledgerChainId],
            srcChainId: chainId,
            dstChainId: ledgerChainId
        });
        bytes memory payload = abi.encode(data);

        return _estimateFee(message, payload);
    }

    /// @notice Estimates the gas fee for a message
    /// @dev Estimates the gas fee for a message to the cross-chain relay
    /// @param message The cross-chain message metadata
    /// @param payload The actual message payload
    function _estimateFee(OrderlyCrossChainMessage.MessageV1 memory message, bytes memory payload) internal view returns (uint256) {
        if (message.option == uint8(OrderlyCrossChainMessage.CrossChainOption.LayerZeroV1)) {
            return crossChainRelay.estimateGasFee(message, payload);
        } else if (message.option == uint8(OrderlyCrossChainMessage.CrossChainOption.LayerZeroV2)) {
            return crossChainRelayV2.estimateGasFee(message, payload);
        } else {
            revert("VaultCrossChainManager: ccRelayOption not match");
        }
    }

    /// @notice Initiates a deposit to the ledger
    /// @dev Constructs and sends a cross-chain message through the relay
    /// @param data The deposit information including token and amount details
    function deposit(VaultTypes.VaultDeposit memory data) external override onlyVault {
        OrderlyCrossChainMessage.MessageV1 memory message = OrderlyCrossChainMessage.MessageV1({
            method: uint8(OrderlyCrossChainMessage.CrossChainMethod.Deposit),
            option: ccRelayOption,
            payloadDataType: uint8(OrderlyCrossChainMessage.PayloadDataType.VaultTypesVaultDeposit),
            srcCrossChainManager: address(this),
            dstCrossChainManager: ledgerCrossChainManagers[ledgerChainId],
            srcChainId: chainId,
            dstChainId: ledgerChainId
        });
        bytes memory payload = abi.encode(data);
        _sendMessage(message, payload);
    }

    /// @notice Initiates a deposit with native token fee payment
    /// @dev Allows paying cross-chain fees in native tokens (e.g., ETH)
    /// @param data The deposit information including token and amount details
    function depositWithFee(VaultTypes.VaultDeposit memory data) external payable override onlyVault {
        OrderlyCrossChainMessage.MessageV1 memory message = OrderlyCrossChainMessage.MessageV1({
            method: uint8(OrderlyCrossChainMessage.CrossChainMethod.Deposit),
            option: ccRelayOption,
            payloadDataType: uint8(OrderlyCrossChainMessage.PayloadDataType.VaultTypesVaultDeposit),
            srcCrossChainManager: address(this),
            dstCrossChainManager: ledgerCrossChainManagers[ledgerChainId],
            srcChainId: chainId,
            dstChainId: ledgerChainId
        });
        bytes memory payload = abi.encode(data);

        _sendMessageWithFee(message, payload);
    }

    /// @notice Initiates a deposit with fee refund capability
    /// @dev Allows specifying a refund address for unused cross-chain fees
    /// @param refundReceiver Address to receive any unused fee refunds
    /// @param data The deposit information including token and amount details
    function depositWithFeeRefund(address refundReceiver, VaultTypes.VaultDeposit memory data)
        external
        payable
        override
        onlyVault
    {
        OrderlyCrossChainMessage.MessageV1 memory message = OrderlyCrossChainMessage.MessageV1({
            method: uint8(OrderlyCrossChainMessage.CrossChainMethod.Deposit),
            option: ccRelayOption,
            payloadDataType: uint8(OrderlyCrossChainMessage.PayloadDataType.VaultTypesVaultDeposit),
            srcCrossChainManager: address(this),
            dstCrossChainManager: ledgerCrossChainManagers[ledgerChainId],
            srcChainId: chainId,
            dstChainId: ledgerChainId
        });
        bytes memory payload = abi.encode(data);

        _sendMessageWithFeeRefund(refundReceiver, message, payload);
    }

    /// @notice Sends withdrawal confirmation back to the ledger
    /// @dev Called after vault processes a withdrawal
    /// @param data The withdrawal information to confirm
    function withdraw(VaultTypes.VaultWithdraw memory data) external override onlyVault {
        OrderlyCrossChainMessage.MessageV1 memory message = OrderlyCrossChainMessage.MessageV1({
            method: uint8(OrderlyCrossChainMessage.CrossChainMethod.WithdrawFinish),
            option: ccRelayOption,
            payloadDataType: uint8(OrderlyCrossChainMessage.PayloadDataType.VaultTypesVaultWithdraw),
            srcCrossChainManager: address(this),
            dstCrossChainManager: ledgerCrossChainManagers[ledgerChainId],
            srcChainId: chainId,
            dstChainId: ledgerChainId
        });
        bytes memory payload = abi.encode(data);

        _sendMessage(message, payload);
    }

    /// @notice Sends burn completion confirmation to the ledger
    /// @dev Called after vault completes a token burn operation
    /// @param data The burn completion information
    function burnFinish(RebalanceTypes.RebalanceBurnCCFinishData memory data) external override onlyVault {
        OrderlyCrossChainMessage.MessageV1 memory message = OrderlyCrossChainMessage.MessageV1({
            method: uint8(OrderlyCrossChainMessage.CrossChainMethod.RebalanceBurnFinish),
            option: ccRelayOption,
            payloadDataType: uint8(OrderlyCrossChainMessage.PayloadDataType.RebalanceBurnCCFinishData),
            srcCrossChainManager: address(this),
            dstCrossChainManager: ledgerCrossChainManagers[ledgerChainId],
            srcChainId: chainId,
            dstChainId: ledgerChainId
        });
        bytes memory payload = abi.encode(data);

        _sendMessage(message, payload);
    }

    /// @notice Sends mint completion confirmation to the ledger
    /// @dev Called after vault completes a token mint operation
    /// @param data The mint completion information
    function mintFinish(RebalanceTypes.RebalanceMintCCFinishData memory data) external override onlyVault {
        OrderlyCrossChainMessage.MessageV1 memory message = OrderlyCrossChainMessage.MessageV1({
            method: uint8(OrderlyCrossChainMessage.CrossChainMethod.RebalanceMintFinish),
            option: ccRelayOption,
            payloadDataType: uint8(OrderlyCrossChainMessage.PayloadDataType.RebalanceMintCCFinishData),
            srcCrossChainManager: address(this),
            dstCrossChainManager: ledgerCrossChainManagers[ledgerChainId],
            srcChainId: chainId,
            dstChainId: ledgerChainId
        });
        bytes memory payload = abi.encode(data);

        _sendMessage(message, payload);
    }



    /// @notice Sends a message
    /// @dev Sends a message to the cross-chain relay
    /// @param message The cross-chain message metadata
    /// @param payload The actual message payload
    function _sendMessage(OrderlyCrossChainMessage.MessageV1 memory message, bytes memory payload) internal {
        if (message.option == uint8(OrderlyCrossChainMessage.CrossChainOption.LayerZeroV1)) {
            crossChainRelay.sendMessage(message, payload);
        } else if (message.option == uint8(OrderlyCrossChainMessage.CrossChainOption.LayerZeroV2)) {
            crossChainRelayV2.sendMessage(message, payload);
        } else {
            revert("VaultCrossChainManager: ccRelayOption not match");
        }
    }

    /// @notice Sends a message with fee payment
    /// @dev Allows paying cross-chain fees in native tokens (e.g., ETH)
    /// @param message The cross-chain message metadata
    /// @param payload The actual message payload
    function _sendMessageWithFee(OrderlyCrossChainMessage.MessageV1 memory message, bytes memory payload) internal {
        if (message.option == uint8(OrderlyCrossChainMessage.CrossChainOption.LayerZeroV1)) {
            crossChainRelay.sendMessageWithFee{value: msg.value}(message, payload);
        } else if (message.option == uint8(OrderlyCrossChainMessage.CrossChainOption.LayerZeroV2)) {
            crossChainRelayV2.sendMessageWithFee{value: msg.value}(message, payload);
        } else {
            revert("VaultCrossChainManager: ccRelayOption not match");
        }
    }

    /// @notice Sends a message with fee refund capability
    /// @dev Allows specifying a refund address for unused cross-chain fees
    /// @param refundReceiver Address to receive any unused fee refunds
    /// @param message The cross-chain message metadata
    /// @param payload The actual message payload
    function _sendMessageWithFeeRefund(address refundReceiver, OrderlyCrossChainMessage.MessageV1 memory message, bytes memory payload) internal {
        if (message.option == uint8(OrderlyCrossChainMessage.CrossChainOption.LayerZeroV1)) {
            crossChainRelay.sendMessageWithFeeRefund{value: msg.value}(refundReceiver, message, payload);
        } else if (message.option == uint8(OrderlyCrossChainMessage.CrossChainOption.LayerZeroV2)) {
            crossChainRelayV2.sendMessageWithFeeRefund{value: msg.value}(refundReceiver, message, payload);
        } else {
            revert("VaultCrossChainManager: ccRelayOption not match");
        }
    }

    
    /// @notice Sends a test withdrawal confirmation back to the ledger
    /// @dev Used for testing cross-chain communication
    function _sendTestWithdrawBack() internal {
        VaultTypes.VaultWithdraw memory data = VaultTypes.VaultWithdraw({
            accountId: bytes32(0),
            sender: address(0),
            receiver: address(0),
            brokerHash: bytes32(0),
            tokenHash: Utils.calculateStringHash("CrossChainManagerTest"),
            tokenAmount: 0,
            fee: 0,
            withdrawNonce: 0
        });
        OrderlyCrossChainMessage.MessageV1 memory message = OrderlyCrossChainMessage.MessageV1({
            method: uint8(OrderlyCrossChainMessage.CrossChainMethod.WithdrawFinish),
            option: ccRelayOption,
            payloadDataType: uint8(OrderlyCrossChainMessage.PayloadDataType.VaultTypesVaultWithdraw),
            srcCrossChainManager: address(this),
            dstCrossChainManager: ledgerCrossChainManagers[ledgerChainId],
            srcChainId: chainId,
            dstChainId: ledgerChainId
        });
        bytes memory payload = abi.encode(data);

        _sendMessage(message, payload);
    }

    /// @notice Returns the role identifier for this contract
    /// @return A string indicating this is the vault cross-chain manager
    function getRole() external pure returns (string memory) {
        return "vault";
    }
}
"
    },
    "lib/contract-evm/src/interface/IVault.sol": {
      "content": "// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;

import "./../library/types/VaultTypes.sol";
import "./../library/types/RebalanceTypes.sol";
import "./../library/types/EventTypes.sol";

interface IVault {
    error OnlyCrossChainManagerCanCall();
    error AccountIdInvalid();
    error TokenNotAllowed();
    error DepositTokenDisabled();
    error InvalidTokenAddress();
    error BrokerNotAllowed();
    error BalanceNotEnough(uint256 balance, uint128 amount);
    error AddressZero();
    error EnumerableSetError();
    error ZeroDepositFee();
    error ZeroDeposit();
    error ZeroCodeLength();
    error NotZeroCodeLength();
    error DepositExceedLimit();
    error NativeTokenDepositAmountMismatch();
    error NotRebalanceEnableToken();
    error SwapAlreadySubmitted();
    error InvalidSwapSignature();
    error CeffuAddressMismatch(address want, address got);

    // @deprecated
    event AccountDeposit(
        bytes32 indexed accountId,
        address indexed userAddress,
        uint64 indexed depositNonce,
        bytes32 tokenHash,
        uint128 tokenAmount
    );

    event AccountDepositTo(
        bytes32 indexed accountId,
        address indexed userAddress,
        uint64 indexed depositNonce,
        bytes32 tokenHash,
        uint128 tokenAmount
    );

    event AccountWithdraw(
        bytes32 indexed accountId,
        uint64 indexed withdrawNonce,
        bytes32 brokerHash,
        address sender,
        address receiver,
        bytes32 tokenHash,
        uint128 tokenAmount,
        uint128 fee
    );

    event AccountDelegate(
        address indexed delegateContract,
        bytes32 indexed brokerHash,
        address indexed delegateSigner,
        uint256 chainId,
        uint256 blockNumber
    );

    event SetAllowedToken(bytes32 indexed _tokenHash, bool _allowed);
    event SetAllowedBroker(bytes32 indexed _brokerHash, bool _allowed);
    event ChangeTokenAddressAndAllow(bytes32 indexed _tokenHash, address _tokenAddress);
    event ChangeCrossChainManager(address oldAddress, address newAddress);
    event ChangeDepositLimit(address indexed _tokenAddress, uint256 _limit);
    event WithdrawFailed(address indexed token, address indexed receiver, uint256 amount);
    event SetRebalanceEnableToken(bytes32 indexed _tokenHash, bool _allowed);
    event DelegateSwapExecuted(bytes32 indexed tradeId, bytes32 inTokenHash, uint256 inTokenAmount, address to, uint256 value);

    event SetProtocolVaultAddress(address _oldProtocolVaultAddress, address _newProtocolVaultAddress);
    event SetCeffuAddress(address _oldCeffuAddress, address _newCeffuAddress);
    event DisableDepositToken(bytes32 indexed _tokenHash);
    event EnableDepositToken(bytes32 indexed _tokenHash);

    // SetBroker from ledger events
    event SetBrokerFromLedgerAlreadySet(bytes32 indexed brokerHash, uint256 dstChainId, bool allowed);
    event SetBrokerFromLedgerSuccess(bytes32 indexed brokerHash, uint256 dstChainId, bool allowed);

    function initialize() external;

    function deposit(VaultTypes.VaultDepositFE calldata data) external payable;
    function depositTo(address receiver, VaultTypes.VaultDepositFE calldata data) external payable;
    function getDepositFee(address recevier, VaultTypes.VaultDepositFE calldata data) external view returns (uint256);
    function enableDepositFee(bool _enabled) external;
    function withdraw(VaultTypes.VaultWithdraw calldata data) external;
    function delegateSigner(VaultTypes.VaultDelegate calldata data) external;
    function withdraw2Contract(VaultTypes.VaultWithdraw2Contract calldata data) external;

    // CCTP: functions for receive rebalance msg
    function rebalanceMint(RebalanceTypes.RebalanceMintCCData calldata data) external;
    function rebalanceBurn(RebalanceTypes.RebalanceBurnCCData calldata data) external;
    function setTokenMessengerContract(address _tokenMessengerContract) external;
    function setRebalanceMessengerContract(address _rebalanceMessengerContract) external;

    // admin call
    function setCrossChainManager(address _crossChainManagerAddress) external;
    function setDepositLimit(address _tokenAddress, uint256 _limit) external;
    function setProtocolVaultAddress(address _protocolVaultAddress) external;
    function emergencyPause() external;
    function emergencyUnpause() external;

    // whitelist
    function setAllowedToken(bytes32 _tokenHash, bool _allowed) external;
    function setAllowedBroker(bytes32 _brokerHash, bool _allowed) external;
    function setNativeTokenHash(bytes32 _nativeTokenHash) external;
    function setNativeTokenDepositLimit(uint256 _nativeTokenDepositLimit) external;
    function setRebalanceEnableToken(bytes32 _tokenHash, bool _allowed) external;
    function disableDepositToken(bytes32 _tokenHash) external;
    function enableDepositToken(bytes32 _tokenHash) external;
    function changeTokenAddressAndAllow(bytes32 _tokenHash, address _tokenAddress) external;
    function getAllowedToken(bytes32 _tokenHash) external view returns (address);
    function getAllowedBroker(bytes32 _brokerHash) external view returns (bool);
    function getAllAllowedToken() external view returns (bytes32[] memory);
    function getAllAllowedBroker() external view returns (bytes32[] memory);
    function getAllRebalanceEnableToken() external view returns (bytes32[] memory);

    // cross-chain broker management
    function setBrokerFromLedger(EventTypes.SetBrokerData calldata data) external;

    // Delegate swap function
    function setSwapOperator(address _swapOperator) external;
    function setSwapSigner(address _swapSigner) external;
    function isSwapSubmitted(bytes32 tradeId) external view returns (bool);
    function delegateSwap(VaultTypes.DelegateSwap calldata data) external;
}
"
    },
    "lib/contract-evm/src/library/types/VaultTypes.sol": {
      "content": "// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;

/// @title VaultTypes library
/// @author Orderly_Rubick
library VaultTypes {
    struct VaultDepositFE {
        bytes32 accountId;
        bytes32 brokerHash;
        bytes32 tokenHash;
        uint128 tokenAmount;
    }

    struct VaultDeposit {
        bytes32 accountId;
        address userAddress;
        bytes32 brokerHash;
        bytes32 tokenHash;
        uint128 tokenAmount;
        uint64 depositNonce; // deposit nonce
    }

    struct VaultWithdraw {
        bytes32 accountId;
        bytes32 brokerHash;
        bytes32 tokenHash;
        uint128 tokenAmount;
        uint128 fee;
        address sender;
        address receiver;
        uint64 withdrawNonce; // withdraw nonce
    }

    struct VaultDelegate {
        bytes32 brokerHash;
        address delegateSigner;
    }

    enum VaultEnum {
        ProtocolVault,
        UserVault,
        Ceffu
    }

    struct VaultWithdraw2Contract {
        VaultEnum vaultType;
        bytes32 accountId;
        bytes32 brokerHash;
        bytes32 tokenHash;
        uint128 tokenAmount;
        uint128 fee;
        address sender;
        address receiver;
        uint64 withdrawNonce;
        uint256 clientId;
    }

    struct DelegateSwap {
        bytes32 tradeId;
        uint256 chainId;
        bytes32 inTokenHash;
        uint256 inTokenAmount;
        address to;
        uint256 value;
        bytes swapCalldata;
        // signature
        bytes32 r;
        bytes32 s;
        uint8 v;
    }
}
"
    },
    "lib/contract-evm/src/library/types/EventTypes.sol": {
      "content": "// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;

/// @title EventTypes library
/// @author Orderly_Rubick
library EventTypes {
    // EventUpload
    struct EventUpload {
        EventUploadData[] events;
        bytes32 r;
        bytes32 s;
        uint8 v;
        uint8 count;
        uint64 batchId;
    }

    struct EventUploadData {
        uint8 bizType; // 1 - withdraw, 2 - settlement, 3 - adl, 4 - liquidation, 5 - fee distribution, 6 - delegate signer, 7 - delegate withdraw, 12 - balance transfer, 13 - swap result upload
        uint64 eventId;
        bytes data;
    }

    // WithdrawData
    struct WithdrawData {
        uint128 tokenAmount;
        uint128 fee;
        uint256 chainId; // target withdraw chain
        bytes32 accountId;
        bytes32 r; // String to bytes32, big endian?
        bytes32 s;
        uint8 v;
        address sender;
        uint64 withdrawNonce;
        address receiver;
        uint64 timestamp;
        string brokerId; // only this field is string, others should be bytes32 hashedBrokerId
        string tokenSymbol; // only this field is string, others should be bytes32 hashedTokenSymbol
    }

    // WithdrawDataSol
    struct WithdrawDataSol {
        uint128 tokenAmount;
        uint128 fee;
        uint256 chainId; // target withdraw chain
        bytes32 accountId;
        bytes32 r;
        bytes32 s;
        bytes32 sender;
        bytes32 receiver;
        uint64 withdrawNonce;
        uint64 timestamp;
        string brokerId; // only this field is string, others should be bytes32 hashedBrokerId
        string tokenSymbol; // only this field is string, others should be bytes32 hashedTokenSymbol
    }

    struct Settlement {
        bytes32 accountId;
        bytes32 settledAssetHash;
        bytes32 insuranceAccountId;
        int128 settledAmount;
        uint128 insuranceTransferAmount;
        uint64 timestamp;
        SettlementExecution[] settlementExecutions;
    }

    struct SettlementExecution {
        bytes32 symbolHash;
        uint128 markPrice;
        int128 sumUnitaryFundings;
        int128 settledAmount;
    }

    struct Adl {
        bytes32 accountId;
        bytes32 insuranceAccountId;
        bytes32 symbolHash;
        int128 positionQtyTransfer;
        int128 costPositionTransfer;
        uint128 adlPrice;
        int128 sumUnitaryFundings;
        uint64 timestamp;
    }

    struct AdlV2 {
        bytes32 accountId;
        bytes32 symbolHash;
        int128 positionQtyTransfer;
        int128 costPositionTransfer;
        uint128 adlPrice;
        int128 sumUnitaryFundings;
        uint64 timestamp;
        bool isInsuranceAccount;
    }

    struct Liquidation {
        bytes32 liquidatedAccountId;
        bytes32 insuranceAccountId;
        bytes32 liquidatedAssetHash;
        uint128 insuranceTransferAmount;
        uint64 timestamp;
        LiquidationTransfer[] liquidationTransfers;
    }

    struct LiquidationTransfer {
        bytes32 liquidatorAccountId;
        bytes32 symbolHash;
        int128 positionQtyTransfer;
        int128 costPositionTransfer;
        int128 liquidatorFee;
        int128 insuranceFee;
        int128 liquidationFee;
        uint128 markPrice;
        int128 sumUnitaryFundings;
        uint64 liquidationTransferId;
    }

    struct LiquidationV2 {
        bytes32 accountId;
        bytes32 liquidatedAssetHash;
        int128 insuranceTransferAmount;
        uint64 timestamp;
        bool isInsuranceAccount;
        LiquidationTransferV2[] liquidationTransfers;
    }

    struct LiquidationTransferV2 {
        bytes32 symbolHash;
        int128 positionQtyTransfer;
        int128 costPositionTransfer;
        int128 fee;
        uint128 markPrice;
        int128 sumUnitaryFundings;
    }

    struct FeeDistribution {
        bytes32 fromAccountId;
        bytes32 toAccountId;
        uint128 amount;
        bytes32 tokenHash;
    }

    struct DelegateSigner {
        address delegateSigner;
        address delegateContract;
        bytes32 brokerHash;
        uint256 chainId;
    }

    enum VaultEnum {
        ProtocolVault,
        UserVault,
        Ceffu
    }

    struct Withdraw2Contract {
        uint128 tokenAmount;
        uint128 fee;
        uint256 chainId; // target withdraw chain
        bytes32 accountId;
        VaultEnum vaultType;
        address sender;
        uint64 withdrawNonce;
        address receiver; // maybe optional?
        uint64 timestamp;
        bytes32 brokerHash;
        bytes32 tokenHash;
        uint256 clientId;
    }

    struct BalanceTransfer {
        bytes32 accountId;
        uint128 amount;
        bytes32 tokenHash;
        bool isFromAccountId;
        uint8 transferType;
    }

    struct SwapResult {
      bytes32 accountId;
      bytes32 buyTokenHash;
      bytes32 sellTokenHash;
      int128 buyQuantity;
      int128 sellQuantity;
      uint256 chainId;
      uint8 swapStatus; // OFF_CHAIN_SUCCESS(0), ON_CHAIN_SUCCESS(1), ON_CHAIN_FAILED(2)
    }

    // SetBrokerData - for cross-chain broker addition or removal
    struct SetBrokerData {
        bytes32 brokerHash;  // The hash of the broker to be added or removed
        uint256 dstChainId;  // The destination chain ID where broker should be modified
        bool allowed;        // true = add broker, false = remove broker
    }
}
"
    },
    "lib/contract-evm/src/library/types/RebalanceTypes.sol": {
      "content": "// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;

/// @title RebalanceTypes library
/// @author Orderly_Rubick
library RebalanceTypes {
    enum RebalanceStatusEnum {
        None,
        Pending,
        Succ,
        Fail
    }

    // RebalanceStatus
    struct RebalanceStatus {
        uint64 rebalanceId; // Because the mapping key rebalanceId is mod, so we need to record the real rebalanceId
        RebalanceStatusEnum burnStatus;
        RebalanceStatusEnum mintStatus;
    }
    // RebalanceBurnUploadData

    struct RebalanceBurnUploadData {
        bytes32 r;
        bytes32 s;
        uint8 v;
        uint64 rebalanceId;
        uint128 amount;
        bytes32 tokenHash;
        uint256 burnChainId;
        uint256 mintChainId;
    }

    struct RebalanceBurnCCData {
        uint32 dstDomain;
        uint64 rebalanceId;
        uint128 amount;
        bytes32 tokenHash;
        uint256 burnChainId;
        uint256 mintChainId;
        address dstVaultAddress;
    }

    struct RebalanceBurnCCFinishData {
        bool success;
        uint64 rebalanceId;
        uint128 amount;
        bytes32 tokenHash;
        uint256 burnChainId;
        uint256 mintChainId;
    }

    // RebalanceMintUploadData
    struct RebalanceMintUploadData {
        bytes32 r;
        bytes32 s;
        uint8 v;
        uint64 rebalanceId;
        uint128 amount;
        bytes32 tokenHash;
        uint256 burnChainId;
        uint256 mintChainId;
        bytes messageBytes;
        bytes messageSignature;
    }

    struct RebalanceMintCCData {
        uint64 rebalanceId;
        uint128 amount;
        bytes32 tokenHash;
        uint256 burnChainId;
        uint256 mintChainId;
        bytes messageBytes;
        bytes messageSignature;
    }

    struct RebalanceMintCCFinishData {
        bool success;
        uint64 rebalanceId;
        uint128 amount;
        bytes32 tokenHash;
        uint256 burnChainId;
        uint256 mintChainId;
    }
}
"
    },
    "lib/contract-evm/src/library/Utils.sol": {
      "content": "// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;

/// @title Utils library
/// @author Orderly_Rubick Orderly_Zion
library Utils {
    // legacy account id
    function getAccountId(address _userAddr, string memory _brokerId) internal pure returns (bytes32) {
        return keccak256(abi.encode(_userAddr, calculateStringHash(_brokerId)));
    }

    // legacy account id
    function calculateAccountId(address _userAddr, bytes32 _brokerHash) internal pure returns (bytes32) {
        return keccak256(abi.encode(_userAddr, _brokerHash));
    }

    // pv account id
    function calculateStrategyVaultAccountId(address _vault, address _userAddr, bytes32 _brokerHash)
        internal
        pure
        returns (bytes32)
    {
        return keccak256(abi.encode(_vault, _userAddr, _brokerHash));
    }

    function calculateStringHash(string memory _str) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(_str));
    }

    // legacy account id for evm
    function validateAccountId(bytes32 _accountId, bytes32 _brokerHash, address _userAddress)
        internal
        pure
        returns (bool)
    {
        return keccak256(abi.encode(_userAddress, _brokerHash)) == _accountId;
    }

    // legacy account id for solana
    function validateAccountId(bytes32 _accountId, bytes32 _brokerHash, bytes32 _userAddress)
        internal
        pure
        returns (bool)
    {
        return keccak256(abi.encode(_userAddress, _brokerHash)) == _accountId;
    }

    function validateStrategyVaultAccountId(
        address _vault,
        bytes32 _accountId,
        bytes32 _brokerHash,
        address _userAddress
    ) internal pure returns (bool) {
        return calculateStrategyVaultAccountId(_vault, _userAddress, _brokerHash) == _accountId;
    }

    // both legacy accountId and pv accountId are valid
    function validateExtendedAccountId(address _vault, bytes32 _accountId, bytes32 _brokerHash, address _userAddress)
        internal
        pure
        returns (bool)
    {
        return validateAccountId(_accountId, _brokerHash, _userAddress)
            || validateStrategyVaultAccountId(_vault, _accountId, _brokerHash, _userAddress);
    }

    function toBytes32(address addr) internal pure returns (bytes32) {
        return bytes32(abi.encode(addr));
    }

    function bytes32ToBytes(bytes32 _bytes32) internal pure returns (bytes memory) {
        return abi.encodePacked(_bytes32);
    }
}
"
    },
    "node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";

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

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    function __Ownable_init() internal onlyInitializing {
        __Ownable_init_unchained();
    }

    function __Ownable_init_unchained() internal onlyInitializing {
        _transferOwnership(_msgSender());
    }

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

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

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

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

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

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

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[49] private __gap;
}
"
    },
    "node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)

pragma solidity ^0.8.0;

import "../../interfaces/draft-IERC1822Upgradeable.sol";
import "../ERC1967/ERC1967UpgradeUpgradeable.sol";
import "./Initializable.sol";

/**
 * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
 * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
 *
 * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
 * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
 * `UUPSUpgradeable` with a custom implementation of upgrades.
 *
 * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
 *
 * _Available since v4.1._
 */
abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {
    function __UUPSUpgradeable_init() internal onlyInitializing {
    }

    function __UUPSUpgradeable_init_unchained() internal onlyInitializing {
    }
    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
    address private immutable __self = address(this);

    /**
     * @dev Check that the execution is being performed through a delegatecall call and that the execution context is
     * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
     * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
     * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
     * fail.
     */
    modifier onlyProxy() {
        require(address(this) != __self, "Function must be called through delegatecall");
        require(_getImplementation() == __self, "Function must be called through active proxy");
        _;
    }

    /**
     * @dev Check that the execution is not being performed through a delegate call. This allows a function to be
     * callable on the implementing contract but not through proxies.
     */
    modifier notDelegated() {
        require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall");
        _;
    }

    /**
     * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the
     * implementation. It is used to validate the implementation's compatibility when performing an upgrade.
     *
     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
     * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
     */
    function proxiableUUID() external view virtual override notDelegated returns (bytes32) {
        return _IMPLEMENTATION_SLOT;
    }

    /**
     * @dev Upgrade the implementation of the proxy to `newImplementation`.
     *
     * Calls {_authorizeUpgrade}.
     *
     * Emits an {Upgraded} event.
     *
     * @custom:oz-upgrades-unsafe-allow-reachable delegatecall
     */
    function upgradeTo(address newImplementation) public virtual onlyProxy {
        _authorizeUpgrade(newImplementation);
        _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
    }

    /**
     * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
     * encoded in `data`.
     *
     * Calls {_authorizeUpgrade}.
     *
     * Emits an {Upgraded} event.
     *
     * @custom:oz-upgrades-unsafe-allow-reachable delegatecall
     */
    function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {
        _authorizeUpgrade(newImplementation);
        _upgradeToAndCallUUPS(newImplementation, data, true);
    }

    /**
     * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
     * {upgradeTo} and {upgradeToAndCall}.
     *
     * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
     *
     * ```solidity
     * function _authorizeUpgrade(address) internal override onlyOwner {}
     * ```
     */
    function _authorizeUpgrade(address newImplementation) internal virtual;

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[50] private __gap;
}
"
    },
    "node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.2;

import "../../utils/AddressUpgradeable.sol";

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
 * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
 * case an upgrade adds a module that needs to be initialized.
 *
 * For example:
 *
 * [.hljs-theme-light.nopadding]
 * ```solidity
 * contract MyToken is ERC20Upgradeable {
 *     function initialize() initializer public {
 *         __ERC20_init("MyToken", "MTK");
 *     }
 * }
 *
 * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
 *     function initializeV2() reinitializer(2) public {
 *         __ERC20Permit_init("MyToken");
 *     }
 * }
 * ```
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
 * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() {
 *     _disableInitializers();
 * }
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     * @custom:oz-retyped-from bool
     */
    uint8 private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Triggered when the contract has been initialized or reinitialized.
     */
    event Initialized(uint8 version);

    /**
     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
     * `onlyInitializing` functions can be used to initialize parent contracts.
     *
     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
     * constructor.
     *
     * Emits an {Initialized} event.
     */
    modifier initializer() {
        bool isTopLevelCall = !_initializing;
        require(
            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
            "Initializable: contract is already initialized"
        );
        _initialized = 1;
        if (isTopLevelCall) {
            _initializing = true;
        }
        _;
        if (isTopLevelCall) {
            _initializing = false;
            emit Initialized(1);
        }
    }

    /**
     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
     * used to initialize parent contracts.
     *
     * A reinitializer may be used after the original initialization step. This is essential to configure modules that
     * are added through upgrades and that require initialization.
     *
     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
     * cannot be nested. If one is invoked in the context of another, execution will revert.
     *
     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
     * a contract, executing them in the right order is up to the developer or operator.
     *
     * WARNING: setting the version to 255 will prevent any future reinitialization.
     *
     * Emits an {Initialized} event.
     */
    modifier reinitializer(uint8 version) {
        require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
        _initialized = version;
        _initializing = true;
        _;
        _initializing = false;
        emit Initialized(version);
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} and {reinitializer} modifiers, directly or indirectly.
     */
    modifier onlyInitializing() {
        require(_initializing, "Initializable: contract is not initializing");
        _;
    }

    /**
     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
     * through proxies.
     *
     * Emits an {Initialized} event the first time it is successfully executed.
     */
    function _disableInitializers() internal virtual {
        require(!_initializing, "Initializable: contract is initializing");
        if (_initialized != type(uint8).max) {
            _initialized = type(uint8).max;
            emit Initialized(type(uint8).max);
        }
    }

    /**
     * @dev Returns the highest version that has been initialized. See {reinitializer}.
     */
    function _getInitializedVersion() internal view returns (uint8) {
        return _initialized;
    }

    /**
     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
     */
    function _isInitializing() internal view returns (bool) {
        return _initializing;
    }
}
"
    },
    "contracts/interface/IVaultCrossChainManager.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

// Importing necessary utility libraries and types
import "../utils/OrderlyCrossChainMessage.sol";
import "contract-evm/src/library/types/AccountTypes.sol";
import "contract-evm/src/library/types/VaultTypes.sol";
import "contract-evm/src/library/types/RebalanceTypes.sol";

/// @title IVaultCrossChainManager Interface
/// @notice Interface for managing cross-chain activities related to the vault.
interface IVaultCrossChainManager {
    /// @notice Triggers a withdrawal from the ledger.
    /// @param withdraw Struct containing withdrawal data.
    function withdraw(VaultTypes.VaultWithdraw memory withdraw) external;

    /// @notice Triggers a finish msg from vault to ledger to inform the status of burn
    /// @param data Struct containing burn data.
    function burnFinish(RebalanceTypes.RebalanceBurnCCFinishData memory data) external;

    /// @notice Triggers a finish msg from vault to ledger to inform the status of mint
    /// @param data Struct containing mint data.
    function mintFinish(RebalanceTypes.RebalanceMintCCFinishData memory data) external;

    /// @notice Initiates a deposit to the vault.
    /// @param data Struct containing deposit data.
    function deposit(VaultTypes.VaultDeposit memory data) external;

    /// @notice Initiates a deposit to the vault along with native fees.
    /// @param data Struct containing deposit data.
    function depositWithFee(VaultTypes.VaultDeposit memory data) external payable;

    /// @notice Initiates a deposit to the vault along with native fees.
    /// @param refundReceiver Address of the receiver of the deposit fee refund.
    /// @param data Struct containing deposit data.
    function depositWithFeeRefund(address refundReceiver, VaultTypes.VaultDeposit memory data) external payable;

    /// @notice Fetches the deposit fee based on deposit data.
    /// @param data Struct containing deposit data.
    /// @return fee The calculated deposit fee.
    function getDepositFee(VaultTypes.VaultDeposit memory data) external view returns (uint256);

    /// @notice Sets the vault address.
    /// @param vault Address of the new vault.
    function setVault(address vault) external;

    /// @notice Sets the cross-chain relay address.
    /// @param crossChainRelay Address of the new cross-chain relay.
    function setCrossChainRelay(address crossChainRelay) external;
}
"
    },
    "contracts/interface/IOrderlyCrossChain.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "../utils/OrderlyCrossChainMessage.sol";

// Interface for the Cross Chain Operations
interface IOrderlyCrossChain {
    // Event to be emitted when a message is sent
    event MessageSent(OrderlyCrossChainMessage.MessageV1 message, bytes payload);

    // Event to be emitted when a message is received
    event MessageReceived(OrderlyCrossChainMessage.MessageV1 message, bytes payload);

    /// @notice estimate gas fee
    /// @param data message data
    /// @param payload payload
    function estimateGasFee(OrderlyCrossChainMessage.MessageV1 memory data, bytes memory payload)
        external
        view
        returns (uint256);

    /// @notice send message
    /// @param message message
    /// @param payload payload
    function sendMessage(OrderlyCrossChainMessage.MessageV1 memory message, bytes memory payload) external payable;

    /// @notice send message with fee, so no estimate gas fee will not run
    /// @param message message
    /// @param payload payload
    function sendMessageWithFee(OrderlyCrossChainMessage.MessageV1 memory message, bytes memory payload)
        external
        payable;

    /// @notice send message with fee, so no estimate gas fee will not run
    /// @param refundReceiver receiver of the refund
    /// @param message message
    /// @param payload payload
    function sendMessageWithFeeRefund(
        address refundReceiver,
        OrderlyCrossChainMessage.MessageV1 memory message,
        bytes memory payload
    ) external payable;

    /// @notice receive message after decoding the message
    /// @param message message
    /// @param payload payload
    function receiveMessage(OrderlyCrossChainMessage.MessageV1 memory message, bytes memory payload) external payable;
}

// Interface for the Cross Chain Receiver
interface IOrderlyCrossChainReceiver {
    /// @notice receive message from relay, relay will call this function to send messages
    /// @param message message
    /// @param payload payload
    function receiveMessage(OrderlyCrossChainMessage.MessageV1 memory message, bytes memory payload) external;
}
"
    },
    "contracts/utils/OrderlyCrossChainMessage.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

// Library to handle the conversion of the message structure to bytes array and vice versa
library OrderlyCrossChainMessage {
    // List of methods that can be called cross-chain
    enum CrossChainOption {LayerZeroV1, LayerZeroV2}

    enum CrossChainMethod {
        Deposit, // from vault to ledger
        Withdraw, // from ledger to vault
        WithdrawFinish, // from vault to ledger
        Ping, // for message testing
        PingPong, // ABA message testing
        RebalanceBurn, // burn request from ledger to vault
        RebalanceBurnFinish, // burn request finish from vault to ledger
        RebalanceMint, // mint request from ledger to vault
        RebalanceMintFinish, //  mint request finish from vault to ledger
        Withdraw2Contract, // withdraw to contract address
        SetBroker // set broker status from ledger to vault
    }

    enum PayloadDataType {
        EventTypesWithdrawData,
        AccountTypesAccountDeposit,
        AccountTypesAccountWithdraw,
        VaultTypesVaultDeposit,
        VaultTypesVaultWithdraw,
        RebalanceBurnCCData,
        RebalanceBurnCCFinishData,
        RebalanceMintCCData,
        RebalanceMintCCFinishData,
        EventTypesWithdraw2Contract,
        EventTypesSetBrokerData
    }

    // The structure of the message
    struct MessageV1 {
        uint8 method; // enum CrossChainMethod to uint8
        uint8 option; // enum CrossChainOption to uint8
        uint8 payloadDataType; // enum PayloadDataType to uint8
        address srcCrossChainManager; // Source cross-chain manager address
        address dstCrossChainManager; // Target cross-chain manager address
        uint256 srcChainId; // Source blockchain ID
        uint256 dstChainId; // Target blockchain ID
    }

    // Encode the message structure to bytes array
    function encodeMessageV1AndPayload(MessageV1 memory message, bytes memory payload)
        internal
        pure
        returns (bytes memory)
    {
        return abi.encode(message, payload);
    }

    // Decode the bytes array to message structure
    function decodeMessageV1AndPayload(bytes memory data) internal pure returns (MessageV1 memory, bytes memory) {
        (MessageV1 memory message, bytes memory payload) = abi.decode(data, (MessageV1, bytes));
        return (message, payload);
    }
}
"
    },
    "node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";

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

    function __Context_init_unchained() internal onlyInitializing {
    }
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

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

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[50] private __gap;
}
"
    },
    "node_modules/@openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)

pragma solidity ^0.8.0;

/**
 * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
 * proxy whose upgrades are fully controlled by the current implementation.
 */
interface IERC1822ProxiableUpgradeable {
    /**
     * @dev Returns the stor

Tags:
Multisig, Swap, Upgradeable, Multi-Signature, Factory|addr:0x9452d87e138a258c550933e0951bcbd274ea3461|verified:true|block:23549882|tx:0x02b2e1997fdbea6797fbea82ab9d3a31313a4d26cfbe3cd32ed8cc71e25134d9|first_check:1760256767

Submitted on: 2025-10-12 10:12:50

Comments

Log in to comment.

No comments yet.