ETH Price: $3,414.17 (+3.08%)

Contract

0x01dF6fb6a28a89d6bFa53b2b3F20644AbF417678
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Set Approval For...212503702024-11-23 12:13:594 hrs ago1732364039IN
Superform : Super Positions
0 ETH0.000279519.62753314
Set Approval For...212503582024-11-23 12:11:354 hrs ago1732363895IN
Superform : Super Positions
0 ETH0.0004539.25760981
Set Approval For...212503292024-11-23 12:05:474 hrs ago1732363547IN
Superform : Super Positions
0 ETH0.0005166710.55882924
Set Approval For...212503282024-11-23 12:05:354 hrs ago1732363535IN
Superform : Super Positions
0 ETH0.0005084210.39024184
Set Approval For...212503222024-11-23 12:04:234 hrs ago1732363463IN
Superform : Super Positions
0 ETH0.000474559.69809192
Set Approval For...212502402024-11-23 11:47:594 hrs ago1732362479IN
Superform : Super Positions
0 ETH0.000440749.00719918
Set Approval For...212502292024-11-23 11:45:475 hrs ago1732362347IN
Superform : Super Positions
0 ETH0.0005003710.22565646
Set Approval For...212501542024-11-23 11:30:475 hrs ago1732361447IN
Superform : Super Positions
0 ETH0.000460439.40940423
Set Approval For...212501392024-11-23 11:27:475 hrs ago1732361267IN
Superform : Super Positions
0 ETH0.000505410.32845512
Set Approval For...212500702024-11-23 11:13:475 hrs ago1732360427IN
Superform : Super Positions
0 ETH0.0005357810.94945129
Set Approval For...212500472024-11-23 11:09:115 hrs ago1732360151IN
Superform : Super Positions
0 ETH0.0004926610.07072138
Set Approval For...212498612024-11-23 10:31:596 hrs ago1732357919IN
Superform : Super Positions
0 ETH0.000485129.91403204
Set Approval For...212498502024-11-23 10:29:476 hrs ago1732357787IN
Superform : Super Positions
0 ETH0.000445699.10831533
Set Approval For...212498192024-11-23 10:23:356 hrs ago1732357415IN
Superform : Super Positions
0 ETH0.0005513211.26700129
Set Approval For...212495952024-11-23 9:38:357 hrs ago1732354715IN
Superform : Super Positions
0 ETH0.0005228310.68464066
Set Approval For...212495452024-11-23 9:28:357 hrs ago1732354115IN
Superform : Super Positions
0 ETH0.0005671811.59114774
Set Approval For...212494862024-11-23 9:16:477 hrs ago1732353407IN
Superform : Super Positions
0 ETH0.0005351810.93706983
Set Approval For...212494062024-11-23 9:00:477 hrs ago1732352447IN
Superform : Super Positions
0 ETH0.0006914614.13087733
Set Approval For...212492502024-11-23 8:29:358 hrs ago1732350575IN
Superform : Super Positions
0 ETH0.0007070714.44981617
Set Approval For...212491732024-11-23 8:14:118 hrs ago1732349651IN
Superform : Super Positions
0 ETH0.0005174410.57458244
Set Approval For...212490882024-11-23 7:57:118 hrs ago1732348631IN
Superform : Super Positions
0 ETH0.0005575611.3945291
Set Approval For...212489892024-11-23 7:37:119 hrs ago1732347431IN
Superform : Super Positions
0 ETH0.0005182610.59136216
Set Approval For...212487242024-11-23 6:43:5910 hrs ago1732344239IN
Superform : Super Positions
0 ETH0.0004908110.03042112
Set Approval For...212486742024-11-23 6:33:5910 hrs ago1732343639IN
Superform : Super Positions
0 ETH0.0004916510.04755298
Set Approval For...212481962024-11-23 4:57:5911 hrs ago1732337879IN
Superform : Super Positions
0 ETH0.0003347911.52203681
View all transactions

Latest 13 internal transactions

Advanced mode:
Parent Transaction Hash Block From To
211378632024-11-07 19:29:2315 days ago1731007763
Superform : Super Positions
 Contract Creation0 ETH
205134592024-08-12 15:34:59103 days ago1723476899
Superform : Super Positions
 Contract Creation0 ETH
205042602024-08-11 8:44:35104 days ago1723365875
Superform : Super Positions
 Contract Creation0 ETH
204815242024-08-08 4:37:59107 days ago1723091879
Superform : Super Positions
 Contract Creation0 ETH
204457002024-08-03 4:43:11112 days ago1722660191
Superform : Super Positions
 Contract Creation0 ETH
204456772024-08-03 4:38:35112 days ago1722659915
Superform : Super Positions
 Contract Creation0 ETH
204456292024-08-03 4:28:59112 days ago1722659339
Superform : Super Positions
 Contract Creation0 ETH
202601612024-07-08 6:59:35138 days ago1720421975
Superform : Super Positions
 Contract Creation0 ETH
201760192024-06-26 12:59:23150 days ago1719406763
Superform : Super Positions
 Contract Creation0 ETH
195838372024-04-04 17:18:59232 days ago1712251139
Superform : Super Positions
 Contract Creation0 ETH
195836582024-04-04 16:42:35233 days ago1712248955
Superform : Super Positions
 Contract Creation0 ETH
194707252024-03-19 18:58:23248 days ago1710874703
Superform : Super Positions
 Contract Creation0 ETH
190755182024-01-24 9:11:35304 days ago1706087495  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
SuperPositions

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 200 runs

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

import { ERC1155A } from "ERC1155A/ERC1155A.sol";
import { aERC20 } from "ERC1155A/aERC20.sol";
import { Broadcastable } from "src/crosschain-data/utils/Broadcastable.sol";
import { ISuperPositions } from "src/interfaces/ISuperPositions.sol";
import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol";
import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol";
import { ISuperformFactory } from "src/interfaces/ISuperformFactory.sol";
import { IBaseForm } from "src/interfaces/IBaseForm.sol";
import { IPaymentHelper } from "./interfaces/IPaymentHelper.sol";
import { Error } from "src/libraries/Error.sol";
import { DataLib } from "src/libraries/DataLib.sol";
import {
    TransactionType,
    ReturnMultiData,
    ReturnSingleData,
    CallbackType,
    AMBMessage,
    BroadcastMessage
} from "src/types/DataTypes.sol";
import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";

/// @title SuperPositions
/// @dev Cross-chain LP token minted on source chain
/// @author Zeropoint Labs
contract SuperPositions is ISuperPositions, ERC1155A, Broadcastable {
    using DataLib for uint256;

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

    ISuperRegistry public immutable superRegistry;
    uint64 public immutable CHAIN_ID;
    uint8 internal constant CORE_STATE_REGISTRY_ID = 1;
    bytes32 internal constant DEPLOY_NEW_AERC20 = keccak256("DEPLOY_NEW_AERC20");

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

    /// @dev maps all transaction data routed through the smart contract.
    mapping(uint256 transactionId => TxHistory txHistory) public override txHistory;

    /// @dev is the base uri set by admin
    string public dynamicURI;

    /// @dev is the base uri frozen status
    bool public dynamicURIFrozen;

    /// @dev nonce for aERC20 broadcast
    uint256 public xChainPayloadCounter;

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

    modifier onlyRouter() {
        if (msg.sender != superRegistry.getAddress(keccak256("SUPERFORM_ROUTER"))) revert Error.NOT_SUPERFORM_ROUTER();
        _;
    }

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

    /// @dev is used in same chain case (as superform is available on the chain to validate caller)
    modifier onlyMinter(uint256 superformId) {
        address router = superRegistry.getAddress(keccak256("SUPERFORM_ROUTER"));

        /// if msg.sender isn't superformRouter then it must be state registry of that form
        if (msg.sender != router) {
            uint8 registryId = superRegistry.getStateRegistryId(msg.sender);

            (address superform,,) = DataLib.getSuperform(superformId);
            uint8 formRegistryId = IBaseForm(superform).getStateRegistryId();

            if (registryId != formRegistryId) {
                revert Error.NOT_MINTER();
            }
        }

        _;
    }

    modifier onlyBroadcastRegistry() {
        if (msg.sender != superRegistry.getAddress(keccak256("BROADCAST_REGISTRY"))) {
            revert Error.NOT_BROADCAST_REGISTRY();
        }
        _;
    }

    modifier onlyBatchMinter(uint256[] memory superformIds) {
        address router = superRegistry.getAddress(keccak256("SUPERFORM_ROUTER"));

        /// if msg.sender isn't superformRouter then it must be state registry for that superform
        if (msg.sender != router) {
            uint256 len = superformIds.length;
            for (uint256 i; i < len; ++i) {
                (, uint32 formImplementationId,) = DataLib.getSuperform(superformIds[i]);
                uint8 registryId = superRegistry.getStateRegistryId(msg.sender);

                if (uint32(registryId) != formImplementationId) {
                    revert Error.NOT_MINTER();
                }
            }
        }
        _;
    }

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

    /// @param dynamicURI_  URL for external metadata of ERC1155 SuperPositions
    /// @param superRegistry_ the superform registry contract
    constructor(
        string memory dynamicURI_,
        address superRegistry_,
        string memory name_,
        string memory symbol_
    )
        ERC1155A(name_, symbol_)
    {
        if (block.chainid > type(uint64).max) {
            revert Error.BLOCK_CHAIN_ID_OUT_OF_BOUNDS();
        }

        CHAIN_ID = uint64(block.chainid);

        superRegistry = ISuperRegistry(superRegistry_);
        dynamicURI = dynamicURI_;
    }

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

    /// @inheritdoc ERC1155A
    function supportsInterface(bytes4 interfaceId_) public view virtual override(ERC1155A, IERC165) returns (bool) {
        return super.supportsInterface(interfaceId_);
    }

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

    /// @inheritdoc ISuperPositions
    function updateTxHistory(
        uint256 payloadId_,
        uint256 txInfo_,
        address receiverAddressSP_
    )
        external
        override
        onlyRouter
    {
        txHistory[payloadId_] = TxHistory({ txInfo: txInfo_, receiverAddressSP: receiverAddressSP_ });

        emit TxHistorySet(payloadId_, txInfo_, receiverAddressSP_);
    }

    /// @inheritdoc ISuperPositions
    function mintSingle(address receiverAddressSP_, uint256 id_, uint256 amount_) external override onlyMinter(id_) {
        _mint(receiverAddressSP_, msg.sender, id_, amount_, "");
    }

    /// @inheritdoc ISuperPositions
    function mintBatch(
        address receiverAddressSP_,
        uint256[] memory ids_,
        uint256[] memory amounts_
    )
        external
        override
        onlyBatchMinter(ids_)
    {
        if (ids_.length != amounts_.length) revert Error.ARRAY_LENGTH_MISMATCH();
        _batchMint(receiverAddressSP_, msg.sender, ids_, amounts_, "");
    }

    /// @inheritdoc ISuperPositions
    function burnSingle(address srcSender_, uint256 id_, uint256 amount_) external override onlyRouter {
        _burn(srcSender_, msg.sender, id_, amount_);
    }

    /// @inheritdoc ISuperPositions
    function burnBatch(
        address srcSender_,
        uint256[] memory ids_,
        uint256[] memory amounts_
    )
        external
        override
        onlyRouter
    {
        if (ids_.length != amounts_.length) revert Error.ARRAY_LENGTH_MISMATCH();
        _batchBurn(srcSender_, msg.sender, ids_, amounts_);
    }

    /// @inheritdoc ISuperPositions
    function stateMultiSync(AMBMessage memory data_) external override returns (uint64 srcChainId_) {
        /// @dev here we decode the txInfo and params from the data brought back from destination

        (uint256 returnTxType, uint256 callbackType, uint8 multi,,,) = data_.txInfo.decodeTxInfo();

        if (callbackType != uint256(CallbackType.RETURN) && callbackType != uint256(CallbackType.FAIL)) {
            revert Error.INVALID_PAYLOAD_TYPE();
        }

        /// @dev decode remaining info on superPositions to mint from destination
        ReturnMultiData memory returnData = abi.decode(data_.params, (ReturnMultiData));

        _validateStateSyncer(returnData.superformIds);

        uint256 txInfo = txHistory[returnData.payloadId].txInfo;

        /// @dev if txInfo is zero then the payloadId is invalid for ack
        if (txInfo == 0) {
            revert Error.TX_HISTORY_NOT_FOUND();
        }

        uint256 txType;

        /// @dev decode initial payload info stored on source chain in this contract
        (txType,,,,, srcChainId_) = txInfo.decodeTxInfo();

        /// @dev verify this is a not single vault mint
        if (multi != 1) revert Error.INVALID_PAYLOAD_TYPE();
        /// @dev compare txType to be the same (dst/src)
        if (returnTxType != txType) revert Error.SRC_TX_TYPE_MISMATCH();

        /// @dev mint super positions accordingly
        if (
            (txType == uint256(TransactionType.DEPOSIT) && callbackType == uint256(CallbackType.RETURN))
                || (txType == uint256(TransactionType.WITHDRAW) && callbackType == uint256(CallbackType.FAIL))
        ) {
            _batchMint(
                txHistory[returnData.payloadId].receiverAddressSP,
                msg.sender,
                returnData.superformIds,
                returnData.amounts,
                ""
            );
        } else {
            revert Error.INVALID_PAYLOAD_TYPE();
        }

        emit Completed(returnData.payloadId);
    }

    /// @inheritdoc ISuperPositions
    function stateSync(AMBMessage memory data_) external override returns (uint64 srcChainId_) {
        /// @dev here we decode the txInfo and params from the data brought back from destination

        (uint256 returnTxType, uint256 callbackType, uint8 multi,,,) = data_.txInfo.decodeTxInfo();

        if (callbackType != uint256(CallbackType.RETURN) && callbackType != uint256(CallbackType.FAIL)) {
            revert Error.INVALID_PAYLOAD_TYPE();
        }

        /// @dev decode remaining info on superPositions to mint from destination
        ReturnSingleData memory returnData = abi.decode(data_.params, (ReturnSingleData));
        _validateStateSyncer(returnData.superformId);

        uint256 txInfo = txHistory[returnData.payloadId].txInfo;

        /// @dev if txInfo is zero then the payloadId is invalid for ack
        if (txInfo == 0) {
            revert Error.TX_HISTORY_NOT_FOUND();
        }

        uint256 txType;

        /// @dev decode initial payload info stored on source chain in this contract
        (txType,,,,, srcChainId_) = txInfo.decodeTxInfo();

        /// @dev this is a not multi vault mint
        if (multi != 0) revert Error.INVALID_PAYLOAD_TYPE();
        /// @dev compare txType to be the same (dst/src)
        if (returnTxType != txType) revert Error.SRC_TX_TYPE_MISMATCH();

        /// @dev mint super positions accordingly
        if (
            (txType == uint256(TransactionType.DEPOSIT) && callbackType == uint256(CallbackType.RETURN))
                || (txType == uint256(TransactionType.WITHDRAW) && callbackType == uint256(CallbackType.FAIL))
        ) {
            _mint(
                txHistory[returnData.payloadId].receiverAddressSP,
                msg.sender,
                returnData.superformId,
                returnData.amount,
                ""
            );
        } else {
            revert Error.INVALID_PAYLOAD_TYPE();
        }

        emit Completed(returnData.payloadId);
    }

    /// @inheritdoc ISuperPositions
    function stateSyncBroadcast(bytes memory data_) external payable override onlyBroadcastRegistry {
        BroadcastMessage memory transmuterPayload = abi.decode(data_, (BroadcastMessage));

        if (transmuterPayload.messageType != DEPLOY_NEW_AERC20) {
            revert Error.INVALID_MESSAGE_TYPE();
        }
        _deployTransmuter(transmuterPayload.message);
    }

    /// @inheritdoc ISuperPositions
    function setDynamicURI(string memory dynamicURI_, bool freeze_) external override onlyProtocolAdmin {
        if (dynamicURIFrozen) {
            revert Error.DYNAMIC_URI_FROZEN();
        }

        string memory oldURI = dynamicURI;
        dynamicURI = dynamicURI_;
        dynamicURIFrozen = freeze_;

        emit DynamicURIUpdated(oldURI, dynamicURI_, freeze_);
    }

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

    /// @notice Used to construct return url
    function _baseURI() internal view override returns (string memory) {
        return dynamicURI;
    }

    /// @dev helps validate the state registry id for minting superform id
    /// @dev is used in cross chain case (as superform is not available on the chain to validate caller)
    function _validateStateSyncer(uint256 superformId_) internal view {
        uint8 registryId = superRegistry.getStateRegistryId(msg.sender);
        _isValidStateSyncer(registryId, superformId_);
    }

    /// @dev helps validate the state registry id for minting superform id
    function _validateStateSyncer(uint256[] memory superformIds_) internal view {
        uint8 registryId = superRegistry.getStateRegistryId(msg.sender);
        for (uint256 i; i < superformIds_.length; ++i) {
            _isValidStateSyncer(registryId, superformIds_[i]);
        }
    }

    function _isValidStateSyncer(uint8 registryId_, uint256 superformId_) internal view {
        /// @dev registryId_ zero check is done in superRegistry.getStateRegistryId()

        /// @dev If registryId is 1, meaning CoreStateRegistry, no further checks are necessary.
        /// @dev This is because CoreStateRegistry is the default minter for all kinds of forms
        /// @dev In case registryId is > 1, we need to check if the registryId matches the formImplementationId
        if (registryId_ == CORE_STATE_REGISTRY_ID) {
            return;
        }

        (, uint32 formImplementationId,) = DataLib.getSuperform(superformId_);
        uint8 formRegistryId = ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY")))
            .getFormStateRegistryId(formImplementationId);

        if (registryId_ != formRegistryId) {
            revert Error.NOT_MINTER_STATE_REGISTRY_ROLE();
        }
    }

    function _registerAERC20(uint256 id) internal override returns (address aErc20Token) {
        if (!ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))).isSuperform(id)) {
            revert Error.SUPERFORM_ID_NONEXISTENT();
        }
        (address superform,,) = id.getSuperform();

        string memory name = IBaseForm(superform).superformYieldTokenName();
        string memory symbol = IBaseForm(superform).superformYieldTokenSymbol();
        uint8 decimal = uint8(IBaseForm(superform).getVaultDecimals());
        aErc20Token = address(new aERC20(name, symbol, decimal));
        /// @dev broadcast and deploy to the other destination chains
        BroadcastMessage memory transmuterPayload = BroadcastMessage(
            "SUPER_POSITIONS",
            DEPLOY_NEW_AERC20,
            abi.encode(CHAIN_ID, ++xChainPayloadCounter, id, name, symbol, decimal)
        );

        _broadcast(
            superRegistry.getAddress(keccak256("BROADCAST_REGISTRY")),
            superRegistry.getAddress(keccak256("PAYMASTER")),
            abi.encode(transmuterPayload),
            IPaymentHelper(superRegistry.getAddress(keccak256("PAYMENT_HELPER"))).getRegisterTransmuterAMBData()
        );

        emit AERC20TokenRegistered(id, aErc20Token);

        return aErc20Token;
    }

    /// @dev deploys new transmuter on broadcasting
    function _deployTransmuter(bytes memory message_) internal {
        (,, uint256 superformId, string memory name, string memory symbol, uint8 decimal) =
            abi.decode(message_, (uint64, uint256, uint256, string, string, uint8));
        if (aErc20TokenId[superformId] != address(0)) revert AERC20_ALREADY_REGISTERED();

        address aErc20Token = address(new aERC20(name, symbol, decimal));

        aErc20TokenId[superformId] = aErc20Token;

        emit AERC20TokenRegistered(superformId, aErc20Token);
    }
}

File 2 of 33 : ERC1155A.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import { IERC1155A } from "./interfaces/IERC1155A.sol";
import { IaERC20 } from "./interfaces/IaERC20.sol";
import { Strings } from "openzeppelin-contracts/contracts/utils/Strings.sol";
import { IERC165 } from "openzeppelin-contracts/contracts/interfaces/IERC165.sol";
import { IERC1155 } from "openzeppelin-contracts/contracts/interfaces/IERC1155.sol";
import { IERC1155MetadataURI } from "openzeppelin-contracts/contracts/interfaces/IERC1155MetadataURI.sol";
import { IERC1155Errors } from "openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol";
import { IERC1155Receiver } from "openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol";

