creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/common/AccessControl.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity 0.8.13;\n\nimport \"./Ownable.sol\";\n\n/**\n * @title AccessControl\n * @dev This abstract contract implements access control mechanism based on roles.\n * Each role can have one or more addresses associated with it, which are granted\n * permission to execute functions with the onlyRole modifier.\n */\nabstract contract AccessControl is Ownable {\n    /**\n     * @dev A mapping of roles to a mapping of addresses to boolean values indicating whether or not they have the role.\n     */\n    mapping(bytes32 => mapping(address => bool)) private _permits;\n\n    /**\n     * @dev Emitted when a role is granted to an address.\n     */\n    event RoleGranted(bytes32 indexed role, address indexed grantee);\n\n    /**\n     * @dev Emitted when a role is revoked from an address.\n     */\n    event RoleRevoked(bytes32 indexed role, address indexed revokee);\n\n    /**\n     * @dev Error message thrown when an address does not have permission to execute a function with onlyRole modifier.\n     */\n    error NoPermit(bytes32 role);\n\n    /**\n     * @dev Constructor that sets the owner of the contract.\n     */\n    constructor(address owner_) Ownable(owner_) {}\n\n    /**\n     * @dev Modifier that restricts access to addresses having roles\n     * Throws an error if the caller do not have permit\n     */\n    modifier onlyRole(bytes32 role) {\n        if (!_permits[role][msg.sender]) revert NoPermit(role);\n        _;\n    }\n\n    /**\n     * @dev Checks and reverts if an address do not have a specific role.\n     * @param role_ The role to check.\n     * @param address_ The address to check.\n     */\n    function _checkRole(bytes32 role_, address address_) internal virtual {\n        if (!_hasRole(role_, address_)) revert NoPermit(role_);\n    }\n\n    /**\n     * @dev Grants a role to a given address.\n     * @param role_ The role to grant.\n     * @param grantee_ The address to grant the role to.\n     * Emits a RoleGranted event.\n     * Can only be called by the owner of the contract.\n     */\n    function grantRole(\n        bytes32 role_,\n        address grantee_\n    ) external virtual onlyOwner {\n        _grantRole(role_, grantee_);\n    }\n\n    /**\n     * @dev Revokes a role from a given address.\n     * @param role_ The role to revoke.\n     * @param revokee_ The address to revoke the role from.\n     * Emits a RoleRevoked event.\n     * Can only be called by the owner of the contract.\n     */\n    function revokeRole(\n        bytes32 role_,\n        address revokee_\n    ) external virtual onlyOwner {\n        _revokeRole(role_, revokee_);\n    }\n\n    /**\n     * @dev Internal function to grant a role to a given address.\n     * @param role_ The role to grant.\n     * @param grantee_ The address to grant the role to.\n     * Emits a RoleGranted event.\n     */\n    function _grantRole(bytes32 role_, address grantee_) internal {\n        _permits[role_][grantee_] = true;\n        emit RoleGranted(role_, grantee_);\n    }\n\n    /**\n     * @dev Internal function to revoke a role from a given address.\n     * @param role_ The role to revoke.\n     * @param revokee_ The address to revoke the role from.\n     * Emits a RoleRevoked event.\n     */\n    function _revokeRole(bytes32 role_, address revokee_) internal {\n        _permits[role_][revokee_] = false;\n        emit RoleRevoked(role_, revokee_);\n    }\n\n    /**\n     * @dev Checks whether an address has a specific role.\n     * @param role_ The role to check.\n     * @param address_ The address to check.\n     * @return A boolean value indicating whether or not the address has the role.\n     */\n    function hasRole(\n        bytes32 role_,\n        address address_\n    ) external view returns (bool) {\n        return _hasRole(role_, address_);\n    }\n\n    function _hasRole(\n        bytes32 role_,\n        address address_\n    ) internal view returns (bool) {\n        return _permits[role_][address_];\n    }\n}\n"
      },
      "contracts/common/Gauge.sol": {
        "content": "pragma solidity 0.8.13;\n\nabstract contract Gauge {\n    struct LimitParams {\n        uint256 lastUpdateTimestamp;\n        uint256 ratePerSecond;\n        uint256 maxLimit;\n        uint256 lastUpdateLimit;\n    }\n\n    error AmountOutsideLimit();\n\n    function _getCurrentLimit(\n        LimitParams storage _params\n    ) internal view returns (uint256 _limit) {\n        uint256 timeElapsed = block.timestamp - _params.lastUpdateTimestamp;\n        uint256 limitIncrease = timeElapsed * _params.ratePerSecond;\n\n        if (limitIncrease + _params.lastUpdateLimit > _params.maxLimit) {\n            _limit = _params.maxLimit;\n        } else {\n            _limit = limitIncrease + _params.lastUpdateLimit;\n        }\n    }\n\n    function _consumePartLimit(\n        uint256 amount_,\n        LimitParams storage _params\n    ) internal returns (uint256 consumedAmount, uint256 pendingAmount) {\n        uint256 currentLimit = _getCurrentLimit(_params);\n        _params.lastUpdateTimestamp = block.timestamp;\n        if (currentLimit >= amount_) {\n            _params.lastUpdateLimit = currentLimit - amount_;\n            consumedAmount = amount_;\n            pendingAmount = 0;\n        } else {\n            _params.lastUpdateLimit = 0;\n            consumedAmount = currentLimit;\n            pendingAmount = amount_ - currentLimit;\n        }\n    }\n\n    function _consumeFullLimit(\n        uint256 amount_,\n        LimitParams storage _params\n    ) internal {\n        uint256 currentLimit = _getCurrentLimit(_params);\n        if (currentLimit >= amount_) {\n            _params.lastUpdateTimestamp = block.timestamp;\n            _params.lastUpdateLimit = currentLimit - amount_;\n        } else {\n            revert AmountOutsideLimit();\n        }\n    }\n}\n"
      },
      "contracts/common/Ownable.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity 0.8.13;\n\n/**\n * @title Ownable\n * @dev The Ownable contract provides a simple way to manage ownership of a contract\n * and allows for ownership to be transferred to a nominated address.\n */\nabstract contract Ownable {\n    address private _owner;\n    address private _nominee;\n\n    event OwnerNominated(address indexed nominee);\n    event OwnerClaimed(address indexed claimer);\n\n    error OnlyOwner();\n    error OnlyNominee();\n\n    /**\n     * @dev Sets the contract's owner to the address that is passed to the constructor.\n     */\n    constructor(address owner_) {\n        _claimOwner(owner_);\n    }\n\n    /**\n     * @dev Modifier that restricts access to only the contract's owner.\n     * Throws an error if the caller is not the owner.\n     */\n    modifier onlyOwner() {\n        if (msg.sender != _owner) revert OnlyOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the current owner of the contract.\n     */\n    function owner() external view returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Returns the current nominee for ownership of the contract.\n     */\n    function nominee() external view returns (address) {\n        return _nominee;\n    }\n\n    /**\n     * @dev Allows the current owner to nominate a new owner for the contract.\n     * Throws an error if the caller is not the owner.\n     * Emits an `OwnerNominated` event with the address of the nominee.\n     */\n    function nominateOwner(address nominee_) external {\n        if (msg.sender != _owner) revert OnlyOwner();\n        _nominee = nominee_;\n        emit OwnerNominated(_nominee);\n    }\n\n    /**\n     * @dev Allows the nominated owner to claim ownership of the contract.\n     * Throws an error if the caller is not the nominee.\n     * Sets the nominated owner as the new owner of the contract.\n     * Emits an `OwnerClaimed` event with the address of the new owner.\n     */\n    function claimOwner() external {\n        if (msg.sender != _nominee) revert OnlyNominee();\n        _claimOwner(msg.sender);\n    }\n\n    /**\n     * @dev Internal function that sets the owner of the contract to the specified address\n     * and sets the nominee to address(0).\n     */\n    function _claimOwner(address claimer_) internal {\n        _owner = claimer_;\n        _nominee = address(0);\n        emit OwnerClaimed(claimer_);\n    }\n}\n"
      },
      "contracts/interfaces/IPlug.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity 0.8.13;\n\n/**\n * @title IPlug\n * @notice Interface for a plug contract that executes the message received from a source chain.\n */\ninterface IPlug {\n    /**\n     * @dev this should be only executable by socket\n     * @notice executes the message received from source chain\n     * @notice It is expected to have original sender checks in the destination plugs using payload\n     * @param srcChainSlug_ chain slug of source\n     * @param payload_ the data which is needed by plug at inbound call on remote\n     */\n    function inbound(\n        uint32 srcChainSlug_,\n        bytes calldata payload_\n    ) external payable;\n}\n"
      },
      "contracts/interfaces/ISocket.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity 0.8.13;\n\n/**\n * @title ISocket\n * @notice An interface for a cross-chain communication contract\n * @dev This interface provides methods for transmitting and executing messages between chains,\n * connecting a plug to a remote chain and setting up switchboards for the message transmission\n * This interface also emits events for important operations such as message transmission, execution status,\n * and plug connection\n */\ninterface ISocket {\n    /**\n     * @notice A struct containing fees required for message transmission and execution\n     * @param transmissionFees fees needed for transmission\n     * @param switchboardFees fees needed by switchboard\n     * @param executionFee fees needed for execution\n     */\n    struct Fees {\n        uint128 transmissionFees;\n        uint128 executionFee;\n        uint128 switchboardFees;\n    }\n\n    /**\n     * @title MessageDetails\n     * @dev This struct defines the details of a message to be executed in a Decapacitor contract.\n     */\n    struct MessageDetails {\n        // A unique identifier for the message.\n        bytes32 msgId;\n        // The fee to be paid for executing the message.\n        uint256 executionFee;\n        // The maximum amount of gas that can be used to execute the message.\n        uint256 minMsgGasLimit;\n        // The extra params which provides msg value and additional info needed for message exec\n        bytes32 executionParams;\n        // The payload data to be executed in the message.\n        bytes payload;\n    }\n\n    /**\n     * @title ExecutionDetails\n     * @dev This struct defines the execution details\n     */\n    struct ExecutionDetails {\n        // packet id\n        bytes32 packetId;\n        // proposal count\n        uint256 proposalCount;\n        // gas limit needed to execute inbound\n        uint256 executionGasLimit;\n        // proof data required by the Decapacitor contract to verify the message's authenticity\n        bytes decapacitorProof;\n        // signature of executor\n        bytes signature;\n    }\n\n    /**\n     * @notice emits the message details when a new message arrives at outbound\n     * @param localChainSlug local chain slug\n     * @param localPlug local plug address\n     * @param dstChainSlug remote chain slug\n     * @param dstPlug remote plug address\n     * @param msgId message id packed with remoteChainSlug and nonce\n     * @param minMsgGasLimit gas limit needed to execute the inbound at remote\n     * @param payload the data which will be used by inbound at remote\n     */\n    event MessageOutbound(\n        uint32 localChainSlug,\n        address localPlug,\n        uint32 dstChainSlug,\n        address dstPlug,\n        bytes32 msgId,\n        uint256 minMsgGasLimit,\n        bytes32 executionParams,\n        bytes32 transmissionParams,\n        bytes payload,\n        Fees fees\n    );\n\n    /**\n     * @notice emits the status of message after inbound call\n     * @param msgId msg id which is executed\n     */\n    event ExecutionSuccess(bytes32 msgId);\n\n    /**\n     * @notice emits the config set by a plug for a remoteChainSlug\n     * @param plug address of plug on current chain\n     * @param siblingChainSlug sibling chain slug\n     * @param siblingPlug address of plug on sibling chain\n     * @param inboundSwitchboard inbound switchboard (select from registered options)\n     * @param outboundSwitchboard outbound switchboard (select from registered options)\n     * @param capacitor capacitor selected based on outbound switchboard\n     * @param decapacitor decapacitor selected based on inbound switchboard\n     */\n    event PlugConnected(\n        address plug,\n        uint32 siblingChainSlug,\n        address siblingPlug,\n        address inboundSwitchboard,\n        address outboundSwitchboard,\n        address capacitor,\n        address decapacitor\n    );\n\n    /**\n     * @notice registers a message\n     * @dev Packs the message and includes it in a packet with capacitor\n     * @param remoteChainSlug_ the remote chain slug\n     * @param minMsgGasLimit_ the gas limit needed to execute the payload on remote\n     * @param payload_ the data which is needed by plug at inbound call on remote\n     */\n    function outbound(\n        uint32 remoteChainSlug_,\n        uint256 minMsgGasLimit_,\n        bytes32 executionParams_,\n        bytes32 transmissionParams_,\n        bytes memory payload_\n    ) external payable returns (bytes32 msgId);\n\n    /**\n     * @notice executes a message\n     * @param executionDetails_ the packet details, proof and signature needed for message execution\n     * @param messageDetails_ the message details\n     */\n    function execute(\n        ISocket.ExecutionDetails calldata executionDetails_,\n        ISocket.MessageDetails calldata messageDetails_\n    ) external payable;\n\n    /**\n     * @notice sets the config specific to the plug\n     * @param siblingChainSlug_ the sibling chain slug\n     * @param siblingPlug_ address of plug present at sibling chain to call inbound\n     * @param inboundSwitchboard_ the address of switchboard to use for receiving messages\n     * @param outboundSwitchboard_ the address of switchboard to use for sending messages\n     */\n    function connect(\n        uint32 siblingChainSlug_,\n        address siblingPlug_,\n        address inboundSwitchboard_,\n        address outboundSwitchboard_\n    ) external;\n\n    /**\n     * @notice Retrieves the minimum fees required for a message with a specified gas limit and destination chain.\n     * @param minMsgGasLimit_ The gas limit of the message.\n     * @param remoteChainSlug_ The slug of the destination chain for the message.\n     * @param plug_ The address of the plug through which the message is sent.\n     * @return totalFees The minimum fees required for the specified message.\n     */\n    function getMinFees(\n        uint256 minMsgGasLimit_,\n        uint256 payloadSize_,\n        bytes32 executionParams_,\n        bytes32 transmissionParams_,\n        uint32 remoteChainSlug_,\n        address plug_\n    ) external view returns (uint256 totalFees);\n\n    /**\n     * @notice returns chain slug\n     * @return chainSlug current chain slug\n     */\n    function chainSlug() external view returns (uint32 chainSlug);\n\n    function globalMessageCount() external view returns (uint64);\n\n    /**\n     * @notice returns the config for given `plugAddress_` and `siblingChainSlug_`\n     * @param siblingChainSlug_ the sibling chain slug\n     * @param plugAddress_ address of plug present at current chain\n     */\n    function getPlugConfig(\n        address plugAddress_,\n        uint32 siblingChainSlug_\n    )\n        external\n        view\n        returns (\n            address siblingPlug,\n            address inboundSwitchboard__,\n            address outboundSwitchboard__,\n            address capacitor__,\n            address decapacitor__\n        );\n}\n"
      },
      "contracts/libraries/ExcessivelySafeCall.sol": {
        "content": "// SPDX-License-Identifier: MIT OR Apache-2.0\npragma solidity 0.8.13;\n\nlibrary ExcessivelySafeCall {\n    uint constant LOW_28_MASK =\n        0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff;\n\n    /// @notice Use when you _really_ really _really_ don't trust the called\n    /// contract. This prevents the called contract from causing reversion of\n    /// the caller in as many ways as we can.\n    /// @dev The main difference between this and a solidity low-level call is\n    /// that we limit the number of bytes that the callee can cause to be\n    /// copied to caller memory. This prevents stupid things like malicious\n    /// contracts returning 10,000,000 bytes causing a local OOG when copying\n    /// to memory.\n    /// @param _target The address to call\n    /// @param _gas The amount of gas to forward to the remote contract\n    /// @param _maxCopy The maximum number of bytes of returndata to copy\n    /// to memory.\n    /// @param _calldata The data to send to the remote contract\n    /// @return success and returndata, as `.call()`. Returndata is capped to\n    /// `_maxCopy` bytes.\n    function excessivelySafeCall(\n        address _target,\n        uint _gas,\n        uint16 _maxCopy,\n        bytes memory _calldata\n    ) internal returns (bool, bytes memory) {\n        // set up for assembly call\n        uint _toCopy;\n        bool _success;\n        bytes memory _returnData = new bytes(_maxCopy);\n        // dispatch message to recipient\n        // by assembly calling \"handle\" function\n        // we call via assembly to avoid memcopying a very large returndata\n        // returned by a malicious contract\n        assembly {\n            _success := call(\n                _gas, // gas\n                _target, // recipient\n                0, // ether value\n                add(_calldata, 0x20), // inloc\n                mload(_calldata), // inlen\n                0, // outloc\n                0 // outlen\n            )\n            // limit our copy to 256 bytes\n            _toCopy := returndatasize()\n            if gt(_toCopy, _maxCopy) {\n                _toCopy := _maxCopy\n            }\n            // Store the length of the copied bytes\n            mstore(_returnData, _toCopy)\n            // copy the bytes from returndata[0:_toCopy]\n            returndatacopy(add(_returnData, 0x20), 0, _toCopy)\n        }\n        return (_success, _returnData);\n    }\n\n    /// @notice Use when you _really_ really _really_ don't trust the called\n    /// contract. This prevents the called contract from causing reversion of\n    /// the caller in as many ways as we can.\n    /// @dev The main difference between this and a solidity low-level call is\n    /// that we limit the number of bytes that the callee can cause to be\n    /// copied to caller memory. This prevents stupid things like malicious\n    /// contracts returning 10,000,000 bytes causing a local OOG when copying\n    /// to memory.\n    /// @param _target The address to call\n    /// @param _gas The amount of gas to forward to the remote contract\n    /// @param _maxCopy The maximum number of bytes of returndata to copy\n    /// to memory.\n    /// @param _calldata The data to send to the remote contract\n    /// @return success and returndata, as `.call()`. Returndata is capped to\n    /// `_maxCopy` bytes.\n    function excessivelySafeStaticCall(\n        address _target,\n        uint _gas,\n        uint16 _maxCopy,\n        bytes memory _calldata\n    ) internal view returns (bool, bytes memory) {\n        // set up for assembly call\n        uint _toCopy;\n        bool _success;\n        bytes memory _returnData = new bytes(_maxCopy);\n        // dispatch message to recipient\n        // by assembly calling \"handle\" function\n        // we call via assembly to avoid memcopying a very large returndata\n        // returned by a malicious contract\n        assembly {\n            _success := staticcall(\n                _gas, // gas\n                _target, // recipient\n                add(_calldata, 0x20), // inloc\n                mload(_calldata), // inlen\n                0, // outloc\n                0 // outlen\n            )\n            // limit our copy to 256 bytes\n            _toCopy := returndatasize()\n            if gt(_toCopy, _maxCopy) {\n                _toCopy := _maxCopy\n            }\n            // Store the length of the copied bytes\n            mstore(_returnData, _toCopy)\n            // copy the bytes from returndata[0:_toCopy]\n            returndatacopy(add(_returnData, 0x20), 0, _toCopy)\n        }\n        return (_success, _returnData);\n    }\n\n    /**\n     * @notice Swaps function selectors in encoded contract calls\n     * @dev Allows reuse of encoded calldata for functions with identical\n     * argument types but different names. It simply swaps out the first 4 bytes\n     * for the new selector. This function modifies memory in place, and should\n     * only be used with caution.\n     * @param _newSelector The new 4-byte selector\n     * @param _buf The encoded contract args\n     */\n    function swapSelector(\n        bytes4 _newSelector,\n        bytes memory _buf\n    ) internal pure {\n        require(_buf.length >= 4);\n        uint _mask = LOW_28_MASK;\n        assembly {\n            // load the first word of\n            let _word := mload(add(_buf, 0x20))\n            // mask out the top 4 bytes\n            // /x\n            _word := and(_word, _mask)\n            _word := or(_newSelector, _word)\n            mstore(add(_buf, 0x20), _word)\n        }\n    }\n}\n"
      },
      "contracts/libraries/RescueFundsLib.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity 0.8.13;\n\nimport \"lib/solmate/src/utils/SafeTransferLib.sol\";\n\nerror ZeroAddress();\n\n/**\n * @title RescueFundsLib\n * @dev A library that provides a function to rescue funds from a contract.\n */\n\nlibrary RescueFundsLib {\n    /**\n     * @dev The address used to identify ETH.\n     */\n    address public constant ETH_ADDRESS =\n        address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);\n\n    /**\n     * @dev thrown when the given token address don't have any code\n     */\n    error InvalidTokenAddress();\n\n    /**\n     * @dev Rescues funds from a contract.\n     * @param token_ The address of the token contract.\n     * @param rescueTo_ The address of the user.\n     * @param amount_ The amount of tokens to be rescued.\n     */\n    function rescueFunds(\n        address token_,\n        address rescueTo_,\n        uint256 amount_\n    ) internal {\n        if (rescueTo_ == address(0)) revert ZeroAddress();\n\n        if (token_ == ETH_ADDRESS) {\n            SafeTransferLib.safeTransferETH(rescueTo_, amount_);\n        } else {\n            if (token_.code.length == 0) revert InvalidTokenAddress();\n            SafeTransferLib.safeTransfer(ERC20(token_), rescueTo_, amount_);\n        }\n    }\n}\n"
      },
      "contracts/superbridge/ConnectorPlug.sol": {
        "content": "pragma solidity 0.8.13;\n\nimport \"../common/Ownable.sol\";\nimport {ISocket} from \"../interfaces/ISocket.sol\";\nimport {IPlug} from \"../interfaces/IPlug.sol\";\nimport {RescueFundsLib} from \"../libraries/RescueFundsLib.sol\";\n\ninterface IHub {\n    function receiveInbound(bytes memory payload_) external;\n}\n\ninterface IConnector {\n    function outbound(\n        uint256 msgGasLimit_,\n        bytes memory payload_\n    ) external payable;\n\n    function siblingChainSlug() external view returns (uint32);\n\n    function getMinFees(\n        uint256 msgGasLimit_\n    ) external view returns (uint256 totalFees);\n}\n\ncontract ConnectorPlug is IConnector, IPlug, Ownable {\n    IHub public immutable hub__;\n    ISocket public immutable socket__;\n    uint32 public immutable siblingChainSlug;\n\n    error NotHub();\n    error NotSocket();\n\n    event ConnectorPlugDisconnected();\n\n    constructor(\n        address hub_,\n        address socket_,\n        uint32 siblingChainSlug_\n    ) Ownable(msg.sender) {\n        hub__ = IHub(hub_);\n        socket__ = ISocket(socket_);\n        siblingChainSlug = siblingChainSlug_;\n    }\n\n    function outbound(\n        uint256 msgGasLimit_,\n        bytes memory payload_\n    ) external payable override {\n        if (msg.sender != address(hub__)) revert NotHub();\n\n        socket__.outbound{value: msg.value}(\n            siblingChainSlug,\n            msgGasLimit_,\n            bytes32(0),\n            bytes32(0),\n            payload_\n        );\n    }\n\n    function inbound(\n        uint32 /* siblingChainSlug_ */, // cannot be connected for any other slug, immutable variable\n        bytes calldata payload_\n    ) external payable override {\n        if (msg.sender != address(socket__)) revert NotSocket();\n        hub__.receiveInbound(payload_);\n    }\n\n    function getMinFees(\n        uint256 msgGasLimit_\n    ) external view override returns (uint256 totalFees) {\n        return\n            socket__.getMinFees(\n                msgGasLimit_,\n                64,\n                bytes32(0),\n                bytes32(0),\n                siblingChainSlug,\n                address(this)\n            );\n    }\n\n    function connect(\n        address siblingPlug_,\n        address switchboard_\n    ) external onlyOwner {\n        socket__.connect(\n            siblingChainSlug,\n            siblingPlug_,\n            switchboard_,\n            switchboard_\n        );\n    }\n\n    function disconnect() external onlyOwner {\n        (\n            ,\n            address inboundSwitchboard,\n            address outboundSwitchboard,\n            ,\n\n        ) = socket__.getPlugConfig(address(this), siblingChainSlug);\n\n        socket__.connect(\n            siblingChainSlug,\n            address(0),\n            inboundSwitchboard,\n            outboundSwitchboard\n        );\n\n        emit ConnectorPlugDisconnected();\n    }\n\n    /**\n     * @notice Rescues funds from the contract if they are locked by mistake.\n     * @param token_ The address of the token contract.\n     * @param rescueTo_ The address where rescued tokens need to be sent.\n     * @param amount_ The amount of tokens to be rescued.\n     */\n    function rescueFunds(\n        address token_,\n        address rescueTo_,\n        uint256 amount_\n    ) external onlyOwner {\n        RescueFundsLib.rescueFunds(token_, rescueTo_, amount_);\n    }\n}\n"
      },
      "contracts/superbridge/Controller.sol": {
        "content": "pragma solidity 0.8.13;\n\nimport {IExchangeRate} from \"./ExchangeRate.sol\";\nimport {Ownable} from \"../common/Ownable.sol\";\nimport {Gauge} from \"../common/Gauge.sol\";\nimport {IConnector, IHub} from \"./ConnectorPlug.sol\";\nimport {IMintableERC20} from \"./IMintableERC20.sol\";\nimport {RescueFundsLib} from \"../libraries/RescueFundsLib.sol\";\n\ncontract Controller is IHub, Gauge, Ownable(msg.sender) {\n    IMintableERC20 public immutable token__;\n    IExchangeRate public exchangeRate__;\n\n    struct UpdateLimitParams {\n        bool isMint;\n        address connector;\n        uint256 maxLimit;\n        uint256 ratePerSecond;\n    }\n\n    // connectorPoolId => totalLockedAmount\n    mapping(uint256 => uint256) public poolLockedAmounts;\n\n    // connector => connectorPoolId\n    mapping(address => uint256) public connectorPoolIds;\n\n    // connector => mintLimitParams\n    mapping(address => LimitParams) _mintLimitParams;\n\n    // connector => burnLimitParams\n    mapping(address => LimitParams) _burnLimitParams;\n\n    // connector => receiver => amount\n    mapping(address => mapping(address => uint256)) public pendingMints;\n\n    // connector => amount\n    mapping(address => uint256) public connectorPendingMints;\n\n    uint256 public totalMinted;\n\n    error ConnectorUnavailable();\n    error InvalidPoolId();\n    error ZeroAmount();\n    event ExchangeRateUpdated(address exchangeRate);\n    event ConnectorPoolIdUpdated(address connector, uint256 poolId);\n    event LimitParamsUpdated(UpdateLimitParams[] updates);\n    event TokensWithdrawn(\n        address connector,\n        address withdrawer,\n        address receiver,\n        uint256 burnAmount\n    );\n    event PendingTokensMinted(\n        address connector,\n        address receiver,\n        uint256 mintAmount,\n        uint256 pendingAmount\n    );\n    event TokensPending(\n        address connecter,\n        address receiver,\n        uint256 pendingAmount,\n        uint256 totalPendingAmount\n    );\n    event TokensMinted(address connecter, address receiver, uint256 mintAmount);\n\n    constructor(address token_, address exchangeRate_) {\n        token__ = IMintableERC20(token_);\n        exchangeRate__ = IExchangeRate(exchangeRate_);\n    }\n\n    function updateExchangeRate(address exchangeRate_) external onlyOwner {\n        exchangeRate__ = IExchangeRate(exchangeRate_);\n        emit ExchangeRateUpdated(exchangeRate_);\n    }\n\n    function updateConnectorPoolId(\n        address[] calldata connectors,\n        uint256[] calldata poolIds\n    ) external onlyOwner {\n        uint256 length = connectors.length;\n        for (uint256 i; i < length; i++) {\n            if (poolIds[i] == 0) revert InvalidPoolId();\n            connectorPoolIds[connectors[i]] = poolIds[i];\n            emit ConnectorPoolIdUpdated(connectors[i], poolIds[i]);\n        }\n    }\n\n    function updateLimitParams(\n        UpdateLimitParams[] calldata updates_\n    ) external onlyOwner {\n        for (uint256 i; i < updates_.length; i++) {\n            if (updates_[i].isMint) {\n                _consumePartLimit(0, _mintLimitParams[updates_[i].connector]); // to keep current limit in sync\n                _mintLimitParams[updates_[i].connector].maxLimit = updates_[i]\n                    .maxLimit;\n                _mintLimitParams[updates_[i].connector]\n                    .ratePerSecond = updates_[i].ratePerSecond;\n            } else {\n                _consumePartLimit(0, _burnLimitParams[updates_[i].connector]); // to keep current limit in sync\n                _burnLimitParams[updates_[i].connector].maxLimit = updates_[i]\n                    .maxLimit;\n                _burnLimitParams[updates_[i].connector]\n                    .ratePerSecond = updates_[i].ratePerSecond;\n            }\n        }\n\n        emit LimitParamsUpdated(updates_);\n    }\n\n    // do we throttle burn amount or unlock amount? burn for now\n    function withdrawFromAppChain(\n        address receiver_,\n        uint256 burnAmount_,\n        uint256 msgGasLimit_,\n        address connector_\n    ) external payable {\n        if (burnAmount_ == 0) revert ZeroAmount();\n\n        if (_burnLimitParams[connector_].maxLimit == 0)\n            revert ConnectorUnavailable();\n\n        _consumeFullLimit(burnAmount_, _burnLimitParams[connector_]); // reverts on limit hit\n\n        totalMinted -= burnAmount_;\n        _burn(msg.sender, burnAmount_);\n\n        uint256 connectorPoolId = connectorPoolIds[connector_];\n        if (connectorPoolId == 0) revert InvalidPoolId();\n        uint256 unlockAmount = exchangeRate__.getUnlockAmount(\n            burnAmount_,\n            poolLockedAmounts[connectorPoolId]\n        );\n        poolLockedAmounts[connectorPoolId] -= unlockAmount; // underflow revert expected\n\n        IConnector(connector_).outbound{value: msg.value}(\n            msgGasLimit_,\n            abi.encode(receiver_, unlockAmount)\n        );\n\n        emit TokensWithdrawn(connector_, msg.sender, receiver_, burnAmount_);\n    }\n\n    function _burn(address user_, uint256 burnAmount_) internal virtual {\n        token__.burn(user_, burnAmount_);\n    }\n\n    function mintPendingFor(address receiver_, address connector_) external {\n        if (_mintLimitParams[connector_].maxLimit == 0)\n            revert ConnectorUnavailable();\n\n        uint256 pendingMint = pendingMints[connector_][receiver_];\n        (uint256 consumedAmount, uint256 pendingAmount) = _consumePartLimit(\n            pendingMint,\n            _mintLimitParams[connector_]\n        );\n\n        pendingMints[connector_][receiver_] = pendingAmount;\n        connectorPendingMints[connector_] -= consumedAmount;\n        totalMinted += consumedAmount;\n\n        token__.mint(receiver_, consumedAmount);\n\n        emit PendingTokensMinted(\n            connector_,\n            receiver_,\n            consumedAmount,\n            pendingAmount\n        );\n    }\n\n    // receive inbound assuming connector called\n    function receiveInbound(bytes memory payload_) external override {\n        if (_mintLimitParams[msg.sender].maxLimit == 0)\n            revert ConnectorUnavailable();\n\n        (address receiver, uint256 lockAmount) = abi.decode(\n            payload_,\n            (address, uint256)\n        );\n        uint256 connectorPoolId = connectorPoolIds[msg.sender];\n        if (connectorPoolId == 0) revert InvalidPoolId();\n        poolLockedAmounts[connectorPoolId] += lockAmount;\n\n        uint256 mintAmount = exchangeRate__.getMintAmount(\n            lockAmount,\n            poolLockedAmounts[connectorPoolId]\n        );\n        (uint256 consumedAmount, uint256 pendingAmount) = _consumePartLimit(\n            mintAmount,\n            _mintLimitParams[msg.sender]\n        );\n\n        if (pendingAmount > 0) {\n            // add instead of overwrite to handle case where already pending amount is left\n            pendingMints[msg.sender][receiver] += pendingAmount;\n            connectorPendingMints[msg.sender] += pendingAmount;\n            emit TokensPending(\n                msg.sender,\n                receiver,\n                pendingAmount,\n                pendingMints[msg.sender][receiver]\n            );\n        }\n\n        totalMinted += consumedAmount;\n        token__.mint(receiver, consumedAmount);\n\n        emit TokensMinted(msg.sender, receiver, consumedAmount);\n    }\n\n    function getMinFees(\n        address connector_,\n        uint256 msgGasLimit_\n    ) external view returns (uint256 totalFees) {\n        return IConnector(connector_).getMinFees(msgGasLimit_);\n    }\n\n    function getCurrentMintLimit(\n        address connector_\n    ) external view returns (uint256) {\n        return _getCurrentLimit(_mintLimitParams[connector_]);\n    }\n\n    function getCurrentBurnLimit(\n        address connector_\n    ) external view returns (uint256) {\n        return _getCurrentLimit(_burnLimitParams[connector_]);\n    }\n\n    function getMintLimitParams(\n        address connector_\n    ) external view returns (LimitParams memory) {\n        return _mintLimitParams[connector_];\n    }\n\n    function getBurnLimitParams(\n        address connector_\n    ) external view returns (LimitParams memory) {\n        return _burnLimitParams[connector_];\n    }\n\n    /**\n     * @notice Rescues funds from the contract if they are locked by mistake.\n     * @param token_ The address of the token contract.\n     * @param rescueTo_ The address where rescued tokens need to be sent.\n     * @param amount_ The amount of tokens to be rescued.\n     */\n    function rescueFunds(\n        address token_,\n        address rescueTo_,\n        uint256 amount_\n    ) external onlyOwner {\n        RescueFundsLib.rescueFunds(token_, rescueTo_, amount_);\n    }\n}\n"
      },
      "contracts/superbridge/ExchangeRate.sol": {
        "content": "pragma solidity 0.8.13;\n\nimport \"../common/Ownable.sol\";\nimport {RescueFundsLib} from \"../libraries/RescueFundsLib.sol\";\n\ninterface IExchangeRate {\n    // not marked pure, may involve state interactions in future\n    function getMintAmount(\n        uint256 lockAmount,\n        uint256 totalLockedAmount\n    ) external returns (uint256 mintAmount);\n\n    // not marked pure, may involve state interactions in future\n    function getUnlockAmount(\n        uint256 burnAmount,\n        uint256 totalLockedAmount\n    ) external returns (uint256 unlockAmount);\n}\n\ncontract ExchangeRate is IExchangeRate, Ownable(msg.sender) {\n    // chainId input needed? what else? slippage?\n    function getMintAmount(\n        uint256 lockAmount,\n        uint256 /* totalLockedAmount */\n    ) external pure returns (uint256 mintAmount) {\n        return lockAmount;\n    }\n\n    function getUnlockAmount(\n        uint256 burnAmount,\n        uint256 /* totalLockedAmount */\n    ) external pure returns (uint256 unlockAmount) {\n        return burnAmount;\n    }\n\n    /**\n     * @notice Rescues funds from the contract if they are locked by mistake.\n     * @param token_ The address of the token contract.\n     * @param rescueTo_ The address where rescued tokens need to be sent.\n     * @param amount_ The amount of tokens to be rescued.\n     */\n    function rescueFunds(\n        address token_,\n        address rescueTo_,\n        uint256 amount_\n    ) external onlyOwner {\n        RescueFundsLib.rescueFunds(token_, rescueTo_, amount_);\n    }\n}\n"
      },
      "contracts/superbridge/FiatTokenV2_1/FiatTokenV2_1_Controller.sol": {
        "content": "pragma solidity 0.8.13;\n\nimport \"lib/solmate/src/utils/SafeTransferLib.sol\";\nimport {Controller} from \"../Controller.sol\";\nimport {IMintableERC20} from \"../IMintableERC20.sol\";\nimport {IFiatTokenV2_1_Mintable} from \"./IFiatTokenV2_1_Mintable.sol\";\n\ncontract FiatTokenV2_1_Controller is Controller {\n    using SafeTransferLib for IMintableERC20;\n\n    constructor(\n        address token_,\n        address exchangeRate_\n    ) Controller(token_, exchangeRate_) {}\n\n    function _burn(address user_, uint256 burnAmount_) internal override {\n        token__.safeTransferFrom(user_, address(this), burnAmount_);\n        IFiatTokenV2_1_Mintable(address(token__)).burn(burnAmount_);\n    }\n}\n"
      },
      "contracts/superbridge/FiatTokenV2_1/IFiatTokenV2_1_Mintable.sol": {
        "content": "pragma solidity 0.8.13;\n\nimport \"lib/solmate/src/tokens/ERC20.sol\";\n\n// USDC's standard token\nabstract contract IFiatTokenV2_1_Mintable is ERC20 {\n    function mint(address receiver_, uint256 amount_) external virtual;\n\n    function burn(uint256 _amount) external virtual;\n}\n"
      },
      "contracts/superbridge/IMintableERC20.sol": {
        "content": "pragma solidity 0.8.13;\n\nimport \"lib/solmate/src/tokens/ERC20.sol\";\n\nabstract contract IMintableERC20 is ERC20 {\n    function mint(address receiver_, uint256 amount_) external virtual;\n\n    function burn(address burner_, uint256 amount_) external virtual;\n}\n"
      },
      "contracts/superbridge/Vault.sol": {
        "content": "pragma solidity 0.8.13;\n\nimport \"lib/solmate/src/utils/SafeTransferLib.sol\";\nimport \"../common/Ownable.sol\";\nimport {Gauge} from \"../common/Gauge.sol\";\nimport {IConnector, IHub} from \"./ConnectorPlug.sol\";\nimport {RescueFundsLib} from \"../libraries/RescueFundsLib.sol\";\n\n// @todo: separate our connecter plugs\ncontract Vault is Gauge, IHub, Ownable(msg.sender) {\n    using SafeTransferLib for ERC20;\n    ERC20 public immutable token__;\n\n    struct UpdateLimitParams {\n        bool isLock;\n        address connector;\n        uint256 maxLimit;\n        uint256 ratePerSecond;\n    }\n\n    // connector => receiver => pendingUnlock\n    mapping(address => mapping(address => uint256)) public pendingUnlocks;\n\n    // connector => amount\n    mapping(address => uint256) public connectorPendingUnlocks;\n\n    // connector => lockLimitParams\n    mapping(address => LimitParams) _lockLimitParams;\n\n    // connector => unlockLimitParams\n    mapping(address => LimitParams) _unlockLimitParams;\n\n    error ConnectorUnavailable();\n    error ZeroAmount();\n\n    event LimitParamsUpdated(UpdateLimitParams[] updates);\n    event TokensDeposited(\n        address connector,\n        address depositor,\n        address receiver,\n        uint256 depositAmount\n    );\n    event PendingTokensTransferred(\n        address connector,\n        address receiver,\n        uint256 unlockedAmount,\n        uint256 pendingAmount\n    );\n    event TokensPending(\n        address connector,\n        address receiver,\n        uint256 pendingAmount,\n        uint256 totalPendingAmount\n    );\n    event TokensUnlocked(\n        address connector,\n        address receiver,\n        uint256 unlockedAmount\n    );\n\n    constructor(address token_) {\n        token__ = ERC20(token_);\n    }\n\n    function updateLimitParams(\n        UpdateLimitParams[] calldata updates_\n    ) external onlyOwner {\n        for (uint256 i; i < updates_.length; i++) {\n            if (updates_[i].isLock) {\n                _consumePartLimit(0, _lockLimitParams[updates_[i].connector]); // to keep current limit in sync\n                _lockLimitParams[updates_[i].connector].maxLimit = updates_[i]\n                    .maxLimit;\n                _lockLimitParams[updates_[i].connector]\n                    .ratePerSecond = updates_[i].ratePerSecond;\n            } else {\n                _consumePartLimit(0, _unlockLimitParams[updates_[i].connector]); // to keep current limit in sync\n                _unlockLimitParams[updates_[i].connector].maxLimit = updates_[i]\n                    .maxLimit;\n                _unlockLimitParams[updates_[i].connector]\n                    .ratePerSecond = updates_[i].ratePerSecond;\n            }\n        }\n\n        emit LimitParamsUpdated(updates_);\n    }\n\n    function depositToAppChain(\n        address receiver_,\n        uint256 amount_,\n        uint256 msgGasLimit_,\n        address connector_\n    ) external payable {\n        if (amount_ == 0) revert ZeroAmount();\n\n        if (_lockLimitParams[connector_].maxLimit == 0)\n            revert ConnectorUnavailable();\n\n        _consumeFullLimit(amount_, _lockLimitParams[connector_]); // reverts on limit hit\n\n        token__.safeTransferFrom(msg.sender, address(this), amount_);\n\n        IConnector(connector_).outbound{value: msg.value}(\n            msgGasLimit_,\n            abi.encode(receiver_, amount_)\n        );\n\n        emit TokensDeposited(connector_, msg.sender, receiver_, amount_);\n    }\n\n    function unlockPendingFor(address receiver_, address connector_) external {\n        if (_unlockLimitParams[connector_].maxLimit == 0)\n            revert ConnectorUnavailable();\n\n        uint256 pendingUnlock = pendingUnlocks[connector_][receiver_];\n        (uint256 consumedAmount, uint256 pendingAmount) = _consumePartLimit(\n            pendingUnlock,\n            _unlockLimitParams[connector_]\n        );\n\n        pendingUnlocks[connector_][receiver_] = pendingAmount;\n        connectorPendingUnlocks[connector_] -= consumedAmount;\n\n        token__.safeTransfer(receiver_, consumedAmount);\n\n        emit PendingTokensTransferred(\n            connector_,\n            receiver_,\n            consumedAmount,\n            pendingAmount\n        );\n    }\n\n    // receive inbound assuming connector called\n    function receiveInbound(bytes memory payload_) external override {\n        if (_unlockLimitParams[msg.sender].maxLimit == 0)\n            revert ConnectorUnavailable();\n\n        (address receiver, uint256 unlockAmount) = abi.decode(\n            payload_,\n            (address, uint256)\n        );\n\n        (uint256 consumedAmount, uint256 pendingAmount) = _consumePartLimit(\n            unlockAmount,\n            _unlockLimitParams[msg.sender]\n        );\n\n        if (pendingAmount > 0) {\n            // add instead of overwrite to handle case where already pending amount is left\n            pendingUnlocks[msg.sender][receiver] += pendingAmount;\n            connectorPendingUnlocks[msg.sender] += pendingAmount;\n            emit TokensPending(\n                msg.sender,\n                receiver,\n                pendingAmount,\n                pendingUnlocks[msg.sender][receiver]\n            );\n        }\n        token__.safeTransfer(receiver, consumedAmount);\n\n        emit TokensUnlocked(msg.sender, receiver, consumedAmount);\n    }\n\n    function getMinFees(\n        address connector_,\n        uint256 msgGasLimit_\n    ) external view returns (uint256 totalFees) {\n        return IConnector(connector_).getMinFees(msgGasLimit_);\n    }\n\n    function getCurrentLockLimit(\n        address connector_\n    ) external view returns (uint256) {\n        return _getCurrentLimit(_lockLimitParams[connector_]);\n    }\n\n    function getCurrentUnlockLimit(\n        address connector_\n    ) external view returns (uint256) {\n        return _getCurrentLimit(_unlockLimitParams[connector_]);\n    }\n\n    function getLockLimitParams(\n        address connector_\n    ) external view returns (LimitParams memory) {\n        return _lockLimitParams[connector_];\n    }\n\n    function getUnlockLimitParams(\n        address connector_\n    ) external view returns (LimitParams memory) {\n        return _unlockLimitParams[connector_];\n    }\n\n    /**\n     * @notice Rescues funds from the contract if they are locked by mistake.\n     * @param token_ The address of the token contract.\n     * @param rescueTo_ The address where rescued tokens need to be sent.\n     * @param amount_ The amount of tokens to be rescued.\n     */\n    function rescueFunds(\n        address token_,\n        address rescueTo_,\n        uint256 amount_\n    ) external onlyOwner {\n        RescueFundsLib.rescueFunds(token_, rescueTo_, amount_);\n    }\n}\n"
      },
      "contracts/supertoken/Execute.sol": {
        "content": "pragma solidity 0.8.13;\n\nimport \"lib/solmate/src/utils/ReentrancyGuard.sol\";\nimport \"../libraries/ExcessivelySafeCall.sol\";\n\n/**\n * @title Execute\n * @notice It enables payload execution and contains relevant storages.\n * @dev This contract implements Socket's IPlug to enable message bridging and IMessageBridge\n * to support any type of message bridge.\n */\ncontract Execute is ReentrancyGuard {\n    using ExcessivelySafeCall for address;\n\n    /**\n     * @notice this struct stores relevant details for a pending payload execution\n     * @param receiver address of receiver where payload executes.\n     * @param siblingChainSlug the unique identifier of the source chain.\n     * @param payload payload to be executed\n     * @param isAmountPending if amount to be bridged is pending\n     */\n    struct PendingExecutionDetails {\n        address receiver;\n        uint32 siblingChainSlug;\n        bytes payload;\n        bool isAmountPending;\n    }\n\n    uint16 private constant MAX_COPY_BYTES = 150;\n    // messageId => PendingExecutionDetails\n    mapping(bytes32 => PendingExecutionDetails) public pendingExecutions;\n\n    ////////////////////////////////////////////////////////\n    ////////////////////// ERRORS //////////////////////////\n    ////////////////////////////////////////////////////////\n\n    error InvalidExecutionRetry();\n    error PendingAmount();\n    error CannotExecuteOnBridgeContracts();\n\n    /**\n     * @notice this function can be used to retry a payload execution if it was not successful.\n     * @param msgId_ The unique identifier of the bridging message.\n     */\n    function retryPayloadExecution(bytes32 msgId_) external nonReentrant {\n        PendingExecutionDetails storage details = pendingExecutions[msgId_];\n        if (details.isAmountPending) revert PendingAmount();\n\n        if (details.receiver == address(0)) revert InvalidExecutionRetry();\n        bool success = _execute(details.receiver, details.payload);\n\n        if (success) _clearPayload(msgId_);\n    }\n\n    /**\n     * @notice this function is used to execute a payload at receiver\n     * @dev receiver address cannot be bridge address or this contract address.\n     * @param target_ address of target.\n     * @param payload_ payload to be executed at target.\n     */\n    function _execute(\n        address target_,\n        bytes memory payload_\n    ) internal returns (bool success) {\n        (success, ) = target_.excessivelySafeCall(\n            gasleft(),\n            MAX_COPY_BYTES,\n            payload_\n        );\n    }\n\n    /**\n     * @notice this function caches the execution payload details if the amount to be bridged\n     * is not pending or execution is reverting\n     */\n    function _cachePayload(\n        bytes32 msgId_,\n        uint32 siblingChainSlug_,\n        bool isAmountPending_,\n        address receiver_,\n        bytes memory payload_\n    ) internal {\n        pendingExecutions[msgId_].receiver = receiver_;\n        pendingExecutions[msgId_].siblingChainSlug = siblingChainSlug_;\n        pendingExecutions[msgId_].payload = payload_;\n        pendingExecutions[msgId_].isAmountPending = isAmountPending_;\n    }\n\n    /**\n     * @notice this function clears the payload details once execution succeeds\n     */\n    function _clearPayload(bytes32 msgId_) internal {\n        pendingExecutions[msgId_].receiver = address(0);\n        pendingExecutions[msgId_].siblingChainSlug = 0;\n        pendingExecutions[msgId_].payload = bytes(\"\");\n        pendingExecutions[msgId_].isAmountPending = false;\n    }\n}\n"
      },
      "contracts/supertoken/IMessageBridge.sol": {
        "content": "pragma solidity 0.8.13;\n\n/**\n * @title IMessageBridge\n * @notice It should be implemented by message bridge integrated to Super token and Vault.\n */\ninterface IMessageBridge {\n    /**\n     * @notice calls socket's outbound function which transmits msg to `siblingChainSlug_`.\n     * @dev Only super token or vault can call this contract\n     * @param siblingChainSlug_ The unique identifier of the sibling chain.\n     * @param msgGasLimit_ min gas limit needed to execute the message on sibling\n     * @param payload_ payload which should be executed at the sibling chain.\n     * @param options_ extra bytes memory can be used by other protocol plugs for additional options\n     */\n    function outbound(\n        uint32 siblingChainSlug_,\n        uint256 msgGasLimit_,\n        bytes memory payload_,\n        bytes memory options_\n    ) external payable returns (bytes32 messageId_);\n\n    /**\n     * @notice this function is used to calculate message id before sending outbound().\n     * @param siblingChainSlug_ The unique identifier of the sibling chain.\n     * @return message id\n     */\n    function getMessageId(\n        uint32 siblingChainSlug_\n    ) external view returns (bytes32);\n}\n"
      },
      "contracts/supertoken/ISuperTokenOrVault.sol": {
        "content": "pragma solidity 0.8.13;\n\n/**\n * @title ISuperTokenOrVault\n * @notice It should be implemented Super token and Vault for plugs to communicate.\n */\ninterface ISuperTokenOrVault {\n    /**\n     * @dev this should be only executable by socket.\n     * @notice executes the message received from source chain.\n     * @notice It is expected to have original sender checks in the destination plugs using payload.\n     * @param siblingChainSlug_ chain slug of source.\n     * @param payload_ the data which is needed to decode receiver, amount, msgId and payload.\n     */\n    function inbound(\n        uint32 siblingChainSlug_,\n        bytes memory payload_\n    ) external payable;\n}\n"
      },
      "contracts/supertoken/plugs/SocketPlug.sol": {
        "content": "pragma solidity 0.8.13;\n\nimport {ISocket} from \"../../interfaces/ISocket.sol\";\nimport {IPlug} from \"../../interfaces/IPlug.sol\";\nimport {AccessControl} from \"../../common/AccessControl.sol\";\nimport {RescueFundsLib} from \"../../libraries/RescueFundsLib.sol\";\nimport {IMessageBridge} from \"./../IMessageBridge.sol\";\nimport {ISuperTokenOrVault} from \"./../ISuperTokenOrVault.sol\";\n\n/**\n * @title SocketPlug\n * @notice It enables message bridging in Super token and Super Token Vault.\n * @dev This contract implements Socket's IPlug to enable message bridging and IMessageBridge\n * to support any type of message bridge.\n */\ncontract SocketPlug is IPlug, AccessControl, IMessageBridge {\n    bytes32 constant RESCUE_ROLE = keccak256(\"RESCUE_ROLE\");\n\n    // socket address\n    ISocket public immutable socket__;\n    // super token or vault address\n    ISuperTokenOrVault public tokenOrVault__;\n\n    // chain slug of current chain\n    uint32 public immutable chainSlug;\n\n    // map of sibling chain slugs with the plug addresses\n    mapping(uint32 => address) public siblingPlugs;\n\n    ////////////////////////////////////////////////////////\n    ////////////////////// EVENTS //////////////////////////\n    ////////////////////////////////////////////////////////\n\n    // emitted when a plug is disconnected\n    event SocketPlugDisconnected(uint32 siblingChainSlug);\n    // emitted when a super token or vault address is set\n    event SuperTokenOrVaultSet();\n\n    ////////////////////////////////////////////////////////\n    ////////////////////// ERRORS //////////////////////////\n    ////////////////////////////////////////////////////////\n\n    error NotSuperTokenOrVault();\n    error NotSocket();\n    error TokenOrVaultAlreadySet();\n\n    /**\n     * @notice constructor for creating a new SocketPlug.\n     * @param socket_ The address of the Socket contract used to transmit messages.\n     * @param owner_ The address of the owner who has the initial admin role.\n     * @param chainSlug_ The unique identifier of the chain this plug is deployed on.\n     */\n    constructor(\n        address socket_,\n        address owner_,\n        uint32 chainSlug_\n    ) AccessControl(owner_) {\n        socket__ = ISocket(socket_);\n        chainSlug = chainSlug_;\n    }\n\n    /**\n     * @notice calls socket's outbound function which transmits msg to `siblingChainSlug_`.\n     * @dev Only super token or vault can call this function\n     * @param siblingChainSlug_ The unique identifier of the sibling chain.\n     * @param msgGasLimit_ min gas limit needed to execute the message on sibling\n     * @param payload_ payload which should be executed at the sibling chain.\n     * @return messageId_ identifier used to get message details from Socket.\n     */\n    function outbound(\n        uint32 siblingChainSlug_,\n        uint256 msgGasLimit_,\n        bytes memory payload_,\n        bytes memory\n    ) external payable returns (bytes32 messageId_) {\n        if (msg.sender != address(tokenOrVault__))\n            revert NotSuperTokenOrVault();\n\n        return\n            socket__.outbound{value: msg.value}(\n                siblingChainSlug_,\n                msgGasLimit_,\n                bytes32(0),\n                bytes32(0),\n                payload_\n            );\n    }\n\n    /**\n     * @notice this function receives the message from sibling chain.\n     * @dev Only socket can call this function.\n     * @param siblingChainSlug_ The unique identifier of the sibling chain.\n     * @param payload_ payload which should be executed at the super token or vault.\n     */\n    function inbound(\n        uint32 siblingChainSlug_,\n        bytes memory payload_\n    ) external payable override {\n        if (msg.sender != address(socket__)) revert NotSocket();\n        tokenOrVault__.inbound(siblingChainSlug_, payload_);\n    }\n\n    /**\n     * @notice this function calculates the fees needed to send the message to Socket.\n     * @param siblingChainSlug_ The unique identifier of the sibling chain.\n     * @param msgGasLimit_ min gas limit needed at destination chain to execute the message.\n     */\n    function getMinFees(\n        uint32 siblingChainSlug_,\n        uint256 msgGasLimit_\n    ) external view returns (uint256 totalFees) {\n        return\n            socket__.getMinFees(\n                msgGasLimit_,\n                96,\n                bytes32(0),\n                bytes32(0),\n                siblingChainSlug_,\n                address(this)\n            );\n    }\n\n    /**\n     * @notice this function is used to set the Super token or Vault address\n     * @dev only owner can set the token address.\n     * @dev this can be called only once.\n     * @param tokenOrVault_ The super token or vault address connected to this plug.\n     */\n    function setSuperTokenOrVault(address tokenOrVault_) external onlyOwner {\n        if (address(tokenOrVault__) != address(0))\n            revert TokenOrVaultAlreadySet();\n        tokenOrVault__ = ISuperTokenOrVault(tokenOrVault_);\n        emit SuperTokenOrVaultSet();\n    }\n\n    /**\n     * @notice this function is used to connect Socket for a `siblingChainSlug_`.\n     * @dev only owner can connect Socket with preferred switchboard address.\n     * @param siblingChainSlug_ The unique identifier of the sibling chain.\n     * @param siblingPlug_ address of plug present at siblingChainSlug_ to call at inbound\n     * @param inboundSwitchboard_ the address of switchboard to use for verifying messages at inbound\n     * @param outboundSwitchboard_ the address of switchboard to use for sending messages\n     */\n    function connect(\n        uint32 siblingChainSlug_,\n        address siblingPlug_,\n        address inboundSwitchboard_,\n        address outboundSwitchboard_\n    ) external onlyOwner {\n        siblingPlugs[siblingChainSlug_] = siblingPlug_;\n\n        socket__.connect(\n            siblingChainSlug_,\n            siblingPlug_,\n            inboundSwitchboard_,\n            outboundSwitchboard_\n        );\n    }\n\n    /**\n     * @notice this function is used to disconnect Socket for a `siblingChainSlug_`.\n     * @dev only owner can disconnect Socket\n     * @dev it sets sibling plug as address(0) which makes it revert at `outbound()` hence\n     * @dev stopping it from sending any message.\n     * @param siblingChainSlug_ The unique identifier of the sibling chain.\n     */\n    function disconnect(uint32 siblingChainSlug_) external onlyOwner {\n        (\n            ,\n            address inboundSwitchboard,\n            address outboundSwitchboard,\n            ,\n\n        ) = socket__.getPlugConfig(address(this), siblingChainSlug_);\n\n        socket__.connect(\n            siblingChainSlug_,\n            address(0),\n            inboundSwitchboard,\n            outboundSwitchboard\n        );\n\n        emit SocketPlugDisconnected(siblingChainSlug_);\n    }\n\n    /**\n     * @notice this function is used to calculate message id before sending outbound().\n     * @param siblingChainSlug_ The unique identifier of the sibling chain.\n     * @return message id\n     */\n    function getMessageId(\n        uint32 siblingChainSlug_\n    ) public view returns (bytes32) {\n        return\n            bytes32(\n                (uint256(chainSlug) << 224) |\n                    (uint256(uint160(siblingPlugs[siblingChainSlug_])) << 64) |\n                    (ISocket(socket__).globalMessageCount())\n            );\n    }\n\n    /**\n     * @notice Rescues funds from the contract if they are locked by mistake.\n     * @param token_ The address of the token contract.\n     * @param rescueTo_ The address where rescued tokens need to be sent.\n     * @param amount_ The amount of tokens to be rescued.\n     */\n    function rescueFunds(\n        address token_,\n        address rescueTo_,\n        uint256 amount_\n    ) external onlyRole(RESCUE_ROLE) {\n        RescueFundsLib.rescueFunds(token_, rescueTo_, amount_);\n    }\n}\n"
      },
      "contracts/supertoken/SuperToken.sol": {
        "content": "pragma solidity 0.8.13;\n\nimport \"lib/solmate/src/tokens/ERC20.sol\";\n\nimport {AccessControl} from \"../common/AccessControl.sol\";\nimport {Gauge} from \"../common/Gauge.sol\";\nimport {RescueFundsLib} from \"../libraries/RescueFundsLib.sol\";\n\nimport \"./Execute.sol\";\nimport \"./IMessageBridge.sol\";\nimport \"./ISuperTokenOrVault.sol\";\n\n/**\n * @title SuperToken\n * @notice An ERC20 contract which enables bridging a token to its sibling chains.\n * @dev This contract implements ISuperTokenOrVault to support message bridging through IMessageBridge compliant contracts.\n */\ncontract SuperToken is\n    ERC20,\n    Gauge,\n    ISuperTokenOrVault,\n    AccessControl,\n    Execute\n{\n    struct UpdateLimitParams {\n        bool isMint;\n        uint32 siblingChainSlug;\n        uint256 maxLimit;\n        uint256 ratePerSecond;\n    }\n\n    bytes32 constant RESCUE_ROLE = keccak256(\"RESCUE_ROLE\");\n    bytes32 constant LIMIT_UPDATER_ROLE = keccak256(\"LIMIT_UPDATER_ROLE\");\n\n    // bridge contract address which provides AMB support\n    IMessageBridge public bridge__;\n\n    // siblingChainSlug => mintLimitParams\n    mapping(uint32 => LimitParams) _receivingLimitParams;\n\n    // siblingChainSlug => burnLimitParams\n    mapping(uint32 => LimitParams) _sendingLimitParams;\n\n    // siblingChainSlug => receiver => identifier => amount\n    mapping(uint32 => mapping(address => mapping(bytes32 => uint256)))\n        public pendingMints;\n\n    // siblingChainSlug => amount\n    mapping(uint32 => uint256) public siblingPendingMints;\n\n    ////////////////////////////////////////////////////////\n    ////////////////////// ERRORS //////////////////////////\n    ////////////////////////////////////////////////////////\n\n    error SiblingNotSupported();\n    error MessageIdMisMatched();\n    error ZeroAmount();\n    error NotMessageBridge();\n\n    ////////////////////////////////////////////////////////\n    ////////////////////// EVENTS //////////////////////////\n    ////////////////////////////////////////////////////////\n\n    // emitted when limit params are updated\n    event LimitParamsUpdated(UpdateLimitParams[] updates);\n    // emitted when message bridge is updated\n    event MessageBridgeUpdated(address newBridge);\n    // emitted at source when tokens are bridged to a sibling chain\n    event BridgeTokens(\n        uint32 siblingChainSlug,\n        address withdrawer,\n        address receiver,\n        uint256 bridgedAmount,\n        bytes32 identifier\n    );\n    // emitted when pending tokens are minted to the receiver\n    event PendingTokensBridged(\n        uint32 siblingChainSlug,\n        address receiver,\n        uint256 mintAmount,\n        uint256 pendingAmount,\n        bytes32 identifier\n    );\n    // emitted when transfer reaches limit and token mint is added to pending queue\n    event TokensPending(\n        uint32 siblingChainSlug,\n        address receiver,\n        uint256 pendingAmount,\n        uint256 totalPendingAmount,\n        bytes32 identifier\n    );\n    // emitted when pending tokens are minted as limits are replenished\n    event TokensBridged(\n        uint32 siblingChainSlug,\n        address receiver,\n        uint256 mintAmount,\n        uint256 totalAmount,\n        bytes32 identifier\n    );\n\n    /**\n     * @notice constructor for creating a new SuperToken.\n     * @param name_ token name\n     * @param symbol_ token symbol\n     * @param decimals_ token decimals (should be same on all chains)\n     * @param initialSupplyHolder_ address to which initial supply will be minted\n     * @param owner_ owner of this contract\n     * @param initialSupply_ initial supply of super token\n     * @param bridge_ message bridge address\n     */\n    constructor(\n        string memory name_,\n        string memory symbol_,\n        uint8 decimals_,\n        address initialSupplyHolder_,\n        address owner_,\n        uint256 initialSupply_,\n        address bridge_\n    ) ERC20(name_, symbol_, decimals_) AccessControl(owner_) {\n        _mint(initialSupplyHolder_, initialSupply_);\n        bridge__ = IMessageBridge(bridge_);\n    }\n\n    /**\n     * @notice this function is used to update message bridge\n     * @dev it can only be updated by owner\n     * @dev should be carefully migrated as it can risk user funds\n     * @param bridge_ new bridge address\n     */\n    function updateMessageBridge(address bridge_) external onlyOwner {\n        bridge__ = IMessageBridge(bridge_);\n        emit MessageBridgeUpdated(bridge_);\n    }\n\n    /**\n     * @notice this function is used to set bridge limits\n     * @dev it can only be updated by owner\n     * @param updates_ can be used to set mint and burn limits for all siblings in one call.\n     */\n    function updateLimitParams(\n        UpdateLimitParams[] calldata updates_\n    ) external onlyRole(LIMIT_UPDATER_ROLE) {\n        for (uint256 i; i < updates_.length; i++) {\n            if (updates_[i].isMint) {\n                _consumePartLimit(\n                    0,\n                    _receivingLimitParams[updates_[i].siblingChainSlug]\n                ); // to keep current limit in sync\n                _receivingLimitParams[updates_[i].siblingChainSlug]\n                    .maxLimit = updates_[i].maxLimit;\n                _receivingLimitParams[updates_[i].siblingChainSlug]\n                    .ratePerSecond = updates_[i].ratePerSecond;\n            } else {\n                _consumePartLimit(\n                    0,\n                    _sendingLimitParams[updates_[i].siblingChainSlug]\n                ); // to keep current limit in sync\n                _sendingLimitParams[updates_[i].siblingChainSlug]\n                    .maxLimit = updates_[i].maxLimit;\n                _sendingLimitParams[updates_[i].siblingChainSlug]\n                    .ratePerSecond = updates_[i].ratePerSecond;\n            }\n        }\n\n        emit LimitParamsUpdated(updates_);\n    }\n\n    /**\n     * @notice this function is called by users to bridge their funds to a sibling chain\n     * @dev it is payable to receive message bridge fees to be paid.\n     * @param receiver_ address receiving bridged tokens\n     * @param siblingChainSlug_ The unique identifier of the sibling chain.\n     * @param sendingAmount_ amount bridged\n     * @param msgGasLimit_ min gas limit needed for execution at destination\n     * @param payload_ payload which is executed at destination with bridged amount at receiver address.\n     * @param options_ additional message bridge options can be provided using this param\n     */\n    function bridge(\n        address receiver_,\n        uint32 siblingChainSlug_,\n        uint256 sendingAmount_,\n        uint256 msgGasLimit_,\n        bytes calldata payload_,\n        bytes calldata options_\n    ) external payable {\n        if (_sendingLimitParams[siblingChainSlug_].maxLimit == 0)\n            revert SiblingNotSupported();\n\n        if (sendingAmount_ == 0) revert ZeroAmount();\n\n        _consumeFullLimit(\n            sendingAmount_,\n            _sendingLimitParams[siblingChainSlug_]\n        ); // reverts on limit hit\n        _burn(msg.sender, sendingAmount_);\n\n        bytes32 messageId = bridge__.getMessageId(siblingChainSlug_);\n\n        // important to get message id as it is used as an\n        // identifier for pending amount and payload caching\n        bytes32 returnedMessageId = bridge__.outbound{value: msg.value}(\n            siblingChainSlug_,\n            msgGasLimit_,\n            abi.encode(receiver_, sendingAmount_, messageId, payload_),\n            options_\n        );\n\n        if (returnedMessageId != messageId) revert MessageIdMisMatched();\n        emit BridgeTokens(\n            siblingChainSlug_,\n            msg.sender,\n            receiver_,\n            sendingAmount_,\n            messageId\n        );\n    }\n\n    /**\n     * @notice this function can be used to mint funds which were in pending state due to limits\n     * @param receiver_ address receiving bridged tokens\n     * @param siblingChainSlug_ The unique identifier of the sibling chain.\n     * @param identifier_ message identifier where message was received to mint funds\n     */\n    function mintPendingFor(\n        address receiver_,\n        uint32 siblingChainSlug_,\n        bytes32 identifier_\n    ) external nonReentrant {\n        if (_receivingLimitParams[siblingChainSlug_].maxLimit == 0)\n            revert SiblingNotSupported();\n\n        uint256 pendingMint = pendingMints[siblingChainSlug_][receiver_][\n            identifier_\n        ];\n        (uint256 consumedAmount, uint256 pendingAmount) = _consumePartLimit(\n            pendingMint,\n            _receivingLimitParams[siblingChainSlug_]\n        );\n\n        pendingMints[siblingChainSlug_][receiver_][identifier_] = pendingAmount;\n        siblingPendingMints[siblingChainSlug_] -= consumedAmount;\n\n        _mint(receiver_, consumedAmount);\n\n        if (\n            pendingAmount == 0 &&\n            pendingExecutions[identifier_].receiver != address(0)\n        ) {\n            // execute\n            pendingExecutions[identifier_].isAmountPending = false;\n            bool success = _execute(\n                receiver_,\n                pendingExecutions[identifier_].payload\n            );\n            if (success) _clearPayload(identifier_);\n        }\n\n        emit PendingTokensBridged(\n            siblingChainSlug_,\n            receiver_,\n            consumedAmount,\n            pendingAmount,\n            identifier_\n        );\n    }\n\n    /**\n     * @notice this function receives the message from message bridge\n     * @dev Only bridge can call this function.\n     * @param siblingChainSlug_ The unique identifier of the sibling chain.\n     * @param payload_ payload which is decoded to get `receiver`, `amount to mint`, `message id` and `payload` to execute after token transfer.\n     */\n    function inbound(\n        uint32 siblingChainSlug_,\n        bytes memory payload_\n    ) external payable override nonReentrant {\n        if (msg.sender != address(bridge__)) revert NotMessageBridge();\n\n        if (_receivingLimitParams[siblingChainSlug_].maxLimit == 0)\n            revert SiblingNotSupported();\n\n        (\n            address receiver,\n            uint256 mintAmount,\n            bytes32 identifier,\n            bytes memory execPayload\n        ) = abi.decode(payload_, (address, uint256, bytes32, bytes));\n\n        (uint256 consumedAmount, uint256 pendingAmount) = _consumePartLimit(\n            mintAmount,\n            _receivingLimitParams[siblingChainSlug_]\n        );\n\n        if (receiver == address(this) || receiver == address(bridge__))\n            revert CannotExecuteOnBridgeContracts();\n\n        _mint(receiver, consumedAmount);\n\n        if (pendingAmount > 0) {\n            pendingMints[siblingChainSlug_][receiver][\n                identifier\n            ] = pendingAmount;\n            siblingPendingMints[siblingChainSlug_] += pendingAmount;\n\n            // if pending amount is more than 0, payload is cached\n            if (execPayload.length > 0)\n                _cachePayload(\n                    identifier,\n                    siblingChainSlug_,\n                    true,\n                    receiver,\n                    execPayload\n                );\n\n            emit TokensPending(\n                siblingChainSlug_,\n                receiver,\n                pendingAmount,\n                pendingMints[siblingChainSlug_][receiver][identifier],\n                identifier\n            );\n        } else if (execPayload.length > 0) {\n            // execute\n            bool success = _execute(receiver, execPayload);\n\n            if (!success)\n                _cachePayload(\n                    identifier,\n                    siblingChainSlug_,\n                    false,\n                    receiver,\n                    execPayload\n                );\n        }\n\n        emit TokensBridged(\n            siblingChainSlug_,\n            receiver,\n            consumedAmount,\n            mintAmount,\n            identifier\n        );\n    }\n\n    function getCurrentReceivingLimit(\n        uint32 siblingChainSlug_\n    ) external view returns (uint256) {\n        return _getCurrentLimit(_receivingLimitParams[siblingChainSlug_]);\n    }\n\n    function getCurrentSendingLimit(\n        uint32 siblingChainSlug_\n    ) external view returns (uint256) {\n        return _getCurrentLimit(_sendingLimitParams[siblingChainSlug_]);\n    }\n\n    function getReceivingLimitParams(\n        uint32 siblingChainSlug_\n    ) external view returns (LimitParams memory) {\n        return _receivingLimitParams[siblingChainSlug_];\n    }\n\n    function getSendingLimitParams(\n        uint32 siblingChainSlug_\n    ) external view returns (LimitParams memory) {\n        return _sendingLimitParams[siblingChainSlug_];\n    }\n\n    /**\n     * @notice Rescues funds from the contract if they are locked by mistake.\n     * @param token_ The address of the token contract.\n     * @param rescueTo_ The address where rescued tokens need to be sent.\n     * @param amount_ The amount of tokens to be rescued.\n     */\n    function rescueFunds(\n        address token_,\n        address rescueTo_,\n        uint256 amount_\n    ) external onlyRole(RESCUE_ROLE) {\n        RescueFundsLib.rescueFunds(token_, rescueTo_, amount_);\n    }\n}\n"
      },
      "contracts/supertoken/SuperTokenVault.sol": {
        "content": "pragma solidity 0.8.13;\n\nimport \"lib/solmate/src/utils/SafeTransferLib.sol\";\n\nimport {AccessControl} from \"../common/AccessControl.sol\";\nimport {Gauge} from \"../common/Gauge.sol\";\nimport {RescueFundsLib} from \"../libraries/RescueFundsLib.sol\";\n\nimport \"./Execute.sol\";\nimport {ISuperTokenOrVault} from \"./ISuperTokenOrVault.sol\";\nimport {IMessageBridge} from \"./IMessageBridge.sol\";\n\n/**\n * @title SuperTokenVault\n * @notice Vault contract which is used to lock/unlock token and enable bridging to its sibling chains.\n * @dev This contract implements ISuperTokenOrVault to support message bridging through IMessageBridge compliant contracts.\n */\ncontract SuperTokenVault is Gauge, ISuperTokenOrVault, AccessControl, Execute {\n    using SafeTransferLib for ERC20;\n\n    struct UpdateLimitParams {\n        bool isLock;\n        uint32 siblingChainSlug;\n        uint256 maxLimit;\n        uint256 ratePerSecond;\n    }\n\n    bytes32 constant RESCUE_ROLE = keccak256(\"RESCUE_ROLE\");\n    bytes32 constant LIMIT_UPDATER_ROLE = keccak256(\"LIMIT_UPDATER_ROLE\");\n\n    ERC20 public immutable token__;\n    IMessageBridge public bridge__;\n\n    // siblingChainSlug => receiver => identifier => pendingUnlock\n    mapping(uint32 => mapping(address => mapping(bytes32 => uint256)))\n        public pendingUnlocks;\n\n    // siblingChainSlug => amount\n    mapping(uint32 => uint256) public siblingPendingUnlocks;\n\n    // siblingChainSlug => lockLimitParams\n    mapping(uint32 => LimitParams) _lockLimitParams;\n\n    // siblingChainSlug => unlockLimitParams\n    mapping(uint32 => LimitParams) _unlockLimitParams;\n\n    ////////////////////////////////////////////////////////\n    ////////////////////// ERRORS //////////////////////////\n    ////////////////////////////////////////////////////////\n\n    error SiblingChainSlugUnavailable();\n    error ZeroAmount();\n    error NotMessageBridge();\n\n    ////////////////////////////////////////////////////////\n    ////////////////////// EVENTS //////////////////////////\n    ////////////////////////////////////////////////////////\n\n    // emitted when a message bridge is updated\n    event MessageBridgeUpdated(address bridge);\n    // emitted when limit params are updated\n    event LimitParamsUpdated(UpdateLimitParams[] updates);\n    // emitted at source when tokens are deposited to be bridged to a sibling chain\n    event TokensDeposited(\n        uint32 siblingChainSlug,\n        address depositor,\n        address receiver,\n        uint256 depositAmount\n    );\n    // emitted when pending tokens are transferred to the receiver\n    event PendingTokensTransferred(\n        uint32 siblingChainSlug,\n        address receiver,\n        uint256 unlockedAmount,\n        uint256 pendingAmount\n    );\n    // emitted when transfer reaches limit and token transfer is added to pending queue\n    event TokensPending(\n        uint32 siblingChainSlug,\n        address receiver,\n        uint256 pendingAmount,\n        uint256 totalPendingAmount\n    );\n    // emitted when pending tokens are unlocked as limits are replenished\n    event TokensUnlocked(\n        uint32 siblingChainSlug,\n        address receiver,\n        uint256 unlockedAmount\n    );\n\n    /**\n     * @notice constructor for creating a new SuperTokenVault.\n     * @param token_ token contract address which is to be bridged.\n     * @param owner_ owner of this contract\n     * @param bridge_ message bridge address\n     */\n    constructor(\n        address token_,\n        address owner_,\n        address bridge_\n    ) AccessControl(owner_) {\n        token__ = ERC20(token_);\n        bridge__ = IMessageBridge(bridge_);\n    }\n\n    /**\n     * @notice this function is used to update message bridge\n     * @dev it can only be updated by owner\n     * @dev should be carefully migrated as it can risk user funds\n     * @param bridge_ new bridge address\n     */\n    function updateMessageBridge(address bridge_) external onlyOwner {\n        bridge__ = IMessageBridge(bridge_);\n        emit MessageBridgeUpdated(bridge_);\n    }\n\n    /**\n     * @notice this function is used to set bridge limits\n     * @dev it can only be updated by owner\n     * @param updates_ can be used to set mint and burn limits for all siblings in one call.\n     */\n    function updateLimitParams(\n        UpdateLimitParams[] calldata updates_\n    ) external onlyRole(LIMIT_UPDATER_ROLE) {\n        for (uint256 i; i < updates_.length; i++) {\n            if (updates_[i].isLock) {\n                _consumePartLimit(\n                    0,\n                    _lockLimitParams[updates_[i].siblingChainSlug]\n                ); // to keep current limit in sync\n                _lockLimitParams[updates_[i].siblingChainSlug]\n                    .maxLimit = updates_[i].maxLimit;\n                _lockLimitParams[updates_[i].siblingChainSlug]\n                    .ratePerSecond = updates_[i].ratePerSecond;\n            } else {\n                _consumePartLimit(\n                    0,\n                    _unlockLimitParams[updates_[i].siblingChainSlug]\n                ); // to keep current limit in sync\n                _unlockLimitParams[updates_[i].siblingChainSlug]\n                    .maxLimit = updates_[i].maxLimit;\n                _unlockLimitParams[updates_[i].siblingChainSlug]\n                    .ratePerSecond = updates_[i].ratePerSecond;\n            }\n        }\n\n        emit LimitParamsUpdated(updates_);\n    }\n\n    /**\n     * @notice this function is called by users to bridge their funds to a sibling chain\n     * @dev it is payable to receive message bridge fees to be paid.\n     * @param receiver_ address receiving bridged tokens\n     * @param siblingChainSlug_ The unique identifier of the sibling chain.\n     * @param amount_ amount bridged\n     * @param msgGasLimit_ min gas limit needed for execution at destination\n     * @param payload_ payload which is executed at destination with bridged amount at receiver address.\n     * @param options_ additional message bridge options can be provided using this param\n     */\n    function bridge(\n        address receiver_,\n        uint32 siblingChainSlug_,\n        uint256 amount_,\n        uint256 msgGasLimit_,\n        bytes calldata payload_,\n        bytes calldata options_\n    ) external payable {\n        if (amount_ == 0) revert ZeroAmount();\n\n        if (_lockLimitParams[siblingChainSlug_].maxLimit == 0)\n            revert SiblingChainSlugUnavailable();\n\n        _consumeFullLimit(amount_, _lockLimitParams[siblingChainSlug_]); // reverts on limit hit\n\n        token__.safeTransferFrom(msg.sender, address(this), amount_);\n\n        bytes32 messageId = bridge__.getMessageId(siblingChainSlug_);\n        bridge__.outbound{value: msg.value}(\n            siblingChainSlug_,\n            msgGasLimit_,\n            abi.encode(receiver_, amount_, messageId, payload_),\n            options_\n        );\n\n        emit TokensDeposited(siblingChainSlug_, msg.sender, receiver_, amount_);\n    }\n\n    /**\n     * @notice this function can be used to unlock funds which were in pending state due to limits\n     * @param receiver_ address receiving bridged tokens\n     * @param siblingChainSlug_ The unique identifier of the sibling chain.\n     * @param identifier_ message identifier where message was received to unlock funds\n     */\n    function unlockPendingFor(\n        address receiver_,\n        uint32 siblingChainSlug_,\n        bytes32 identifier_\n    ) external nonReentrant {\n        if (_unlockLimitParams[siblingChainSlug_].maxLimit == 0)\n            revert SiblingChainSlugUnavailable();\n\n        uint256 pendingUnlock = pendingUnlocks[siblingChainSlug_][receiver_][\n            identifier_\n        ];\n        (uint256 consumedAmount, uint256 pendingAmount) = _consumePartLimit(\n            pendingUnlock,\n            _unlockLimitParams[siblingChainSlug_]\n        );\n\n        pendingUnlocks[siblingChainSlug_][receiver_][\n            identifier_\n        ] = pendingAmount;\n        siblingPendingUnlocks[siblingChainSlug_] -= consumedAmount;\n\n        token__.safeTransfer(receiver_, consumedAmount);\n\n        if (\n            pendingAmount == 0 &&\n            pendingExecutions[identifier_].receiver != address(0)\n        ) {\n            // execute\n            pendingExecutions[identifier_].isAmountPending = false;\n            bool success = _execute(\n                receiver_,\n                pendingExecutions[identifier_].payload\n            );\n            if (success) _clearPayload(identifier_);\n        }\n\n        emit PendingTokensTransferred(\n            siblingChainSlug_,\n            receiver_,\n            consumedAmount,\n            pendingAmount\n        );\n    }\n\n    /**\n     * @notice this function receives the message from message bridge\n     * @dev Only bridge can call this function.\n     * @param siblingChainSlug_ The unique identifier of the sibling chain.\n     * @param payload_ payload which is decoded to get `receiver`, `amount to mint`, `message id` and `payload` to execute after token transfer.\n     */\n    function inbound(\n        uint32 siblingChainSlug_,\n        bytes memory payload_\n    ) external payable override nonReentrant {\n        if (msg.sender != address(bridge__)) revert NotMessageBridge();\n\n        if (_unlockLimitParams[siblingChainSlug_].maxLimit == 0)\n            revert SiblingChainSlugUnavailable();\n\n        (\n            address receiver,\n            uint256 unlockAmount,\n            bytes32 identifier,\n            bytes memory execPayload\n        ) = abi.decode(payload_, (address, uint256, bytes32, bytes));\n\n        if (receiver == address(this) || receiver == address(bridge__))\n            revert CannotExecuteOnBridgeContracts();\n\n        (uint256 consumedAmount, uint256 pendingAmount) = _consumePartLimit(\n            unlockAmount,\n            _unlockLimitParams[siblingChainSlug_]\n        );\n\n        token__.safeTransfer(receiver, consumedAmount);\n\n        if (pendingAmount > 0) {\n            // add instead of overwrite to handle case where already pending amount is left\n            pendingUnlocks[siblingChainSlug_][receiver][\n                identifier\n            ] += pendingAmount;\n            siblingPendingUnlocks[siblingChainSlug_] += pendingAmount;\n\n            // cache payload\n            if (execPayload.length > 0)\n                _cachePayload(\n                    identifier,\n                    siblingChainSlug_,\n                    true,\n                    receiver,\n                    execPayload\n                );\n\n            emit TokensPending(\n                siblingChainSlug_,\n                receiver,\n                pendingAmount,\n                pendingUnlocks[siblingChainSlug_][receiver][identifier]\n            );\n        } else if (execPayload.length > 0) {\n            // execute\n            bool success = _execute(receiver, execPayload);\n\n            if (!success)\n                _cachePayload(\n                    identifier,\n                    siblingChainSlug_,\n                    false,\n                    receiver,\n                    execPayload\n                );\n        }\n\n        emit TokensUnlocked(siblingChainSlug_, receiver, consumedAmount);\n    }\n\n    function getCurrentLockLimit(\n        uint32 siblingChainSlug_\n    ) external view returns (uint256) {\n        return _getCurrentLimit(_lockLimitParams[siblingChainSlug_]);\n    }\n\n    function getCurrentUnlockLimit(\n        uint32 siblingChainSlug_\n    ) external view returns (uint256) {\n        return _getCurrentLimit(_unlockLimitParams[siblingChainSlug_]);\n    }\n\n    function getLockLimitParams(\n        uint32 siblingChainSlug_\n    ) external view returns (LimitParams memory) {\n        return _lockLimitParams[siblingChainSlug_];\n    }\n\n    function getUnlockLimitParams(\n        uint32 siblingChainSlug_\n    ) external view returns (LimitParams memory) {\n        return _unlockLimitParams[siblingChainSlug_];\n    }\n\n    /**\n     * @notice Rescues funds from the contract if they are locked by mistake.\n     * @param token_ The address of the token contract.\n     * @param rescueTo_ The address where rescued tokens need to be sent.\n     * @param amount_ The amount of tokens to be rescued.\n     */\n    function rescueFunds(\n        address token_,\n        address rescueTo_,\n        uint256 amount_\n    ) external onlyRole(RESCUE_ROLE) {\n        RescueFundsLib.rescueFunds(token_, rescueTo_, amount_);\n    }\n}\n"
      },
      "lib/solmate/src/tokens/ERC20.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\nabstract contract ERC20 {\n    /*//////////////////////////////////////////////////////////////\n                                 EVENTS\n    //////////////////////////////////////////////////////////////*/\n\n    event Transfer(address indexed from, address indexed to, uint256 amount);\n\n    event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n    /*//////////////////////////////////////////////////////////////\n                            METADATA STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    string public name;\n\n    string public symbol;\n\n    uint8 public immutable decimals;\n\n    /*//////////////////////////////////////////////////////////////\n                              ERC20 STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    uint256 public totalSupply;\n\n    mapping(address => uint256) public balanceOf;\n\n    mapping(address => mapping(address => uint256)) public allowance;\n\n    /*//////////////////////////////////////////////////////////////\n                            EIP-2612 STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    uint256 internal immutable INITIAL_CHAIN_ID;\n\n    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\n\n    mapping(address => uint256) public nonces;\n\n    /*//////////////////////////////////////////////////////////////\n                               CONSTRUCTOR\n    //////////////////////////////////////////////////////////////*/\n\n    constructor(\n        string memory _name,\n        string memory _symbol,\n        uint8 _decimals\n    ) {\n        name = _name;\n        symbol = _symbol;\n        decimals = _decimals;\n\n        INITIAL_CHAIN_ID = block.chainid;\n        INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                               ERC20 LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function approve(address spender, uint256 amount) public virtual returns (bool) {\n        allowance[msg.sender][spender] = amount;\n\n        emit Approval(msg.sender, spender, amount);\n\n        return true;\n    }\n\n    function transfer(address to, uint256 amount) public virtual returns (bool) {\n        balanceOf[msg.sender] -= amount;\n\n        // Cannot overflow because the sum of all user\n        // balances can't exceed the max uint256 value.\n        unchecked {\n            balanceOf[to] += amount;\n        }\n\n        emit Transfer(msg.sender, to, amount);\n\n        return true;\n    }\n\n    function transferFrom(\n        address from,\n        address to,\n        uint256 amount\n    ) public virtual returns (bool) {\n        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\n\n        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\n\n        balanceOf[from] -= amount;\n\n        // Cannot overflow because the sum of all user\n        // balances can't exceed the max uint256 value.\n        unchecked {\n            balanceOf[to] += amount;\n        }\n\n        emit Transfer(from, to, amount);\n\n        return true;\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                             EIP-2612 LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) public virtual {\n        require(deadline >= block.timestamp, \"PERMIT_DEADLINE_EXPIRED\");\n\n        // Unchecked because the only math done is incrementing\n        // the owner's nonce which cannot realistically overflow.\n        unchecked {\n            address recoveredAddress = ecrecover(\n                keccak256(\n                    abi.encodePacked(\n                        \"\\x19\\x01\",\n                        DOMAIN_SEPARATOR(),\n                        keccak256(\n                            abi.encode(\n                                keccak256(\n                                    \"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\"\n                                ),\n                                owner,\n                                spender,\n                                value,\n                                nonces[owner]++,\n                                deadline\n                            )\n                        )\n                    )\n                ),\n                v,\n                r,\n                s\n            );\n\n            require(recoveredAddress != address(0) && recoveredAddress == owner, \"INVALID_SIGNER\");\n\n            allowance[recoveredAddress][spender] = value;\n        }\n\n        emit Approval(owner, spender, value);\n    }\n\n    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n        return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\n    }\n\n    function computeDomainSeparator() internal view virtual returns (bytes32) {\n        return\n            keccak256(\n                abi.encode(\n                    keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n                    keccak256(bytes(name)),\n                    keccak256(\"1\"),\n                    block.chainid,\n                    address(this)\n                )\n            );\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                        INTERNAL MINT/BURN LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function _mint(address to, uint256 amount) internal virtual {\n        totalSupply += amount;\n\n        // Cannot overflow because the sum of all user\n        // balances can't exceed the max uint256 value.\n        unchecked {\n            balanceOf[to] += amount;\n        }\n\n        emit Transfer(address(0), to, amount);\n    }\n\n    function _burn(address from, uint256 amount) internal virtual {\n        balanceOf[from] -= amount;\n\n        // Cannot underflow because a user's balance\n        // will never be larger than the total supply.\n        unchecked {\n            totalSupply -= amount;\n        }\n\n        emit Transfer(from, address(0), amount);\n    }\n}\n"
      },
      "lib/solmate/src/utils/ReentrancyGuard.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Gas optimized reentrancy protection for smart contracts.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ReentrancyGuard.sol)\n/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol)\nabstract contract ReentrancyGuard {\n    uint256 private locked = 1;\n\n    modifier nonReentrant() virtual {\n        require(locked == 1, \"REENTRANCY\");\n\n        locked = 2;\n\n        _;\n\n        locked = 1;\n    }\n}\n"
      },
      "lib/solmate/src/utils/SafeTransferLib.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\nimport {ERC20} from \"../tokens/ERC20.sol\";\n\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)\n/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.\n/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.\nlibrary SafeTransferLib {\n    /*//////////////////////////////////////////////////////////////\n                             ETH OPERATIONS\n    //////////////////////////////////////////////////////////////*/\n\n    function safeTransferETH(address to, uint256 amount) internal {\n        bool success;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Transfer the ETH and store if it succeeded or not.\n            success := call(gas(), to, amount, 0, 0, 0, 0)\n        }\n\n        require(success, \"ETH_TRANSFER_FAILED\");\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                            ERC20 OPERATIONS\n    //////////////////////////////////////////////////////////////*/\n\n    function safeTransferFrom(\n        ERC20 token,\n        address from,\n        address to,\n        uint256 amount\n    ) internal {\n        bool success;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Get a pointer to some free memory.\n            let freeMemoryPointer := mload(0x40)\n\n            // Write the abi-encoded calldata into memory, beginning with the function selector.\n            mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)\n            mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \"from\" argument.\n            mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \"to\" argument.\n            mstore(add(freeMemoryPointer, 68), amount) // Append the \"amount\" argument. Masking not required as it's a full 32 byte type.\n\n            success := and(\n                // Set success to whether the call reverted, if not we check it either\n                // returned exactly 1 (can't just be non-zero data), or had no return data.\n                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n                // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.\n                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n                // Counterintuitively, this call must be positioned second to the or() call in the\n                // surrounding and() call or else returndatasize() will be zero during the computation.\n                call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)\n            )\n        }\n\n        require(success, \"TRANSFER_FROM_FAILED\");\n    }\n\n    function safeTransfer(\n        ERC20 token,\n        address to,\n        uint256 amount\n    ) internal {\n        bool success;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Get a pointer to some free memory.\n            let freeMemoryPointer := mload(0x40)\n\n            // Write the abi-encoded calldata into memory, beginning with the function selector.\n            mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\n            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \"to\" argument.\n            mstore(add(freeMemoryPointer, 36), amount) // Append the \"amount\" argument. Masking not required as it's a full 32 byte type.\n\n            success := and(\n                // Set success to whether the call reverted, if not we check it either\n                // returned exactly 1 (can't just be non-zero data), or had no return data.\n                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\n                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n                // Counterintuitively, this call must be positioned second to the or() call in the\n                // surrounding and() call or else returndatasize() will be zero during the computation.\n                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\n            )\n        }\n\n        require(success, \"TRANSFER_FAILED\");\n    }\n\n    function safeApprove(\n        ERC20 token,\n        address to,\n        uint256 amount\n    ) internal {\n        bool success;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Get a pointer to some free memory.\n            let freeMemoryPointer := mload(0x40)\n\n            // Write the abi-encoded calldata into memory, beginning with the function selector.\n            mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)\n            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \"to\" argument.\n            mstore(add(freeMemoryPointer, 36), amount) // Append the \"amount\" argument. Masking not required as it's a full 32 byte type.\n\n            success := and(\n                // Set success to whether the call reverted, if not we check it either\n                // returned exactly 1 (can't just be non-zero data), or had no return data.\n                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\n                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n                // Counterintuitively, this call must be positioned second to the or() call in the\n                // surrounding and() call or else returndatasize() will be zero during the computation.\n                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\n            )\n        }\n\n        require(success, \"APPROVE_FAILED\");\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 999999
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      },
      "libraries": {}
    }
  }}