creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/bridge/Base.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IMintableERC20} from \"../interfaces/IMintableERC20.sol\";\nimport {IConnector} from \"../interfaces/IConnector.sol\";\nimport \"lib/solmate/src/utils/SafeTransferLib.sol\";\nimport \"../interfaces/IHook.sol\";\nimport \"../common/Errors.sol\";\nimport \"lib/solmate/src/utils/ReentrancyGuard.sol\";\nimport \"../interfaces/IBridge.sol\";\nimport \"../utils/RescueBase.sol\";\nimport \"../common/Constants.sol\";\n\nabstract contract Base is ReentrancyGuard, IBridge, RescueBase {\n    address public immutable token;\n    bytes32 public bridgeType;\n    IHook public hook__;\n    // message identifier => cache\n    mapping(bytes32 => bytes) public identifierCache;\n\n    // connector => cache\n    mapping(address => bytes) public connectorCache;\n\n    mapping(address => bool) public validConnectors;\n\n    event ConnectorStatusUpdated(address connector, bool status);\n\n    event HookUpdated(address newHook);\n\n    event BridgingTokens(\n        address connector,\n        address sender,\n        address receiver,\n        uint256 amount,\n        bytes32 messageId\n    );\n    event TokensBridged(\n        address connecter,\n        address receiver,\n        uint256 amount,\n        bytes32 messageId\n    );\n\n    constructor(address token_) AccessControl(msg.sender) {\n        if (token_ != ETH_ADDRESS && token_.code.length == 0)\n            revert InvalidTokenContract();\n        token = token_;\n        _grantRole(RESCUE_ROLE, msg.sender);\n    }\n\n    /**\n     * @notice this function is used to update hook\n     * @dev it can only be updated by owner\n     * @dev should be carefully migrated as it can risk user funds\n     * @param hook_ new hook address\n     */\n    function updateHook(\n        address hook_,\n        bool approve_\n    ) external virtual onlyOwner {\n        // remove the approval from the old hook\n        if (token != ETH_ADDRESS) {\n            if (ERC20(token).allowance(address(this), address(hook__)) > 0) {\n                SafeTransferLib.safeApprove(ERC20(token), address(hook__), 0);\n            }\n            if (approve_) {\n                SafeTransferLib.safeApprove(\n                    ERC20(token),\n                    hook_,\n                    type(uint256).max\n                );\n            }\n        }\n        hook__ = IHook(hook_);\n\n        emit HookUpdated(hook_);\n    }\n\n    function updateConnectorStatus(\n        address[] calldata connectors,\n        bool[] calldata statuses\n    ) external onlyOwner {\n        uint256 length = connectors.length;\n        for (uint256 i; i < length; i++) {\n            validConnectors[connectors[i]] = statuses[i];\n            emit ConnectorStatusUpdated(connectors[i], statuses[i]);\n        }\n    }\n\n    /**\n     * @notice Executes pre-bridge operations before initiating a token bridge transfer.\n     * @dev This internal function is called before initiating a token bridge transfer.\n     * It validates the receiver address and the connector, and if a pre-hook contract is defined,\n     * it executes the source pre-hook call.\n     * @param connector_ The address of the connector responsible for the transfer.\n     * @param transferInfo_ Information about the transfer.\n     * @return transferInfo Information about the transfer after pre-bridge operations.\n     * @return postHookData Data returned from the pre-hook call.\n     * @dev Reverts with `ZeroAddressReceiver` if the receiver address is zero.\n     * Reverts with `InvalidConnector` if the connector address is not valid.\n     */\n    function _beforeBridge(\n        address connector_,\n        TransferInfo memory transferInfo_\n    )\n        internal\n        returns (TransferInfo memory transferInfo, bytes memory postHookData)\n    {\n        if (transferInfo_.receiver == address(0)) revert ZeroAddressReceiver();\n        if (!validConnectors[connector_]) revert InvalidConnector();\n        if (token == ETH_ADDRESS && msg.value < transferInfo_.amount)\n            revert InsufficientMsgValue();\n\n        if (address(hook__) != address(0)) {\n            (transferInfo, postHookData) = hook__.srcPreHookCall(\n                SrcPreHookCallParams(connector_, msg.sender, transferInfo_)\n            );\n        }\n    }\n\n    /**\n     * @notice Executes post-bridge operations after completing a token bridge transfer.\n     * @dev This internal function is called after completing a token bridge transfer.\n     * It executes the source post-hook call if a hook contract is defined, calculates fees,\n     * calls the outbound function of the connector, and emits an event for tokens withdrawn.\n     * @param msgGasLimit_ The gas limit for the outbound call.\n     * @param connector_ The address of the connector responsible for the transfer.\n     * @param options_ Additional options for the outbound call.\n     * @param postSrcHookData_ Data returned from the source post-hook call.\n     * @param transferInfo_ Information about the transfer.\n     * @dev Reverts with `MessageIdMisMatched` if the returned message ID does not match the expected message ID.\n     */\n    function _afterBridge(\n        uint256 msgGasLimit_,\n        address connector_,\n        bytes memory options_,\n        bytes memory postSrcHookData_,\n        TransferInfo memory transferInfo_\n    ) internal {\n        TransferInfo memory transferInfo = transferInfo_;\n        if (address(hook__) != address(0)) {\n            transferInfo = hook__.srcPostHookCall(\n                SrcPostHookCallParams(\n                    connector_,\n                    options_,\n                    postSrcHookData_,\n                    transferInfo_\n                )\n            );\n        }\n\n        uint256 fees = token == ETH_ADDRESS\n            ? msg.value - transferInfo.amount\n            : msg.value;\n\n        bytes32 messageId = IConnector(connector_).getMessageId();\n        bytes32 returnedMessageId = IConnector(connector_).outbound{\n            value: fees\n        }(\n            msgGasLimit_,\n            abi.encode(\n                transferInfo.receiver,\n                transferInfo.amount,\n                messageId,\n                transferInfo.data\n            ),\n            options_\n        );\n        if (returnedMessageId != messageId) revert MessageIdMisMatched();\n\n        emit BridgingTokens(\n            connector_,\n            msg.sender,\n            transferInfo.receiver,\n            transferInfo.amount,\n            messageId\n        );\n    }\n\n    /**\n     * @notice Executes pre-mint operations before minting tokens.\n     * @dev This internal function is called before minting tokens.\n     * It validates the caller as a valid connector, checks if the receiver is not this contract, the bridge contract,\n     * or the token contract, and executes the destination pre-hook call if a hook contract is defined.\n     * @param transferInfo_ Information about the transfer.\n     * @return postHookData Data returned from the destination pre-hook call.\n     * @return transferInfo Information about the transfer after pre-mint operations.\n     * @dev Reverts with `InvalidConnector` if the caller is not a valid connector.\n     * Reverts with `CannotTransferOrExecuteOnBridgeContracts` if the receiver is this contract, the bridge contract,\n     * or the token contract.\n     */\n    function _beforeMint(\n        uint32,\n        TransferInfo memory transferInfo_\n    )\n        internal\n        returns (bytes memory postHookData, TransferInfo memory transferInfo)\n    {\n        if (!validConnectors[msg.sender]) revert InvalidConnector();\n\n        // no need of source check here, as if invalid caller, will revert with InvalidPoolId\n        if (\n            transferInfo_.receiver == address(this) ||\n            // transferInfo_.receiver == address(bridge__) ||\n            transferInfo_.receiver == token\n        ) revert CannotTransferOrExecuteOnBridgeContracts();\n\n        if (address(hook__) != address(0)) {\n            (postHookData, transferInfo) = hook__.dstPreHookCall(\n                DstPreHookCallParams(\n                    msg.sender,\n                    connectorCache[msg.sender],\n                    transferInfo_\n                )\n            );\n        }\n    }\n\n    /**\n     * @notice Executes post-mint operations after minting tokens.\n     * @dev This internal function is called after minting tokens.\n     * It executes the destination post-hook call if a hook contract is defined and updates cache data.\n     * @param messageId_ The unique identifier for the mint transaction.\n     * @param postHookData_ Data returned from the destination pre-hook call.\n     * @param transferInfo_ Information about the mint transaction.\n     */\n    function _afterMint(\n        uint256,\n        bytes32 messageId_,\n        bytes memory postHookData_,\n        TransferInfo memory transferInfo_\n    ) internal {\n        if (address(hook__) != address(0)) {\n            CacheData memory cacheData = hook__.dstPostHookCall(\n                DstPostHookCallParams(\n                    msg.sender,\n                    messageId_,\n                    connectorCache[msg.sender],\n                    postHookData_,\n                    transferInfo_\n                )\n            );\n\n            identifierCache[messageId_] = cacheData.identifierCache;\n            connectorCache[msg.sender] = cacheData.connectorCache;\n        }\n\n        emit TokensBridged(\n            msg.sender,\n            transferInfo_.receiver,\n            transferInfo_.amount,\n            messageId_\n        );\n    }\n\n    /**\n     * @notice Executes pre-retry operations before retrying a failed transaction.\n     * @dev This internal function is called before retrying a failed transaction.\n     * It validates the connector, retrieves cache data for the given message ID,\n     * and executes the pre-retry hook if defined.\n     * @param connector_ The address of the connector responsible for the failed transaction.\n     * @param messageId_ The unique identifier for the failed transaction.\n     * @return postRetryHookData Data returned from the pre-retry hook call.\n     * @return transferInfo Information about the transfer.\n     * @dev Reverts with `InvalidConnector` if the connector is not valid.\n     * Reverts with `NoPendingData` if there is no pending data for the given message ID.\n     */\n    function _beforeRetry(\n        address connector_,\n        bytes32 messageId_\n    )\n        internal\n        returns (\n            bytes memory postRetryHookData,\n            TransferInfo memory transferInfo\n        )\n    {\n        if (!validConnectors[connector_]) revert InvalidConnector();\n\n        CacheData memory cacheData = CacheData(\n            identifierCache[messageId_],\n            connectorCache[connector_]\n        );\n\n        if (cacheData.identifierCache.length == 0) revert NoPendingData();\n        (postRetryHookData, transferInfo) = hook__.preRetryHook(\n            PreRetryHookCallParams(connector_, cacheData)\n        );\n    }\n\n    /**\n     * @notice Executes post-retry operations after retrying a failed transaction.\n     * @dev This internal function is called after retrying a failed transaction.\n     * It retrieves cache data for the given message ID, executes the post-retry hook if defined,\n     * and updates cache data.\n     * @param connector_ The address of the connector responsible for the failed transaction.\n     * @param messageId_ The unique identifier for the failed transaction.\n     * @param postRetryHookData Data returned from the pre-retry hook call.\n     */\n    function _afterRetry(\n        address connector_,\n        bytes32 messageId_,\n        bytes memory postRetryHookData\n    ) internal {\n        CacheData memory cacheData = CacheData(\n            identifierCache[messageId_],\n            connectorCache[connector_]\n        );\n\n        (cacheData) = hook__.postRetryHook(\n            PostRetryHookCallParams(\n                connector_,\n                messageId_,\n                postRetryHookData,\n                cacheData\n            )\n        );\n        identifierCache[messageId_] = cacheData.identifierCache;\n        connectorCache[connector_] = cacheData.connectorCache;\n    }\n\n    /**\n     * @notice Retrieves the minimum fees required for a transaction from a connector.\n     * @dev This function returns the minimum fees required for a transaction from the specified connector,\n     * based on the provided message gas limit and payload size.\n     * @param connector_ The address of the connector.\n     * @param msgGasLimit_ The gas limit for the transaction.\n     * @param payloadSize_ The size of the payload for the transaction.\n     * @return totalFees The total minimum fees required for the transaction.\n     */\n    function getMinFees(\n        address connector_,\n        uint256 msgGasLimit_,\n        uint256 payloadSize_\n    ) external view returns (uint256 totalFees) {\n        return IConnector(connector_).getMinFees(msgGasLimit_, payloadSize_);\n    }\n}\n"
      },
      "contracts/bridge/Controller.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./Base.sol\";\n\ncontract Controller is Base {\n    uint256 public totalMinted;\n\n    constructor(address token_) Base(token_) {\n        bridgeType = NORMAL_CONTROLLER;\n    }\n\n    /**\n     * @notice Bridges tokens between chains.\n     * @dev This function allows bridging tokens between different chains.\n     * @param receiver_ The address to receive the bridged tokens.\n     * @param amount_ The amount of tokens to bridge.\n     * @param msgGasLimit_ The gas limit for the execution of the bridging process.\n     * @param connector_ The address of the connector contract responsible for the bridge.\n     * @param execPayload_ The payload for executing the bridging process on the connector.\n     * @param options_ Additional options for the bridging process.\n     */\n    function bridge(\n        address receiver_,\n        uint256 amount_,\n        uint256 msgGasLimit_,\n        address connector_,\n        bytes calldata execPayload_,\n        bytes calldata options_\n    ) external payable nonReentrant {\n        (\n            TransferInfo memory transferInfo,\n            bytes memory postHookData\n        ) = _beforeBridge(\n                connector_,\n                TransferInfo(receiver_, amount_, execPayload_)\n            );\n\n        // to maintain socket dl specific accounting for super token\n        // re check this logic for mint and mint use cases and if other minter involved\n        totalMinted -= transferInfo.amount;\n        _burn(msg.sender, transferInfo.amount);\n        _afterBridge(\n            msgGasLimit_,\n            connector_,\n            options_,\n            postHookData,\n            transferInfo\n        );\n    }\n\n    /**\n     * @notice Receives inbound tokens from another chain.\n     * @dev This function is used to receive tokens from another chain.\n     * @param siblingChainSlug_ The identifier of the sibling chain.\n     * @param payload_ The payload containing the inbound tokens.\n     */\n    function receiveInbound(\n        uint32 siblingChainSlug_,\n        bytes memory payload_\n    ) external payable override nonReentrant {\n        (\n            address receiver,\n            uint256 lockAmount,\n            bytes32 messageId,\n            bytes memory extraData\n        ) = abi.decode(payload_, (address, uint256, bytes32, bytes));\n\n        // convert to shares\n        TransferInfo memory transferInfo = TransferInfo(\n            receiver,\n            lockAmount,\n            extraData\n        );\n        bytes memory postHookData;\n        (postHookData, transferInfo) = _beforeMint(\n            siblingChainSlug_,\n            transferInfo\n        );\n\n        _mint(transferInfo.receiver, transferInfo.amount);\n        totalMinted += transferInfo.amount;\n\n        _afterMint(lockAmount, messageId, postHookData, transferInfo);\n    }\n\n    /**\n     * @notice Retry a failed transaction.\n     * @dev This function allows retrying a failed transaction sent through a connector.\n     * @param connector_ The address of the connector contract responsible for the failed transaction.\n     * @param messageId_ The unique identifier of the failed transaction.\n     */\n    function retry(\n        address connector_,\n        bytes32 messageId_\n    ) external nonReentrant {\n        (\n            bytes memory postRetryHookData,\n            TransferInfo memory transferInfo\n        ) = _beforeRetry(connector_, messageId_);\n        _mint(transferInfo.receiver, transferInfo.amount);\n        totalMinted += transferInfo.amount;\n\n        _afterRetry(connector_, messageId_, postRetryHookData);\n    }\n\n    function _burn(address user_, uint256 burnAmount_) internal virtual {\n        IMintableERC20(token).burn(user_, burnAmount_);\n    }\n\n    function _mint(address user_, uint256 mintAmount_) internal virtual {\n        if (mintAmount_ == 0) return;\n        IMintableERC20(token).mint(user_, mintAmount_);\n    }\n}\n"
      },
      "contracts/bridge/FiatTokenV2_1/FiatTokenV2_1_Controller.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport {IFiatTokenV2_1_Mintable} from \"./IFiatTokenV2_1_Mintable.sol\";\nimport \"../Controller.sol\";\n\ncontract FiatTokenV2_1_Controller is Controller {\n    using SafeTransferLib for ERC20;\n\n    constructor(address token_) Controller(token_) {\n        bridgeType = FIAT_TOKEN_CONTROLLER;\n    }\n\n    function _burn(address user_, uint256 burnAmount_) internal override {\n        ERC20(token).safeTransferFrom(user_, address(this), burnAmount_);\n        IFiatTokenV2_1_Mintable(address(token)).burn(burnAmount_);\n    }\n}\n"
      },
      "contracts/bridge/FiatTokenV2_1/IFiatTokenV2_1_Mintable.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma 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/bridge/Vault.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./Base.sol\";\nimport \"../interfaces/IConnector.sol\";\nimport \"lib/solmate/src/tokens/ERC20.sol\";\n\n/**\n * @title SuperToken\n * @notice A 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 Vault is Base {\n    using SafeTransferLib for ERC20;\n\n    // /**\n    //  * @notice constructor for creating a new SuperTokenVault.\n    //  * @param token_ token contract address which is to be bridged.\n    //  */\n\n    constructor(address token_) Base(token_) {\n        bridgeType = token_ == ETH_ADDRESS ? NATIVE_VAULT : ERC20_VAULT;\n    }\n\n    /**\n     * @notice Bridges tokens between chains.\n     * @dev This function allows bridging tokens between different chains.\n     * @param receiver_ The address to receive the bridged tokens.\n     * @param amount_ The amount of tokens to bridge.\n     * @param msgGasLimit_ The gas limit for the execution of the bridging process.\n     * @param connector_ The address of the connector contract responsible for the bridge.\n     * @param execPayload_ The payload for executing the bridging process on the connector.\n     * @param options_ Additional options for the bridging process.\n     */\n    function bridge(\n        address receiver_,\n        uint256 amount_,\n        uint256 msgGasLimit_,\n        address connector_,\n        bytes calldata execPayload_,\n        bytes calldata options_\n    ) external payable nonReentrant {\n        (\n            TransferInfo memory transferInfo,\n            bytes memory postHookData\n        ) = _beforeBridge(\n                connector_,\n                TransferInfo(receiver_, amount_, execPayload_)\n            );\n\n        _receiveTokens(transferInfo.amount);\n\n        _afterBridge(\n            msgGasLimit_,\n            connector_,\n            options_,\n            postHookData,\n            transferInfo\n        );\n    }\n\n    /**\n     * @notice Receives inbound tokens from another chain.\n     * @dev This function is used to receive tokens from another chain.\n     * @param siblingChainSlug_ The identifier of the sibling chain.\n     * @param payload_ The payload containing the inbound tokens.\n     */\n    function receiveInbound(\n        uint32 siblingChainSlug_,\n        bytes memory payload_\n    ) external payable override nonReentrant {\n        (\n            address receiver,\n            uint256 unlockAmount,\n            bytes32 messageId,\n            bytes memory extraData\n        ) = abi.decode(payload_, (address, uint256, bytes32, bytes));\n\n        TransferInfo memory transferInfo = TransferInfo(\n            receiver,\n            unlockAmount,\n            extraData\n        );\n\n        bytes memory postHookData;\n        (postHookData, transferInfo) = _beforeMint(\n            siblingChainSlug_,\n            transferInfo\n        );\n\n        _transferTokens(transferInfo.receiver, transferInfo.amount);\n\n        _afterMint(unlockAmount, messageId, postHookData, transferInfo);\n    }\n\n    /**\n     * @notice Retry a failed transaction.\n     * @dev This function allows retrying a failed transaction sent through a connector.\n     * @param connector_ The address of the connector contract responsible for the failed transaction.\n     * @param messageId_ The unique identifier of the failed transaction.\n     */\n    function retry(\n        address connector_,\n        bytes32 messageId_\n    ) external nonReentrant {\n        (\n            bytes memory postRetryHookData,\n            TransferInfo memory transferInfo\n        ) = _beforeRetry(connector_, messageId_);\n        _transferTokens(transferInfo.receiver, transferInfo.amount);\n\n        _afterRetry(connector_, messageId_, postRetryHookData);\n    }\n\n    function _transferTokens(address receiver_, uint256 amount_) internal {\n        if (amount_ == 0) return;\n        if (address(token) == ETH_ADDRESS) {\n            SafeTransferLib.safeTransferETH(receiver_, amount_);\n        } else {\n            ERC20(token).safeTransfer(receiver_, amount_);\n        }\n    }\n\n    function _receiveTokens(uint256 amount_) internal {\n        if (amount_ == 0 || address(token) == ETH_ADDRESS) return;\n        ERC20(token).safeTransferFrom(msg.sender, address(this), amount_);\n    }\n}\n"
      },
      "contracts/common/Constants.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\naddress constant ETH_ADDRESS = address(\n    0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE\n);\n\nbytes32 constant NORMAL_CONTROLLER = keccak256(\"NORMAL_CONTROLLER\");\nbytes32 constant FIAT_TOKEN_CONTROLLER = keccak256(\"FIAT_TOKEN_CONTROLLER\");\n\nbytes32 constant LIMIT_HOOK = keccak256(\"LIMIT_HOOK\");\nbytes32 constant LIMIT_EXECUTION_HOOK = keccak256(\"LIMIT_EXECUTION_HOOK\");\nbytes32 constant LIMIT_EXECUTION_YIELD_HOOK = keccak256(\n    \"LIMIT_EXECUTION_YIELD_HOOK\"\n);\nbytes32 constant LIMIT_EXECUTION_YIELD_TOKEN_HOOK = keccak256(\n    \"LIMIT_EXECUTION_YIELD_TOKEN_HOOK\"\n);\n\nbytes32 constant ERC20_VAULT = keccak256(\"ERC20_VAULT\");\nbytes32 constant NATIVE_VAULT = keccak256(\"NATIVE_VAULT\");\n"
      },
      "contracts/common/Errors.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nerror SiblingNotSupported();\nerror NotAuthorized();\nerror NotBridge();\nerror NotSocket();\nerror ConnectorUnavailable();\nerror InvalidPoolId();\nerror CannotTransferOrExecuteOnBridgeContracts();\nerror NoPendingData();\nerror MessageIdMisMatched();\nerror NotMessageBridge();\nerror InvalidSiblingChainSlug();\nerror InvalidTokenContract();\nerror InvalidExchangeRateContract();\nerror InvalidConnector();\nerror InvalidConnectorPoolId();\nerror ZeroAddressReceiver();\nerror ZeroAddress();\nerror ZeroAmount();\nerror DebtRatioTooHigh();\nerror NotEnoughAssets();\nerror VaultShutdown();\nerror InsufficientFunds();\nerror PermitDeadlineExpired();\nerror InvalidSigner();\nerror InsufficientMsgValue();\n"
      },
      "contracts/common/Structs.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nstruct UpdateLimitParams {\n    bool isMint;\n    address connector;\n    uint256 maxLimit;\n    uint256 ratePerSecond;\n}\n\nstruct SrcPreHookCallParams {\n    address connector;\n    address msgSender;\n    TransferInfo transferInfo;\n}\n\nstruct SrcPostHookCallParams {\n    address connector;\n    bytes options;\n    bytes postSrcHookData;\n    TransferInfo transferInfo;\n}\n\nstruct DstPreHookCallParams {\n    address connector;\n    bytes connectorCache;\n    TransferInfo transferInfo;\n}\n\nstruct DstPostHookCallParams {\n    address connector;\n    bytes32 messageId;\n    bytes connectorCache;\n    bytes postHookData;\n    TransferInfo transferInfo;\n}\n\nstruct PreRetryHookCallParams {\n    address connector;\n    CacheData cacheData;\n}\n\nstruct PostRetryHookCallParams {\n    address connector;\n    bytes32 messageId;\n    bytes postRetryHookData;\n    CacheData cacheData;\n}\n\nstruct TransferInfo {\n    address receiver;\n    uint256 amount;\n    bytes data;\n}\n\nstruct CacheData {\n    bytes identifierCache;\n    bytes connectorCache;\n}\n\nstruct LimitParams {\n    uint256 lastUpdateTimestamp;\n    uint256 ratePerSecond;\n    uint256 maxLimit;\n    uint256 lastUpdateLimit;\n}\n"
      },
      "contracts/ConnectorPlug.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./utils/RescueBase.sol\";\nimport {ISocket} from \"./interfaces/ISocket.sol\";\nimport {IPlug} from \"./interfaces/IPlug.sol\";\nimport {IConnector} from \"./interfaces/IConnector.sol\";\nimport {IBridge} from \"./interfaces/IBridge.sol\";\nimport \"./common/Errors.sol\";\n\ncontract ConnectorPlug is IConnector, IPlug, RescueBase {\n    IBridge public immutable bridge__;\n    ISocket public immutable socket__;\n    uint32 public immutable siblingChainSlug;\n    uint256 public messageIdPart;\n\n    event ConnectorPlugDisconnected();\n\n    constructor(\n        address bridge_,\n        address socket_,\n        uint32 siblingChainSlug_\n    ) AccessControl(msg.sender) {\n        bridge__ = IBridge(bridge_);\n        socket__ = ISocket(socket_);\n        siblingChainSlug = siblingChainSlug_;\n        _grantRole(RESCUE_ROLE, msg.sender);\n    }\n\n    function outbound(\n        uint256 msgGasLimit_,\n        bytes memory payload_,\n        bytes memory\n    ) external payable override returns (bytes32 messageId_) {\n        if (msg.sender != address(bridge__)) revert NotBridge();\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    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        bridge__.receiveInbound(siblingChainSlug_, payload_);\n    }\n\n    /**\n     * @notice this function calculates the fees needed to send the message to Socket.\n     * @param msgGasLimit_ min gas limit needed at destination chain to execute the message.\n     */\n    function getMinFees(\n        uint256 msgGasLimit_,\n        uint256 payloadSize_\n    ) external view returns (uint256 totalFees) {\n        return\n            socket__.getMinFees(\n                msgGasLimit_,\n                payloadSize_,\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        messageIdPart =\n            (uint256(socket__.chainSlug()) << 224) |\n            (uint256(uint160(siblingPlug_)) << 64);\n\n        socket__.connect(\n            siblingChainSlug,\n            siblingPlug_,\n            switchboard_,\n            switchboard_\n        );\n    }\n\n    function disconnect() external onlyOwner {\n        messageIdPart = 0;\n\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 this function is used to calculate message id before sending outbound().\n     * @return messageId\n     */\n    function getMessageId() external view returns (bytes32) {\n        return bytes32(messageIdPart | (socket__.globalMessageCount()));\n    }\n}\n"
      },
      "contracts/hooks/Controller_YieldLimitExecHook.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\";\nimport {FixedPointMathLib} from \"lib/solmate/src/utils/FixedPointMathLib.sol\";\nimport {IStrategy} from \"../interfaces/IStrategy.sol\";\nimport {IMintableERC20} from \"../interfaces/IMintableERC20.sol\";\nimport \"lib/solmate/src/utils/SafeTransferLib.sol\";\nimport {IConnector} from \"../ConnectorPlug.sol\";\nimport \"./LimitExecutionHook.sol\";\n\ninterface IYieldToken {\n    function updateTotalUnderlyingAssets(uint256 amount_) external;\n\n    function calculateMintAmount(uint256 amount_) external returns (uint256);\n\n    function convertToShares(\n        uint256 underlyingAssets\n    ) external view returns (uint256);\n\n    function transfer(address to_, uint256 amount_) external returns (bool);\n\n    function convertToAssets(uint256 shares) external view returns (uint256);\n}\n\n// limits on underlying or visible tokens\ncontract Controller_YieldLimitExecHook is LimitExecutionHook {\n    using SafeTransferLib for IMintableERC20;\n    using FixedPointMathLib for uint256;\n\n    uint256 private constant MAX_BPS = 10_000;\n    IYieldToken public immutable yieldToken__;\n\n    // total yield\n    uint256 public totalUnderlyingAssets;\n\n    // if true, no funds can be invested in the strategy\n    bool public emergencyShutdown;\n\n    event ShutdownStateUpdated(bool shutdownState);\n\n    modifier notShutdown() {\n        if (emergencyShutdown) revert VaultShutdown();\n        _;\n    }\n\n    constructor(\n        address underlyingAsset_,\n        address controller_,\n        address executionHelper_\n    ) LimitExecutionHook(msg.sender, controller_, executionHelper_, true) {\n        yieldToken__ = IYieldToken(underlyingAsset_);\n        hookType = LIMIT_EXECUTION_YIELD_TOKEN_HOOK;\n        _grantRole(LIMIT_UPDATER_ROLE, msg.sender);\n    }\n\n    // assumed transfer info inputs are validated at controller\n    // transfer info data is untrusted\n    function srcPreHookCall(\n        SrcPreHookCallParams calldata params_\n    )\n        public\n        override\n        notShutdown\n        returns (TransferInfo memory transferInfo, bytes memory postSrcHookData)\n    {\n        super.srcPreHookCall(params_);\n        uint256 amount = params_.transferInfo.amount;\n        postSrcHookData = abi.encode(amount);\n\n        totalUnderlyingAssets -= amount;\n        transferInfo = params_.transferInfo;\n        transferInfo.amount = yieldToken__.convertToShares(amount);\n    }\n\n    function srcPostHookCall(\n        SrcPostHookCallParams memory srcPostHookCallParams_\n    )\n        public\n        override\n        isVaultOrController\n        returns (TransferInfo memory transferInfo)\n    {\n        yieldToken__.updateTotalUnderlyingAssets(totalUnderlyingAssets);\n\n        transferInfo.receiver = srcPostHookCallParams_.transferInfo.receiver;\n        transferInfo.data = abi.encode(\n            srcPostHookCallParams_.options,\n            srcPostHookCallParams_.transferInfo.data\n        );\n        transferInfo.amount = abi.decode(\n            srcPostHookCallParams_.postSrcHookData,\n            (uint256)\n        );\n    }\n\n    /**\n     * @notice This function is called before the execution of a destination hook.\n     * @dev It checks if the sibling chain is supported, consumes a part of the limit, and prepares post-hook data.\n     */\n    function dstPreHookCall(\n        DstPreHookCallParams calldata params_\n    )\n        public\n        override\n        notShutdown\n        isVaultOrController\n        returns (bytes memory postHookData, TransferInfo memory transferInfo)\n    {\n        (uint256 increasedUnderlying, bytes memory payload) = abi.decode(\n            params_.transferInfo.data,\n            (uint256, bytes)\n        );\n\n        _poolDstHook(params_.connector, increasedUnderlying);\n        totalUnderlyingAssets += increasedUnderlying;\n        yieldToken__.updateTotalUnderlyingAssets(totalUnderlyingAssets);\n\n        yieldToken__.updateTotalUnderlyingAssets(totalUnderlyingAssets);\n\n        if (params_.transferInfo.amount == 0)\n            return (abi.encode(0, 0, 0, address(0)), transferInfo);\n\n        (uint256 consumedUnderlying, uint256 pendingUnderlying) = _limitDstHook(\n            params_.connector,\n            params_.transferInfo.amount\n        );\n        uint256 sharesToMint = yieldToken__.calculateMintAmount(\n            params_.transferInfo.amount\n        );\n\n        postHookData = abi.encode(\n            consumedUnderlying,\n            pendingUnderlying,\n            params_.transferInfo.amount,\n            params_.transferInfo.receiver\n        );\n\n        transferInfo = params_.transferInfo;\n        if (pendingUnderlying != 0) transferInfo.receiver = address(this);\n        transferInfo.amount = sharesToMint;\n        transferInfo.data = payload;\n    }\n\n    /**\n     * @notice Handles post-hook logic after the execution of a destination hook.\n     * @dev This function processes post-hook data to update the identifier cache and sibling chain cache.\n     */\n    function dstPostHookCall(\n        DstPostHookCallParams calldata params_\n    )\n        public\n        override\n        isVaultOrController\n        notShutdown\n        returns (CacheData memory cacheData)\n    {\n        (\n            uint256 consumedUnderlying,\n            uint256 pendingUnderlying,\n            uint256 depositUnderlying,\n            address receiver\n        ) = abi.decode(\n                params_.postHookData,\n                (uint256, uint256, uint256, address)\n            );\n        bytes memory execPayload = params_.transferInfo.data;\n\n        uint256 connectorPendingShares = _getConnectorPendingAmount(\n            params_.connectorCache\n        );\n\n        uint256 pendingShares;\n        if (pendingUnderlying > 0) {\n            // totalShares * consumedU / totalU\n            uint256 consumedShares = (params_.transferInfo.amount *\n                pendingUnderlying) / depositUnderlying;\n\n            pendingShares = params_.transferInfo.amount - consumedShares;\n\n            cacheData.identifierCache = abi.encode(\n                params_.transferInfo.receiver,\n                pendingShares,\n                params_.connector,\n                execPayload\n            );\n            yieldToken__.transfer(receiver, consumedUnderlying);\n\n            emit TokensPending(\n                params_.connector,\n                params_.transferInfo.receiver,\n                consumedShares,\n                pendingShares,\n                params_.messageId\n            );\n        } else {\n            if (execPayload.length > 0) {\n                // execute\n                bool success = executionHelper__.execute(\n                    params_.transferInfo.receiver,\n                    execPayload,\n                    params_.messageId,\n                    depositUnderlying\n                );\n\n                if (success) {\n                    emit MessageExecuted(\n                        params_.messageId,\n                        params_.transferInfo.receiver\n                    );\n                    cacheData.identifierCache = new bytes(0);\n                } else\n                    cacheData.identifierCache = abi.encode(\n                        params_.transferInfo.receiver,\n                        0,\n                        params_.connector,\n                        execPayload\n                    );\n            } else cacheData.identifierCache = new bytes(0);\n        }\n\n        cacheData.connectorCache = abi.encode(\n            connectorPendingShares + pendingShares\n        );\n    }\n\n    // /**\n    //  * @notice Handles pre-retry hook logic before execution.\n    //  * @dev This function can be used to mint funds which were in a pending state due to limits.\n    //  * @param siblingChainSlug_ The unique identifier of the sibling chain.\n    //  * @param identifierCache_ Identifier cache containing pending mint information.\n    //  * @param connectorCache_ Sibling chain cache containing pending amount information.\n    //  * @return updatedReceiver The updated receiver of the funds.\n    //  * @return consumedUnderlying The amount consumed from the limit.\n    //  * @return postRetryHookData The post-hook data to be processed after the retry hook execution.\n    //  */\n    function preRetryHook(\n        PreRetryHookCallParams calldata params_\n    )\n        public\n        override\n        isVaultOrController\n        notShutdown\n        returns (\n            bytes memory postRetryHookData,\n            TransferInfo memory transferInfo\n        )\n    {\n        (\n            address receiver,\n            uint256 totalPendingShares,\n            address connector,\n\n        ) = abi.decode(\n                params_.cacheData.identifierCache,\n                (address, uint256, address, bytes)\n            );\n\n        if (connector != params_.connector) revert InvalidConnector();\n\n        (uint256 consumedShares, uint256 pendingShares) = _limitDstHook(\n            params_.connector,\n            totalPendingShares\n        );\n\n        postRetryHookData = abi.encode(receiver, consumedShares, pendingShares);\n        uint256 consumedUnderlying = yieldToken__.convertToAssets(\n            consumedShares\n        );\n        yieldToken__.transfer(receiver, consumedUnderlying);\n\n        transferInfo = TransferInfo(transferInfo.receiver, 0, bytes(\"\"));\n    }\n\n    // /**\n    //  * @notice Handles post-retry hook logic after execution.\n    //  * @dev This function updates the identifier cache and sibling chain cache based on the post-hook data.\n    //  * @param siblingChainSlug_ The unique identifier of the sibling chain.\n    //  * @param identifierCache_ Identifier cache containing pending mint information.\n    //  * @param connectorCache_ Sibling chain cache containing pending amount information.\n    //  * @param postRetryHookData_ The post-hook data containing updated receiver and consumed/pending amounts.\n    //  * @return newIdentifierCache The updated identifier cache.\n    //  * @return newConnectorCache The updated sibling chain cache.\n    //  */\n    function postRetryHook(\n        PostRetryHookCallParams calldata params_\n    ) public override returns (CacheData memory cacheData) {\n        return super.postRetryHook(params_);\n    }\n\n    function updateEmergencyShutdownState(\n        bool shutdownState_\n    ) external onlyOwner {\n        emergencyShutdown = shutdownState_;\n        emit ShutdownStateUpdated(shutdownState_);\n    }\n}\n"
      },
      "contracts/hooks/HookBase.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/solmate/src/utils/ReentrancyGuard.sol\";\nimport \"../common/Errors.sol\";\nimport \"../common/Constants.sol\";\nimport \"../interfaces/IHook.sol\";\nimport \"../utils/RescueBase.sol\";\n\n/**\n * @title Base contract for super token and vault\n * @notice It contains relevant execution payload storages.\n * @dev This contract implements Socket's IPlug to enable message bridging and IMessageBridge\n * to support any type of message bridge.\n */\nabstract contract HookBase is ReentrancyGuard, IHook, RescueBase {\n    address public immutable vaultOrController;\n    bytes32 public hookType;\n\n    /**\n     * @notice Constructor for creating a new SuperToken.\n     */\n    constructor(\n        address owner_,\n        address vaultOrController_\n    ) AccessControl(owner_) {\n        vaultOrController = vaultOrController_;\n        _grantRole(RESCUE_ROLE, owner_);\n    }\n\n    modifier isVaultOrController() {\n        if (msg.sender != vaultOrController) revert NotAuthorized();\n        _;\n    }\n}\n"
      },
      "contracts/hooks/LimitExecutionHook.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./plugins/LimitPlugin.sol\";\nimport \"./plugins/ExecutionHelper.sol\";\nimport \"./plugins/ConnectorPoolPlugin.sol\";\nimport \"../interfaces/IController.sol\";\n\ncontract LimitExecutionHook is LimitPlugin, ConnectorPoolPlugin {\n    bool public useControllerPools;\n    ExecutionHelper executionHelper__;\n\n    event MessageExecuted(bytes32 indexed messageId, address indexed receiver);\n\n    /**\n     * @notice Constructor for creating a new SuperToken.\n     * @param owner_ Owner of this contract.\n     */\n    constructor(\n        address owner_,\n        address controller_,\n        address executionHelper_,\n        bool useControllerPools_\n    ) HookBase(owner_, controller_) {\n        useControllerPools = useControllerPools_;\n        executionHelper__ = ExecutionHelper(executionHelper_);\n        hookType = LIMIT_EXECUTION_HOOK;\n        _grantRole(LIMIT_UPDATER_ROLE, owner_);\n    }\n\n    function setExecutionHelper(address executionHelper_) external onlyOwner {\n        executionHelper__ = ExecutionHelper(executionHelper_);\n    }\n\n    function srcPreHookCall(\n        SrcPreHookCallParams calldata params_\n    )\n        public\n        virtual\n        isVaultOrController\n        returns (TransferInfo memory, bytes memory)\n    {\n        if (useControllerPools)\n            _poolSrcHook(params_.connector, params_.transferInfo.amount);\n        _limitSrcHook(params_.connector, params_.transferInfo.amount);\n        return (params_.transferInfo, bytes(\"\"));\n    }\n\n    function srcPostHookCall(\n        SrcPostHookCallParams memory params_\n    ) public virtual isVaultOrController returns (TransferInfo memory) {\n        return params_.transferInfo;\n    }\n\n    function dstPreHookCall(\n        DstPreHookCallParams calldata params_\n    )\n        public\n        virtual\n        isVaultOrController\n        returns (bytes memory postHookData, TransferInfo memory transferInfo)\n    {\n        if (useControllerPools)\n            _poolDstHook(params_.connector, params_.transferInfo.amount);\n\n        (uint256 consumedAmount, uint256 pendingAmount) = _limitDstHook(\n            params_.connector,\n            params_.transferInfo.amount\n        );\n        postHookData = abi.encode(\n            consumedAmount,\n            pendingAmount,\n            params_.transferInfo.amount\n        );\n        transferInfo = params_.transferInfo;\n        transferInfo.amount = consumedAmount;\n    }\n\n    function dstPostHookCall(\n        DstPostHookCallParams calldata params_\n    ) public virtual isVaultOrController returns (CacheData memory cacheData) {\n        bytes memory execPayload = params_.transferInfo.data;\n\n        (\n            uint256 consumedAmount,\n            uint256 pendingAmount,\n            uint256 bridgeAmount\n        ) = abi.decode(params_.postHookData, (uint256, uint256, uint256));\n\n        uint256 connectorPendingAmount = _getConnectorPendingAmount(\n            params_.connectorCache\n        );\n        cacheData.connectorCache = abi.encode(\n            connectorPendingAmount + pendingAmount\n        );\n        cacheData.identifierCache = abi.encode(\n            params_.transferInfo.receiver,\n            pendingAmount,\n            bridgeAmount,\n            params_.connector,\n            execPayload\n        );\n\n        if (pendingAmount > 0) {\n            emit TokensPending(\n                params_.connector,\n                params_.transferInfo.receiver,\n                consumedAmount,\n                pendingAmount,\n                params_.messageId\n            );\n        } else {\n            if (execPayload.length > 0) {\n                // execute\n                bool success = executionHelper__.execute(\n                    params_.transferInfo.receiver,\n                    execPayload,\n                    params_.messageId,\n                    bridgeAmount\n                );\n\n                if (success) {\n                    emit MessageExecuted(\n                        params_.messageId,\n                        params_.transferInfo.receiver\n                    );\n                    cacheData.identifierCache = new bytes(0);\n                }\n            } else cacheData.identifierCache = new bytes(0);\n        }\n    }\n\n    function preRetryHook(\n        PreRetryHookCallParams calldata params_\n    )\n        public\n        virtual\n        isVaultOrController\n        returns (\n            bytes memory postRetryHookData,\n            TransferInfo memory transferInfo\n        )\n    {\n        (address receiver, uint256 pendingMint, , address connector, ) = abi\n            .decode(\n                params_.cacheData.identifierCache,\n                (address, uint256, uint256, address, bytes)\n            );\n\n        if (connector != params_.connector) revert InvalidConnector();\n\n        (uint256 consumedAmount, uint256 pendingAmount) = _limitDstHook(\n            params_.connector,\n            pendingMint\n        );\n\n        postRetryHookData = abi.encode(receiver, consumedAmount, pendingAmount);\n        transferInfo = TransferInfo(receiver, consumedAmount, bytes(\"\"));\n    }\n\n    function postRetryHook(\n        PostRetryHookCallParams calldata params_\n    ) public virtual isVaultOrController returns (CacheData memory cacheData) {\n        (\n            ,\n            ,\n            uint256 bridgeAmount,\n            address connector,\n            bytes memory execPayload\n        ) = abi.decode(\n                params_.cacheData.identifierCache,\n                (address, uint256, uint256, address, bytes)\n            );\n\n        (address receiver, uint256 consumedAmount, uint256 pendingAmount) = abi\n            .decode(params_.postRetryHookData, (address, uint256, uint256));\n\n        uint256 connectorPendingAmount = _getConnectorPendingAmount(\n            params_.cacheData.connectorCache\n        );\n\n        cacheData.connectorCache = abi.encode(\n            connectorPendingAmount - consumedAmount\n        );\n        cacheData.identifierCache = abi.encode(\n            receiver,\n            pendingAmount,\n            bridgeAmount,\n            connector,\n            execPayload\n        );\n\n        emit PendingTokensBridged(\n            params_.connector,\n            receiver,\n            consumedAmount,\n            pendingAmount,\n            params_.messageId\n        );\n\n        if (pendingAmount == 0) {\n            // receiver is not an input from user, can receiver check\n            // no connector check required here, as already done in preRetryHook call in same tx\n\n            // execute\n            bool success = executionHelper__.execute(\n                receiver,\n                execPayload,\n                params_.messageId,\n                bridgeAmount\n            );\n            if (success) {\n                emit MessageExecuted(params_.messageId, receiver);\n                cacheData.identifierCache = new bytes(0);\n            }\n        }\n    }\n\n    function getConnectorPendingAmount(\n        address connector_\n    ) external returns (uint256) {\n        bytes memory cache = IController(vaultOrController).connectorCache(\n            connector_\n        );\n        return _getConnectorPendingAmount(cache);\n    }\n\n    function _getIdentifierPendingAmount(\n        bytes memory identifierCache_\n    ) internal pure returns (uint256) {\n        if (identifierCache_.length > 0) {\n            (, uint256 pendingAmount, , , ) = abi.decode(\n                identifierCache_,\n                (address, uint256, uint256, address, bytes)\n            );\n            return pendingAmount;\n        } else return 0;\n    }\n\n    function getIdentifierPendingAmount(\n        bytes32 messageId_\n    ) external returns (uint256) {\n        bytes memory cache = IController(vaultOrController).identifierCache(\n            messageId_\n        );\n        return _getIdentifierPendingAmount(cache);\n    }\n}\n"
      },
      "contracts/hooks/LimitHook.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"./plugins/LimitPlugin.sol\";\nimport \"../interfaces/IController.sol\";\nimport \"./plugins/ConnectorPoolPlugin.sol\";\n\ncontract LimitHook is LimitPlugin, ConnectorPoolPlugin {\n    bool public immutable useControllerPools;\n\n    /**\n     * @notice Constructor for creating a new SuperToken.\n     * @param owner_ Owner of this contract.\n     */\n    constructor(\n        address owner_,\n        address controller_,\n        bool useControllerPools_\n    ) HookBase(owner_, controller_) {\n        useControllerPools = useControllerPools_;\n        hookType = LIMIT_HOOK;\n        _grantRole(LIMIT_UPDATER_ROLE, owner_);\n    }\n\n    function srcPreHookCall(\n        SrcPreHookCallParams memory params_\n    )\n        external\n        isVaultOrController\n        returns (TransferInfo memory transferInfo, bytes memory postHookData)\n    {\n        if (useControllerPools)\n            _poolSrcHook(params_.connector, params_.transferInfo.amount);\n\n        _limitSrcHook(params_.connector, params_.transferInfo.amount);\n        transferInfo = params_.transferInfo;\n        postHookData = hex\"\";\n    }\n\n    function srcPostHookCall(\n        SrcPostHookCallParams memory params_\n    ) external view isVaultOrController returns (TransferInfo memory) {\n        return params_.transferInfo;\n    }\n\n    function dstPreHookCall(\n        DstPreHookCallParams memory params_\n    )\n        external\n        isVaultOrController\n        returns (bytes memory postHookData, TransferInfo memory transferInfo)\n    {\n        if (useControllerPools)\n            _poolDstHook(params_.connector, params_.transferInfo.amount);\n\n        (uint256 consumedAmount, uint256 pendingAmount) = _limitDstHook(\n            params_.connector,\n            params_.transferInfo.amount\n        );\n        postHookData = abi.encode(consumedAmount, pendingAmount);\n        transferInfo = params_.transferInfo;\n        transferInfo.amount = consumedAmount;\n    }\n\n    function dstPostHookCall(\n        DstPostHookCallParams memory params_\n    ) external isVaultOrController returns (CacheData memory cacheData) {\n        (uint256 consumedAmount, uint256 pendingAmount) = abi.decode(\n            params_.postHookData,\n            (uint256, uint256)\n        );\n        uint256 connectorPendingAmount = _getConnectorPendingAmount(\n            params_.connectorCache\n        );\n        if (pendingAmount > 0) {\n            cacheData = CacheData(\n                abi.encode(\n                    params_.transferInfo.receiver,\n                    pendingAmount,\n                    params_.connector\n                ),\n                abi.encode(connectorPendingAmount + pendingAmount)\n            );\n\n            emit TokensPending(\n                params_.connector,\n                params_.transferInfo.receiver,\n                consumedAmount,\n                pendingAmount,\n                params_.messageId\n            );\n        } else {\n            cacheData = CacheData(\n                bytes(\"\"),\n                abi.encode(connectorPendingAmount + pendingAmount)\n            );\n        }\n    }\n\n    function preRetryHook(\n        PreRetryHookCallParams memory params_\n    )\n        external\n        nonReentrant\n        isVaultOrController\n        returns (\n            bytes memory postRetryHookData,\n            TransferInfo memory transferInfo\n        )\n    {\n        (address updatedReceiver, uint256 pendingMint, address connector) = abi\n            .decode(\n                params_.cacheData.identifierCache,\n                (address, uint256, address)\n            );\n\n        if (connector != params_.connector) revert InvalidConnector();\n\n        (uint256 consumedAmount, uint256 pendingAmount) = _limitDstHook(\n            params_.connector,\n            pendingMint\n        );\n\n        postRetryHookData = abi.encode(\n            updatedReceiver,\n            consumedAmount,\n            pendingAmount\n        );\n        transferInfo = TransferInfo(updatedReceiver, consumedAmount, bytes(\"\"));\n    }\n\n    function postRetryHook(\n        PostRetryHookCallParams calldata params_\n    )\n        external\n        isVaultOrController\n        nonReentrant\n        returns (CacheData memory cacheData)\n    {\n        (\n            address updatedReceiver,\n            uint256 consumedAmount,\n            uint256 pendingAmount\n        ) = abi.decode(params_.postRetryHookData, (address, uint256, uint256));\n\n        // code reaches here after minting/unlocking the pending amount\n        emit PendingTokensBridged(\n            params_.connector,\n            updatedReceiver,\n            consumedAmount,\n            pendingAmount,\n            params_.messageId\n        );\n\n        uint256 connectorPendingAmount = _getConnectorPendingAmount(\n            params_.cacheData.connectorCache\n        );\n        cacheData.connectorCache = abi.encode(\n            connectorPendingAmount - consumedAmount\n        );\n        cacheData.identifierCache = abi.encode(\n            updatedReceiver,\n            pendingAmount,\n            params_.connector\n        );\n\n        if (pendingAmount == 0) {\n            cacheData.identifierCache = new bytes(0);\n        }\n    }\n\n    function getConnectorPendingAmount(\n        address connector_\n    ) external returns (uint256) {\n        bytes memory cache = IController(vaultOrController).connectorCache(\n            connector_\n        );\n        return _getConnectorPendingAmount(cache);\n    }\n\n    function _getIdentifierPendingAmount(\n        bytes memory identifierCache_\n    ) internal pure returns (uint256) {\n        if (identifierCache_.length > 0) {\n            (, uint256 pendingAmount, ) = abi.decode(\n                identifierCache_,\n                (address, uint256, address)\n            );\n            return pendingAmount;\n        } else return 0;\n    }\n\n    function getIdentifierPendingAmount(\n        bytes32 messageId_\n    ) external returns (uint256) {\n        bytes memory cache = IController(vaultOrController).identifierCache(\n            messageId_\n        );\n        return _getIdentifierPendingAmount(cache);\n    }\n}\n"
      },
      "contracts/hooks/plugins/ConnectorPoolPlugin.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\nimport \"../HookBase.sol\";\n\nabstract contract ConnectorPoolPlugin is HookBase {\n    // connectorPoolId => totalLockedAmount\n    mapping(uint256 => uint256) public poolLockedAmounts;\n\n    // connector => connectorPoolId\n    mapping(address => uint256) public connectorPoolIds;\n\n    event ConnectorPoolIdUpdated(address connector, uint256 poolId);\n    event PoolLockedAmountUpdated(uint256 poolId, uint256 amount);\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 updatePoolLockedAmounts(\n        uint256[] calldata poolIds_,\n        uint256[] calldata amounts_\n    ) external onlyOwner {\n        uint256 length = poolIds_.length;\n        for (uint256 i; i < length; i++) {\n            if (poolIds_[i] == 0) revert InvalidPoolId();\n            poolLockedAmounts[poolIds_[i]] = amounts_[i];\n            emit PoolLockedAmountUpdated(poolIds_[i], amounts_[i]);\n        }\n    }\n\n    function _poolSrcHook(address connector_, uint256 amount_) internal {\n        uint256 connectorPoolId = connectorPoolIds[connector_];\n        if (connectorPoolId == 0) revert InvalidPoolId();\n        if (amount_ > poolLockedAmounts[connectorPoolId])\n            revert InsufficientFunds();\n\n        poolLockedAmounts[connectorPoolId] -= amount_;\n    }\n\n    function _poolDstHook(\n        address connector_,\n        uint256 amount_\n    ) internal returns (uint256 oldLockedAmount) {\n        uint256 connectorPoolId = connectorPoolIds[connector_];\n        if (connectorPoolId == 0) revert InvalidPoolId();\n\n        oldLockedAmount = poolLockedAmounts[connectorPoolId];\n        poolLockedAmounts[connectorPoolId] += amount_;\n    }\n}\n"
      },
      "contracts/hooks/plugins/ExecutionHelper.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../../libraries/ExcessivelySafeCall.sol\";\nimport \"../../utils/RescueBase.sol\";\nimport \"../../common/Errors.sol\";\n\n/**\n * @title ExecutionHelper\n * @notice It is an untrusted contract used for payload execution by Super token and Vault.\n */\ncontract ExecutionHelper is RescueBase {\n    using ExcessivelySafeCall for address;\n    uint16 private constant MAX_COPY_BYTES = 0;\n    address public hook;\n    bytes32 public messageId;\n    uint256 public bridgeAmount;\n\n    constructor(address owner_) AccessControl(owner_) {\n        _grantRole(RESCUE_ROLE, owner_);\n    }\n\n    modifier onlyHook() {\n        require(msg.sender == hook, \"ExecutionHelper: only hook\");\n        _;\n    }\n\n    function setHook(address hook_) external onlyOwner {\n        hook = hook_;\n    }\n\n    /**\n     * @notice this function is used to execute a payload at target_\n     * @dev receiver address cannot be 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        bytes32 messageId_,\n        uint256 bridgeAmount_\n    ) external onlyHook returns (bool success) {\n        if (target_ == address(this)) return false;\n\n        messageId = messageId_;\n        bridgeAmount = bridgeAmount_;\n\n        (success, ) = target_.excessivelySafeCall(\n            gasleft(),\n            MAX_COPY_BYTES,\n            payload_\n        );\n\n        messageId = bytes32(0);\n        bridgeAmount = 0;\n    }\n}\n"
      },
      "contracts/hooks/plugins/LimitPlugin.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"../HookBase.sol\";\nimport {Gauge} from \"../../utils/Gauge.sol\";\n\nabstract contract LimitPlugin is Gauge, HookBase {\n    bytes32 constant LIMIT_UPDATER_ROLE = keccak256(\"LIMIT_UPDATER_ROLE\");\n\n    // connector => receivingLimitParams\n    mapping(address => LimitParams) _receivingLimitParams;\n\n    // connector => sendingLimitParams\n    mapping(address => LimitParams) _sendingLimitParams;\n\n    ////////////////////////////////////////////////////////\n    ////////////////////// EVENTS //////////////////////////\n    ////////////////////////////////////////////////////////\n\n    // Emitted when limit parameters are updated\n    event LimitParamsUpdated(UpdateLimitParams[] updates);\n\n    // Emitted when pending tokens are minted to the receiver\n    event PendingTokensBridged(\n        address connector,\n        address receiver,\n        uint256 consumedAmount,\n        uint256 pendingAmount,\n        bytes32 messageId\n    );\n    // Emitted when the transfer reaches the limit, and the token mint is added to the pending queue\n    event TokensPending(\n        address connector,\n        address receiver,\n        uint256 consumedAmount,\n        uint256 pendingAmount,\n        bytes32 messageId\n    );\n\n    /**\n     * @notice This function is used to set bridge limits.\n     * @dev It can only be updated by the owner.\n     * @param updates An array of structs containing update parameters.\n     */\n    function updateLimitParams(\n        UpdateLimitParams[] calldata updates\n    ) external onlyRole(LIMIT_UPDATER_ROLE) {\n        for (uint256 i = 0; i < updates.length; i++) {\n            if (updates[i].isMint) {\n                _consumePartLimit(\n                    0,\n                    _receivingLimitParams[updates[i].connector]\n                ); // To keep the current limit in sync\n                _receivingLimitParams[updates[i].connector].maxLimit = updates[\n                    i\n                ].maxLimit;\n                _receivingLimitParams[updates[i].connector]\n                    .ratePerSecond = updates[i].ratePerSecond;\n            } else {\n                _consumePartLimit(0, _sendingLimitParams[updates[i].connector]); // To keep the current limit in sync\n                _sendingLimitParams[updates[i].connector].maxLimit = updates[i]\n                    .maxLimit;\n                _sendingLimitParams[updates[i].connector]\n                    .ratePerSecond = updates[i].ratePerSecond;\n            }\n        }\n\n        emit LimitParamsUpdated(updates);\n    }\n\n    function getCurrentReceivingLimit(\n        address connector_\n    ) external view returns (uint256) {\n        return _getCurrentLimit(_receivingLimitParams[connector_]);\n    }\n\n    function getCurrentSendingLimit(\n        address connector_\n    ) external view returns (uint256) {\n        return _getCurrentLimit(_sendingLimitParams[connector_]);\n    }\n\n    function getReceivingLimitParams(\n        address connector_\n    ) external view returns (LimitParams memory) {\n        return _receivingLimitParams[connector_];\n    }\n\n    function getSendingLimitParams(\n        address connector_\n    ) external view returns (LimitParams memory) {\n        return _sendingLimitParams[connector_];\n    }\n\n    function _limitSrcHook(address connector_, uint256 amount_) internal {\n        if (_sendingLimitParams[connector_].maxLimit == 0)\n            revert SiblingNotSupported();\n\n        _consumeFullLimit(amount_, _sendingLimitParams[connector_]); // Reverts on limit hit\n    }\n\n    function _limitDstHook(\n        address connector_,\n        uint256 amount_\n    ) internal returns (uint256 consumedAmount, uint256 pendingAmount) {\n        if (_receivingLimitParams[connector_].maxLimit == 0)\n            revert SiblingNotSupported();\n\n        (consumedAmount, pendingAmount) = _consumePartLimit(\n            amount_,\n            _receivingLimitParams[connector_]\n        );\n    }\n\n    function _getConnectorPendingAmount(\n        bytes memory connectorCache_\n    ) internal pure returns (uint256) {\n        if (connectorCache_.length > 0) {\n            return abi.decode(connectorCache_, (uint256));\n        } else return 0;\n    }\n}\n"
      },
      "contracts/hooks/Vault_YieldLimitExecHook.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\";\nimport {FixedPointMathLib} from \"lib/solmate/src/utils/FixedPointMathLib.sol\";\nimport {IStrategy} from \"../interfaces/IStrategy.sol\";\nimport \"lib/solmate/src/tokens/ERC20.sol\";\n\nimport \"lib/solmate/src/utils/SafeTransferLib.sol\";\nimport {IConnector} from \"../ConnectorPlug.sol\";\n\nimport \"./LimitExecutionHook.sol\";\n\ncontract Vault_YieldLimitExecHook is LimitExecutionHook {\n    using SafeTransferLib for ERC20;\n    using FixedPointMathLib for uint256;\n\n    uint256 private constant MAX_BPS = 10_000;\n\n    IStrategy public strategy; // address of the strategy contract\n    ERC20 public immutable underlyingAsset__;\n\n    uint256 public totalLockedInStrategy; // total funds deposited in strategy\n\n    uint256 public totalIdle; // Amount of tokens that are in the vault\n    uint256 public totalDebt; // Amount of tokens that strategy have borrowed\n    uint128 public lastRebalanceTimestamp; // Timestamp of last rebalance\n\n    uint128 public rebalanceDelay; // Delay between rebalance\n    uint256 public debtRatio; // Debt ratio for the Vault (in BPS, <= 10k)\n    bool public emergencyShutdown; // if true, no funds can be invested in the strategy\n\n    uint256 public lastTotalUnderlyingAssetsSynced;\n\n    event WithdrawFromStrategy(uint256 withdrawn);\n    event Rebalanced(\n        uint256 totalIdle,\n        uint256 totalDebt,\n        uint256 credit,\n        uint256 debtOutstanding\n    );\n    event ShutdownStateUpdated(bool shutdownState);\n    event DebtRatioUpdated(uint256 debtRatio);\n    event StrategyUpdated(address strategy);\n    event RebalanceDelayUpdated(uint128 rebalanceDelay);\n\n    modifier notShutdown() {\n        if (emergencyShutdown) revert VaultShutdown();\n        _;\n    }\n\n    constructor(\n        uint256 debtRatio_,\n        uint128 rebalanceDelay_,\n        address strategy_,\n        address underlyingAsset_,\n        address vault_,\n        address executionHelper_,\n        bool useControllerPools_\n    )\n        LimitExecutionHook(\n            msg.sender,\n            vault_,\n            executionHelper_,\n            useControllerPools_\n        )\n    {\n        underlyingAsset__ = ERC20(underlyingAsset_);\n        debtRatio = debtRatio_;\n        rebalanceDelay = rebalanceDelay_;\n        strategy = IStrategy(strategy_);\n        hookType = LIMIT_EXECUTION_YIELD_HOOK;\n        _grantRole(LIMIT_UPDATER_ROLE, msg.sender);\n    }\n\n    /**\n     * @dev This function calls the srcHookCall function of the connector contract,\n     * passing in the receiver, amount, siblingChainSlug, extradata, and msg.sender, and returns\n     * the updated receiver, amount, and extradata.\n     */\n    function srcPreHookCall(\n        SrcPreHookCallParams calldata params_\n    ) public override notShutdown returns (TransferInfo memory, bytes memory) {\n        totalIdle += params_.transferInfo.amount;\n        return super.srcPreHookCall(params_);\n    }\n\n    function srcPostHookCall(\n        SrcPostHookCallParams memory srcPostHookCallParams_\n    )\n        public\n        override\n        isVaultOrController\n        returns (TransferInfo memory transferInfo)\n    {\n        _checkDelayAndRebalance();\n\n        uint256 totalUnderlyingAsset = strategy.estimatedTotalAssets() +\n            totalIdle;\n        uint256 totalYieldSync = totalUnderlyingAsset -\n            lastTotalUnderlyingAssetsSynced;\n        lastTotalUnderlyingAssetsSynced = totalUnderlyingAsset;\n\n        transferInfo = srcPostHookCallParams_.transferInfo;\n        if (srcPostHookCallParams_.transferInfo.amount == 0) {\n            transferInfo.data = abi.encode(totalYieldSync, bytes(\"\"));\n        } else {\n            transferInfo.data = abi.encode(\n                totalYieldSync,\n                srcPostHookCallParams_.transferInfo.data\n            );\n        }\n    }\n\n    /**\n     * @notice This function is called before the execution of a destination hook.\n     * @dev It checks if the sibling chain is supported, consumes a part of the limit, and prepares post-hook data.\n     */\n    function dstPreHookCall(\n        DstPreHookCallParams calldata params_\n    )\n        public\n        override\n        notShutdown\n        returns (bytes memory postHookData, TransferInfo memory transferInfo)\n    {\n        (postHookData, transferInfo) = super.dstPreHookCall(params_);\n\n        // ensure vault have enough idle underlyingAssets\n        if (transferInfo.amount > totalUnderlyingAssets())\n            revert NotEnoughAssets();\n\n        (bytes memory options_, bytes memory payload_) = abi.decode(\n            params_.transferInfo.data,\n            (bytes, bytes)\n        );\n        bool pullFromStrategy = abi.decode(options_, (bool));\n\n        if (transferInfo.amount > totalIdle) {\n            if (pullFromStrategy) {\n                _withdrawFromStrategy(transferInfo.amount - totalIdle);\n            } else {\n                (\n                    uint256 consumedUnderlying,\n                    uint256 pendingUnderlying,\n                    uint256 bridgeUnderlying\n                ) = abi.decode(postHookData, (uint256, uint256, uint256));\n\n                pendingUnderlying += transferInfo.amount - totalIdle;\n                postHookData = abi.encode(\n                    transferInfo.amount,\n                    pendingUnderlying,\n                    bridgeUnderlying\n                );\n                transferInfo.amount = totalIdle;\n\n                // Update the lastUpdateLimit as consumedAmount is reduced to totalIdle. This is to ensure that the\n                // receiving limit is updated by correct transferred amount.\n                LimitParams storage receivingParams = _receivingLimitParams[\n                    params_.connector\n                ];\n\n                receivingParams.lastUpdateLimit +=\n                    consumedUnderlying -\n                    transferInfo.amount;\n            }\n            totalIdle = 0;\n        } else totalIdle -= transferInfo.amount;\n\n        transferInfo.data = payload_;\n        transferInfo.receiver = params_.transferInfo.receiver;\n    }\n\n    function dstPostHookCall(\n        DstPostHookCallParams calldata params_\n    ) public override returns (CacheData memory cacheData) {\n        return super.dstPostHookCall(params_);\n    }\n\n    /**\n     * @notice Handles pre-retry hook logic before execution.\n     * @dev This function can be used to mint funds which were in a pending state due to limits.\n     */\n    function preRetryHook(\n        PreRetryHookCallParams calldata params_\n    )\n        public\n        override\n        notShutdown\n        returns (\n            bytes memory postRetryHookData,\n            TransferInfo memory transferInfo\n        )\n    {\n        (postRetryHookData, transferInfo) = super.preRetryHook(params_);\n        if (transferInfo.amount > totalIdle) {\n            _withdrawFromStrategy(transferInfo.amount - totalIdle);\n            totalIdle = 0;\n        } else totalIdle -= transferInfo.amount;\n    }\n\n    function postRetryHook(\n        PostRetryHookCallParams calldata params_\n    ) public override returns (CacheData memory cacheData) {\n        return super.postRetryHook(params_);\n    }\n\n    function withdrawFromStrategy(\n        uint256 underlyingAsset_\n    ) external onlyOwner returns (uint256) {\n        return _withdrawFromStrategy(underlyingAsset_);\n    }\n\n    function _withdrawFromStrategy(\n        uint256 underlyingAsset_\n    ) internal returns (uint256 withdrawn) {\n        uint256 preBalance = underlyingAsset__.balanceOf(address(this));\n        strategy.withdraw(underlyingAsset_);\n        withdrawn = underlyingAsset__.balanceOf(address(this)) - preBalance;\n        totalIdle += withdrawn;\n        totalDebt -= withdrawn;\n\n        underlyingAsset__.transfer(vaultOrController, withdrawn);\n        emit WithdrawFromStrategy(withdrawn);\n    }\n\n    function _withdrawAllFromStrategy() internal returns (uint256) {\n        uint256 preBalance = underlyingAsset__.balanceOf(address(this));\n        strategy.withdrawAll();\n        uint256 withdrawn = underlyingAsset__.balanceOf(address(this)) -\n            preBalance;\n        totalIdle += withdrawn;\n        totalDebt = 0;\n\n        underlyingAsset__.transfer(vaultOrController, withdrawn);\n        emit WithdrawFromStrategy(withdrawn);\n        return withdrawn;\n    }\n\n    function rebalance() external notShutdown {\n        _rebalance();\n    }\n\n    function _checkDelayAndRebalance() internal {\n        uint128 timeElapsed = uint128(block.timestamp) - lastRebalanceTimestamp;\n        if (timeElapsed >= rebalanceDelay) {\n            _rebalance();\n        }\n    }\n\n    function _rebalance() internal {\n        if (address(strategy) == address(0)) return;\n        lastRebalanceTimestamp = uint128(block.timestamp);\n        // Compute the line of credit the Vault is able to offer the Strategy (if any)\n        uint256 credit = _creditAvailable();\n        uint256 pendingDebt = _debtOutstanding();\n\n        if (credit > 0) {\n            // Credit surplus, give to Strategy\n            totalIdle -= credit;\n            totalDebt += credit;\n            totalLockedInStrategy += credit;\n            underlyingAsset__.safeTransferFrom(\n                vaultOrController,\n                address(strategy),\n                credit\n            );\n            strategy.invest();\n        } else if (pendingDebt > 0) {\n            // Credit deficit, take from Strategy\n            _withdrawFromStrategy(pendingDebt);\n        }\n\n        emit Rebalanced(totalIdle, totalDebt, credit, pendingDebt);\n    }\n\n    /// @notice Returns the total quantity of all underlyingAssets under control of this\n    ///    Vault, whether they're loaned out to a Strategy, or currently held in\n    /// the Vault.\n    /// @return total quantity of all underlyingAssets under control of this Vault\n    function totalUnderlyingAssets() public view returns (uint256) {\n        return strategy.estimatedTotalAssets() + totalIdle;\n    }\n\n    function _creditAvailable() internal view returns (uint256) {\n        uint256 vaultTotalAssets = totalUnderlyingAssets();\n        uint256 vaultDebtLimit = (debtRatio * vaultTotalAssets) / MAX_BPS;\n        uint256 vaultTotalDebt = totalDebt;\n\n        if (vaultDebtLimit <= vaultTotalDebt) return 0;\n\n        // Start with debt limit left for the Strategy\n        uint256 availableCredit = vaultDebtLimit - vaultTotalDebt;\n\n        // Can only borrow up to what the contract has in reserve\n        // NOTE: Running near 100% is discouraged\n        return Math.min(availableCredit, totalIdle);\n    }\n\n    function creditAvailable() external view returns (uint256) {\n        // @notice\n        //     Amount of tokens in Vault a Strategy has access to as a credit line.\n        //     This will check the Strategy's debt limit, as well as the tokens\n        //     available in the Vault, and determine the maximum amount of tokens\n        //     (if any) the Strategy may draw on.\n        //     In the rare case the Vault is in emergency shutdown this will return 0.\n        // @param strategy The Strategy to check. Defaults to caller.\n        // @return The quantity of tokens available for the Strategy to draw on.\n\n        return _creditAvailable();\n    }\n\n    function _debtOutstanding() internal view returns (uint256) {\n        // See note on `debtOutstanding()`.\n        if (debtRatio == 0) {\n            return totalDebt;\n        }\n\n        uint256 debtLimit = ((debtRatio * totalUnderlyingAssets()) / MAX_BPS);\n\n        if (totalDebt <= debtLimit) return 0;\n        else return totalDebt - debtLimit;\n    }\n\n    function debtOutstanding() external view returns (uint256) {\n        // @notice\n        //     Determines if `strategy` is past its debt limit and if any tokens\n        //     should be withdrawn to the Vault.\n        // @return The quantity of tokens to withdraw.\n\n        return _debtOutstanding();\n    }\n\n    function updateEmergencyShutdownState(\n        bool shutdownState_,\n        bool detachStrategy\n    ) external onlyOwner {\n        if (shutdownState_ && detachStrategy) {\n            // If we're exiting emergency shutdown, we need to empty strategy\n            _withdrawAllFromStrategy();\n            strategy = IStrategy(address(0));\n        }\n        emergencyShutdown = shutdownState_;\n        emit ShutdownStateUpdated(shutdownState_);\n    }\n\n    ////////////////////////////////////////////////////////\n    ////////////////////// SETTERS //////////////////////////\n    ////////////////////////////////////////////////////////\n\n    function setDebtRatio(uint256 debtRatio_) external onlyOwner {\n        if (debtRatio_ > MAX_BPS) revert DebtRatioTooHigh();\n        debtRatio = debtRatio_;\n\n        emit DebtRatioUpdated(debtRatio_);\n    }\n\n    function setStrategy(address strategy_) external onlyOwner {\n        strategy = IStrategy(strategy_);\n        emit StrategyUpdated(strategy_);\n    }\n\n    function setRebalanceDelay(uint128 rebalanceDelay_) external onlyOwner {\n        rebalanceDelay = rebalanceDelay_;\n        emit RebalanceDelayUpdated(rebalanceDelay_);\n    }\n}\n"
      },
      "contracts/interfaces/IBridge.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\ninterface IBridge {\n    function bridge(\n        address receiver_,\n        uint256 amount_,\n        uint256 msgGasLimit_,\n        address connector_,\n        bytes calldata execPayload_,\n        bytes calldata options_\n    ) external payable;\n\n    function receiveInbound(\n        uint32 siblingChainSlug_,\n        bytes memory payload_\n    ) external payable;\n\n    function retry(address connector_, bytes32 messageId_) external;\n}\n"
      },
      "contracts/interfaces/IConnector.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.13;\n\ninterface IConnector {\n    function outbound(\n        uint256 msgGasLimit_,\n        bytes memory payload_,\n        bytes memory options_\n    ) external payable returns (bytes32 messageId_);\n\n    function siblingChainSlug() external view returns (uint32);\n\n    function getMinFees(\n        uint256 msgGasLimit_,\n        uint256 payloadSize_\n    ) external view returns (uint256 totalFees);\n\n    function getMessageId() external view returns (bytes32);\n}\n"
      },
      "contracts/interfaces/IController.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.13;\n\ninterface IController {\n    function identifierCache(\n        bytes32 messageId_\n    ) external payable returns (bytes memory cache);\n\n    function connectorCache(\n        address connector_\n    ) external payable returns (bytes memory cache);\n}\n"
      },
      "contracts/interfaces/IHook.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\nimport \"../common/Structs.sol\";\n\ninterface IHook {\n    /**\n     * @notice Executes pre-hook call for source underlyingAsset.\n     * @dev This function is used to execute a pre-hook call for the source underlyingAsset before initiating a transfer.\n     * @param params_ Parameters for the pre-hook call.\n     * @return transferInfo Information about the transfer.\n     * @return postSrcHookData returned from the pre-hook call.\n     */\n    function srcPreHookCall(\n        SrcPreHookCallParams calldata params_\n    )\n        external\n        returns (\n            TransferInfo memory transferInfo,\n            bytes memory postSrcHookData\n        );\n\n    function srcPostHookCall(\n        SrcPostHookCallParams calldata params_\n    ) external returns (TransferInfo memory transferInfo);\n\n    /**\n     * @notice Executes pre-hook call for destination underlyingAsset.\n     * @dev This function is used to execute a pre-hook call for the destination underlyingAsset before initiating a transfer.\n     * @param params_ Parameters for the pre-hook call.\n     */\n    function dstPreHookCall(\n        DstPreHookCallParams calldata params_\n    )\n        external\n        returns (bytes memory postHookData, TransferInfo memory transferInfo);\n\n    /**\n     * @notice Executes post-hook call for destination underlyingAsset.\n     * @dev This function is used to execute a post-hook call for the destination underlyingAsset after completing a transfer.\n     * @param params_ Parameters for the post-hook call.\n     * @return cacheData Cached data for the post-hook call.\n     */\n    function dstPostHookCall(\n        DstPostHookCallParams calldata params_\n    ) external returns (CacheData memory cacheData);\n\n    /**\n     * @notice Executes a pre-retry hook for a failed transaction.\n     * @dev This function is used to execute a pre-retry hook for a failed transaction.\n     * @param params_ Parameters for the pre-retry hook.\n     * @return postRetryHookData Data from the post-retry hook.\n     * @return transferInfo Information about the transfer.\n     */\n    function preRetryHook(\n        PreRetryHookCallParams calldata params_\n    )\n        external\n        returns (\n            bytes memory postRetryHookData,\n            TransferInfo memory transferInfo\n        );\n\n    /**\n     * @notice Executes a post-retry hook for a failed transaction.\n     * @dev This function is used to execute a post-retry hook for a failed transaction.\n     * @param params_ Parameters for the post-retry hook.\n     * @return cacheData Cached data for the post-retry hook.\n     */\n    function postRetryHook(\n        PostRetryHookCallParams calldata params_\n    ) external returns (CacheData memory cacheData);\n}\n"
      },
      "contracts/interfaces/ILimitHook.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\nimport \"./IHook.sol\";\n\ninterface ILimitHook is IHook {\n    function updateLimitParams(UpdateLimitParams[] calldata updates) external;\n\n    function checkLimit(address user, uint256 amount) external view;\n\n    function getIdentifierPendingAmount(\n        bytes32 messageId_\n    ) external returns (uint256);\n\n    function getConnectorPendingAmount(\n        address connector_\n    ) external returns (uint256);\n\n    function getCurrentReceivingLimit(\n        address connector_\n    ) external view returns (uint256);\n\n    function getCurrentSendingLimit(\n        address connector_\n    ) external view returns (uint256);\n\n    function getReceivingLimitParams(\n        address connector_\n    ) external view returns (LimitParams memory);\n\n    function getSendingLimitParams(\n        address connector_\n    ) external view returns (LimitParams memory);\n}\n"
      },
      "contracts/interfaces/IMintableERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\ninterface IMintableERC20 {\n    function mint(address receiver_, uint256 amount_) external;\n\n    function burn(address burner_, uint256 amount_) external;\n}\n"
      },
      "contracts/interfaces/IPlug.sol": {
        "content": "// SPDX-License-Identifier: MIT\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: MIT\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/interfaces/IStrategy.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\n/**\n * @title IStrategy\n * @notice Interface for strategy contract which interacts with other protocols\n */\ninterface IStrategy {\n    function withdraw(uint256 amount_) external returns (uint256 loss_);\n\n    function withdrawAll() external;\n\n    function estimatedTotalAssets()\n        external\n        view\n        returns (uint256 totalUnderlyingAssets_);\n\n    function invest() external;\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\";\nimport \"lib/solmate/src/tokens/ERC20.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/token/SuperToken.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\n\nimport \"lib/solmate/src/tokens/ERC20.sol\";\nimport \"../utils/RescueBase.sol\";\nimport \"../interfaces/IHook.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 ERC20, RescueBase {\n    // for all controller access (mint, burn)\n    bytes32 constant CONTROLLER_ROLE = keccak256(\"CONTROLLER_ROLE\");\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     */\n    constructor(\n        string memory name_,\n        string memory symbol_,\n        uint8 decimals_,\n        address initialSupplyHolder_,\n        address owner_,\n        uint256 initialSupply_\n    ) ERC20(name_, symbol_, decimals_) AccessControl(owner_) {\n        _mint(initialSupplyHolder_, initialSupply_);\n        _grantRole(RESCUE_ROLE, owner_);\n    }\n\n    function burn(\n        address user_,\n        uint256 amount_\n    ) external onlyRole(CONTROLLER_ROLE) {\n        _burn(user_, amount_);\n    }\n\n    function mint(\n        address receiver_,\n        uint256 amount_\n    ) external onlyRole(CONTROLLER_ROLE) {\n        _mint(receiver_, amount_);\n    }\n}\n"
      },
      "contracts/token/yield-token/YieldToken.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity 0.8.13;\n\nimport \"./YieldTokenBase.sol\";\nimport {IStrategy} from \"../../interfaces/IStrategy.sol\";\nimport {IConnector} from \"../../interfaces/IConnector.sol\";\nimport {IHook} from \"../../interfaces/IHook.sol\";\n\n// add shutdown\ncontract YieldToken is YieldTokenBase {\n    using FixedPointMathLib for uint256;\n\n    bytes32 constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n    bytes32 constant HOOK_ROLE = keccak256(\"HOOK_ROLE\");\n\n    constructor(\n        string memory name_,\n        string memory symbol_,\n        uint8 decimals_\n    ) YieldTokenBase(name_, symbol_, decimals_) AccessControl(msg.sender) {\n        _grantRole(RESCUE_ROLE, msg.sender);\n    }\n\n    // move to hook\n    // fix to round up and check other cases\n    function calculateMintAmount(\n        uint256 underlyingAssets_\n    ) external view returns (uint256) {\n        // total supply -> total shares\n        // total yield -> total underlying from all chains\n        // yield sent from src chain includes new amount hence subtracted here\n        uint256 supply = _totalSupply; // Saves an extra SLOAD if _totalSupply is non-zero.\n        return\n            supply == 0\n                ? underlyingAssets_\n                : underlyingAssets_.mulDivDown(\n                    supply,\n                    totalUnderlyingAssets - underlyingAssets_\n                );\n    }\n\n    function burn(\n        address user_,\n        uint256 shares_\n    ) external nonReentrant onlyRole(MINTER_ROLE) {\n        _burn(user_, shares_);\n    }\n\n    // minter role\n    function mint(\n        address receiver_,\n        uint256 amount_\n    ) external nonReentrant onlyRole(MINTER_ROLE) {\n        _mint(receiver_, amount_);\n    }\n\n    // hook role\n    function updateTotalUnderlyingAssets(\n        uint256 amount_\n    ) external onlyRole(HOOK_ROLE) {\n        _updateTotalUnderlyingAssets(amount_);\n    }\n\n    function _updateTotalUnderlyingAssets(uint256 amount_) internal {\n        totalUnderlyingAssets = amount_;\n    }\n}\n"
      },
      "contracts/token/yield-token/YieldTokenBase.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\nimport \"lib/openzeppelin-contracts/contracts/security/ReentrancyGuard.sol\";\nimport {FixedPointMathLib} from \"lib/solmate/src/utils/FixedPointMathLib.sol\";\nimport \"../../utils/RescueBase.sol\";\nimport \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\";\nimport {PermitDeadlineExpired, InvalidSigner} from \"../../common/Errors.sol\";\n\nabstract contract YieldTokenBase is RescueBase, ReentrancyGuard, IERC20 {\n    using FixedPointMathLib for uint256;\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 internal _totalSupply;\n\n    mapping(address => uint256) internal _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                            YIELD STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    // total yield from all siblings\n    uint256 public totalUnderlyingAssets;\n\n    /*//////////////////////////////////////////////////////////////\n                               CONSTRUCTOR\n    //////////////////////////////////////////////////////////////*/\n\n    constructor(string memory _name, string memory _symbol, uint8 _decimals) {\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 convertToShares(\n        uint256 underlyingAssets\n    ) public view virtual returns (uint256) {\n        uint256 supply = _totalSupply; // Saves an extra SLOAD if _totalSupply is non-zero.\n        return\n            supply == 0\n                ? underlyingAssets\n                : underlyingAssets.mulDivDown(supply, totalUnderlyingAssets);\n    }\n\n    function convertToAssets(\n        uint256 shares\n    ) public view virtual returns (uint256) {\n        uint256 supply = _totalSupply; // Saves an extra SLOAD if _totalSupply is non-zero.\n        return\n            supply == 0\n                ? shares\n                : shares.mulDivDown(totalUnderlyingAssets, supply);\n    }\n\n    function balanceOf(address user_) external view returns (uint256) {\n        uint256 balance = _balanceOf[user_];\n        if (balance == 0) return 0;\n        return convertToAssets(balance);\n    }\n\n    // recheck for multi yield\n    function totalSupply() external view returns (uint256) {\n        if (_totalSupply == 0) return 0;\n        return totalUnderlyingAssets;\n    }\n\n    function approve(\n        address spender_,\n        uint256 amount_\n    ) public virtual returns (bool) {\n        uint256 shares = convertToShares(amount_);\n        allowance[msg.sender][spender_] = shares;\n\n        emit Approval(msg.sender, spender_, shares);\n\n        return true;\n    }\n\n    function transfer(\n        address to_,\n        uint256 amount_\n    ) public override returns (bool) {\n        uint256 sharesToTransfer = convertToShares(amount_);\n        _balanceOf[msg.sender] -= sharesToTransfer;\n\n        // Cannot overflow because the sum of all user\n        // balances can't exceed the max uint256 value.\n        unchecked {\n            _balanceOf[to_] += sharesToTransfer;\n        }\n\n        emit Transfer(msg.sender, to_, amount_);\n\n        return true;\n    }\n\n    // transfer changes shares balance but reduces the amount\n    function transferFrom(\n        address from_,\n        address to_,\n        uint256 amount_\n    ) public override returns (bool) {\n        uint256 sharesToTransfer = convertToShares(amount_);\n\n        uint256 allowed = allowance[from_][msg.sender]; // Saves gas for limited approvals.\n\n        if (allowed != type(uint256).max)\n            allowance[from_][msg.sender] = allowed - sharesToTransfer;\n\n        _balanceOf[from_] -= sharesToTransfer;\n\n        // Cannot overflow because the sum of all user\n        // balances can't exceed the max uint256 value.\n        unchecked {\n            _balanceOf[to_] += sharesToTransfer;\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        if (deadline < block.timestamp) revert PermitDeadlineExpired();\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                                convertToShares(value),\n                                nonces[owner]++,\n                                deadline\n                            )\n                        )\n                    )\n                ),\n                v,\n                r,\n                s\n            );\n\n            if (recoveredAddress == address(0) || recoveredAddress != owner)\n                revert InvalidSigner();\n\n            allowance[recoveredAddress][spender] = convertToShares(value);\n        }\n\n        emit Approval(owner, spender, convertToShares(value));\n    }\n\n    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n        return\n            block.chainid == INITIAL_CHAIN_ID\n                ? INITIAL_DOMAIN_SEPARATOR\n                : computeDomainSeparator();\n    }\n\n    function computeDomainSeparator() internal view virtual returns (bytes32) {\n        return\n            keccak256(\n                abi.encode(\n                    keccak256(\n                        \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n                    ),\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"
      },
      "contracts/utils/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/utils/Faucet.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\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(\n        address indexed owner,\n        address indexed spender,\n        uint256 amount\n    );\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(string memory _name, string memory _symbol, uint8 _decimals) {\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(\n        address spender,\n        uint256 amount\n    ) 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(\n        address to,\n        uint256 amount\n    ) 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)\n            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(\n                recoveredAddress != address(0) && recoveredAddress == owner,\n                \"INVALID_SIGNER\"\n            );\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\n            block.chainid == INITIAL_CHAIN_ID\n                ? INITIAL_DOMAIN_SEPARATOR\n                : computeDomainSeparator();\n    }\n\n    function computeDomainSeparator() internal view virtual returns (bytes32) {\n        return\n            keccak256(\n                abi.encode(\n                    keccak256(\n                        \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n                    ),\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\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(\n                freeMemoryPointer,\n                0x23b872dd00000000000000000000000000000000000000000000000000000000\n            )\n            mstore(\n                add(freeMemoryPointer, 4),\n                and(from, 0xffffffffffffffffffffffffffffffffffffffff)\n            ) // Append and mask the \"from\" argument.\n            mstore(\n                add(freeMemoryPointer, 36),\n                and(to, 0xffffffffffffffffffffffffffffffffffffffff)\n            ) // 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(\n                    and(eq(mload(0), 1), gt(returndatasize(), 31)),\n                    iszero(returndatasize())\n                ),\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(ERC20 token, address to, uint256 amount) 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(\n                freeMemoryPointer,\n                0xa9059cbb00000000000000000000000000000000000000000000000000000000\n            )\n            mstore(\n                add(freeMemoryPointer, 4),\n                and(to, 0xffffffffffffffffffffffffffffffffffffffff)\n            ) // 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(\n                    and(eq(mload(0), 1), gt(returndatasize(), 31)),\n                    iszero(returndatasize())\n                ),\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(ERC20 token, address to, uint256 amount) 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(\n                freeMemoryPointer,\n                0x095ea7b300000000000000000000000000000000000000000000000000000000\n            )\n            mstore(\n                add(freeMemoryPointer, 4),\n                and(to, 0xffffffffffffffffffffffffffffffffffffffff)\n            ) // 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(\n                    and(eq(mload(0), 1), gt(returndatasize(), 31)),\n                    iszero(returndatasize())\n                ),\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\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\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\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\n/**\n * @title Base contract for super token and vault\n * @notice It contains relevant execution payload storages.\n * @dev This contract implements Socket's IPlug to enable message bridging and IMessageBridge\n * to support any type of message bridge.\n */\nabstract contract RescueBase is AccessControl {\n    bytes32 constant RESCUE_ROLE = keccak256(\"RESCUE_ROLE\");\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\ncontract Faucet is RescueBase {\n    using SafeTransferLib for ERC20;\n\n    constructor() AccessControl(msg.sender) {\n        _grantRole(RESCUE_ROLE, msg.sender);\n    }\n\n    function getTokens(address receiver_, address[] calldata tokens_) external {\n        for (uint256 i = 0; i < tokens_.length; i++) {\n            ERC20 token = ERC20(tokens_[i]);\n            uint256 amount = 10 ** token.decimals() * 1000;\n            token.safeTransfer(receiver_, amount);\n        }\n    }\n}\n"
      },
      "contracts/utils/Gauge.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\nimport \"../common/Structs.sol\";\n\nabstract contract Gauge {\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/utils/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/utils/RescueBase.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.13;\nimport {RescueFundsLib} from \"../libraries/RescueFundsLib.sol\";\nimport {AccessControl} from \"./AccessControl.sol\";\n\n/**\n * @title Base contract for super token and vault\n * @notice It contains relevant execution payload storages.\n * @dev This contract implements Socket's IPlug to enable message bridging and IMessageBridge\n * to support any type of message bridge.\n */\nabstract contract RescueBase is AccessControl {\n    bytes32 constant RESCUE_ROLE = keccak256(\"RESCUE_ROLE\");\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/openzeppelin-contracts/contracts/security/ReentrancyGuard.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    constructor() {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Down, // Toward negative infinity\n        Up, // Toward infinity\n        Zero // Toward zero\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds up instead\n     * of rounding down.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n     * with further edits by Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod0 := mul(x, y)\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1, \"Math: mulDiv overflow\");\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n            // See https://cs.stackexchange.com/q/138556/92363.\n\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\n            uint256 twos = denominator & (~denominator + 1);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n            // in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n        }\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/FixedPointMathLib.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Arithmetic library with operations for fixed-point numbers.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)\n/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)\nlibrary FixedPointMathLib {\n    /*//////////////////////////////////////////////////////////////\n                    SIMPLIFIED FIXED POINT OPERATIONS\n    //////////////////////////////////////////////////////////////*/\n\n    uint256 internal constant MAX_UINT256 = 2**256 - 1;\n\n    uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.\n\n    function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.\n    }\n\n    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.\n    }\n\n    function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.\n    }\n\n    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                    LOW LEVEL FIXED POINT OPERATIONS\n    //////////////////////////////////////////////////////////////*/\n\n    function mulDivDown(\n        uint256 x,\n        uint256 y,\n        uint256 denominator\n    ) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))\n            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {\n                revert(0, 0)\n            }\n\n            // Divide x * y by the denominator.\n            z := div(mul(x, y), denominator)\n        }\n    }\n\n    function mulDivUp(\n        uint256 x,\n        uint256 y,\n        uint256 denominator\n    ) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))\n            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {\n                revert(0, 0)\n            }\n\n            // If x * y modulo the denominator is strictly greater than 0,\n            // 1 is added to round up the division of x * y by the denominator.\n            z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator))\n        }\n    }\n\n    function rpow(\n        uint256 x,\n        uint256 n,\n        uint256 scalar\n    ) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            switch x\n            case 0 {\n                switch n\n                case 0 {\n                    // 0 ** 0 = 1\n                    z := scalar\n                }\n                default {\n                    // 0 ** n = 0\n                    z := 0\n                }\n            }\n            default {\n                switch mod(n, 2)\n                case 0 {\n                    // If n is even, store scalar in z for now.\n                    z := scalar\n                }\n                default {\n                    // If n is odd, store x in z for now.\n                    z := x\n                }\n\n                // Shifting right by 1 is like dividing by 2.\n                let half := shr(1, scalar)\n\n                for {\n                    // Shift n right by 1 before looping to halve it.\n                    n := shr(1, n)\n                } n {\n                    // Shift n right by 1 each iteration to halve it.\n                    n := shr(1, n)\n                } {\n                    // Revert immediately if x ** 2 would overflow.\n                    // Equivalent to iszero(eq(div(xx, x), x)) here.\n                    if shr(128, x) {\n                        revert(0, 0)\n                    }\n\n                    // Store x squared.\n                    let xx := mul(x, x)\n\n                    // Round to the nearest number.\n                    let xxRound := add(xx, half)\n\n                    // Revert if xx + half overflowed.\n                    if lt(xxRound, xx) {\n                        revert(0, 0)\n                    }\n\n                    // Set x to scaled xxRound.\n                    x := div(xxRound, scalar)\n\n                    // If n is even:\n                    if mod(n, 2) {\n                        // Compute z * x.\n                        let zx := mul(z, x)\n\n                        // If z * x overflowed:\n                        if iszero(eq(div(zx, x), z)) {\n                            // Revert if x is non-zero.\n                            if iszero(iszero(x)) {\n                                revert(0, 0)\n                            }\n                        }\n\n                        // Round to the nearest number.\n                        let zxRound := add(zx, half)\n\n                        // Revert if zx + half overflowed.\n                        if lt(zxRound, zx) {\n                            revert(0, 0)\n                        }\n\n                        // Return properly scaled zxRound.\n                        z := div(zxRound, scalar)\n                    }\n                }\n            }\n        }\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                        GENERAL NUMBER UTILITIES\n    //////////////////////////////////////////////////////////////*/\n\n    function sqrt(uint256 x) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let y := x // We start y at x, which will help us make our initial estimate.\n\n            z := 181 // The \"correct\" value is 1, but this saves a multiplication later.\n\n            // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad\n            // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.\n\n            // We check y >= 2^(k + 8) but shift right by k bits\n            // each branch to ensure that if x >= 256, then y >= 256.\n            if iszero(lt(y, 0x10000000000000000000000000000000000)) {\n                y := shr(128, y)\n                z := shl(64, z)\n            }\n            if iszero(lt(y, 0x1000000000000000000)) {\n                y := shr(64, y)\n                z := shl(32, z)\n            }\n            if iszero(lt(y, 0x10000000000)) {\n                y := shr(32, y)\n                z := shl(16, z)\n            }\n            if iszero(lt(y, 0x1000000)) {\n                y := shr(16, y)\n                z := shl(8, z)\n            }\n\n            // Goal was to get z*z*y within a small factor of x. More iterations could\n            // get y in a tighter range. Currently, we will have y in [256, 256*2^16).\n            // We ensured y >= 256 so that the relative difference between y and y+1 is small.\n            // That's not possible if x < 256 but we can just verify those cases exhaustively.\n\n            // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.\n            // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.\n            // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.\n\n            // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range\n            // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.\n\n            // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate\n            // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.\n\n            // There is no overflow risk here since y < 2^136 after the first branch above.\n            z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.\n\n            // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n\n            // If x+1 is a perfect square, the Babylonian method cycles between\n            // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.\n            // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division\n            // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.\n            // If you don't care whether the floor or ceil square root is returned, you can remove this statement.\n            z := sub(z, lt(div(x, z), z))\n        }\n    }\n\n    function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Mod x by y. Note this will return\n            // 0 instead of reverting if y is zero.\n            z := mod(x, y)\n        }\n    }\n\n    function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Divide x by y. Note this will return\n            // 0 instead of reverting if y is zero.\n            r := div(x, y)\n        }\n    }\n\n    function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Add 1 to x * y if x % y > 0. Note this will\n            // return 0 instead of reverting if y is zero.\n            z := add(gt(mod(x, y), 0), div(x, y))\n        }\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": {}
    }
  }}