/// @title ERC1155A
/// @dev Single/range based id approve capability with conversion to ERC20s
/// @author Zeropoint Labs
abstract contract ERC1155A is IERC1155A, IERC1155Errors {
    //////////////////////////////////////////////////////////////
    //                         CONSTANTS                        //
    //////////////////////////////////////////////////////////////

    bytes private constant EMPTY_BYTES = bytes("");

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

    /// @dev ERC20-like mapping for single id supply.
    mapping(uint256 => uint256) private _totalSupply;

    /// @dev ERC20-like mapping for single id approvals.
    mapping(address owner => mapping(address operator => mapping(uint256 id => uint256 amount))) private allowances;

    /// @dev Implementation copied from solmate/ERC1155
    mapping(address => mapping(uint256 => uint256)) public balanceOf;

    /// @dev Implementation copied from solmate/ERC1155
    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /// @dev mapping of token ids to aErc20 token addresses
    mapping(uint256 id => address aErc20Token) public aErc20TokenId;

    /// @dev ERC1155A name
    string public name;
    /// @dev ERC1155A symbol
    string public symbol;

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

    /// @dev Initializes ERC1155A
    /// @param name_ ERC1155A name
    /// @param symbol_ ERC1155A symbol
    constructor(string memory name_, string memory symbol_) {
        name = name_;
        symbol = symbol_;
    }

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

    // Basic Token Information
    // --------------------------

    /// @inheritdoc IERC1155A
    function totalSupply(uint256 id) external view virtual returns (uint256) {
        return _totalSupply[id];
    }

    /// @inheritdoc IERC1155A
    function exists(uint256 id) external view virtual returns (bool) {
        return _totalSupply[id] != 0;
    }

    /// @inheritdoc IERC1155
    function balanceOfBatch(
        address[] memory owners,
        uint256[] memory ids
    )
        public
        view
        virtual
        returns (uint256[] memory balances)
    {
        if (owners.length != ids.length) revert LENGTH_MISMATCH();

        balances = new uint256[](owners.length);

        for (uint256 i; i < owners.length; ++i) {
            balances[i] = balanceOf[owners[i]][ids[i]];
        }
    }

    // Allowance and Approval Checking
    // --------------------------------

    /// @inheritdoc IERC1155A
    function allowance(address owner, address operator, uint256 id) public view virtual returns (uint256) {
        return allowances[owner][operator][id];
    }

    // aERC20 Token Management
    // ------------------------

    /// @inheritdoc IERC1155A
    function aERC20Exists(uint256 id) external view virtual returns (bool) {
        return aErc20TokenId[id] != address(0);
    }

    /// @inheritdoc IERC1155A
    function getERC20TokenAddress(uint256 id) external view virtual override returns (address) {
        return aErc20TokenId[id];
    }

    // Metadata and Interface Support
    // ------------------------------

    /// @inheritdoc IERC1155A
    function uri(uint256 id) public view virtual returns (string memory) {
        return string.concat(_baseURI(), Strings.toString(id));
    }

    /// @dev return interface checks
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId // ERC165 Interface ID for ERC165
            || interfaceId == type(IERC1155).interfaceId // ERC165 Interface ID for ERC1155
            || interfaceId == type(IERC1155MetadataURI).interfaceId; // ERC165 Interface ID for ERC1155MetadataURI
    }

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

    // Token Approval Management
    // --------------------------

    /// @inheritdoc IERC1155A
    function setApprovalForOne(address operator, uint256 id, uint256 amount) public virtual {
        _setAllowance(msg.sender, operator, id, amount, true);
    }

    /// @inheritdoc IERC1155A
    function setApprovalForMany(address operator, uint256[] memory ids, uint256[] memory amounts) public virtual {
        uint256 idsLength = ids.length;
        if (idsLength != amounts.length) revert LENGTH_MISMATCH();

        for (uint256 i; i < idsLength; ++i) {
            _setAllowance(msg.sender, operator, ids[i], amounts[i], true);
        }
    }

    /// @inheritdoc IERC1155
    function setApprovalForAll(address operator, bool approved) public virtual {
        if (operator == address(0)) revert ZERO_ADDRESS();
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    // Allowance Modification
    // -----------------------

    /// @inheritdoc IERC1155A
    function increaseAllowance(address operator, uint256 id, uint256 addedValue) public virtual returns (bool) {
        _setAllowance(msg.sender, operator, id, allowance(msg.sender, operator, id) + addedValue, true);
        return true;
    }

    /// @inheritdoc IERC1155A
    function decreaseAllowance(address operator, uint256 id, uint256 subtractedValue) public virtual returns (bool) {
        return _decreaseAllowance(msg.sender, operator, id, subtractedValue, true);
    }

    /// @inheritdoc IERC1155A
    function increaseAllowanceForMany(
        address operator,
        uint256[] memory ids,
        uint256[] memory addedValues
    )
        public
        virtual
        returns (bool)
    {
        uint256 idsLength = ids.length;
        if (idsLength != addedValues.length) revert LENGTH_MISMATCH();

        for (uint256 i; i < idsLength; ++i) {
            _setAllowance(msg.sender, operator, ids[i], allowance(msg.sender, operator, ids[i]) + addedValues[i], true);
        }

        return true;
    }

    /// @inheritdoc IERC1155A
    function decreaseAllowanceForMany(
        address operator,
        uint256[] memory ids,
        uint256[] memory subtractedValues
    )
        public
        virtual
        returns (bool)
    {
        uint256 idsLength = ids.length;
        if (idsLength != subtractedValues.length) revert LENGTH_MISMATCH();

        for (uint256 i; i < idsLength; ++i) {
            _decreaseAllowance(msg.sender, operator, ids[i], subtractedValues[i], true);
        }

        return true;
    }

    // Token Transfer Functions
    // -------------------------

    /// @notice see {IERC1155-safeTransferFrom}
    /// @dev adds supports for user to not have called setApprovalForAll
    /// @dev single id approval is senior in execution flow
    /// @dev if approved for all, function executes without reducing allowance
    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    )
        public
        virtual
        override
    {
        if (from == address(0) || to == address(0)) revert ZERO_ADDRESS();

        address operator = msg.sender;

        /// @dev message sender is not from and is not approved for all
        if (from != operator && !isApprovedForAll[from][operator]) {
            _decreaseAllowance(from, operator, id, amount, false);
            _safeTransferFrom(from, to, id, amount);
        } else {
            /// @dev message sender is from || is approved for all
            _safeTransferFrom(from, to, id, amount);
        }

        emit TransferSingle(operator, from, to, id, amount);
        _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);
    }

    /// @notice see {IERC1155-safeBatchTransferFrom}
    /// @dev adds supports for user to not have called setApprovalForAll
    /// @dev single id approvals are senior in execution flow
    /// @dev if approved for all, function executes without reducing allowance
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    )
        public
        virtual
        override
    {
        if (from == address(0) || to == address(0)) revert ZERO_ADDRESS();

        uint256 len = ids.length;
        if (len != amounts.length) revert LENGTH_MISMATCH();

        address operator = msg.sender;

        /// @dev case to handle single id / multi id approvals
        if (operator != from && !isApprovedForAll[from][operator]) {
            uint256 id;
            uint256 amount;

            for (uint256 i; i < len; ++i) {
                id = ids[i];
                amount = amounts[i];

                _decreaseAllowance(from, operator, id, amount, false);
                _safeTransferFrom(from, to, id, amount);
            }
        } else {
            for (uint256 i; i < len; ++i) {
                _safeTransferFrom(from, to, ids[i], amounts[i]);
            }
        }

        emit TransferBatch(operator, from, to, ids, amounts);
        _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);
    }

    // Token Transmutation
    // --------------------

    /// @inheritdoc IERC1155A
    function transmuteToERC20(address owner, uint256 id, uint256 amount, address receiver) external override {
        if (owner == address(0) || receiver == address(0)) revert ZERO_ADDRESS();
        /// @dev an approval is needed to burn
        _burn(owner, msg.sender, id, amount);

        address aERC20Token = aErc20TokenId[id];
        if (aERC20Token == address(0)) revert AERC20_NOT_REGISTERED();

        IaERC20(aERC20Token).mint(receiver, amount);
        emit TransmutedToERC20(owner, id, amount, receiver);
    }

    /// @inheritdoc IERC1155A
    function transmuteToERC1155A(address owner, uint256 id, uint256 amount, address receiver) external override {
        if (owner == address(0) || receiver == address(0)) revert ZERO_ADDRESS();

        address aERC20Token = aErc20TokenId[id];
        if (aERC20Token == address(0)) revert AERC20_NOT_REGISTERED();

        /// @dev an approval is needed to burn
        IaERC20(aERC20Token).burn(owner, msg.sender, amount);
        _mint(receiver, msg.sender, id, amount, EMPTY_BYTES);

        emit TransmutedToERC1155A(owner, id, amount, receiver);
    }

    /// @inheritdoc IERC1155A
    function transmuteBatchToERC20(
        address owner,
        uint256[] memory ids,
        uint256[] memory amounts,
        address receiver
    )
        external
        override
    {
        if (owner == address(0) || receiver == address(0)) revert ZERO_ADDRESS();

        uint256 idsLength = ids.length; // Saves MLOADs.
        if (idsLength != amounts.length) revert LENGTH_MISMATCH();

        /// @dev an approval is needed to burn
        _batchBurn(owner, msg.sender, ids, amounts);

        for (uint256 i; i < idsLength; ++i) {
            address aERC20Token = aErc20TokenId[ids[i]];
            if (aERC20Token == address(0)) revert AERC20_NOT_REGISTERED();

            IaERC20(aERC20Token).mint(receiver, amounts[i]);
        }

        emit TransmutedBatchToERC20(owner, ids, amounts, receiver);
    }

    /// @inheritdoc IERC1155A
    function transmuteBatchToERC1155A(
        address owner,
        uint256[] memory ids,
        uint256[] memory amounts,
        address receiver
    )
        external
        override
    {
        if (owner == address(0) || receiver == address(0)) revert ZERO_ADDRESS();

        uint256 idsLength = ids.length; // Saves MLOADs.
        if (idsLength != amounts.length) revert LENGTH_MISMATCH();

        uint256 id;
        uint256 amount;

        for (uint256 i; i < ids.length; ++i) {
            id = ids[i];
            amount = amounts[i];

            address aERC20Token = aErc20TokenId[id];
            if (aERC20Token == address(0)) revert AERC20_NOT_REGISTERED();
            /// @dev an approval is needed on each aERC20 to burn
            IaERC20(aERC20Token).burn(owner, msg.sender, amount);
        }

        _batchMint(receiver, msg.sender, ids, amounts, EMPTY_BYTES);

        emit TransmutedBatchToERC1155A(owner, ids, amounts, receiver);
    }

    // aERC20 Registration
    // --------------------

    /// @inheritdoc IERC1155A
    function registerAERC20(uint256 id) external payable override returns (address) {
        if (_totalSupply[id] == 0) revert ID_NOT_MINTED_YET();
        if (aErc20TokenId[id] != address(0)) revert AERC20_ALREADY_REGISTERED();

        address aErc20Token = _registerAERC20(id);

        aErc20TokenId[id] = aErc20Token;
        return aErc20TokenId[id];
    }

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

    // Token Transfer and Balance Management
    // --------------------------------------

    /// @notice Internal safeTranferFrom function called after all checks from the public function are done
    /// @dev Notice `operator` param. It's msg.sender to the safeTransferFrom function. Function is specific to
    /// @dev singleId approve logic.
    function _safeTransferFrom(address from, address to, uint256 id, uint256 amount) internal virtual {
        balanceOf[from][id] -= amount;
        balanceOf[to][id] += amount;
    }

    /// @dev Implementation copied from solmate/ERC1155 and adapted with operator logic
    function _mint(address to, address operator, uint256 id, uint256 amount, bytes memory data) internal virtual {
        balanceOf[to][id] += amount;
        _totalSupply[id] += amount;

        emit TransferSingle(operator, address(0), to, id, amount);
        _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);
    }

    /// @dev Implementation copied from solmate/ERC1155 and adapted with operator logic
    function _batchMint(
        address to,
        address operator,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    )
        internal
        virtual
    {
        uint256 idsLength = ids.length; // Saves MLOADs.
        if (idsLength != amounts.length) revert LENGTH_MISMATCH();

        uint256 id;
        uint256 amount;
        for (uint256 i; i < idsLength; ++i) {
            id = ids[i];
            amount = amounts[i];

            balanceOf[to][id] += amount;
            _totalSupply[id] += amount;
        }

        emit TransferBatch(operator, address(0), to, ids, amounts);
        _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);
    }

    /// @dev Implementation copied from solmate/ERC1155 and adapted with operator logic
    function _burn(address from, address operator, uint256 id, uint256 amount) internal virtual {
        // Check if the msg.sender is the owner or is approved for all tokens
        /// Most implementations of _burn don't use allowance, but it is a good practice to check for it
        /// Otherwise it could allow to burn tokens on which no explicit allowance is given
        if (operator != from && !isApprovedForAll[from][operator]) {
            _decreaseAllowance(from, operator, id, amount, false);
        }

        // Update the balances and total supply
        _safeTransferFrom(from, address(0), id, amount);
        _totalSupply[id] -= amount;

        emit TransferSingle(operator, from, address(0), id, amount);
    }

    /// @dev Implementation copied from solmate/ERC1155 and adapted with operator logic
    function _batchBurn(
        address from,
        address operator,
        uint256[] memory ids,
        uint256[] memory amounts
    )
        internal
        virtual
    {
        uint256 idsLength = ids.length; // Saves MLOADs.
        if (idsLength != amounts.length) revert LENGTH_MISMATCH();

        uint256 id;
        uint256 amount;
        /// @dev case to handle single id / multi id approvals
        if (operator != from && !isApprovedForAll[from][operator]) {
            for (uint256 i; i < idsLength; ++i) {
                id = ids[i];
                amount = amounts[i];

                _decreaseAllowance(from, operator, id, amount, false);
                _safeTransferFrom(from, address(0), id, amount);
                _totalSupply[ids[i]] -= amounts[i];
            }
        } else {
            for (uint256 i; i < idsLength; ++i) {
                id = ids[i];
                amount = amounts[i];

                _safeTransferFrom(from, address(0), id, amount);
                _totalSupply[ids[i]] -= amounts[i];
            }
        }

        emit TransferBatch(operator, from, address(0), ids, amounts);
    }

    // Allowance and Approval Handling
    // --------------------------------

    /// @notice Internal function for decreasing single id approval amount
    /// @dev Only to be used by address(this)
    /// @dev Notice `owner` param, only contract functions should be able to define it
    /// @dev Re-adapted from ERC20
    function _decreaseAllowance(
        address owner,
        address operator,
        uint256 id,
        uint256 subtractedValue,
        bool emitEvent
    )
        internal
        virtual
        returns (bool)
    {
        uint256 currentAllowance = allowance(owner, operator, id);
        if (currentAllowance < subtractedValue) revert DECREASED_ALLOWANCE_BELOW_ZERO();
        _setAllowance(owner, operator, id, currentAllowance - subtractedValue, emitEvent);

        return true;
    }

    /// @notice Internal function for setting single id approval
    /// @dev Used for fine-grained control over approvals with increase/decrease allowance
    /// @dev Notice `owner` param, only contract functions should be able to define it
    function _setAllowance(
        address owner,
        address operator,
        uint256 id,
        uint256 amount,
        bool emitEvent
    )
        internal
        virtual
    {
        if (owner == address(0)) revert ZERO_ADDRESS();
        if (operator == address(0)) revert ZERO_ADDRESS();

        allowances[owner][operator][id] = amount;

        if (emitEvent) {
            emit ApprovalForOne(owner, operator, id, amount);
        }
    }

    // ERC1155A Transfer Checks
    // ------------------------

    /// @dev Implementation copied from openzeppelin-contracts/ERC1155 with new custom error logic
    function _doSafeTransferAcceptanceCheck(
        address operator,
        address from,
        address to,
        uint256 id,
        uint256 value,
        bytes memory data
    )
        private
    {
        if (to.code.length != 0) {
            try IERC1155Receiver(to).onERC1155Received(operator, from, id, value, data) returns (bytes4 response) {
                if (response != IERC1155Receiver.onERC1155Received.selector) {
                    // Tokens rejected
                    revert ERC1155InvalidReceiver(to);
                }
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    // non-ERC1155Receiver implementer
                    revert ERC1155InvalidReceiver(to);
                } else {
                    /// @solidity memory-safe-assembly
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            if (to == address(0)) revert TRANSFER_TO_ADDRESS_ZERO();
        }
    }

    /// @dev Implementation copied from openzeppelin-contracts/ERC1155 with new custom error logic  and revert on
    /// transfer to address 0
    function _doSafeBatchTransferAcceptanceCheck(
        address operator,
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory values,
        bytes memory data
    )
        private
    {
        if (to.code.length != 0) {
            try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, values, data) returns (bytes4 response)
            {
                if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {
                    // Tokens rejected
                    revert ERC1155InvalidReceiver(to);
                }
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    // non-ERC1155Receiver implementer
                    revert ERC1155InvalidReceiver(to);
                } else {
                    /// @solidity memory-safe-assembly
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            if (to == address(0)) revert TRANSFER_TO_ADDRESS_ZERO();
        }
    }

    // aERC20 Token Creation
    // ----------------------

    /// @dev allows a developer to integrate their logic to create an aERC20
    function _registerAERC20(uint256 id) internal virtual returns (address aErc20Token);

    // Metadata and URI Handling
    // --------------------------

    /// @dev Used to construct return url
    function _baseURI() internal view virtual returns (string memory);
}

File 3 of 33 : aERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import { IaERC20 } from "./interfaces/IaERC20.sol";
import { ERC20 } from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";

/// @title aERC20
/// @dev ERC20 tokens out of 1155A
/// @author Zeropoint Labs
contract aERC20 is ERC20, IaERC20 {

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

    address public immutable ERC1155A;
    uint8 private immutable TOKEN_DECIMALS;

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

    modifier onlyTokenTransmuter() {
        if (msg.sender != ERC1155A) {
            revert ONLY_ERC1155A();
        }
        _;
    }

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

    constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) {
        ERC1155A = msg.sender;
        TOKEN_DECIMALS = decimals_;
    }

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

    /// inheritdoc IaERC20
    function decimals() public view override returns (uint8) {
        return TOKEN_DECIMALS;
    }

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

    /// inheritdoc IaERC20
    function mint(address owner, uint256 amount) external override onlyTokenTransmuter {
        _mint(owner, amount);
    }

    /// inheritdoc IaERC20
    function burn(address owner, address operator, uint256 amount) external override onlyTokenTransmuter {
        if (owner != operator) _spendAllowance(owner, operator, amount);

        _burn(owner, amount);
    }
}

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

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

/// @title Broadcastable
/// @dev Can be inherited in contracts that wish to support broadcasting
/// @author ZeroPoint Labs
abstract contract Broadcastable {
    //////////////////////////////////////////////////////////////
    //                  INTERNAL FUNCTIONS                      //
    //////////////////////////////////////////////////////////////

    /// @dev broadcasts state changes to all connected remote chains
    /// @param broadcastRegistry_ is the address of the broadcast registry contract.
    /// @param payMaster_ is the address of the paymaster contract.
    /// @param message_ is the crosschain message to be sent.
    /// @param extraData_ is the amb override information.
    function _broadcast(
        address broadcastRegistry_,
        address payMaster_,
        bytes memory message_,
        bytes memory extraData_
    )
        internal
    {
        (uint8 ambId, bytes memory broadcastParams) = abi.decode(extraData_, (uint8, bytes));

        /// @dev if the broadcastParams are wrong this will revert
        (uint256 gasFee, bytes memory extraData) = abi.decode(broadcastParams, (uint256, bytes));

        if (msg.value < gasFee) {
            revert Error.INVALID_BROADCAST_FEE();
        }

        /// @dev ambIds are validated inside the broadcast state registry
        IBroadcastRegistry(broadcastRegistry_).broadcastPayload{ value: gasFee }(
            msg.sender, ambId, gasFee, message_, extraData
        );

        if (msg.value > gasFee) {
            /// @dev forwards the rest to paymaster
            (bool success,) = payable(payMaster_).call{ value: msg.value - gasFee }("");

            if (!success) {
                revert Error.FAILED_TO_SEND_NATIVE();
            }
        }
    }
}

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

import { IERC1155A } from "ERC1155A/interfaces/IERC1155A.sol";
import { AMBMessage } from "../types/DataTypes.sol";

/// @title ISuperPositions
/// @dev Interface for SuperPositions
/// @author Zeropoint Labs
interface ISuperPositions is IERC1155A {

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

    struct TxHistory {
        uint256 txInfo;
        address receiverAddressSP;
    }
    
    //////////////////////////////////////////////////////////////
    //                          EVENTS                          //
    //////////////////////////////////////////////////////////////

    /// @dev is emitted when a dynamic uri is updated
    event DynamicURIUpdated(string indexed oldURI, string indexed newURI, bool indexed frozen);

    /// @dev is emitted when a cross-chain transaction is completed.
    event Completed(uint256 indexed txId);

    /// @dev is emitted when a aErc20 token is registered
    event AERC20TokenRegistered(uint256 indexed tokenId, address indexed tokenAddress);

    /// @dev is emitted when a tx info is saved
    event TxHistorySet(uint256 indexed payloadId, uint256 txInfo, address indexed receiverAddress);

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

    /// @dev returns the payload header and the receiver address for a tx id on the source chain
    /// @param txId_ is the identifier of the transaction issued by superform router
    /// @return txInfo is the header of the payload
    /// @return receiverAddressSP is the address of the receiver of superPositions
    function txHistory(uint256 txId_) external view returns (uint256 txInfo, address receiverAddressSP);

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

    /// @dev saves the message being sent together with the associated id formulated in a router
    /// @param payloadId_ is the id of the message being saved
    /// @param txInfo_ is the header of the AMBMessage of the transaction being saved
    /// @param receiverAddressSP_ is the address of the receiver of superPositions
    function updateTxHistory(uint256 payloadId_, uint256 txInfo_, address receiverAddressSP_) external;

    /// @dev allows minter to mint shares on source
    /// @param receiverAddress_ is the beneficiary of shares
    /// @param id_ is the id of the shares
    /// @param amount_ is the amount of shares to mint
    function mintSingle(address receiverAddress_, uint256 id_, uint256 amount_) external;

    /// @dev allows minter to mint shares on source in batch
    /// @param receiverAddress_ is the beneficiary of shares
    /// @param ids_ are the ids of the shares
    /// @param amounts_ are the amounts of shares to mint
    function mintBatch(address receiverAddress_, uint256[] memory ids_, uint256[] memory amounts_) external;

    /// @dev allows superformRouter to burn shares on source
    /// @notice burn is done optimistically by the router in the beginning of the withdraw transactions
    /// @notice in case the withdraw tx fails on the destination, shares are reminted through stateSync
    /// @param srcSender_ is the address of the sender
    /// @param id_ is the id of the shares
    /// @param amount_ is the amount of shares to burn
    function burnSingle(address srcSender_, uint256 id_, uint256 amount_) external;

    /// @dev allows burner to burn shares on source in batch
    /// @param srcSender_ is the address of the sender
    /// @param ids_ are the ids of the shares
    /// @param amounts_ are the amounts of shares to burn
    function burnBatch(address srcSender_, uint256[] memory ids_, uint256[] memory amounts_) external;

    /// @dev allows state registry contract to mint shares on source
    /// @param data_ is the received information to be processed.
    /// @return srcChainId_ is the decoded srcChainId.
    function stateMultiSync(AMBMessage memory data_) external returns (uint64 srcChainId_);

    /// @dev allows state registry contract to mint shares on source
    /// @param data_ is the received information to be processed.
    /// @return srcChainId_ is the decoded srcChainId.
    function stateSync(AMBMessage memory data_) external returns (uint64 srcChainId_);

    /// @dev sets the dynamic uri for NFT
    /// @param dynamicURI_ is the dynamic uri of the NFT
    /// @param freeze_ is to prevent updating the metadata once migrated to IPFS
    function setDynamicURI(string memory dynamicURI_, bool freeze_) external;

    /// @dev allows to create sERC0 using broadcast state registry
    /// @param data_ is the crosschain payload
    function stateSyncBroadcast(bytes memory data_) external payable;
}

File 6 of 33 : 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 7 of 33 : 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 8 of 33 : 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 9 of 33 : IBaseForm.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;

import { InitSingleVaultData } from "src/types/DataTypes.sol";
import { IERC165 } from "openzeppelin-contracts/contracts/utils/introspection/IERC165.sol";
import { IERC4626 } from "openzeppelin-contracts/contracts/interfaces/IERC4626.sol";

/// @title IBaseForm
/// @dev Interface for BaseForm
/// @author ZeroPoint Labs
interface IBaseForm is IERC165 {
    
    //////////////////////////////////////////////////////////////
    //                          EVENTS                           //
    //////////////////////////////////////////////////////////////

    /// @dev is emitted when a new vault is added by the admin.
    event VaultAdded(uint256 indexed id, IERC4626 indexed vault);

    /// @dev is emitted when a payload is processed by the destination contract.
    event Processed(
        uint64 indexed srcChainID,
        uint64 indexed dstChainId,
        uint256 indexed srcPayloadId,
        uint256 amount,
        address vault
    );

    /// @dev is emitted when an emergency withdrawal is processed
    event EmergencyWithdrawalProcessed(address indexed refundAddress, uint256 indexed amount);

    /// @dev is emitted when dust is forwarded to the paymaster
    event FormDustForwardedToPaymaster(address indexed token, uint256 indexed amount);

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

    /// @notice get Superform name of the ERC20 vault representation
    /// @return The ERC20 name
    function superformYieldTokenName() external view returns (string memory);

    /// @notice get Superform symbol of the ERC20 vault representation
    /// @return The ERC20 symbol
    function superformYieldTokenSymbol() external view returns (string memory);

    /// @notice get the state registry id associated with the vault
    function getStateRegistryId() external view returns (uint8);

    /// @notice Returns the vault address
    /// @return The address of the vault
    function getVaultAddress() external view returns (address);

    /// @notice Returns the vault address
    /// @return The address of the vault asset
    function getVaultAsset() external view returns (address);

    /// @notice Returns the name of the vault.
    /// @return The name of the vault
    function getVaultName() external view returns (string memory);

    /// @notice Returns the symbol of a vault.
    /// @return The symbol associated with a vault
    function getVaultSymbol() external view returns (string memory);

    /// @notice Returns the number of decimals in a vault for accounting purposes
    /// @return The number of decimals in the vault balance
    function getVaultDecimals() external view returns (uint256);

    /// @notice Returns the amount of underlying tokens each share of a vault is worth.
    /// @return The pricePerVaultShare value
    function getPricePerVaultShare() external view returns (uint256);

    /// @notice Returns the amount of vault shares owned by the form.
    /// @return The form's vault share balance
    function getVaultShareBalance() external view returns (uint256);

    /// @notice get the total amount of underlying managed in the ERC4626 vault
    function getTotalAssets() external view returns (uint256);

    /// @notice get the total amount of unredeemed vault shares in circulation
    function getTotalSupply() external view returns (uint256);

    /// @notice get the total amount of assets received if shares are actually redeemed
    /// @notice https://eips.ethereum.org/EIPS/eip-4626
    function getPreviewPricePerVaultShare() external view returns (uint256);

    /// @dev API may need to know state of funds deployed
    function previewDepositTo(uint256 assets_) external view returns (uint256);

    /// @notice positionBalance() -> .vaultIds&destAmounts
    /// @return how much of an asset + interest (accrued) is to withdraw from the Vault
    function previewWithdrawFrom(uint256 assets_) external view returns (uint256);

    /// @dev API may need to know state of funds deployed
    function previewRedeemFrom(uint256 shares_) external view returns (uint256);

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

    /// @dev process same chain id deposits
    /// @param singleVaultData_  A bytes representation containing all the data required to make a form action
    /// @param srcSender_ The address of the sender of the transaction
    /// @return shares  The amount of vault shares received
    function directDepositIntoVault(
        InitSingleVaultData memory singleVaultData_,
        address srcSender_
    )
        external
        payable
        returns (uint256 shares);

    /// @dev process same chain id deposits
    /// @param singleVaultData_  A bytes representation containing all the data required to make a form action
    /// @param srcSender_ The address of the sender of the transaction
    /// @param srcChainId_ The chain id of the source chain
    /// @return shares  The amount of vault shares received
    /// @dev is shares is `0` then no further action/acknowledgement needs to be sent
    function xChainDepositIntoVault(
        InitSingleVaultData memory singleVaultData_,
        address srcSender_,
        uint64 srcChainId_
    )
        external
        returns (uint256 shares);

    /// @dev process withdrawal of asset from a vault
    /// @param singleVaultData_  A bytes representation containing all the data required to make a form action
    /// @param srcSender_ The address of the sender of the transaction
    /// @return assets  The amount of assets received
    function directWithdrawFromVault(
        InitSingleVaultData memory singleVaultData_,
        address srcSender_
    )
        external
        returns (uint256 assets);

    /// @dev process withdrawal of asset from a vault
    /// @param singleVaultData_  A bytes representation containing all the data required to make a form action
    /// @param srcSender_ The address of the sender of the transaction
    /// @param srcChainId_ The chain id of the source chain
    /// @return assets The amount of assets received
    function xChainWithdrawFromVault(
        InitSingleVaultData memory singleVaultData_,
        address srcSender_,
        uint64 srcChainId_
    )
        external
        returns (uint256 assets);

    /// @dev process withdrawal of shares if form is paused
    /// @param receiverAddress_ The address to refund the shares to
    /// @param amount_ The amount of vault shares to refund
    function emergencyWithdraw(address receiverAddress_, uint256 amount_) external;

    /// @dev moves all dust in the contract to Paymaster contract
    /// @param token_ The address of the token to forward
    function forwardDustToPaymaster(address token_) external;
}

File 10 of 33 : IPaymentHelper.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 IPaymentHelper {
    //////////////////////////////////////////////////////////////
    //                           STRUCTS                         //
    //////////////////////////////////////////////////////////////

    /// @param nativeFeedOracle is the native price feed oracle
    /// @param gasPriceOracle is the gas price oracle
    /// @param swapGasUsed is the swap gas params
    /// @param updateGasUsed 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
    struct PaymentHelperConfig {
        address nativeFeedOracle;
        address gasPriceOracle;
        uint256 swapGasUsed;
        uint256 updateGasUsed;
        uint256 depositGasUsed;
        uint256 withdrawGasUsed;
        uint256 defaultNativePrice;
        uint256 defaultGasPrice;
        uint256 dstGasPerByte;
        uint256 ackGasCost;
        uint256 timelockCost;
        uint256 emergencyCost;
    }

    //////////////////////////////////////////////////////////////
    //                          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 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 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 updates config for register transmuter amb params
    /// @param extraDataForTransmuter_ is the broadcast extra data
    function updateRegisterAERC20Params(bytes memory extraDataForTransmuter_) external;
}

File 11 of 33 : 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 12 of 33 : 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 13 of 33 : 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 14 of 33 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 15 of 33 : IERC1155A.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import { IERC1155 } from "openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol";

/// @title IERC1155A
/// @author Zeropoint Labs
/// @dev Single/range based id approve capability with conversion to ERC20s
interface IERC1155A is IERC1155 {
    //////////////////////////////////////////////////////////////
    //                          EVENTS                          //
    //////////////////////////////////////////////////////////////

    /// @dev emitted when single id approval is set
    event ApprovalForOne(address indexed owner, address indexed spender, uint256 id, uint256 amount);

    /// @dev emitted when an ERC1155A id is transmuted to an aERC20
    event TransmutedToERC20(address indexed user, uint256 id, uint256 amount, address indexed receiver);

    /// @dev emitted when an aERC20 is transmuted to an ERC1155 id
    event TransmutedToERC1155A(address indexed user, uint256 id, uint256 amount, address indexed receiver);

    /// @dev emitted when multiple ERC1155A ids are transmuted to aERC20s
    event TransmutedBatchToERC20(address indexed user, uint256[] ids, uint256[] amounts, address indexed receiver);

    /// @dev emitted when multiple aERC20s are transmuted to ERC1155A ids
    event TransmutedBatchToERC1155A(address indexed user, uint256[] ids, uint256[] amounts, address indexed receiver);

    //////////////////////////////////////////////////////////////
    //                          ERRORS                          //
    //////////////////////////////////////////////////////////////

    /// @dev thrown if aERC20 was already registered
    error AERC20_ALREADY_REGISTERED();

    /// @dev thrown if aERC20 was not registered
    error AERC20_NOT_REGISTERED();

    /// @dev thrown if allowance amount will be decreased below zero
    error DECREASED_ALLOWANCE_BELOW_ZERO();

    /// @dev thrown if the associated ERC1155A id has not been minted before registering an aERC20
    error ID_NOT_MINTED_YET();

    /// @dev thrown if there is a length mismatch in batch operations
    error LENGTH_MISMATCH();

    /// @dev thrown if transfer is made to address 0
    error TRANSFER_TO_ADDRESS_ZERO();

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

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

    /// @notice Public getter for existing single id total supply
    /// @param id id of the ERC1155
    function totalSupply(uint256 id) external view returns (uint256);

    /// @notice Public getter to know if a token id exists
    /// @dev determines based on total supply for the id
    /// @param id id of the ERC1155
    function exists(uint256 id) external view returns (bool);

    /// @notice Public getter for existing single id approval
    /// @param owner address of the owner of the ERC1155A id
    /// @param spender address of the contract to approve
    /// @param id id of the ERC1155A to approve
    function allowance(address owner, address spender, uint256 id) external returns (uint256);

    /// @notice handy helper to check if a AERC20 is registered
    /// @param id id of the ERC1155
    function aERC20Exists(uint256 id) external view returns (bool);

    /// @notice Public getter for the address of the aErc20 token for a given ERC1155 id
    /// @param id id of the ERC1155 to get the aErc20 token address for
    /// @return aERC20 address of the aErc20 token for the given ERC1155 id
    function getERC20TokenAddress(uint256 id) external view returns (address aERC20);

    /// @notice Compute return string from baseURI set for this contract and unique vaultId
    /// @param id id of the ERC1155
    function uri(uint256 id) external view returns (string memory);

    /// @notice ERC1155A name
    function name() external view returns (string memory);

    /// @notice ERC1155A symbol
    function symbol() external view returns (string memory);

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

    /// @notice Public function for setting single id approval
    /// @dev Notice `owner` param, it will always be msg.sender, see _setApprovalForOne()
    /// @param spender address of the contract to approve
    /// @param id id of the ERC1155A to approve
    /// @param amount amount of the ERC1155A to approve
    function setApprovalForOne(address spender, uint256 id, uint256 amount) external;

    /// @notice Public function for setting multiple id approval
    /// @dev extension of sigle id approval
    /// @param spender address of the contract to approve
    /// @param ids ids of the ERC1155A to approve
    /// @param amounts amounts of the ERC1155A to approve
    function setApprovalForMany(address spender, uint256[] memory ids, uint256[] memory amounts) external;

    /// @notice Public function for increasing single id approval amount
    /// @dev Re-adapted from ERC20
    /// @param spender address of the contract to approve
    /// @param id id of the ERC1155A to approve
    /// @param addedValue amount of the allowance to increase by
    function increaseAllowance(address spender, uint256 id, uint256 addedValue) external returns (bool);

    /// @notice Public function for decreasing single id approval amount
    /// @dev Re-adapted from ERC20
    /// @param spender address of the contract to approve
    /// @param id id of the ERC1155A to approve
    /// @param subtractedValue amount of the allowance to decrease by
    function decreaseAllowance(address spender, uint256 id, uint256 subtractedValue) external returns (bool);

    /// @notice Public function for increasing multiple id approval amount at once
    /// @dev extension of single id increase allowance
    /// @param spender address of the contract to approve
    /// @param ids ids of the ERC1155A to approve
    /// @param addedValues amounts of the allowance to increase by
    function increaseAllowanceForMany(
        address spender,
        uint256[] memory ids,
        uint256[] memory addedValues
    )
        external
        returns (bool);

    /// @notice Public function for decreasing multiple id approval amount at once
    /// @dev extension of single id decrease allowance
    /// @param spender address of the contract to approve
    /// @param ids ids of the ERC1155A to approve
    /// @param subtractedValues amounts of the allowance to decrease by
    function decreaseAllowanceForMany(
        address spender,
        uint256[] memory ids,
        uint256[] memory subtractedValues
    )
        external
        returns (bool);

    /// @notice Turn ERC1155A id into an aERC20
    /// @dev allows owner to send ERC1155A id as an aERC20 to receiver
    /// @param owner address of the user on whose behalf this transmutation is happening
    /// @param id id of the ERC20s to transmute to aERC20
    /// @param amount amount of the ERC20s to transmute to aERC20
    /// @param receiver address of the user to receive the aERC20 token
    function transmuteToERC20(address owner, uint256 id, uint256 amount, address receiver) external;

    /// @notice Turn aERC20 into an ERC1155A id
    /// @dev allows owner to send ERC20 as an ERC1155A id to receiver
    /// @param owner address of the user on whose behalf this transmutation is happening
    /// @param id id of the ERC20s to transmute to erc1155
    /// @param amount amount of the ERC20s to transmute to erc1155
    /// @param receiver address of the user to receive the erc1155 token id
    function transmuteToERC1155A(address owner, uint256 id, uint256 amount, address receiver) external;

    /// @notice Turn ERC1155A ids into aERC20s
    /// @dev allows owner to send ERC1155A ids as aERC20s to receiver
    /// @param owner address of the user on whose behalf this transmutation is happening
    /// @param ids ids of the ERC1155A to transmute
    /// @param amounts amounts of the ERC1155A to transmute
    /// @param receiver address of the user to receive the aERC20 tokens
    function transmuteBatchToERC20(
        address owner,
        uint256[] memory ids,
        uint256[] memory amounts,
        address receiver
    )
        external;

    /// @notice Turn aERC20s into ERC1155A ids
    /// @dev allows owner to send aERC20s as ERC1155A ids to receiver
    /// @param owner address of the user on whose behalf this transmutation is happening
    /// @param ids ids of the ERC20 to transmute
    /// @param amounts amounts of the ERC20 to transmute
    /// @param receiver address of the user to receive the ERC1155 token ids
    function transmuteBatchToERC1155A(
        address owner,
        uint256[] memory ids,
        uint256[] memory amounts,
        address receiver
    )
        external;

    /// @notice payable to allow any implementing cross-chain protocol to be paid for fees for broadcasting
    /// @dev should emit any required events inside _registerAERC20 internal function
    /// @param id of the ERC1155 to create a ERC20 for
    function registerAERC20(uint256 id) external payable returns (address);
}

File 16 of 33 : IaERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";

/// @title IaERC20
/// @author Zeropoint Labs
/// @dev ERC20 tokens out of 1155A
interface IaERC20 is IERC20 {

    /// @dev thrown if ERC1155A is not caller for mint/burn in transmute
    error ONLY_ERC1155A();

    /// @dev allows msg.sender set in constructor to mint
    /// @param owner address of the owner of the tokens
    /// @param amount amount of tokens to mint
    function mint(address owner, uint256 amount) external;

    /// @dev allows msg.sender set in constructor to burn
    /// @param owner address of the owner of the tokens
    /// @param operator address of the operator of the tokens
    /// @param amount amount of tokens to burn
    function burn(address owner, address operator, uint256 amount) external;
}

File 17 of 33 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)

pragma solidity ^0.8.20;

import {Math} from "./math/Math.sol";
import {SignedMath} from "./math/SignedMath.sol";

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant HEX_DIGITS = "0123456789abcdef";
    uint8 private constant ADDRESS_LENGTH = 20;

    /**
     * @dev The `value` string doesn't fit in the specified `length`.
     */
    error StringsInsufficientHexLength(uint256 value, uint256 length);

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `int256` to its ASCII `string` decimal representation.
     */
    function toStringSigned(int256 value) internal pure returns (string memory) {
        return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        uint256 localValue = value;
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = HEX_DIGITS[localValue & 0xf];
            localValue >>= 4;
        }
        if (localValue != 0) {
            revert StringsInsufficientHexLength(value, length);
        }
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal
     * representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
    }

    /**
     * @dev Returns true if the two strings are equal.
     */
    function equal(string memory a, string memory b) internal pure returns (bool) {
        return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
    }
}

File 18 of 33 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../utils/introspection/IERC165.sol";

File 19 of 33 : IERC1155.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1155.sol)

pragma solidity ^0.8.20;

import {IERC1155} from "../token/ERC1155/IERC1155.sol";

File 20 of 33 : IERC1155MetadataURI.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1155MetadataURI.sol)

pragma solidity ^0.8.20;

import {IERC1155MetadataURI} from "../token/ERC1155/extensions/IERC1155MetadataURI.sol";

File 21 of 33 : draft-IERC6093.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;

/**
 * @dev Standard ERC-20 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
 */
interface IERC20Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC20InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC20InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     * @param allowance Amount of tokens a `spender` is allowed to operate with.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC20InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC20InvalidSpender(address spender);
}

/**
 * @dev Standard ERC-721 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
 */
interface IERC721Errors {
    /**
     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
     * Used in balance queries.
     * @param owner Address of the current owner of a token.
     */
    error ERC721InvalidOwner(address owner);

    /**
     * @dev Indicates a `tokenId` whose `owner` is the zero address.
     * @param tokenId Identifier number of a token.
     */
    error ERC721NonexistentToken(uint256 tokenId);

    /**
     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param tokenId Identifier number of a token.
     * @param owner Address of the current owner of a token.
     */
    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC721InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC721InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param tokenId Identifier number of a token.
     */
    error ERC721InsufficientApproval(address operator, uint256 tokenId);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC721InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC721InvalidOperator(address operator);
}

/**
 * @dev Standard ERC-1155 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
 */
interface IERC1155Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     * @param tokenId Identifier number of a token.
     */
    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC1155InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC1155InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param owner Address of the current owner of a token.
     */
    error ERC1155MissingApprovalForAll(address operator, address owner);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC1155InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC1155InvalidOperator(address operator);

    /**
     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
     * Used in batch transfers.
     * @param idsLength Length of the array of token identifiers
     * @param valuesLength Length of the array of token amounts
     */
    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}

File 22 of 33 : IERC1155Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/IERC1155Receiver.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../../utils/introspection/IERC165.sol";

/**
 * @dev Interface that must be implemented by smart contracts in order to receive
 * ERC-1155 token transfers.
 */
interface IERC1155Receiver is IERC165 {
    /**
     * @dev Handles the receipt of a single ERC-1155 token type. This function is
     * called at the end of a `safeTransferFrom` after the balance has been updated.
     *
     * NOTE: To accept the transfer, this must return
     * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
     * (i.e. 0xf23a6e61, or its own function selector).
     *
     * @param operator The address which initiated the transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param id The ID of the token being transferred
     * @param value The amount of tokens being transferred
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
     */
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    ) external returns (bytes4);

    /**
     * @dev Handles the receipt of a multiple ERC-1155 token types. This function
     * is called at the end of a `safeBatchTransferFrom` after the balances have
     * been updated.
     *
     * NOTE: To accept the transfer(s), this must return
     * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
     * (i.e. 0xbc197c81, or its own function selector).
     *
     * @param operator The address which initiated the batch transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param ids An array containing ids of each token being transferred (order and length must match values array)
     * @param values An array containing amounts of each token being transferred (order and length must match ids array)
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
     */
    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external returns (bytes4);
}

File 23 of 33 : ERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * The default value of {decimals} is 18. To change this, you should override
 * this function so it returns a different value.
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC-20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the ERC may not emit
 * these events, as it isn't required by the specification.
 */
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
    mapping(address account => uint256) private _balances;

    mapping(address account => mapping(address spender => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the default value returned by this function, unless
     * it's overridden.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `value`.
     */
    function transfer(address to, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, value);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, value);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the ERC. See the note at the beginning of {ERC20}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `value`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `value`.
     */
    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, value);
        _transfer(from, to, value);
        return true;
    }

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _transfer(address from, address to, uint256 value) internal {
        if (from == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        if (to == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(from, to, value);
    }

    /**
     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
     * this function.
     *
     * Emits a {Transfer} event.
     */
    function _update(address from, address to, uint256 value) internal virtual {
        if (from == address(0)) {
            // Overflow check required: The rest of the code assumes that totalSupply never overflows
            _totalSupply += value;
        } else {
            uint256 fromBalance = _balances[from];
            if (fromBalance < value) {
                revert ERC20InsufficientBalance(from, fromBalance, value);
            }
            unchecked {
                // Overflow not possible: value <= fromBalance <= totalSupply.
                _balances[from] = fromBalance - value;
            }
        }

        if (to == address(0)) {
            unchecked {
                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
                _totalSupply -= value;
            }
        } else {
            unchecked {
                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
                _balances[to] += value;
            }
        }

        emit Transfer(from, to, value);
    }

    /**
     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
     * Relies on the `_update` mechanism
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _mint(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(address(0), account, value);
    }

    /**
     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
     * Relies on the `_update` mechanism.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead
     */
    function _burn(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        _update(account, address(0), value);
    }

    /**
     * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     *
     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        _approve(owner, spender, value, true);
    }

    /**
     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
     *
     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
     * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
     * `Approval` event during `transferFrom` operations.
     *
     * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
     * true using the following override:
     * ```
     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
     *     super._approve(owner, spender, value, true);
     * }
     * ```
     *
     * Requirements are the same as {_approve}.
     */
    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
        if (owner == address(0)) {
            revert ERC20InvalidApprover(address(0));
        }
        if (spender == address(0)) {
            revert ERC20InvalidSpender(address(0));
        }
        _allowances[owner][spender] = value;
        if (emitEvent) {
            emit Approval(owner, spender, value);
        }
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `value`.
     *
     * Does not update the allowance value in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Does not emit an {Approval} event.
     */
    function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            if (currentAllowance < value) {
                revert ERC20InsufficientAllowance(spender, currentAllowance, value);
            }
            unchecked {
                _approve(owner, spender, currentAllowance - value, false);
            }
        }
    }
}

File 24 of 33 : IBroadcastRegistry.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;

/// @title IBroadcastRegistry
/// @dev Interface for BroadcastRegistry
/// @author ZeroPoint Labs
interface IBroadcastRegistry {
    //////////////////////////////////////////////////////////////
    //              EXTERNAL WRITE FUNCTIONS                    //
    //////////////////////////////////////////////////////////////

    /// @dev emitted when a payload is broadcasted
    event PayloadSent(address indexed sender);

    /// @dev emitted when a broadcast payload is received
    event PayloadReceived(uint256 indexed payloadId, uint64 indexed srcChainId);

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

    /// @dev allows core contracts to send payload to all configured destination chain.
    /// @param srcSender_ is the caller of the function (used for gas refunds).
    /// @param ambId_ is the identifier of the arbitrary message bridge to be used
    /// @param gasFee_ is the gas fee to be used for broadcasting
    /// @param message_ is the crosschain payload to be broadcasted
    /// @param extraData_ defines all the message bridge related overrides
    function broadcastPayload(
        address srcSender_,
        uint8 ambId_,
        uint256 gasFee_,
        bytes memory message_,
        bytes memory extraData_
    )
        external
        payable;

    /// @dev allows ambs to write broadcasted payloads
    function receiveBroadcastPayload(uint64 srcChainId_, bytes memory message_) external;

    /// @dev allows privileged actors to process broadcasted payloads
    /// @param payloadId_ is the identifier of the cross-chain payload
    function processPayload(uint256 payloadId_) external;
}

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

File 26 of 33 : IERC4626.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC4626.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../token/ERC20/IERC20.sol";
import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol";

/**
 * @dev Interface of the ERC-4626 "Tokenized Vault Standard", as defined in
 * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].
 */
interface IERC4626 is IERC20, IERC20Metadata {
    event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);

    event Withdraw(
        address indexed sender,
        address indexed receiver,
        address indexed owner,
        uint256 assets,
        uint256 shares
    );

    /**
     * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
     *
     * - MUST be an ERC-20 token contract.
     * - MUST NOT revert.
     */
    function asset() external view returns (address assetTokenAddress);

    /**
     * @dev Returns the total amount of the underlying asset that is “managed” by Vault.
     *
     * - SHOULD include any compounding that occurs from yield.
     * - MUST be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT revert.
     */
    function totalAssets() external view returns (uint256 totalManagedAssets);

    /**
     * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
     * scenario where all the conditions are met.
     *
     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT show any variations depending on the caller.
     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
     * - MUST NOT revert.
     *
     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
     * from.
     */
    function convertToShares(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
     * scenario where all the conditions are met.
     *
     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT show any variations depending on the caller.
     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
     * - MUST NOT revert.
     *
     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
     * from.
     */
    function convertToAssets(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
     * through a deposit call.
     *
     * - MUST return a limited value if receiver is subject to some deposit limit.
     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
     * - MUST NOT revert.
     */
    function maxDeposit(address receiver) external view returns (uint256 maxAssets);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
     * current on-chain conditions.
     *
     * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
     *   call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
     *   in the same transaction.
     * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
     *   deposit would be accepted, regardless if the user has enough tokens approved, etc.
     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by depositing.
     */
    function previewDeposit(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
     *
     * - MUST emit the Deposit event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   deposit execution, and are accounted for during deposit.
     * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
     *   approving enough underlying tokens to the Vault contract, etc).
     *
     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
     */
    function deposit(uint256 assets, address receiver) external returns (uint256 shares);

    /**
     * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
     * - MUST return a limited value if receiver is subject to some mint limit.
     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
     * - MUST NOT revert.
     */
    function maxMint(address receiver) external view returns (uint256 maxShares);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
     * current on-chain conditions.
     *
     * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
     *   in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
     *   same transaction.
     * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
     *   would be accepted, regardless if the user has enough tokens approved, etc.
     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by minting.
     */
    function previewMint(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
     *
     * - MUST emit the Deposit event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
     *   execution, and are accounted for during mint.
     * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
     *   approving enough underlying tokens to the Vault contract, etc).
     *
     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
     */
    function mint(uint256 shares, address receiver) external returns (uint256 assets);

    /**
     * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
     * Vault, through a withdraw call.
     *
     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
     * - MUST NOT revert.
     */
    function maxWithdraw(address owner) external view returns (uint256 maxAssets);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
     * given current on-chain conditions.
     *
     * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
     *   call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
     *   called
     *   in the same transaction.
     * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
     *   the withdrawal would be accepted, regardless if the user has enough shares, etc.
     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by depositing.
     */
    function previewWithdraw(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
     *
     * - MUST emit the Withdraw event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   withdraw execution, and are accounted for during withdraw.
     * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
     *   not having enough shares, etc).
     *
     * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
     * Those methods should be performed separately.
     */
    function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);

    /**
     * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
     * through a redeem call.
     *
     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
     * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
     * - MUST NOT revert.
     */
    function maxRedeem(address owner) external view returns (uint256 maxShares);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
     * given current on-chain conditions.
     *
     * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
     *   in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
     *   same transaction.
     * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
     *   redemption would be accepted, regardless if the user has enough shares, etc.
     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by redeeming.
     */
    function previewRedeem(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
     *
     * - MUST emit the Withdraw event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   redeem execution, and are accounted for during redeem.
     * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
     *   not having enough shares, etc).
     *
     * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
     * Those methods should be performed separately.
     */
    function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
}

File 27 of 33 : IERC1155.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/IERC1155.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../../utils/introspection/IERC165.sol";

/**
 * @dev Required interface of an ERC-1155 compliant contract, as defined in the
 * https://eips.ethereum.org/EIPS/eip-1155[ERC].
 */
interface IERC1155 is IERC165 {
    /**
     * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.
     */
    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);

    /**
     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
     * transfers.
     */
    event TransferBatch(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256[] ids,
        uint256[] values
    );

    /**
     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
     * `approved`.
     */
    event ApprovalForAll(address indexed account, address indexed operator, bool approved);

    /**
     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
     *
     * If an {URI} event was emitted for `id`, the standard
     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
     * returned by {IERC1155MetadataURI-uri}.
     */
    event URI(string value, uint256 indexed id);

    /**
     * @dev Returns the value of tokens of token type `id` owned by `account`.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function balanceOf(address account, uint256 id) external view returns (uint256);

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
     *
     * Requirements:
     *
     * - `accounts` and `ids` must have the same length.
     */
    function balanceOfBatch(
        address[] calldata accounts,
        uint256[] calldata ids
    ) external view returns (uint256[] memory);

    /**
     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
     *
     * Emits an {ApprovalForAll} event.
     *
     * Requirements:
     *
     * - `operator` cannot be the caller.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
     *
     * See {setApprovalForAll}.
     */
    function isApprovedForAll(address account, address operator) external view returns (bool);

    /**
     * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.
     *
     * WARNING: This function can potentially allow a reentrancy attack when transferring tokens
     * to an untrusted contract, when invoking {onERC1155Received} on the receiver.
     * Ensure to follow the checks-effects-interactions pattern and consider employing
     * reentrancy guards when interacting with untrusted contracts.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
     * - `from` must have a balance of tokens of type `id` of at least `value` amount.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
     *
     * WARNING: This function can potentially allow a reentrancy attack when transferring tokens
     * to an untrusted contract, when invoking {onERC1155BatchReceived} on the receiver.
     * Ensure to follow the checks-effects-interactions pattern and consider employing
     * reentrancy guards when interacting with untrusted contracts.
     *
     * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.
     *
     * Requirements:
     *
     * - `ids` and `values` must have the same length.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external;
}

File 28 of 33 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

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

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

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

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

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

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

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

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

File 29 of 33 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)

pragma solidity ^0.8.20;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Muldiv operation overflow.
     */
    error MathOverflowedMulDiv();

    enum Rounding {
        Floor, // Toward negative infinity
        Ceil, // Toward positive infinity
        Trunc, // Toward zero
        Expand // Away from zero
    }

    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds towards infinity instead
     * of rounding towards zero.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        if (b == 0) {
            // Guarantee the same behavior as in a regular Solidity division.
            return a / b;
        }

        // The following calculation ensures accurate ceiling division without overflow.
        // Since a is non-zero, (a - 1) / b will not overflow.
        // The largest possible result occurs when (a - 1) / b is type(uint256).max,
        // but the largest value we can obtain is type(uint256).max - 1, which happens
        // when a = type(uint256).max and b = 1.
        unchecked {
            return a == 0 ? 0 : (a - 1) / b + 1;
        }
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
     * denominator == 0.
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
     * Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0 = x * y; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            if (denominator <= prod1) {
                revert MathOverflowedMulDiv();
            }

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.
            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.

            uint256 twos = denominator & (0 - denominator);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
            // works in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
     * towards zero.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
        }
    }

    /**
     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
     */
    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
        return uint8(rounding) % 2 == 1;
    }
}

File 30 of 33 : SignedMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)

pragma solidity ^0.8.20;

/**
 * @dev Standard signed math utilities missing in the Solidity language.
 */
library SignedMath {
    /**
     * @dev Returns the largest of two signed numbers.
     */
    function max(int256 a, int256 b) internal pure returns (int256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two signed numbers.
     */
    function min(int256 a, int256 b) internal pure returns (int256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two signed numbers without overflow.
     * The result is rounded towards zero.
     */
    function average(int256 a, int256 b) internal pure returns (int256) {
        // Formula from the book "Hacker's Delight"
        int256 x = (a & b) + ((a ^ b) >> 1);
        return x + (int256(uint256(x) >> 255) & (a ^ b));
    }

    /**
     * @dev Returns the absolute unsigned value of a signed value.
     */
    function abs(int256 n) internal pure returns (uint256) {
        unchecked {
            // must be unchecked in order to support `n = type(int256).min`
            return uint256(n >= 0 ? n : -n);
        }
    }
}

File 31 of 33 : IERC1155MetadataURI.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/extensions/IERC1155MetadataURI.sol)

pragma solidity ^0.8.20;

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

/**
 * @dev Interface of the optional ERC1155MetadataExtension interface, as defined
 * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[ERC].
 */
interface IERC1155MetadataURI is IERC1155 {
    /**
     * @dev Returns the URI for token type `id`.
     *
     * If the `\{id\}` substring is present in the URI, it must be replaced by
     * clients with the actual token type ID.
     */
    function uri(uint256 id) external view returns (string memory);
}

File 32 of 33 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;

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

/**
 * @dev Interface for the optional metadata functions from the ERC-20 standard.
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

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

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

File 33 of 33 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol)

pragma solidity ^0.8.20;

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

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

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",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"dynamicURI_","type":"string"},{"internalType":"address","name":"superRegistry_","type":"address"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AERC20_ALREADY_REGISTERED","type":"error"},{"inputs":[],"name":"AERC20_NOT_REGISTERED","type":"error"},{"inputs":[],"name":"ARRAY_LENGTH_MISMATCH","type":"error"},{"inputs":[],"name":"BLOCK_CHAIN_ID_OUT_OF_BOUNDS","type":"error"},{"inputs":[],"name":"DECREASED_ALLOWANCE_BELOW_ZERO","type":"error"},{"inputs":[],"name":"DYNAMIC_URI_FROZEN","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC1155InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC1155InvalidApprover","type":"error"},{"inputs":[{"internalType":"uint256","name":"idsLength","type":"uint256"},{"internalType":"uint256","name":"valuesLength","type":"uint256"}],"name":"ERC1155InvalidArrayLength","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC1155InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC1155InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC1155InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC1155MissingApprovalForAll","type":"error"},{"inputs":[],"name":"FAILED_TO_SEND_NATIVE","type":"error"},{"inputs":[],"name":"ID_NOT_MINTED_YET","type":"error"},{"inputs":[],"name":"INVALID_BROADCAST_FEE","type":"error"},{"inputs":[],"name":"INVALID_CHAIN_ID","type":"error"},{"inputs":[],"name":"INVALID_MESSAGE_TYPE","type":"error"},{"inputs":[],"name":"INVALID_PAYLOAD_TYPE","type":"error"},{"inputs":[],"name":"LENGTH_MISMATCH","type":"error"},{"inputs":[],"name":"NOT_BROADCAST_REGISTRY","type":"error"},{"inputs":[],"name":"NOT_MINTER","type":"error"},{"inputs":[],"name":"NOT_MINTER_STATE_REGISTRY_ROLE","type":"error"},{"inputs":[],"name":"NOT_PROTOCOL_ADMIN","type":"error"},{"inputs":[],"name":"NOT_SUPERFORM_ROUTER","type":"error"},{"inputs":[],"name":"SRC_TX_TYPE_MISMATCH","type":"error"},{"inputs":[],"name":"SUPERFORM_ID_NONEXISTENT","type":"error"},{"inputs":[],"name":"TRANSFER_TO_ADDRESS_ZERO","type":"error"},{"inputs":[],"name":"TX_HISTORY_NOT_FOUND","type":"error"},{"inputs":[],"name":"ZERO_ADDRESS","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"}],"name":"AERC20TokenRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ApprovalForOne","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"txId","type":"uint256"}],"name":"Completed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"oldURI","type":"string"},{"indexed":true,"internalType":"string","name":"newURI","type":"string"},{"indexed":true,"internalType":"bool","name":"frozen","type":"bool"}],"name":"DynamicURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"}],"name":"TransmutedBatchToERC1155A","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"}],"name":"TransmutedBatchToERC20","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"}],"name":"TransmutedToERC1155A","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"}],"name":"TransmutedToERC20","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"payloadId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"txInfo","type":"uint256"},{"indexed":true,"internalType":"address","name":"receiverAddress","type":"address"}],"name":"TxHistorySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[],"name":"CHAIN_ID","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"aERC20Exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"aErc20TokenId","outputs":[{"internalType":"address","name":"aErc20Token","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"owners","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"balances","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"srcSender_","type":"address"},{"internalType":"uint256[]","name":"ids_","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts_","type":"uint256[]"}],"name":"burnBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"srcSender_","type":"address"},{"internalType":"uint256","name":"id_","type":"uint256"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"burnSingle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"subtractedValues","type":"uint256[]"}],"name":"decreaseAllowanceForMany","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"dynamicURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dynamicURIFrozen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getERC20TokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"addedValues","type":"uint256[]"}],"name":"increaseAllowanceForMany","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiverAddressSP_","type":"address"},{"internalType":"uint256[]","name":"ids_","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts_","type":"uint256[]"}],"name":"mintBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiverAddressSP_","type":"address"},{"internalType":"uint256","name":"id_","type":"uint256"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"mintSingle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"registerAERC20","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"setApprovalForMany","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setApprovalForOne","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"dynamicURI_","type":"string"},{"internalType":"bool","name":"freeze_","type":"bool"}],"name":"setDynamicURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"txInfo","type":"uint256"},{"internalType":"bytes","name":"params","type":"bytes"}],"internalType":"struct AMBMessage","name":"data_","type":"tuple"}],"name":"stateMultiSync","outputs":[{"internalType":"uint64","name":"srcChainId_","type":"uint64"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"txInfo","type":"uint256"},{"internalType":"bytes","name":"params","type":"bytes"}],"internalType":"struct AMBMessage","name":"data_","type":"tuple"}],"name":"stateSync","outputs":[{"internalType":"uint64","name":"srcChainId_","type":"uint64"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data_","type":"bytes"}],"name":"stateSyncBroadcast","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"superRegistry","outputs":[{"internalType":"contract ISuperRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId_","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"address","name":"receiver","type":"address"}],"name":"transmuteBatchToERC1155A","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"address","name":"receiver","type":"address"}],"name":"transmuteBatchToERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"transmuteToERC1155A","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"transmuteToERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"transactionId","type":"uint256"}],"name":"txHistory","outputs":[{"internalType":"uint256","name":"txInfo","type":"uint256"},{"internalType":"address","name":"receiverAddressSP","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"payloadId_","type":"uint256"},{"internalType":"uint256","name":"txInfo_","type":"uint256"},{"internalType":"address","name":"receiverAddressSP_","type":"address"}],"name":"updateTxHistory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"xChainPayloadCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

60c06040523480156200001157600080fd5b506040516200602e3803806200602e83398101604081905262000034916200017a565b81816005620000448382620002be565b506006620000538282620002be565b5050506001600160401b034611156200007f57604051637ecdf93360e01b815260040160405180910390fd5b6001600160401b03461660a0526001600160a01b0383166080526008620000a78582620002be565b50505050506200038a565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000da57600080fd5b81516001600160401b0380821115620000f757620000f7620000b2565b604051601f8301601f19908116603f01168101908282118183101715620001225762000122620000b2565b81604052838152602092508660208588010111156200014057600080fd5b600091505b8382101562000164578582018301518183018401529082019062000145565b6000602085830101528094505050505092915050565b600080600080608085870312156200019157600080fd5b84516001600160401b0380821115620001a957600080fd5b620001b788838901620000c8565b602088015190965091506001600160a01b0382168214620001d757600080fd5b604087015191945080821115620001ed57600080fd5b620001fb88838901620000c8565b935060608701519150808211156200021257600080fd5b506200022187828801620000c8565b91505092959194509250565b600181811c908216806200024257607f821691505b6020821081036200026357634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002b9576000816000526020600020601f850160051c81016020861015620002945750805b601f850160051c820191505b81811015620002b557828155600101620002a0565b5050505b505050565b81516001600160401b03811115620002da57620002da620000b2565b620002f281620002eb84546200022d565b8462000269565b602080601f8311600181146200032a5760008415620003115750858301515b600019600386901b1c1916600185901b178555620002b5565b600085815260208120601f198616915b828110156200035b578886015182559484019460019091019084016200033a565b50858210156200037a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a051615c0762000427600039600081816106d60152612a2101526000818161041501528181610b50015281816112760152818161171f0152818161195f015281816119f801528181611e0101528181611ede01528181611ffb0152818161230d0152818161272601528181612abe01528181612b6901528181612c36015281816131c50152818161331d0152613d470152615c076000f3fe608060405260043610620002825760003560e01c80637081ce5e1162000153578063cdde3d6b11620000c5578063e985e9c51162000084578063e985e9c514620008b3578063ec73732114620008f2578063ed7a8e421462000917578063edf387c5146200093c578063f242432a1462000954578063ff61011a146200097957600080fd5b8063cdde3d6b14620007fa578063d7ea0c23146200081f578063d81d0a15146200083b578063e673070f1462000860578063e6ddad4c146200089c57600080fd5b806395d89b41116200011257806395d89b411462000742578063a22cb465146200075a578063a49f9516146200077f578063bd85b03914620007a4578063cd4622eb14620007d557600080fd5b80637081ce5e146200063e57806375fcbd86146200066357806385e1f4d014620006c25780638d04e40e14620006f85780639473655c146200071d57600080fd5b806333e3072111620001f95780635029d0c811620001b85780635029d0c8146200054b578063540ed9c01462000570578063598af9e714620005aa5780635fa8d76414620005cf57806367bc406514620005f45780636b20c454146200061957600080fd5b806333e30721146200045c57806349e5b649146200049a5780634e1273f414620004bf5780634ec1bec714620004f35780634f558e79146200051857600080fd5b80630e89341c11620002465780630e89341c146200039d578063132b481614620003c2578063137bc42714620003e957806324c73dda14620004015780632eb2c2d6146200043757600080fd5b8062fdd58e146200028757806301ffc9a714620002d65780630282acfc146200030c57806306fdde03146200035f578063093e31641462000386575b600080fd5b3480156200029457600080fd5b50620002c3620002a636600462003e7e565b600260209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b348015620002e357600080fd5b50620002fb620002f536600462003ec4565b6200099e565b6040519015158152602001620002cd565b3480156200031957600080fd5b50620003466200032b36600462003eeb565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001620002cd565b3480156200036c57600080fd5b5062000377620009b1565b604051620002cd919062003f59565b620003466200039736600462003eeb565b62000a47565b348015620003aa57600080fd5b5062000377620003bc36600462003eeb565b62000aec565b348015620003cf57600080fd5b50620003e7620003e136600462003f6e565b62000b2c565b005b348015620003f657600080fd5b506200037762000c0b565b3480156200040e57600080fd5b50620003467f000000000000000000000000000000000000000000000000000000000000000081565b3480156200044457600080fd5b50620003e76200045636600462004141565b62000c1a565b3480156200046957600080fd5b50620004816200047b366004620041fc565b62000e0f565b6040516001600160401b039091168152602001620002cd565b348015620004a757600080fd5b5062000481620004b9366004620041fc565b62000fcd565b348015620004cc57600080fd5b50620004e4620004de36600462004291565b62001138565b604051620002cd91906200439e565b3480156200050057600080fd5b50620003e762000512366004620043b3565b62001252565b3480156200052557600080fd5b50620002fb6200053736600462003eeb565b600090815260208190526040902054151590565b3480156200055857600080fd5b50620003e76200056a366004620043ef565b620013a1565b3480156200057d57600080fd5b50620003466200058f36600462003eeb565b6000908152600460205260409020546001600160a01b031690565b348015620005b757600080fd5b50620002c3620005c936600462004482565b6200157b565b348015620005dc57600080fd5b50620003e7620005ee366004620044c8565b620015ad565b3480156200060157600080fd5b50620002fb62000613366004620044c8565b62001635565b3480156200062657600080fd5b50620003e762000638366004620044c8565b620016fb565b3480156200064b57600080fd5b50620003e76200065d36600462004546565b620017f8565b3480156200067057600080fd5b50620006a46200068236600462003eeb565b600760205260009081526040902080546001909101546001600160a01b031682565b604080519283526001600160a01b03909116602083015201620002cd565b348015620006cf57600080fd5b50620004817f000000000000000000000000000000000000000000000000000000000000000081565b3480156200070557600080fd5b50620003e76200071736600462003f6e565b6200192e565b3480156200072a57600080fd5b50620003e76200073c36600462004546565b62001b32565b3480156200074f57600080fd5b506200037762001c7d565b3480156200076757600080fd5b50620003e76200077936600462004599565b62001c8c565b3480156200078c57600080fd5b50620003e76200079e36600462003f6e565b62001d20565b348015620007b157600080fd5b50620002c3620007c336600462003eeb565b60009081526020819052604090205490565b348015620007e257600080fd5b50620002fb620007f4366004620044c8565b62001d30565b3480156200080757600080fd5b50620002fb6200081936600462003f6e565b62001db6565b3480156200082c57600080fd5b50600954620002fb9060ff1681565b3480156200084857600080fd5b50620003e76200085a366004620044c8565b62001dd0565b3480156200086d57600080fd5b50620002fb6200087f36600462003eeb565b6000908152600460205260409020546001600160a01b0316151590565b620003e7620008ad366004620045d7565b62001fc6565b348015620008c057600080fd5b50620002fb620008d23660046200460f565b600360209081526000928352604080842090915290825290205460ff1681565b348015620008ff57600080fd5b50620003e762000911366004620043ef565b62002115565b3480156200092457600080fd5b50620003e76200093636600462004642565b620022d8565b3480156200094957600080fd5b50620002c3600a5481565b3480156200096157600080fd5b50620003e762000973366004620046a3565b6200254a565b3480156200098657600080fd5b50620002fb6200099836600462003f6e565b6200267a565b6000620009ab826200269b565b92915050565b60058054620009c09062004713565b80601f0160208091040260200160405190810160405280929190818152602001828054620009ee9062004713565b801562000a3f5780601f1062000a135761010080835404028352916020019162000a3f565b820191906000526020600020905b81548152906001019060200180831162000a2157829003601f168201915b505050505081565b600081815260208190526040812054810362000a7657604051631b5bd2df60e31b815260040160405180910390fd5b6000828152600460205260409020546001600160a01b03161562000aad576040516347d4e9ad60e11b815260040160405180910390fd5b600062000aba83620026ee565b60009384526004602052604090932080546001600160a01b0319166001600160a01b0390941693841790555090919050565b606062000af862002d5a565b62000b038362002df4565b60405160200162000b169291906200474f565b6040516020818303038152906040529050919050565b6040516321f8a72160e01b815260008051602062005bb283398151915260048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa15801562000ba0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000bc6919062004782565b6001600160a01b0316336001600160a01b03161462000bf85760405163158a2f6b60e01b815260040160405180910390fd5b62000c068333848462002e8d565b505050565b60088054620009c09062004713565b6001600160a01b038516158062000c3857506001600160a01b038416155b1562000c575760405163538ba4f960e01b815260040160405180910390fd5b82518251811462000c7b5760405163899ef10d60e01b815260040160405180910390fd5b336001600160a01b038716811480159062000cbc57506001600160a01b0380881660009081526003602090815260408083209385168352929052205460ff16155b1562000d405760008060005b8481101562000d375787818151811062000ce65762000ce6620047a2565b6020026020010151925086818151811062000d055762000d05620047a2565b6020026020010151915062000d1f8a858585600062002f74565b5062000d2e8a8a858562002fcf565b60010162000cc8565b50505062000d9d565b60005b8281101562000d9b5762000d92888888848151811062000d675762000d67620047a2565b602002602001015188858151811062000d845762000d84620047a2565b602002602001015162002fcf565b60010162000d43565b505b856001600160a01b0316876001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb888860405162000dee929190620047b8565b60405180910390a462000e0681888888888862003049565b50505050505050565b805160009060ff80821691600881901c9091169060101c6001821480159062000e39575060028214155b1562000e585760405163641c695560e01b815260040160405180910390fd5b6000856020015180602001905181019062000e749190620047ea565b905062000e858160200151620031ad565b80516000908152600760205260408120549081900362000eb85760405163eed061b760e01b815260040160405180910390fd5b60c081901c955060ff8082169084161562000ee65760405163641c695560e01b815260040160405180910390fd5b80861462000f0757604051633ca5012160e21b815260040160405180910390fd5b8015801562000f165750600185145b8062000f2e575060018114801562000f2e5750600285145b1562000f7e5782516000908152600760209081526040808320600101548287015182880151835194850190935293835262000f78936001600160a01b039091169233929062003249565b62000f97565b60405163641c695560e01b815260040160405180910390fd5b82516040517fdfd517ed69f8a0a57d49fe494e4864fac3cfe3585c14c0bfddf39f72463ec3fd90600090a2505050505050919050565b805160009060ff80821691600881901c9091169060101c6001821480159062000ff7575060028214155b15620010165760405163641c695560e01b815260040160405180910390fd5b600085602001518060200190518101906200103291906200488f565b905062001043816020015162003305565b805160009081526007602052604081205490819003620010765760405163eed061b760e01b815260040160405180910390fd5b60c081901c955060ff808216908416600114620010a65760405163641c695560e01b815260040160405180910390fd5b808614620010c757604051633ca5012160e21b815260040160405180910390fd5b80158015620010d65750600185145b80620010ee5750600181148015620010ee5750600285145b1562000f7e5782516000908152600760209081526040808320600101548287015182880151835194850190935293835262000f78936001600160a01b0390911692339290620033d3565b606081518351146200115d5760405163899ef10d60e01b815260040160405180910390fd5b82516001600160401b0381111562001179576200117962003fa6565b604051908082528060200260200182016040528015620011a3578160200160208202803683370190505b50905060005b83518110156200124b5760026000858381518110620011cc57620011cc620047a2565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008483815181106200120b576200120b620047a2565b6020026020010151815260200190815260200160002054828281518110620012375762001237620047a2565b6020908102919091010152600101620011a9565b5092915050565b6040516321f8a72160e01b815260008051602062005bb283398151915260048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa158015620012c6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620012ec919062004782565b6001600160a01b0316336001600160a01b0316146200131e5760405163158a2f6b60e01b815260040160405180910390fd5b6040805180820182528381526001600160a01b0383811660208084018281526000898152600783528690209451855551600190940180546001600160a01b0319169490931693909317909155915184815285917f226fd1a430a7a15fa93582471a806bc430535d985fa9547a69921a9499bf492b910160405180910390a3505050565b6001600160a01b0384161580620013bf57506001600160a01b038116155b15620013de5760405163538ba4f960e01b815260040160405180910390fd5b825182518114620014025760405163899ef10d60e01b815260040160405180910390fd5b60008060005b86518110156200150457868181518110620014275762001427620047a2565b60200260200101519250858181518110620014465762001446620047a2565b602090810291909101810151600085815260049092526040909120549092506001600160a01b0316806200148d576040516369f28dc960e11b815260040160405180910390fd5b604051633dae446f60e21b81526001600160a01b038a811660048301523360248301526044820185905282169063f6b911bc90606401600060405180830381600087803b158015620014de57600080fd5b505af1158015620014f3573d6000803e3d6000fd5b505050505080600101905062001408565b50620015238433888860405180602001604052806000815250620033d3565b836001600160a01b0316876001600160a01b03167f2ec4237e89b1c7ccb8710672dc83af16f1949c33f3b313eeaab1a626e6aa442788886040516200156a929190620047b8565b60405180910390a350505050505050565b6001600160a01b0392831660009081526001602090815260408083209490951682529283528381209181529152205490565b815181518114620015d15760405163899ef10d60e01b815260040160405180910390fd5b60005b818110156200162e57620016253386868481518110620015f857620015f8620047a2565b6020026020010151868581518110620016155762001615620047a2565b6020026020010151600162003535565b600101620015d4565b5050505050565b815181516000919081146200165d5760405163899ef10d60e01b815260040160405180910390fd5b60005b81811015620016ef57620016e63387878481518110620016845762001684620047a2565b6020026020010151878581518110620016a157620016a1620047a2565b6020026020010151620016d2338c8c8981518110620016c457620016c4620047a2565b60200260200101516200157b565b620016de91906200494a565b600162003535565b60010162001660565b50600195945050505050565b6040516321f8a72160e01b815260008051602062005bb283398151915260048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa1580156200176f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001795919062004782565b6001600160a01b0316336001600160a01b031614620017c75760405163158a2f6b60e01b815260040160405180910390fd5b8051825114620017ea57604051634456f5e960e11b815260040160405180910390fd5b62000c06833384846200360b565b6001600160a01b03841615806200181657506001600160a01b038116155b15620018355760405163538ba4f960e01b815260040160405180910390fd5b620018438433858562002e8d565b6000838152600460205260409020546001600160a01b0316806200187a576040516369f28dc960e11b815260040160405180910390fd5b6040516340c10f1960e01b81526001600160a01b038381166004830152602482018590528216906340c10f1990604401600060405180830381600087803b158015620018c557600080fd5b505af1158015620018da573d6000803e3d6000fd5b505060408051878152602081018790526001600160a01b038087169450891692507f4420f38d0f4ce916c1d0da8d37675c007978eaaa4a8c2cc4231fd52a7a57b61491015b60405180910390a35050505050565b6040516321f8a72160e01b815260008051602062005bb2833981519152600482015282906000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906321f8a72190602401602060405180830381865afa158015620019a7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620019cd919062004782565b9050336001600160a01b0382161462001b1457604051632f6438ab60e01b81523360048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632f6438ab90602401602060405180830381865afa15801562001a48573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001a6e919062004977565b9050600062001a7d8462003884565b505090506000816001600160a01b03166391deb8826040518163ffffffff1660e01b8152600401602060405180830381865afa15801562001ac2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001ae8919062004977565b90508060ff168360ff161462001b1057604051622450cd60e21b815260040160405180910390fd5b5050505b6200162e853386866040518060200160405280600081525062003249565b6001600160a01b038416158062001b5057506001600160a01b038116155b1562001b6f5760405163538ba4f960e01b815260040160405180910390fd5b6000838152600460205260409020546001600160a01b03168062001ba6576040516369f28dc960e11b815260040160405180910390fd5b604051633dae446f60e21b81526001600160a01b0386811660048301523360248301526044820185905282169063f6b911bc90606401600060405180830381600087803b15801562001bf757600080fd5b505af115801562001c0c573d6000803e3d6000fd5b5050505062001c2e823386866040518060200160405280600081525062003249565b816001600160a01b0316856001600160a01b03167f9195fdebb74042f1bd7abc0ded779a6e10ae01e0ad5f5546cb7e421d65a5666686866040516200191f929190918252602082015260400190565b60068054620009c09062004713565b6001600160a01b03821662001cb45760405163538ba4f960e01b815260040160405180910390fd5b3360008181526003602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b62000c0633848484600162003535565b8151815160009190811462001d585760405163899ef10d60e01b815260040160405180910390fd5b60005b81811015620016ef5762001dac338787848151811062001d7f5762001d7f620047a2565b602002602001015187858151811062001d9c5762001d9c620047a2565b6020026020010151600162002f74565b5060010162001d5b565b600062001dc833858585600162002f74565b949350505050565b6040516321f8a72160e01b815260008051602062005bb2833981519152600482015282906000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906321f8a72190602401602060405180830381865afa15801562001e49573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001e6f919062004782565b9050336001600160a01b0382161462001f8557815160005b8181101562001f8257600062001eb985838151811062001eab5762001eab620047a2565b602002602001015162003884565b50604051632f6438ab60e01b8152336004820152909250600091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632f6438ab90602401602060405180830381865afa15801562001f26573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001f4c919062004977565b905060ff811663ffffffff83161462001f7757604051622450cd60e21b815260040160405180910390fd5b505060010162001e87565b50505b825184511462001fa857604051634456f5e960e11b815260040160405180910390fd5b6200162e8533868660405180602001604052806000815250620033d3565b6040516321f8a72160e01b81527f86a7f6b88da6de42c331676d4da78508adfef4970dc8aa541004f26b6eef4ab960048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa1580156200204b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002071919062004782565b6001600160a01b0316336001600160a01b031614620020a35760405163b0acaf9d60e01b815260040160405180910390fd5b600081806020019051810190620020bb9190620049e1565b90507f62fe4458baf33f94c99b0a629b6b8fae9f220aa42242d61592a0454d37a7484c8160200151146200210257604051634c8b6b4f60e11b815260040160405180910390fd5b620021118160400151620038b9565b5050565b6001600160a01b03841615806200213357506001600160a01b038116155b15620021525760405163538ba4f960e01b815260040160405180910390fd5b825182518114620021765760405163899ef10d60e01b815260040160405180910390fd5b62002184853386866200360b565b60005b818110156200229057600060046000878481518110620021ab57620021ab620047a2565b6020908102919091018101518252810191909152604001600020546001600160a01b0316905080620021f0576040516369f28dc960e11b815260040160405180910390fd5b806001600160a01b03166340c10f1985878581518110620022155762002215620047a2565b60200260200101516040518363ffffffff1660e01b81526004016200224f9291906001600160a01b03929092168252602082015260400190565b600060405180830381600087803b1580156200226a57600080fd5b505af11580156200227f573d6000803e3d6000fd5b505050505080600101905062002187565b50816001600160a01b0316856001600160a01b03167f1c57454fefbe0a2a0aa1926734e74f4cb5137003ccf5e6edfde51c79163fbf3786866040516200191f929190620047b8565b6040516321f8a72160e01b81527f6b50fa17b77d24e42e27a04b69fe50cd6967cfb767d18de0bd5fe7e1a32aa86860048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa1580156200235d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002383919062004782565b6040516369ac88f960e11b81523360048201526001600160a01b03919091169063d35911f290602401602060405180830381865afa158015620023ca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620023f0919062004a77565b6200240e57604051633721555560e21b815260040160405180910390fd5b60095460ff1615620024335760405163fb407daf60e01b815260040160405180910390fd5b600060088054620024449062004713565b80601f0160208091040260200160405190810160405280929190818152602001828054620024729062004713565b8015620024c35780601f106200249757610100808354040283529160200191620024c3565b820191906000526020600020905b815481529060010190602001808311620024a557829003601f168201915b505050505090508260089081620024db919062004ae3565b506009805460ff1916831515908117909155604051620024fd90859062004baf565b60405180910390208260405162002515919062004baf565b604051908190038120907f5386175ed3f7187aa4eae65398696731724636ea68ccda712d3119159f5b115990600090a4505050565b6001600160a01b03851615806200256857506001600160a01b038416155b15620025875760405163538ba4f960e01b815260040160405180910390fd5b336001600160a01b0386168114801590620025c857506001600160a01b0380871660009081526003602090815260408083209385168352929052205460ff16155b15620025f357620025de86828686600062002f74565b50620025ed8686868662002fcf565b62002601565b620026018686868662002fcf565b846001600160a01b0316866001600160a01b0316826001600160a01b03167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6287876040516200265a929190918252602082015260400190565b60405180910390a462002672818787878787620039b7565b505050505050565b60006200269133858585620016d2338a8a6200157b565b5060019392505050565b60006001600160e01b031982166301ffc9a760e01b1480620026cd57506001600160e01b03198216636cdb3d1360e11b145b80620009ab57506001600160e01b031982166303a24d0760e21b1492915050565b6040516321f8a72160e01b81527fbcc180fb907e9ae431665de4bc74305c00b7b27442aadd477980ecc4bb14c01160048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa15801562002776573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200279c919062004782565b6001600160a01b031663b5c75697836040518263ffffffff1660e01b8152600401620027ca91815260200190565b602060405180830381865afa158015620027e8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200280e919062004a77565b6200282c5760405163a412f06560e01b815260040160405180910390fd5b6000620028398362003884565b505090506000816001600160a01b03166320592d986040518163ffffffff1660e01b8152600401600060405180830381865afa1580156200287e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620028a8919081019062004bcd565b90506000826001600160a01b03166317a57e086040518163ffffffff1660e01b8152600401600060405180830381865afa158015620028eb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262002915919081019062004bcd565b90506000836001600160a01b031663c32dcd896040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002958573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200297e919062004c05565b9050828282604051620029919062003e57565b6200299f9392919062004c1f565b604051809103906000f080158015620029bc573d6000803e3d6000fd5b509450600060405180606001604052806040518060400160405280600f81526020016e53555045525f504f534954494f4e5360881b81525081526020017f62fe4458baf33f94c99b0a629b6b8fae9f220aa42242d61592a0454d37a7484c81526020017f0000000000000000000000000000000000000000000000000000000000000000600a6000815462002a519062004c5c565b918290555060405162002a719291908c908a908a908a9060200162004c78565b60408051808303601f190181529181529152516321f8a72160e01b81527f86a7f6b88da6de42c331676d4da78508adfef4970dc8aa541004f26b6eef4ab9600482015290915062002d1a907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa15801562002b0e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002b34919062004782565b6040516321f8a72160e01b81527fbddfa8c39a1f6275bcfb3aa5c70638c466999edbf14e6162d81b3492caca9fce60048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa15801562002bb9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002bdf919062004782565b8360405160200162002bf2919062004cd3565b60408051808303601f19018152908290526321f8a72160e01b82527fab437a16135e856111e538dc45051dd9c2778c6069d25a22fb9ac4766c356aa16004830152907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa15801562002c86573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002cac919062004782565b6001600160a01b03166353d69edc6040518163ffffffff1660e01b8152600401600060405180830381865afa15801562002cea573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262002d14919081019062004bcd565b62003aab565b6040516001600160a01b0387169088907f733ac2a007cd3853c362154b5f081e3ad8f60fd4e892fa3a0ca14a266ff897f890600090a35050505050919050565b60606008805462002d6b9062004713565b80601f016020809104026020016040519081016040528092919081815260200182805462002d999062004713565b801562002dea5780601f1062002dbe5761010080835404028352916020019162002dea565b820191906000526020600020905b81548152906001019060200180831162002dcc57829003601f168201915b5050505050905090565b6060600062002e038362003c05565b60010190506000816001600160401b0381111562002e255762002e2562003fa6565b6040519080825280601f01601f19166020018201604052801562002e50576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508462002e5a57509392505050565b836001600160a01b0316836001600160a01b03161415801562002ed657506001600160a01b0380851660009081526003602090815260408083209387168352929052205460ff16155b1562002eee5762002eec84848484600062002f74565b505b62002efd846000848462002fcf565b6000828152602081905260408120805483929062002f1d90849062004d1a565b909155505060408051838152602081018390526000916001600160a01b0387811692908716917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a450505050565b60008062002f848787876200157b565b90508381101562002fa857604051630422f8c360e31b815260040160405180910390fd5b62002fc287878762002fbb888662004d1a565b8762003535565b5060019695505050505050565b6001600160a01b0384166000908152600260209081526040808320858452909152812080548392906200300490849062004d1a565b90915550506001600160a01b0383166000908152600260209081526040808320858452909152812080548392906200303e9084906200494a565b909155505050505050565b6001600160a01b0384163b15620031855760405163bc197c8160e01b81526001600160a01b0385169063bc197c819062003090908990899088908890889060040162004d30565b6020604051808303816000875af1925050508015620030ce575060408051601f3d908101601f19168201909252620030cb9181019062004d94565b60015b62003147573d808015620030ff576040519150601f19603f3d011682016040523d82523d6000602084013e62003104565b606091505b5080516000036200313857604051632bfa23e760e11b81526001600160a01b03861660048201526024015b60405180910390fd5b805181602001fd5b5062002672565b6001600160e01b0319811663bc197c8160e01b146200314057604051632bfa23e760e11b81526001600160a01b03861660048201526024016200312f565b6001600160a01b0384166200267257604051635edce13360e01b815260040160405180910390fd5b604051632f6438ab60e01b81523360048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632f6438ab90602401602060405180830381865afa15801562003215573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200323b919062004977565b905062002111818362003ce4565b6001600160a01b0385166000908152600260209081526040808320868452909152812080548492906200327e9084906200494a565b909155505060008381526020819052604081208054849290620032a39084906200494a565b909155505060408051848152602081018490526001600160a01b0380881692600092918816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46200162e84600087868686620039b7565b604051632f6438ab60e01b81523360048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632f6438ab90602401602060405180830381865afa1580156200336d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003393919062004977565b905060005b825181101562000c0657620033ca82848381518110620033bc57620033bc620047a2565b602002602001015162003ce4565b60010162003398565b825182518114620033f75760405163899ef10d60e01b815260040160405180910390fd5b60008060005b83811015620034bf578681815181106200341b576200341b620047a2565b602002602001015192508581815181106200343a576200343a620047a2565b6020026020010151915081600260008b6001600160a01b03166001600160a01b03168152602001908152602001600020600085815260200190815260200160002060008282546200348c91906200494a565b909155505060008381526020819052604081208054849290620034b19084906200494a565b9091555050600101620033fd565b50876001600160a01b031660006001600160a01b0316886001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb898960405162003512929190620047b8565b60405180910390a46200352b8760008a89898962003049565b5050505050505050565b6001600160a01b0385166200355d5760405163538ba4f960e01b815260040160405180910390fd5b6001600160a01b038416620035855760405163538ba4f960e01b815260040160405180910390fd5b6001600160a01b038086166000908152600160209081526040808320938816835292815282822086835290522082905580156200162e57836001600160a01b0316856001600160a01b03167f875251d6c7be5b10ddb14ed4f59395338f15552062d4ad7723265838e316f9a885856040516200191f929190918252602082015260400190565b8151815181146200362f5760405163899ef10d60e01b815260040160405180910390fd5b600080866001600160a01b0316866001600160a01b0316141580156200367b57506001600160a01b038088166000908152600360209081526040808320938a168352929052205460ff16155b156200375c5760005b838110156200375557858181518110620036a257620036a2620047a2565b60200260200101519250848181518110620036c157620036c1620047a2565b60200260200101519150620036db88888585600062002f74565b50620036eb886000858562002fcf565b848181518110620037005762003700620047a2565b6020026020010151600080888481518110620037205762003720620047a2565b60200260200101518152602001908152602001600020600082825462003747919062004d1a565b909155505060010162003684565b5062003821565b60005b838110156200381f578581815181106200377d576200377d620047a2565b602002602001015192508481815181106200379c576200379c620047a2565b60200260200101519150620037b5886000858562002fcf565b848181518110620037ca57620037ca620047a2565b6020026020010151600080888481518110620037ea57620037ea620047a2565b60200260200101518152602001908152602001600020600082825462003811919062004d1a565b90915550506001016200375f565b505b60006001600160a01b0316876001600160a01b0316876001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb888860405162003873929190620047b8565b60405180910390a450505050505050565b8060a081901c60c082901c6000819003620038b25760405163030042b760e01b815260040160405180910390fd5b9193909250565b60008060008084806020019051810190620038d5919062004db4565b600084815260046020526040902054939950919750955093506001600160a01b03161591506200391a9050576040516347d4e9ad60e11b815260040160405180910390fd5b60008383836040516200392d9062003e57565b6200393b9392919062004c1f565b604051809103906000f08015801562003958573d6000803e3d6000fd5b5060008681526004602052604080822080546001600160a01b0319166001600160a01b03851690811790915590519293509187917f733ac2a007cd3853c362154b5f081e3ad8f60fd4e892fa3a0ca14a266ff897f891a3505050505050565b6001600160a01b0384163b15620031855760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190620039fe908990899088908890889060040162004e5d565b6020604051808303816000875af192505050801562003a3c575060408051601f3d908101601f1916820190925262003a399181019062004d94565b60015b62003a6d573d808015620030ff576040519150601f19603f3d011682016040523d82523d6000602084013e62003104565b6001600160e01b0319811663f23a6e6160e01b146200314057604051632bfa23e760e11b81526001600160a01b03861660048201526024016200312f565b6000808280602001905181019062003ac4919062004ea4565b915091506000808280602001905181019062003ae1919062004eed565b915091508134101562003b0757604051631961e86760e01b815260040160405180910390fd5b604051636319827b60e11b81526001600160a01b0389169063c63304f690849062003b3f903390899084908d90899060040162004f1f565b6000604051808303818588803b15801562003b5957600080fd5b505af115801562003b6e573d6000803e3d6000fd5b5050505050813411156200352b5760006001600160a01b03881662003b94843462004d1a565b604051600081818185875af1925050503d806000811462003bd2576040519150601f19603f3d011682016040523d82523d6000602084013e62003bd7565b606091505b505090508062003bfa5760405163220d375360e01b815260040160405180910390fd5b505050505050505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831062003c455772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef8100000000831062003c72576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831062003c9157662386f26fc10000830492506010015b6305f5e100831062003caa576305f5e100830492506008015b612710831062003cbf57612710830492506004015b6064831062003cd2576064830492506002015b600a8310620009ab5760010192915050565b60001960ff83160162003cf5575050565b600062003d028262003884565b506040516321f8a72160e01b81527fbcc180fb907e9ae431665de4bc74305c00b7b27442aadd477980ecc4bb14c0116004820152909250600091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906321f8a72190602401602060405180830381865afa15801562003d8f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003db5919062004782565b60405163297e034f60e11b815263ffffffff841660048201526001600160a01b0391909116906352fc069e90602401602060405180830381865afa15801562003e02573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003e28919062004977565b90508060ff168460ff161462003e515760405163760c22d960e11b815260040160405180910390fd5b50505050565b610c4c8062004f6683390190565b6001600160a01b038116811462003e7b57600080fd5b50565b6000806040838503121562003e9257600080fd5b823562003e9f8162003e65565b946020939093013593505050565b6001600160e01b03198116811462003e7b57600080fd5b60006020828403121562003ed757600080fd5b813562003ee48162003ead565b9392505050565b60006020828403121562003efe57600080fd5b5035919050565b60005b8381101562003f2257818101518382015260200162003f08565b50506000910152565b6000815180845262003f4581602086016020860162003f05565b601f01601f19169290920160200192915050565b60208152600062003ee4602083018462003f2b565b60008060006060848603121562003f8457600080fd5b833562003f918162003e65565b95602085013595506040909401359392505050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171562003fe15762003fe162003fa6565b60405290565b604051601f8201601f191681016001600160401b038111828210171562004012576200401262003fa6565b604052919050565b60006001600160401b0382111562004036576200403662003fa6565b5060051b60200190565b600082601f8301126200405257600080fd5b813560206200406b62004065836200401a565b62003fe7565b8083825260208201915060208460051b8701019350868411156200408e57600080fd5b602086015b84811015620040ac578035835291830191830162004093565b509695505050505050565b60006001600160401b03821115620040d357620040d362003fa6565b50601f01601f191660200190565b6000620040f26200406584620040b7565b90508281528383830111156200410757600080fd5b828260208301376000602084830101529392505050565b600082601f8301126200413057600080fd5b62003ee483833560208501620040e1565b600080600080600060a086880312156200415a57600080fd5b8535620041678162003e65565b94506020860135620041798162003e65565b935060408601356001600160401b03808211156200419657600080fd5b620041a489838a0162004040565b94506060880135915080821115620041bb57600080fd5b620041c989838a0162004040565b93506080880135915080821115620041e057600080fd5b50620041ef888289016200411e565b9150509295509295909350565b6000602082840312156200420f57600080fd5b81356001600160401b03808211156200422757600080fd5b90830190604082860312156200423c57600080fd5b6040516040810181811083821117156200425a576200425a62003fa6565b604052823581526020830135828111156200427457600080fd5b62004282878286016200411e565b60208301525095945050505050565b60008060408385031215620042a557600080fd5b82356001600160401b0380821115620042bd57600080fd5b818501915085601f830112620042d257600080fd5b81356020620042e562004065836200401a565b82815260059290921b840181019181810190898411156200430557600080fd5b948201945b8386101562004330578535620043208162003e65565b825294820194908201906200430a565b965050860135925050808211156200434757600080fd5b50620043568582860162004040565b9150509250929050565b60008151808452602080850194506020840160005b83811015620043935781518752958201959082019060010162004375565b509495945050505050565b60208152600062003ee4602083018462004360565b600080600060608486031215620043c957600080fd5b83359250602084013591506040840135620043e48162003e65565b809150509250925092565b600080600080608085870312156200440657600080fd5b8435620044138162003e65565b935060208501356001600160401b03808211156200443057600080fd5b6200443e8883890162004040565b945060408701359150808211156200445557600080fd5b50620044648782880162004040565b9250506060850135620044778162003e65565b939692955090935050565b6000806000606084860312156200449857600080fd5b8335620044a58162003e65565b92506020840135620044b78162003e65565b929592945050506040919091013590565b600080600060608486031215620044de57600080fd5b8335620044eb8162003e65565b925060208401356001600160401b03808211156200450857600080fd5b620045168783880162004040565b935060408601359150808211156200452d57600080fd5b506200453c8682870162004040565b9150509250925092565b600080600080608085870312156200455d57600080fd5b84356200456a8162003e65565b935060208501359250604085013591506060850135620044778162003e65565b801515811462003e7b57600080fd5b60008060408385031215620045ad57600080fd5b8235620045ba8162003e65565b91506020830135620045cc816200458a565b809150509250929050565b600060208284031215620045ea57600080fd5b81356001600160401b038111156200460157600080fd5b62001dc8848285016200411e565b600080604083850312156200462357600080fd5b8235620046308162003e65565b91506020830135620045cc8162003e65565b600080604083850312156200465657600080fd5b82356001600160401b038111156200466d57600080fd5b8301601f810185136200467f57600080fd5b6200469085823560208401620040e1565b9250506020830135620045cc816200458a565b600080600080600060a08688031215620046bc57600080fd5b8535620046c98162003e65565b94506020860135620046db8162003e65565b9350604086013592506060860135915060808601356001600160401b038111156200470557600080fd5b620041ef888289016200411e565b600181811c908216806200472857607f821691505b6020821081036200474957634e487b7160e01b600052602260045260246000fd5b50919050565b600083516200476381846020880162003f05565b8351908301906200477981836020880162003f05565b01949350505050565b6000602082840312156200479557600080fd5b815162003ee48162003e65565b634e487b7160e01b600052603260045260246000fd5b604081526000620047cd604083018562004360565b8281036020840152620047e1818562004360565b95945050505050565b600060608284031215620047fd57600080fd5b6200480762003fbc565b8251815260208301516020820152604083015160408201528091505092915050565b600082601f8301126200483b57600080fd5b815160206200484e62004065836200401a565b8083825260208201915060208460051b8701019350868411156200487157600080fd5b602086015b84811015620040ac578051835291830191830162004876565b600060208284031215620048a257600080fd5b81516001600160401b0380821115620048ba57600080fd5b9083019060608286031215620048cf57600080fd5b620048d962003fbc565b82518152602083015182811115620048f057600080fd5b620048fe8782860162004829565b6020830152506040830151828111156200491757600080fd5b620049258782860162004829565b60408301525095945050505050565b634e487b7160e01b600052601160045260246000fd5b80820180821115620009ab57620009ab62004934565b805160ff811681146200497257600080fd5b919050565b6000602082840312156200498a57600080fd5b62003ee48262004960565b600082601f830112620049a757600080fd5b8151620049b86200406582620040b7565b818152846020838601011115620049ce57600080fd5b62001dc882602083016020870162003f05565b600060208284031215620049f457600080fd5b81516001600160401b038082111562004a0c57600080fd5b908301906060828603121562004a2157600080fd5b62004a2b62003fbc565b82518281111562004a3b57600080fd5b62004a498782860162004995565b8252506020830151602082015260408301518281111562004a6957600080fd5b620049258782860162004995565b60006020828403121562004a8a57600080fd5b815162003ee4816200458a565b601f82111562000c06576000816000526020600020601f850160051c8101602086101562004ac25750805b601f850160051c820191505b81811015620026725782815560010162004ace565b81516001600160401b0381111562004aff5762004aff62003fa6565b62004b178162004b10845462004713565b8462004a97565b602080601f83116001811462004b4f576000841562004b365750858301515b600019600386901b1c1916600185901b17855562002672565b600085815260208120601f198616915b8281101562004b805788860151825594840194600190910190840162004b5f565b508582101562004b9f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000825162004bc381846020870162003f05565b9190910192915050565b60006020828403121562004be057600080fd5b81516001600160401b0381111562004bf757600080fd5b62001dc88482850162004995565b60006020828403121562004c1857600080fd5b5051919050565b60608152600062004c34606083018662003f2b565b828103602084015262004c48818662003f2b565b91505060ff83166040830152949350505050565b60006001820162004c715762004c7162004934565b5060010190565b6001600160401b038716815285602082015284604082015260c06060820152600062004ca860c083018662003f2b565b828103608084015262004cbc818662003f2b565b91505060ff831660a0830152979650505050505050565b60208152600082516060602084015262004cf1608084018262003f2b565b9050602084015160408401526040840151601f19848303016060850152620047e1828262003f2b565b81810381811115620009ab57620009ab62004934565b6001600160a01b0386811682528516602082015260a06040820181905260009062004d5e9083018662004360565b828103606084015262004d72818662004360565b9050828103608084015262004d88818562003f2b565b98975050505050505050565b60006020828403121562004da757600080fd5b815162003ee48162003ead565b60008060008060008060c0878903121562004dce57600080fd5b86516001600160401b03808216821462004de757600080fd5b602089015160408a015160608b015193995090975095508082111562004e0c57600080fd5b62004e1a8a838b0162004995565b9450608089015191508082111562004e3157600080fd5b5062004e4089828a0162004995565b92505062004e5160a0880162004960565b90509295509295509295565b6001600160a01b03868116825285166020820152604081018490526060810183905260a06080820181905260009062004e999083018462003f2b565b979650505050505050565b6000806040838503121562004eb857600080fd5b62004ec38362004960565b915060208301516001600160401b0381111562004edf57600080fd5b620043568582860162004995565b6000806040838503121562004f0157600080fd5b8251915060208301516001600160401b0381111562004edf57600080fd5b60018060a01b038616815260ff8516602082015283604082015260a06060820152600062004f5160a083018562003f2b565b828103608084015262004d88818562003f2b56fe60c06040523480156200001157600080fd5b5060405162000c4c38038062000c4c833981016040819052620000349162000131565b8282600362000044838262000247565b50600462000053828262000247565b5050336080525060ff1660a05250620003139050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200009157600080fd5b81516001600160401b0380821115620000ae57620000ae62000069565b604051601f8301601f19908116603f01168101908282118183101715620000d957620000d962000069565b8160405283815260209250866020858801011115620000f757600080fd5b600091505b838210156200011b5785820183015181830184015290820190620000fc565b6000602085830101528094505050505092915050565b6000806000606084860312156200014757600080fd5b83516001600160401b03808211156200015f57600080fd5b6200016d878388016200007f565b945060208601519150808211156200018457600080fd5b5062000193868287016200007f565b925050604084015160ff81168114620001ab57600080fd5b809150509250925092565b600181811c90821680620001cb57607f821691505b602082108103620001ec57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000242576000816000526020600020601f850160051c810160208610156200021d5750805b601f850160051c820191505b818110156200023e5782815560010162000229565b5050505b505050565b81516001600160401b0381111562000263576200026362000069565b6200027b81620002748454620001b6565b84620001f2565b602080601f831160018114620002b357600084156200029a5750858301515b600019600386901b1c1916600185901b1785556200023e565b600085815260208120601f198616915b82811015620002e457888601518255948401946001909101908401620002c3565b5085821015620003035787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a0516109056200034760003960006101260152600081816101930152818161030f015261038301526109056000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c806370a082311161007157806370a0823114610165578063906d34db1461018e57806395d89b41146101cd578063a9059cbb146101d5578063dd62ed3e146101e8578063f6b911bc1461022157600080fd5b806306fdde03146100b9578063095ea7b3146100d757806318160ddd146100fa57806323b872dd1461010c578063313ce5671461011f57806340c10f1914610150575b600080fd5b6100c1610234565b6040516100ce919061074e565b60405180910390f35b6100ea6100e53660046107b9565b6102c6565b60405190151581526020016100ce565b6002545b6040519081526020016100ce565b6100ea61011a3660046107e3565b6102e0565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100ce565b61016361015e3660046107b9565b610304565b005b6100fe61017336600461081f565b6001600160a01b031660009081526020819052604090205490565b6101b57f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100ce565b6100c161035b565b6100ea6101e33660046107b9565b61036a565b6100fe6101f6366004610841565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b61016361022f3660046107e3565b610378565b60606003805461024390610874565b80601f016020809104026020016040519081016040528092919081815260200182805461026f90610874565b80156102bc5780601f10610291576101008083540402835291602001916102bc565b820191906000526020600020905b81548152906001019060200180831161029f57829003601f168201915b5050505050905090565b6000336102d48185856103f4565b60019150505b92915050565b6000336102ee858285610401565b6102f9858585610484565b506001949350505050565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461034d57604051630f3e00e560e41b815260040160405180910390fd5b61035782826104e3565b5050565b60606004805461024390610874565b6000336102d4818585610484565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103c157604051630f3e00e560e41b815260040160405180910390fd5b816001600160a01b0316836001600160a01b0316146103e5576103e5838383610401565b6103ef8382610519565b505050565b6103ef838383600161054f565b6001600160a01b03838116600090815260016020908152604080832093861683529290522054600019811461047e578181101561046f57604051637dc7a0d960e11b81526001600160a01b038416600482015260248101829052604481018390526064015b60405180910390fd5b61047e8484848403600061054f565b50505050565b6001600160a01b0383166104ae57604051634b637e8f60e11b815260006004820152602401610466565b6001600160a01b0382166104d85760405163ec442f0560e01b815260006004820152602401610466565b6103ef838383610624565b6001600160a01b03821661050d5760405163ec442f0560e01b815260006004820152602401610466565b61035760008383610624565b6001600160a01b03821661054357604051634b637e8f60e11b815260006004820152602401610466565b61035782600083610624565b6001600160a01b0384166105795760405163e602df0560e01b815260006004820152602401610466565b6001600160a01b0383166105a357604051634a1406b160e11b815260006004820152602401610466565b6001600160a01b038085166000908152600160209081526040808320938716835292905220829055801561047e57826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161061691815260200190565b60405180910390a350505050565b6001600160a01b03831661064f57806002600082825461064491906108ae565b909155506106c19050565b6001600160a01b038316600090815260208190526040902054818110156106a25760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401610466565b6001600160a01b03841660009081526020819052604090209082900390555b6001600160a01b0382166106dd576002805482900390556106fc565b6001600160a01b03821660009081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161074191815260200190565b60405180910390a3505050565b60006020808352835180602085015260005b8181101561077c57858101830151858201604001528201610760565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b03811681146107b457600080fd5b919050565b600080604083850312156107cc57600080fd5b6107d58361079d565b946020939093013593505050565b6000806000606084860312156107f857600080fd5b6108018461079d565b925061080f6020850161079d565b9150604084013590509250925092565b60006020828403121561083157600080fd5b61083a8261079d565b9392505050565b6000806040838503121561085457600080fd5b61085d8361079d565b915061086b6020840161079d565b90509250929050565b600181811c9082168061088857607f821691505b6020821081036108a857634e487b7160e01b600052602260045260246000fd5b50919050565b808201808211156102da57634e487b7160e01b600052601160045260246000fdfea2646970667358221220db917e99493fa2fa6a4547fc1b43871a3bb0974af926415a8e75c68fde7cba2464736f6c634300081700333a2f5529773e03d975be44bdae98a8509bdf1159e407504e558536cde56cf6aca26469706673582212200ed00da5d4127c44efbf778d8cb7b188c25ebe54ec8b7dea2a073097d6ddf09364736f6c63430008170033000000000000000000000000000000000000000000000000000000000000008000000000000000000000000017a332dc7b40ae701485023b219e9d6f493a251400000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000006c68747470733a2f2f697066732d676174657761792e7375706572666f726d2e78797a2f69706e732f6b3531717a693575717535646739306671646f396a36336d353536776c6464657578346d6c67797974687033307a6f7573676833687568797a6f757971382f4a534f4e2f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5375706572506f736974696f6e7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025350000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x608060405260043610620002825760003560e01c80637081ce5e1162000153578063cdde3d6b11620000c5578063e985e9c51162000084578063e985e9c514620008b3578063ec73732114620008f2578063ed7a8e421462000917578063edf387c5146200093c578063f242432a1462000954578063ff61011a146200097957600080fd5b8063cdde3d6b14620007fa578063d7ea0c23146200081f578063d81d0a15146200083b578063e673070f1462000860578063e6ddad4c146200089c57600080fd5b806395d89b41116200011257806395d89b411462000742578063a22cb465146200075a578063a49f9516146200077f578063bd85b03914620007a4578063cd4622eb14620007d557600080fd5b80637081ce5e146200063e57806375fcbd86146200066357806385e1f4d014620006c25780638d04e40e14620006f85780639473655c146200071d57600080fd5b806333e3072111620001f95780635029d0c811620001b85780635029d0c8146200054b578063540ed9c01462000570578063598af9e714620005aa5780635fa8d76414620005cf57806367bc406514620005f45780636b20c454146200061957600080fd5b806333e30721146200045c57806349e5b649146200049a5780634e1273f414620004bf5780634ec1bec714620004f35780634f558e79146200051857600080fd5b80630e89341c11620002465780630e89341c146200039d578063132b481614620003c2578063137bc42714620003e957806324c73dda14620004015780632eb2c2d6146200043757600080fd5b8062fdd58e146200028757806301ffc9a714620002d65780630282acfc146200030c57806306fdde03146200035f578063093e31641462000386575b600080fd5b3480156200029457600080fd5b50620002c3620002a636600462003e7e565b600260209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b348015620002e357600080fd5b50620002fb620002f536600462003ec4565b6200099e565b6040519015158152602001620002cd565b3480156200031957600080fd5b50620003466200032b36600462003eeb565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001620002cd565b3480156200036c57600080fd5b5062000377620009b1565b604051620002cd919062003f59565b620003466200039736600462003eeb565b62000a47565b348015620003aa57600080fd5b5062000377620003bc36600462003eeb565b62000aec565b348015620003cf57600080fd5b50620003e7620003e136600462003f6e565b62000b2c565b005b348015620003f657600080fd5b506200037762000c0b565b3480156200040e57600080fd5b50620003467f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a251481565b3480156200044457600080fd5b50620003e76200045636600462004141565b62000c1a565b3480156200046957600080fd5b50620004816200047b366004620041fc565b62000e0f565b6040516001600160401b039091168152602001620002cd565b348015620004a757600080fd5b5062000481620004b9366004620041fc565b62000fcd565b348015620004cc57600080fd5b50620004e4620004de36600462004291565b62001138565b604051620002cd91906200439e565b3480156200050057600080fd5b50620003e762000512366004620043b3565b62001252565b3480156200052557600080fd5b50620002fb6200053736600462003eeb565b600090815260208190526040902054151590565b3480156200055857600080fd5b50620003e76200056a366004620043ef565b620013a1565b3480156200057d57600080fd5b50620003466200058f36600462003eeb565b6000908152600460205260409020546001600160a01b031690565b348015620005b757600080fd5b50620002c3620005c936600462004482565b6200157b565b348015620005dc57600080fd5b50620003e7620005ee366004620044c8565b620015ad565b3480156200060157600080fd5b50620002fb62000613366004620044c8565b62001635565b3480156200062657600080fd5b50620003e762000638366004620044c8565b620016fb565b3480156200064b57600080fd5b50620003e76200065d36600462004546565b620017f8565b3480156200067057600080fd5b50620006a46200068236600462003eeb565b600760205260009081526040902080546001909101546001600160a01b031682565b604080519283526001600160a01b03909116602083015201620002cd565b348015620006cf57600080fd5b50620004817f000000000000000000000000000000000000000000000000000000000000000181565b3480156200070557600080fd5b50620003e76200071736600462003f6e565b6200192e565b3480156200072a57600080fd5b50620003e76200073c36600462004546565b62001b32565b3480156200074f57600080fd5b506200037762001c7d565b3480156200076757600080fd5b50620003e76200077936600462004599565b62001c8c565b3480156200078c57600080fd5b50620003e76200079e36600462003f6e565b62001d20565b348015620007b157600080fd5b50620002c3620007c336600462003eeb565b60009081526020819052604090205490565b348015620007e257600080fd5b50620002fb620007f4366004620044c8565b62001d30565b3480156200080757600080fd5b50620002fb6200081936600462003f6e565b62001db6565b3480156200082c57600080fd5b50600954620002fb9060ff1681565b3480156200084857600080fd5b50620003e76200085a366004620044c8565b62001dd0565b3480156200086d57600080fd5b50620002fb6200087f36600462003eeb565b6000908152600460205260409020546001600160a01b0316151590565b620003e7620008ad366004620045d7565b62001fc6565b348015620008c057600080fd5b50620002fb620008d23660046200460f565b600360209081526000928352604080842090915290825290205460ff1681565b348015620008ff57600080fd5b50620003e762000911366004620043ef565b62002115565b3480156200092457600080fd5b50620003e76200093636600462004642565b620022d8565b3480156200094957600080fd5b50620002c3600a5481565b3480156200096157600080fd5b50620003e762000973366004620046a3565b6200254a565b3480156200098657600080fd5b50620002fb6200099836600462003f6e565b6200267a565b6000620009ab826200269b565b92915050565b60058054620009c09062004713565b80601f0160208091040260200160405190810160405280929190818152602001828054620009ee9062004713565b801562000a3f5780601f1062000a135761010080835404028352916020019162000a3f565b820191906000526020600020905b81548152906001019060200180831162000a2157829003601f168201915b505050505081565b600081815260208190526040812054810362000a7657604051631b5bd2df60e31b815260040160405180910390fd5b6000828152600460205260409020546001600160a01b03161562000aad576040516347d4e9ad60e11b815260040160405180910390fd5b600062000aba83620026ee565b60009384526004602052604090932080546001600160a01b0319166001600160a01b0390941693841790555090919050565b606062000af862002d5a565b62000b038362002df4565b60405160200162000b169291906200474f565b6040516020818303038152906040529050919050565b6040516321f8a72160e01b815260008051602062005bb283398151915260048201527f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa15801562000ba0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000bc6919062004782565b6001600160a01b0316336001600160a01b03161462000bf85760405163158a2f6b60e01b815260040160405180910390fd5b62000c068333848462002e8d565b505050565b60088054620009c09062004713565b6001600160a01b038516158062000c3857506001600160a01b038416155b1562000c575760405163538ba4f960e01b815260040160405180910390fd5b82518251811462000c7b5760405163899ef10d60e01b815260040160405180910390fd5b336001600160a01b038716811480159062000cbc57506001600160a01b0380881660009081526003602090815260408083209385168352929052205460ff16155b1562000d405760008060005b8481101562000d375787818151811062000ce65762000ce6620047a2565b6020026020010151925086818151811062000d055762000d05620047a2565b6020026020010151915062000d1f8a858585600062002f74565b5062000d2e8a8a858562002fcf565b60010162000cc8565b50505062000d9d565b60005b8281101562000d9b5762000d92888888848151811062000d675762000d67620047a2565b602002602001015188858151811062000d845762000d84620047a2565b602002602001015162002fcf565b60010162000d43565b505b856001600160a01b0316876001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb888860405162000dee929190620047b8565b60405180910390a462000e0681888888888862003049565b50505050505050565b805160009060ff80821691600881901c9091169060101c6001821480159062000e39575060028214155b1562000e585760405163641c695560e01b815260040160405180910390fd5b6000856020015180602001905181019062000e749190620047ea565b905062000e858160200151620031ad565b80516000908152600760205260408120549081900362000eb85760405163eed061b760e01b815260040160405180910390fd5b60c081901c955060ff8082169084161562000ee65760405163641c695560e01b815260040160405180910390fd5b80861462000f0757604051633ca5012160e21b815260040160405180910390fd5b8015801562000f165750600185145b8062000f2e575060018114801562000f2e5750600285145b1562000f7e5782516000908152600760209081526040808320600101548287015182880151835194850190935293835262000f78936001600160a01b039091169233929062003249565b62000f97565b60405163641c695560e01b815260040160405180910390fd5b82516040517fdfd517ed69f8a0a57d49fe494e4864fac3cfe3585c14c0bfddf39f72463ec3fd90600090a2505050505050919050565b805160009060ff80821691600881901c9091169060101c6001821480159062000ff7575060028214155b15620010165760405163641c695560e01b815260040160405180910390fd5b600085602001518060200190518101906200103291906200488f565b905062001043816020015162003305565b805160009081526007602052604081205490819003620010765760405163eed061b760e01b815260040160405180910390fd5b60c081901c955060ff808216908416600114620010a65760405163641c695560e01b815260040160405180910390fd5b808614620010c757604051633ca5012160e21b815260040160405180910390fd5b80158015620010d65750600185145b80620010ee5750600181148015620010ee5750600285145b1562000f7e5782516000908152600760209081526040808320600101548287015182880151835194850190935293835262000f78936001600160a01b0390911692339290620033d3565b606081518351146200115d5760405163899ef10d60e01b815260040160405180910390fd5b82516001600160401b0381111562001179576200117962003fa6565b604051908082528060200260200182016040528015620011a3578160200160208202803683370190505b50905060005b83518110156200124b5760026000858381518110620011cc57620011cc620047a2565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008483815181106200120b576200120b620047a2565b6020026020010151815260200190815260200160002054828281518110620012375762001237620047a2565b6020908102919091010152600101620011a9565b5092915050565b6040516321f8a72160e01b815260008051602062005bb283398151915260048201527f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa158015620012c6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620012ec919062004782565b6001600160a01b0316336001600160a01b0316146200131e5760405163158a2f6b60e01b815260040160405180910390fd5b6040805180820182528381526001600160a01b0383811660208084018281526000898152600783528690209451855551600190940180546001600160a01b0319169490931693909317909155915184815285917f226fd1a430a7a15fa93582471a806bc430535d985fa9547a69921a9499bf492b910160405180910390a3505050565b6001600160a01b0384161580620013bf57506001600160a01b038116155b15620013de5760405163538ba4f960e01b815260040160405180910390fd5b825182518114620014025760405163899ef10d60e01b815260040160405180910390fd5b60008060005b86518110156200150457868181518110620014275762001427620047a2565b60200260200101519250858181518110620014465762001446620047a2565b602090810291909101810151600085815260049092526040909120549092506001600160a01b0316806200148d576040516369f28dc960e11b815260040160405180910390fd5b604051633dae446f60e21b81526001600160a01b038a811660048301523360248301526044820185905282169063f6b911bc90606401600060405180830381600087803b158015620014de57600080fd5b505af1158015620014f3573d6000803e3d6000fd5b505050505080600101905062001408565b50620015238433888860405180602001604052806000815250620033d3565b836001600160a01b0316876001600160a01b03167f2ec4237e89b1c7ccb8710672dc83af16f1949c33f3b313eeaab1a626e6aa442788886040516200156a929190620047b8565b60405180910390a350505050505050565b6001600160a01b0392831660009081526001602090815260408083209490951682529283528381209181529152205490565b815181518114620015d15760405163899ef10d60e01b815260040160405180910390fd5b60005b818110156200162e57620016253386868481518110620015f857620015f8620047a2565b6020026020010151868581518110620016155762001615620047a2565b6020026020010151600162003535565b600101620015d4565b5050505050565b815181516000919081146200165d5760405163899ef10d60e01b815260040160405180910390fd5b60005b81811015620016ef57620016e63387878481518110620016845762001684620047a2565b6020026020010151878581518110620016a157620016a1620047a2565b6020026020010151620016d2338c8c8981518110620016c457620016c4620047a2565b60200260200101516200157b565b620016de91906200494a565b600162003535565b60010162001660565b50600195945050505050565b6040516321f8a72160e01b815260008051602062005bb283398151915260048201527f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa1580156200176f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001795919062004782565b6001600160a01b0316336001600160a01b031614620017c75760405163158a2f6b60e01b815260040160405180910390fd5b8051825114620017ea57604051634456f5e960e11b815260040160405180910390fd5b62000c06833384846200360b565b6001600160a01b03841615806200181657506001600160a01b038116155b15620018355760405163538ba4f960e01b815260040160405180910390fd5b620018438433858562002e8d565b6000838152600460205260409020546001600160a01b0316806200187a576040516369f28dc960e11b815260040160405180910390fd5b6040516340c10f1960e01b81526001600160a01b038381166004830152602482018590528216906340c10f1990604401600060405180830381600087803b158015620018c557600080fd5b505af1158015620018da573d6000803e3d6000fd5b505060408051878152602081018790526001600160a01b038087169450891692507f4420f38d0f4ce916c1d0da8d37675c007978eaaa4a8c2cc4231fd52a7a57b61491015b60405180910390a35050505050565b6040516321f8a72160e01b815260008051602062005bb2833981519152600482015282906000906001600160a01b037f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a251416906321f8a72190602401602060405180830381865afa158015620019a7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620019cd919062004782565b9050336001600160a01b0382161462001b1457604051632f6438ab60e01b81523360048201526000907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b031690632f6438ab90602401602060405180830381865afa15801562001a48573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001a6e919062004977565b9050600062001a7d8462003884565b505090506000816001600160a01b03166391deb8826040518163ffffffff1660e01b8152600401602060405180830381865afa15801562001ac2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001ae8919062004977565b90508060ff168360ff161462001b1057604051622450cd60e21b815260040160405180910390fd5b5050505b6200162e853386866040518060200160405280600081525062003249565b6001600160a01b038416158062001b5057506001600160a01b038116155b1562001b6f5760405163538ba4f960e01b815260040160405180910390fd5b6000838152600460205260409020546001600160a01b03168062001ba6576040516369f28dc960e11b815260040160405180910390fd5b604051633dae446f60e21b81526001600160a01b0386811660048301523360248301526044820185905282169063f6b911bc90606401600060405180830381600087803b15801562001bf757600080fd5b505af115801562001c0c573d6000803e3d6000fd5b5050505062001c2e823386866040518060200160405280600081525062003249565b816001600160a01b0316856001600160a01b03167f9195fdebb74042f1bd7abc0ded779a6e10ae01e0ad5f5546cb7e421d65a5666686866040516200191f929190918252602082015260400190565b60068054620009c09062004713565b6001600160a01b03821662001cb45760405163538ba4f960e01b815260040160405180910390fd5b3360008181526003602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b62000c0633848484600162003535565b8151815160009190811462001d585760405163899ef10d60e01b815260040160405180910390fd5b60005b81811015620016ef5762001dac338787848151811062001d7f5762001d7f620047a2565b602002602001015187858151811062001d9c5762001d9c620047a2565b6020026020010151600162002f74565b5060010162001d5b565b600062001dc833858585600162002f74565b949350505050565b6040516321f8a72160e01b815260008051602062005bb2833981519152600482015282906000906001600160a01b037f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a251416906321f8a72190602401602060405180830381865afa15801562001e49573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001e6f919062004782565b9050336001600160a01b0382161462001f8557815160005b8181101562001f8257600062001eb985838151811062001eab5762001eab620047a2565b602002602001015162003884565b50604051632f6438ab60e01b8152336004820152909250600091506001600160a01b037f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25141690632f6438ab90602401602060405180830381865afa15801562001f26573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001f4c919062004977565b905060ff811663ffffffff83161462001f7757604051622450cd60e21b815260040160405180910390fd5b505060010162001e87565b50505b825184511462001fa857604051634456f5e960e11b815260040160405180910390fd5b6200162e8533868660405180602001604052806000815250620033d3565b6040516321f8a72160e01b81527f86a7f6b88da6de42c331676d4da78508adfef4970dc8aa541004f26b6eef4ab960048201527f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa1580156200204b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002071919062004782565b6001600160a01b0316336001600160a01b031614620020a35760405163b0acaf9d60e01b815260040160405180910390fd5b600081806020019051810190620020bb9190620049e1565b90507f62fe4458baf33f94c99b0a629b6b8fae9f220aa42242d61592a0454d37a7484c8160200151146200210257604051634c8b6b4f60e11b815260040160405180910390fd5b620021118160400151620038b9565b5050565b6001600160a01b03841615806200213357506001600160a01b038116155b15620021525760405163538ba4f960e01b815260040160405180910390fd5b825182518114620021765760405163899ef10d60e01b815260040160405180910390fd5b62002184853386866200360b565b60005b818110156200229057600060046000878481518110620021ab57620021ab620047a2565b6020908102919091018101518252810191909152604001600020546001600160a01b0316905080620021f0576040516369f28dc960e11b815260040160405180910390fd5b806001600160a01b03166340c10f1985878581518110620022155762002215620047a2565b60200260200101516040518363ffffffff1660e01b81526004016200224f9291906001600160a01b03929092168252602082015260400190565b600060405180830381600087803b1580156200226a57600080fd5b505af11580156200227f573d6000803e3d6000fd5b505050505080600101905062002187565b50816001600160a01b0316856001600160a01b03167f1c57454fefbe0a2a0aa1926734e74f4cb5137003ccf5e6edfde51c79163fbf3786866040516200191f929190620047b8565b6040516321f8a72160e01b81527f6b50fa17b77d24e42e27a04b69fe50cd6967cfb767d18de0bd5fe7e1a32aa86860048201527f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa1580156200235d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002383919062004782565b6040516369ac88f960e11b81523360048201526001600160a01b03919091169063d35911f290602401602060405180830381865afa158015620023ca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620023f0919062004a77565b6200240e57604051633721555560e21b815260040160405180910390fd5b60095460ff1615620024335760405163fb407daf60e01b815260040160405180910390fd5b600060088054620024449062004713565b80601f0160208091040260200160405190810160405280929190818152602001828054620024729062004713565b8015620024c35780601f106200249757610100808354040283529160200191620024c3565b820191906000526020600020905b815481529060010190602001808311620024a557829003601f168201915b505050505090508260089081620024db919062004ae3565b506009805460ff1916831515908117909155604051620024fd90859062004baf565b60405180910390208260405162002515919062004baf565b604051908190038120907f5386175ed3f7187aa4eae65398696731724636ea68ccda712d3119159f5b115990600090a4505050565b6001600160a01b03851615806200256857506001600160a01b038416155b15620025875760405163538ba4f960e01b815260040160405180910390fd5b336001600160a01b0386168114801590620025c857506001600160a01b0380871660009081526003602090815260408083209385168352929052205460ff16155b15620025f357620025de86828686600062002f74565b50620025ed8686868662002fcf565b62002601565b620026018686868662002fcf565b846001600160a01b0316866001600160a01b0316826001600160a01b03167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6287876040516200265a929190918252602082015260400190565b60405180910390a462002672818787878787620039b7565b505050505050565b60006200269133858585620016d2338a8a6200157b565b5060019392505050565b60006001600160e01b031982166301ffc9a760e01b1480620026cd57506001600160e01b03198216636cdb3d1360e11b145b80620009ab57506001600160e01b031982166303a24d0760e21b1492915050565b6040516321f8a72160e01b81527fbcc180fb907e9ae431665de4bc74305c00b7b27442aadd477980ecc4bb14c01160048201526000907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa15801562002776573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200279c919062004782565b6001600160a01b031663b5c75697836040518263ffffffff1660e01b8152600401620027ca91815260200190565b602060405180830381865afa158015620027e8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200280e919062004a77565b6200282c5760405163a412f06560e01b815260040160405180910390fd5b6000620028398362003884565b505090506000816001600160a01b03166320592d986040518163ffffffff1660e01b8152600401600060405180830381865afa1580156200287e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620028a8919081019062004bcd565b90506000826001600160a01b03166317a57e086040518163ffffffff1660e01b8152600401600060405180830381865afa158015620028eb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262002915919081019062004bcd565b90506000836001600160a01b031663c32dcd896040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002958573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200297e919062004c05565b9050828282604051620029919062003e57565b6200299f9392919062004c1f565b604051809103906000f080158015620029bc573d6000803e3d6000fd5b509450600060405180606001604052806040518060400160405280600f81526020016e53555045525f504f534954494f4e5360881b81525081526020017f62fe4458baf33f94c99b0a629b6b8fae9f220aa42242d61592a0454d37a7484c81526020017f0000000000000000000000000000000000000000000000000000000000000001600a6000815462002a519062004c5c565b918290555060405162002a719291908c908a908a908a9060200162004c78565b60408051808303601f190181529181529152516321f8a72160e01b81527f86a7f6b88da6de42c331676d4da78508adfef4970dc8aa541004f26b6eef4ab9600482015290915062002d1a907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa15801562002b0e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002b34919062004782565b6040516321f8a72160e01b81527fbddfa8c39a1f6275bcfb3aa5c70638c466999edbf14e6162d81b3492caca9fce60048201527f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa15801562002bb9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002bdf919062004782565b8360405160200162002bf2919062004cd3565b60408051808303601f19018152908290526321f8a72160e01b82527fab437a16135e856111e538dc45051dd9c2778c6069d25a22fb9ac4766c356aa16004830152907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa15801562002c86573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002cac919062004782565b6001600160a01b03166353d69edc6040518163ffffffff1660e01b8152600401600060405180830381865afa15801562002cea573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262002d14919081019062004bcd565b62003aab565b6040516001600160a01b0387169088907f733ac2a007cd3853c362154b5f081e3ad8f60fd4e892fa3a0ca14a266ff897f890600090a35050505050919050565b60606008805462002d6b9062004713565b80601f016020809104026020016040519081016040528092919081815260200182805462002d999062004713565b801562002dea5780601f1062002dbe5761010080835404028352916020019162002dea565b820191906000526020600020905b81548152906001019060200180831162002dcc57829003601f168201915b5050505050905090565b6060600062002e038362003c05565b60010190506000816001600160401b0381111562002e255762002e2562003fa6565b6040519080825280601f01601f19166020018201604052801562002e50576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508462002e5a57509392505050565b836001600160a01b0316836001600160a01b03161415801562002ed657506001600160a01b0380851660009081526003602090815260408083209387168352929052205460ff16155b1562002eee5762002eec84848484600062002f74565b505b62002efd846000848462002fcf565b6000828152602081905260408120805483929062002f1d90849062004d1a565b909155505060408051838152602081018390526000916001600160a01b0387811692908716917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a450505050565b60008062002f848787876200157b565b90508381101562002fa857604051630422f8c360e31b815260040160405180910390fd5b62002fc287878762002fbb888662004d1a565b8762003535565b5060019695505050505050565b6001600160a01b0384166000908152600260209081526040808320858452909152812080548392906200300490849062004d1a565b90915550506001600160a01b0383166000908152600260209081526040808320858452909152812080548392906200303e9084906200494a565b909155505050505050565b6001600160a01b0384163b15620031855760405163bc197c8160e01b81526001600160a01b0385169063bc197c819062003090908990899088908890889060040162004d30565b6020604051808303816000875af1925050508015620030ce575060408051601f3d908101601f19168201909252620030cb9181019062004d94565b60015b62003147573d808015620030ff576040519150601f19603f3d011682016040523d82523d6000602084013e62003104565b606091505b5080516000036200313857604051632bfa23e760e11b81526001600160a01b03861660048201526024015b60405180910390fd5b805181602001fd5b5062002672565b6001600160e01b0319811663bc197c8160e01b146200314057604051632bfa23e760e11b81526001600160a01b03861660048201526024016200312f565b6001600160a01b0384166200267257604051635edce13360e01b815260040160405180910390fd5b604051632f6438ab60e01b81523360048201526000907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b031690632f6438ab90602401602060405180830381865afa15801562003215573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200323b919062004977565b905062002111818362003ce4565b6001600160a01b0385166000908152600260209081526040808320868452909152812080548492906200327e9084906200494a565b909155505060008381526020819052604081208054849290620032a39084906200494a565b909155505060408051848152602081018490526001600160a01b0380881692600092918816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46200162e84600087868686620039b7565b604051632f6438ab60e01b81523360048201526000907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b031690632f6438ab90602401602060405180830381865afa1580156200336d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003393919062004977565b905060005b825181101562000c0657620033ca82848381518110620033bc57620033bc620047a2565b602002602001015162003ce4565b60010162003398565b825182518114620033f75760405163899ef10d60e01b815260040160405180910390fd5b60008060005b83811015620034bf578681815181106200341b576200341b620047a2565b602002602001015192508581815181106200343a576200343a620047a2565b6020026020010151915081600260008b6001600160a01b03166001600160a01b03168152602001908152602001600020600085815260200190815260200160002060008282546200348c91906200494a565b909155505060008381526020819052604081208054849290620034b19084906200494a565b9091555050600101620033fd565b50876001600160a01b031660006001600160a01b0316886001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb898960405162003512929190620047b8565b60405180910390a46200352b8760008a89898962003049565b5050505050505050565b6001600160a01b0385166200355d5760405163538ba4f960e01b815260040160405180910390fd5b6001600160a01b038416620035855760405163538ba4f960e01b815260040160405180910390fd5b6001600160a01b038086166000908152600160209081526040808320938816835292815282822086835290522082905580156200162e57836001600160a01b0316856001600160a01b03167f875251d6c7be5b10ddb14ed4f59395338f15552062d4ad7723265838e316f9a885856040516200191f929190918252602082015260400190565b8151815181146200362f5760405163899ef10d60e01b815260040160405180910390fd5b600080866001600160a01b0316866001600160a01b0316141580156200367b57506001600160a01b038088166000908152600360209081526040808320938a168352929052205460ff16155b156200375c5760005b838110156200375557858181518110620036a257620036a2620047a2565b60200260200101519250848181518110620036c157620036c1620047a2565b60200260200101519150620036db88888585600062002f74565b50620036eb886000858562002fcf565b848181518110620037005762003700620047a2565b6020026020010151600080888481518110620037205762003720620047a2565b60200260200101518152602001908152602001600020600082825462003747919062004d1a565b909155505060010162003684565b5062003821565b60005b838110156200381f578581815181106200377d576200377d620047a2565b602002602001015192508481815181106200379c576200379c620047a2565b60200260200101519150620037b5886000858562002fcf565b848181518110620037ca57620037ca620047a2565b6020026020010151600080888481518110620037ea57620037ea620047a2565b60200260200101518152602001908152602001600020600082825462003811919062004d1a565b90915550506001016200375f565b505b60006001600160a01b0316876001600160a01b0316876001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb888860405162003873929190620047b8565b60405180910390a450505050505050565b8060a081901c60c082901c6000819003620038b25760405163030042b760e01b815260040160405180910390fd5b9193909250565b60008060008084806020019051810190620038d5919062004db4565b600084815260046020526040902054939950919750955093506001600160a01b03161591506200391a9050576040516347d4e9ad60e11b815260040160405180910390fd5b60008383836040516200392d9062003e57565b6200393b9392919062004c1f565b604051809103906000f08015801562003958573d6000803e3d6000fd5b5060008681526004602052604080822080546001600160a01b0319166001600160a01b03851690811790915590519293509187917f733ac2a007cd3853c362154b5f081e3ad8f60fd4e892fa3a0ca14a266ff897f891a3505050505050565b6001600160a01b0384163b15620031855760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190620039fe908990899088908890889060040162004e5d565b6020604051808303816000875af192505050801562003a3c575060408051601f3d908101601f1916820190925262003a399181019062004d94565b60015b62003a6d573d808015620030ff576040519150601f19603f3d011682016040523d82523d6000602084013e62003104565b6001600160e01b0319811663f23a6e6160e01b146200314057604051632bfa23e760e11b81526001600160a01b03861660048201526024016200312f565b6000808280602001905181019062003ac4919062004ea4565b915091506000808280602001905181019062003ae1919062004eed565b915091508134101562003b0757604051631961e86760e01b815260040160405180910390fd5b604051636319827b60e11b81526001600160a01b0389169063c63304f690849062003b3f903390899084908d90899060040162004f1f565b6000604051808303818588803b15801562003b5957600080fd5b505af115801562003b6e573d6000803e3d6000fd5b5050505050813411156200352b5760006001600160a01b03881662003b94843462004d1a565b604051600081818185875af1925050503d806000811462003bd2576040519150601f19603f3d011682016040523d82523d6000602084013e62003bd7565b606091505b505090508062003bfa5760405163220d375360e01b815260040160405180910390fd5b505050505050505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831062003c455772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef8100000000831062003c72576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831062003c9157662386f26fc10000830492506010015b6305f5e100831062003caa576305f5e100830492506008015b612710831062003cbf57612710830492506004015b6064831062003cd2576064830492506002015b600a8310620009ab5760010192915050565b60001960ff83160162003cf5575050565b600062003d028262003884565b506040516321f8a72160e01b81527fbcc180fb907e9ae431665de4bc74305c00b7b27442aadd477980ecc4bb14c0116004820152909250600091506001600160a01b037f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a251416906321f8a72190602401602060405180830381865afa15801562003d8f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003db5919062004782565b60405163297e034f60e11b815263ffffffff841660048201526001600160a01b0391909116906352fc069e90602401602060405180830381865afa15801562003e02573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003e28919062004977565b90508060ff168460ff161462003e515760405163760c22d960e11b815260040160405180910390fd5b50505050565b610c4c8062004f6683390190565b6001600160a01b038116811462003e7b57600080fd5b50565b6000806040838503121562003e9257600080fd5b823562003e9f8162003e65565b946020939093013593505050565b6001600160e01b03198116811462003e7b57600080fd5b60006020828403121562003ed757600080fd5b813562003ee48162003ead565b9392505050565b60006020828403121562003efe57600080fd5b5035919050565b60005b8381101562003f2257818101518382015260200162003f08565b50506000910152565b6000815180845262003f4581602086016020860162003f05565b601f01601f19169290920160200192915050565b60208152600062003ee4602083018462003f2b565b60008060006060848603121562003f8457600080fd5b833562003f918162003e65565b95602085013595506040909401359392505050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171562003fe15762003fe162003fa6565b60405290565b604051601f8201601f191681016001600160401b038111828210171562004012576200401262003fa6565b604052919050565b60006001600160401b0382111562004036576200403662003fa6565b5060051b60200190565b600082601f8301126200405257600080fd5b813560206200406b62004065836200401a565b62003fe7565b8083825260208201915060208460051b8701019350868411156200408e57600080fd5b602086015b84811015620040ac578035835291830191830162004093565b509695505050505050565b60006001600160401b03821115620040d357620040d362003fa6565b50601f01601f191660200190565b6000620040f26200406584620040b7565b90508281528383830111156200410757600080fd5b828260208301376000602084830101529392505050565b600082601f8301126200413057600080fd5b62003ee483833560208501620040e1565b600080600080600060a086880312156200415a57600080fd5b8535620041678162003e65565b94506020860135620041798162003e65565b935060408601356001600160401b03808211156200419657600080fd5b620041a489838a0162004040565b94506060880135915080821115620041bb57600080fd5b620041c989838a0162004040565b93506080880135915080821115620041e057600080fd5b50620041ef888289016200411e565b9150509295509295909350565b6000602082840312156200420f57600080fd5b81356001600160401b03808211156200422757600080fd5b90830190604082860312156200423c57600080fd5b6040516040810181811083821117156200425a576200425a62003fa6565b604052823581526020830135828111156200427457600080fd5b62004282878286016200411e565b60208301525095945050505050565b60008060408385031215620042a557600080fd5b82356001600160401b0380821115620042bd57600080fd5b818501915085601f830112620042d257600080fd5b81356020620042e562004065836200401a565b82815260059290921b840181019181810190898411156200430557600080fd5b948201945b8386101562004330578535620043208162003e65565b825294820194908201906200430a565b965050860135925050808211156200434757600080fd5b50620043568582860162004040565b9150509250929050565b60008151808452602080850194506020840160005b83811015620043935781518752958201959082019060010162004375565b509495945050505050565b60208152600062003ee4602083018462004360565b600080600060608486031215620043c957600080fd5b83359250602084013591506040840135620043e48162003e65565b809150509250925092565b600080600080608085870312156200440657600080fd5b8435620044138162003e65565b935060208501356001600160401b03808211156200443057600080fd5b6200443e8883890162004040565b945060408701359150808211156200445557600080fd5b50620044648782880162004040565b9250506060850135620044778162003e65565b939692955090935050565b6000806000606084860312156200449857600080fd5b8335620044a58162003e65565b92506020840135620044b78162003e65565b929592945050506040919091013590565b600080600060608486031215620044de57600080fd5b8335620044eb8162003e65565b925060208401356001600160401b03808211156200450857600080fd5b620045168783880162004040565b935060408601359150808211156200452d57600080fd5b506200453c8682870162004040565b9150509250925092565b600080600080608085870312156200455d57600080fd5b84356200456a8162003e65565b935060208501359250604085013591506060850135620044778162003e65565b801515811462003e7b57600080fd5b60008060408385031215620045ad57600080fd5b8235620045ba8162003e65565b91506020830135620045cc816200458a565b809150509250929050565b600060208284031215620045ea57600080fd5b81356001600160401b038111156200460157600080fd5b62001dc8848285016200411e565b600080604083850312156200462357600080fd5b8235620046308162003e65565b91506020830135620045cc8162003e65565b600080604083850312156200465657600080fd5b82356001600160401b038111156200466d57600080fd5b8301601f810185136200467f57600080fd5b6200469085823560208401620040e1565b9250506020830135620045cc816200458a565b600080600080600060a08688031215620046bc57600080fd5b8535620046c98162003e65565b94506020860135620046db8162003e65565b9350604086013592506060860135915060808601356001600160401b038111156200470557600080fd5b620041ef888289016200411e565b600181811c908216806200472857607f821691505b6020821081036200474957634e487b7160e01b600052602260045260246000fd5b50919050565b600083516200476381846020880162003f05565b8351908301906200477981836020880162003f05565b01949350505050565b6000602082840312156200479557600080fd5b815162003ee48162003e65565b634e487b7160e01b600052603260045260246000fd5b604081526000620047cd604083018562004360565b8281036020840152620047e1818562004360565b95945050505050565b600060608284031215620047fd57600080fd5b6200480762003fbc565b8251815260208301516020820152604083015160408201528091505092915050565b600082601f8301126200483b57600080fd5b815160206200484e62004065836200401a565b8083825260208201915060208460051b8701019350868411156200487157600080fd5b602086015b84811015620040ac578051835291830191830162004876565b600060208284031215620048a257600080fd5b81516001600160401b0380821115620048ba57600080fd5b9083019060608286031215620048cf57600080fd5b620048d962003fbc565b82518152602083015182811115620048f057600080fd5b620048fe8782860162004829565b6020830152506040830151828111156200491757600080fd5b620049258782860162004829565b60408301525095945050505050565b634e487b7160e01b600052601160045260246000fd5b80820180821115620009ab57620009ab62004934565b805160ff811681146200497257600080fd5b919050565b6000602082840312156200498a57600080fd5b62003ee48262004960565b600082601f830112620049a757600080fd5b8151620049b86200406582620040b7565b818152846020838601011115620049ce57600080fd5b62001dc882602083016020870162003f05565b600060208284031215620049f457600080fd5b81516001600160401b038082111562004a0c57600080fd5b908301906060828603121562004a2157600080fd5b62004a2b62003fbc565b82518281111562004a3b57600080fd5b62004a498782860162004995565b8252506020830151602082015260408301518281111562004a6957600080fd5b620049258782860162004995565b60006020828403121562004a8a57600080fd5b815162003ee4816200458a565b601f82111562000c06576000816000526020600020601f850160051c8101602086101562004ac25750805b601f850160051c820191505b81811015620026725782815560010162004ace565b81516001600160401b0381111562004aff5762004aff62003fa6565b62004b178162004b10845462004713565b8462004a97565b602080601f83116001811462004b4f576000841562004b365750858301515b600019600386901b1c1916600185901b17855562002672565b600085815260208120601f198616915b8281101562004b805788860151825594840194600190910190840162004b5f565b508582101562004b9f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000825162004bc381846020870162003f05565b9190910192915050565b60006020828403121562004be057600080fd5b81516001600160401b0381111562004bf757600080fd5b62001dc88482850162004995565b60006020828403121562004c1857600080fd5b5051919050565b60608152600062004c34606083018662003f2b565b828103602084015262004c48818662003f2b565b91505060ff83166040830152949350505050565b60006001820162004c715762004c7162004934565b5060010190565b6001600160401b038716815285602082015284604082015260c06060820152600062004ca860c083018662003f2b565b828103608084015262004cbc818662003f2b565b91505060ff831660a0830152979650505050505050565b60208152600082516060602084015262004cf1608084018262003f2b565b9050602084015160408401526040840151601f19848303016060850152620047e1828262003f2b565b81810381811115620009ab57620009ab62004934565b6001600160a01b0386811682528516602082015260a06040820181905260009062004d5e9083018662004360565b828103606084015262004d72818662004360565b9050828103608084015262004d88818562003f2b565b98975050505050505050565b60006020828403121562004da757600080fd5b815162003ee48162003ead565b60008060008060008060c0878903121562004dce57600080fd5b86516001600160401b03808216821462004de757600080fd5b602089015160408a015160608b015193995090975095508082111562004e0c57600080fd5b62004e1a8a838b0162004995565b9450608089015191508082111562004e3157600080fd5b5062004e4089828a0162004995565b92505062004e5160a0880162004960565b90509295509295509295565b6001600160a01b03868116825285166020820152604081018490526060810183905260a06080820181905260009062004e999083018462003f2b565b979650505050505050565b6000806040838503121562004eb857600080fd5b62004ec38362004960565b915060208301516001600160401b0381111562004edf57600080fd5b620043568582860162004995565b6000806040838503121562004f0157600080fd5b8251915060208301516001600160401b0381111562004edf57600080fd5b60018060a01b038616815260ff8516602082015283604082015260a06060820152600062004f5160a083018562003f2b565b828103608084015262004d88818562003f2b56fe60c06040523480156200001157600080fd5b5060405162000c4c38038062000c4c833981016040819052620000349162000131565b8282600362000044838262000247565b50600462000053828262000247565b5050336080525060ff1660a05250620003139050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200009157600080fd5b81516001600160401b0380821115620000ae57620000ae62000069565b604051601f8301601f19908116603f01168101908282118183101715620000d957620000d962000069565b8160405283815260209250866020858801011115620000f757600080fd5b600091505b838210156200011b5785820183015181830184015290820190620000fc565b6000602085830101528094505050505092915050565b6000806000606084860312156200014757600080fd5b83516001600160401b03808211156200015f57600080fd5b6200016d878388016200007f565b945060208601519150808211156200018457600080fd5b5062000193868287016200007f565b925050604084015160ff81168114620001ab57600080fd5b809150509250925092565b600181811c90821680620001cb57607f821691505b602082108103620001ec57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000242576000816000526020600020601f850160051c810160208610156200021d5750805b601f850160051c820191505b818110156200023e5782815560010162000229565b5050505b505050565b81516001600160401b0381111562000263576200026362000069565b6200027b81620002748454620001b6565b84620001f2565b602080601f831160018114620002b357600084156200029a5750858301515b600019600386901b1c1916600185901b1785556200023e565b600085815260208120601f198616915b82811015620002e457888601518255948401946001909101908401620002c3565b5085821015620003035787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a0516109056200034760003960006101260152600081816101930152818161030f015261038301526109056000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c806370a082311161007157806370a0823114610165578063906d34db1461018e57806395d89b41146101cd578063a9059cbb146101d5578063dd62ed3e146101e8578063f6b911bc1461022157600080fd5b806306fdde03146100b9578063095ea7b3146100d757806318160ddd146100fa57806323b872dd1461010c578063313ce5671461011f57806340c10f1914610150575b600080fd5b6100c1610234565b6040516100ce919061074e565b60405180910390f35b6100ea6100e53660046107b9565b6102c6565b60405190151581526020016100ce565b6002545b6040519081526020016100ce565b6100ea61011a3660046107e3565b6102e0565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100ce565b61016361015e3660046107b9565b610304565b005b6100fe61017336600461081f565b6001600160a01b031660009081526020819052604090205490565b6101b57f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100ce565b6100c161035b565b6100ea6101e33660046107b9565b61036a565b6100fe6101f6366004610841565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b61016361022f3660046107e3565b610378565b60606003805461024390610874565b80601f016020809104026020016040519081016040528092919081815260200182805461026f90610874565b80156102bc5780601f10610291576101008083540402835291602001916102bc565b820191906000526020600020905b81548152906001019060200180831161029f57829003601f168201915b5050505050905090565b6000336102d48185856103f4565b60019150505b92915050565b6000336102ee858285610401565b6102f9858585610484565b506001949350505050565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461034d57604051630f3e00e560e41b815260040160405180910390fd5b61035782826104e3565b5050565b60606004805461024390610874565b6000336102d4818585610484565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103c157604051630f3e00e560e41b815260040160405180910390fd5b816001600160a01b0316836001600160a01b0316146103e5576103e5838383610401565b6103ef8382610519565b505050565b6103ef838383600161054f565b6001600160a01b03838116600090815260016020908152604080832093861683529290522054600019811461047e578181101561046f57604051637dc7a0d960e11b81526001600160a01b038416600482015260248101829052604481018390526064015b60405180910390fd5b61047e8484848403600061054f565b50505050565b6001600160a01b0383166104ae57604051634b637e8f60e11b815260006004820152602401610466565b6001600160a01b0382166104d85760405163ec442f0560e01b815260006004820152602401610466565b6103ef838383610624565b6001600160a01b03821661050d5760405163ec442f0560e01b815260006004820152602401610466565b61035760008383610624565b6001600160a01b03821661054357604051634b637e8f60e11b815260006004820152602401610466565b61035782600083610624565b6001600160a01b0384166105795760405163e602df0560e01b815260006004820152602401610466565b6001600160a01b0383166105a357604051634a1406b160e11b815260006004820152602401610466565b6001600160a01b038085166000908152600160209081526040808320938716835292905220829055801561047e57826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161061691815260200190565b60405180910390a350505050565b6001600160a01b03831661064f57806002600082825461064491906108ae565b909155506106c19050565b6001600160a01b038316600090815260208190526040902054818110156106a25760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401610466565b6001600160a01b03841660009081526020819052604090209082900390555b6001600160a01b0382166106dd576002805482900390556106fc565b6001600160a01b03821660009081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161074191815260200190565b60405180910390a3505050565b60006020808352835180602085015260005b8181101561077c57858101830151858201604001528201610760565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b03811681146107b457600080fd5b919050565b600080604083850312156107cc57600080fd5b6107d58361079d565b946020939093013593505050565b6000806000606084860312156107f857600080fd5b6108018461079d565b925061080f6020850161079d565b9150604084013590509250925092565b60006020828403121561083157600080fd5b61083a8261079d565b9392505050565b6000806040838503121561085457600080fd5b61085d8361079d565b915061086b6020840161079d565b90509250929050565b600181811c9082168061088857607f821691505b6020821081036108a857634e487b7160e01b600052602260045260246000fd5b50919050565b808201808211156102da57634e487b7160e01b600052601160045260246000fdfea2646970667358221220db917e99493fa2fa6a4547fc1b43871a3bb0974af926415a8e75c68fde7cba2464736f6c634300081700333a2f5529773e03d975be44bdae98a8509bdf1159e407504e558536cde56cf6aca26469706673582212200ed00da5d4127c44efbf778d8cb7b188c25ebe54ec8b7dea2a073097d6ddf09364736f6c63430008170033

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

000000000000000000000000000000000000000000000000000000000000008000000000000000000000000017a332dc7b40ae701485023b219e9d6f493a251400000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000006c68747470733a2f2f697066732d676174657761792e7375706572666f726d2e78797a2f69706e732f6b3531717a693575717535646739306671646f396a36336d353536776c6464657578346d6c67797974687033307a6f7573676833687568797a6f757971382f4a534f4e2f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5375706572506f736974696f6e7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025350000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : dynamicURI_ (string): https://ipfs-gateway.superform.xyz/ipns/k51qzi5uqu5dg90fqdo9j63m556wlddeux4mlgyythp30zousgh3huhyzouyq8/JSON/
Arg [1] : superRegistry_ (address): 0x17A332dC7B40aE701485023b219E9D6f493a2514
Arg [2] : name_ (string): SuperPositions
Arg [3] : symbol_ (string): SP

-----Encoded View---------------
13 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [1] : 00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a2514
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000120
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [4] : 000000000000000000000000000000000000000000000000000000000000006c
Arg [5] : 68747470733a2f2f697066732d676174657761792e7375706572666f726d2e78
Arg [6] : 797a2f69706e732f6b3531717a693575717535646739306671646f396a36336d
Arg [7] : 353536776c6464657578346d6c67797974687033307a6f757367683368756879
Arg [8] : 7a6f757971382f4a534f4e2f0000000000000000000000000000000000000000
Arg [9] : 000000000000000000000000000000000000000000000000000000000000000e
Arg [10] : 5375706572506f736974696f6e73000000000000000000000000000000000000
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [12] : 5350000000000000000000000000000000000000000000000000000000000000


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.