creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n *     doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n *     token.safeTransferFrom(msg.sender, address(this), value);\n *     ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\n     *\n     * CAUTION: See Security Considerations above.\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    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.20;\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 value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens as the allowance of `spender` over the\n     * 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 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` 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 value) external returns (bool);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\nimport {IERC20Permit} from \"../extensions/IERC20Permit.sol\";\nimport {Address} from \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    /**\n     * @dev An operation with an ERC20 token failed.\n     */\n    error SafeERC20FailedOperation(address token);\n\n    /**\n     * @dev Indicates a failed `decreaseAllowance` request.\n     */\n    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        forceApprove(token, spender, oldAllowance + value);\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n     * value, non-reverting calls are assumed to be successful.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n        unchecked {\n            uint256 currentAllowance = token.allowance(address(this), spender);\n            if (currentAllowance < requestedDecrease) {\n                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n            }\n            forceApprove(token, spender, currentAllowance - requestedDecrease);\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data);\n        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n        // and not revert is the subcall reverts.\n\n        (bool success, bytes memory returndata) = address(token).call(data);\n        return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev The ETH balance of the account is not enough to perform the operation.\n     */\n    error AddressInsufficientBalance(address account);\n\n    /**\n     * @dev There's no code at `target` (it is not a contract).\n     */\n    error AddressEmptyCode(address target);\n\n    /**\n     * @dev A call to an address target failed. The target may have reverted.\n     */\n    error FailedInnerCall();\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        if (address(this).balance < amount) {\n            revert AddressInsufficientBalance(address(this));\n        }\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        if (!success) {\n            revert FailedInnerCall();\n        }\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason or custom error, it is bubbled\n     * up by this function (like regular Solidity function calls). However, if\n     * the call reverted with no returned reason, this function reverts with a\n     * {FailedInnerCall} error.\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        if (address(this).balance < value) {\n            revert AddressInsufficientBalance(address(this));\n        }\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n     * unsuccessful call.\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata\n    ) internal view returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            // only check if target is a contract if the call was successful and the return data is empty\n            // otherwise we already know that it was a contract\n            if (returndata.length == 0 && target.code.length == 0) {\n                revert AddressEmptyCode(target);\n            }\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n     * revert reason or with a default {FailedInnerCall} error.\n     */\n    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n     */\n    function _revert(bytes memory returndata) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert FailedInnerCall();\n        }\n    }\n}\n"
      },
      "@shift-defi/core/contracts/defii/execution/Logic.sol": {
        "content": "// SPDX-License-Identifier: SHIFT-1.0\npragma solidity ^0.8.20;\n\nabstract contract Logic {\n    error NotImplemented();\n\n    function claimRewards(address recipient) external payable virtual {\n        revert NotImplemented();\n    }\n\n    function emergencyExit() external payable virtual {\n        revert NotImplemented();\n    }\n\n    function withdrawLiquidity(\n        address recipient,\n        uint256 amount\n    ) external payable virtual {\n        revert NotImplemented();\n    }\n\n    function enter() external payable virtual;\n\n    function exit(uint256 liquidity) external payable virtual;\n\n    function accountLiquidity(\n        address account\n    ) external view virtual returns (uint256);\n}\n"
      },
      "@shift-defi/core/contracts/interfaces/IDefii.sol": {
        "content": "// SPDX-License-Identifier: SHIFT-1.0\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IDefii is IERC20 {\n    /// @notice Instruction type\n    /// @dev SWAP_BRIDGE is combination of SWAP + BRIDGE instructions.\n    /// @dev Data for MIN_LIQUIDITY_DELTA type is just `uint256`\n    enum InstructionType {\n        SWAP,\n        BRIDGE,\n        SWAP_BRIDGE,\n        REMOTE_CALL,\n        MIN_LIQUIDITY_DELTA,\n        MIN_TOKENS_DELTA\n    }\n\n    /// @notice DEFII type\n    enum Type {\n        LOCAL,\n        REMOTE\n    }\n\n    /// @notice DEFII instruction\n    struct Instruction {\n        InstructionType type_;\n        bytes data;\n    }\n\n    /// @notice Swap instruction\n    /// @dev `routerCalldata` - 1inch router calldata from API\n    struct SwapInstruction {\n        address tokenIn;\n        address tokenOut;\n        uint256 amountIn;\n        uint256 minAmountOut;\n        bytes routerCalldata;\n    }\n\n    /// @notice Bridge instruction\n    /// @dev `slippage` should be in bps\n    struct BridgeInstruction {\n        address token;\n        uint256 amount;\n        uint256 slippage;\n        address bridgeAdapter;\n        uint256 value;\n        bytes bridgeParams;\n    }\n\n    /// @notice Swap and bridge instruction. Do swap and bridge all token from swap\n    /// @dev `routerCalldata` - 1inch router calldata from API\n    /// @dev `slippage` should be in bps\n    struct SwapBridgeInstruction {\n        address tokenIn;\n        address tokenOut;\n        uint256 amountIn;\n        uint256 minAmountOut;\n        bytes routerCalldata;\n        address bridgeAdapter;\n        uint256 value;\n        bytes bridgeParams;\n        uint256 slippage;\n    }\n\n    struct MinTokensDeltaInstruction {\n        address[] tokens;\n        uint256[] deltas;\n    }\n\n    /// @notice Enters DEFII with predefined logic\n    /// @param amount Notion amount for enter\n    /// @param positionId Position id (used in callback)\n    /// @param instructions List with instructions for enter\n    /// @dev Caller should implement `IVault` interface\n    function enter(\n        uint256 amount,\n        uint256 positionId,\n        Instruction[] calldata instructions\n    ) external payable;\n\n    /// @notice Exits from DEFII with predefined logic\n    /// @param shares Defii lp amount to burn\n    /// @param positionId Position id (used in callback)\n    /// @param instructions List with instructions for enter\n    /// @dev Caller should implement `IVault` interface\n    function exit(\n        uint256 shares,\n        uint256 positionId,\n        Instruction[] calldata instructions\n    ) external payable;\n\n    /// @notice Withdraw liquidity (eg lp tokens) from\n    /// @param shares Defii lp amount to burn\n    /// @param recipient Address for withdrawal\n    /// @param instructions List with instructions\n    /// @dev Caller should implement `IVault` interface\n    function withdrawLiquidity(\n        address recipient,\n        uint256 shares,\n        Instruction[] calldata instructions\n    ) external payable;\n\n    /// @notice DEFII notion (start token)\n    /// @return notion address\n    // solhint-disable-next-line named-return-values\n    function notion() external view returns (address);\n\n    /// @notice DEFII type\n    /// @return type Type\n    // solhint-disable-next-line named-return-values\n    function defiiType() external pure returns (Type);\n}\n"
      },
      "@shift-defi/core/contracts/libraries/Constants.sol": {
        "content": "// SPDX-License-Identifier: SHIFT-1.0\npragma solidity ^0.8.20;\n\nlibrary Constants {\n    uint256 constant BPS = 1e4;\n}\n"
      },
      "@shift-defi/core/contracts/self-managed/SelfManagedLogic.sol": {
        "content": "// SPDX-License-Identifier: SHIFT-1.0\npragma solidity ^0.8.20;\n\nimport {Logic} from \"../defii/execution/Logic.sol\";\nimport {IDefii} from \"../interfaces/IDefii.sol\";\n\nabstract contract SelfManagedLogic is Logic {\n    error WrongBuildingBlockId(uint256);\n\n    function enterWithParams(bytes memory params) external payable virtual {\n        revert NotImplemented();\n    }\n\n    function emergencyExitPrivate() external payable virtual {\n        revert NotImplemented();\n    }\n\n    function exitBuildingBlock(\n        uint256 buildingBlockId\n    ) external payable virtual;\n}\n"
      },
      "contracts/constants/ethereum.sol": {
        "content": "// SPDX-License-Identifier: SHIFT-1.0\npragma solidity ^0.8.9;\n\naddress constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;\naddress constant USDT = 0xdAC17F958D2ee523a2206206994597C13D831ec7;\naddress constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;\naddress constant wstETH = 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0;\naddress constant wETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;\naddress constant crvUSD = 0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E;\naddress constant XAI = 0xd7C9F0e536dC865Ae858b0C0453Fe76D13c3bEAc;\naddress constant FRAX = 0x853d955aCEf822Db058eb8505911ED77F175b99e;\naddress constant eUSD = 0xA0d69E286B938e21CBf7E51D71F6A4c8918f482F;\naddress constant GHO = 0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f;\n"
      },
      "contracts/logic/ethereum/AuraEthereumGHOUSDCUSDT.sol": {
        "content": "// SPDX-License-Identifier: SHIFT-1.0\npragma solidity ^0.8.9;\n\nimport {SelfManagedLogicWithUtils} from \"../templates/SelfManagedLogicWithUtils.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {GHO, USDC, USDT} from \"../../constants/ethereum.sol\";\n\n\ncontract AuraEthereumGHOUSDCUSDT is SelfManagedLogicWithUtils {\n    address public constant VAULT = 0xBA12222222228d8Ba445958a75a0704d566BF2C8;\n    address public constant POOL = 0x8353157092ED8Be69a9DF8F95af097bbF33Cb2aF;\n    address public constant BOOSTER =\n        0xA57b8d98dAE62B26Ec3bcC4a365338157060B234;\n    address public constant REWARD_POOL =\n        0xBDD6984C3179B099E9D383ee2F44F3A57764BF7d;\n    address public constant BALANCER_QUERIES =\n        0xE39B5e3B6D74016b2F6A9673D7d7493B6DF549d5;\n\n    uint256 public constant POOL_ID = 157;\n\n    function enter() external payable override {\n        uint256 ghoAmount = IERC20(GHO).balanceOf(address(this));\n        uint256 usdcAmount = IERC20(USDC).balanceOf(address(this));\n        uint256 usdtAmount = IERC20(USDT).balanceOf(address(this));\n\n        _approveIfNeeded(GHO, VAULT);\n        _approveIfNeeded(USDT, VAULT);\n        _approveIfNeeded(USDC, VAULT);\n        _approveIfNeeded(POOL, VAULT);\n\n        address[] memory assets = new address[](4);\n        assets[0] = GHO;\n        assets[1] = POOL;\n        assets[2] = USDC;\n        assets[3] = USDT;\n\n        uint256[] memory maxAmountsIn = new uint256[](4);\n        maxAmountsIn[0] = ghoAmount;\n        maxAmountsIn[1] = 0;\n        maxAmountsIn[2] = usdcAmount;\n        maxAmountsIn[3] = usdtAmount;\n\n        uint256[] memory amountsIn = new uint256[](3);\n        amountsIn[0] = ghoAmount;\n        amountsIn[1] = usdcAmount;\n        amountsIn[2] = usdtAmount;\n\n        IBalancerVault.JoinPoolRequest memory joinRequest = IBalancerVault\n            .JoinPoolRequest(\n                assets,\n                maxAmountsIn,\n                // 1 - EXACT_TOKENS_IN_FOR_BPT_OUT instructions;\n                // https://docs.balancer.fi/reference/joins-and-exits/pool-joins.html#userdata\n                abi.encode(uint256(1), amountsIn, uint256(0)),\n                false\n            );\n        bytes32 poolId = IComposableStablePool(POOL).getPoolId();\n        IBalancerVault(VAULT).joinPool(\n            poolId,\n            address(this),\n            address(this),\n            joinRequest\n        );\n        _approveIfNeeded(POOL, BOOSTER);\n        IBooster(BOOSTER).depositAll(POOL_ID, true);\n    }\n    function exit(uint256 liquidity) external payable override {\n        IRewardPool(REWARD_POOL).withdrawAndUnwrap(liquidity, false);\n        _removeLiquidityGHOUSDCUSDT();\n    }\n    function claimRewards(address recipient) external payable override {\n        IRewardPool(REWARD_POOL).getReward(address(this), true);\n        uint256 extraRewardLength = IRewardPool(REWARD_POOL)\n            .extraRewardsLength();\n        address[] memory rewards = new address[](extraRewardLength + 1);\n        for (uint256 i = 0; i < extraRewardLength; i++) {\n            address extraReward = IRewardPool(REWARD_POOL).extraRewards(i);\n            rewards[i] = IStashReward(IExtraReward(extraReward).rewardToken())\n                .baseToken();\n        }\n        rewards[extraRewardLength] = IRewardPool(REWARD_POOL).rewardToken();\n        for (uint8 i = 0; i < rewards.length; i++) {\n            _transferAll(rewards[i], recipient);\n        }\n    }\n    function exitBuildingBlock(\n        uint256 buildingBlockId\n    ) external payable override {\n        if (buildingBlockId == 0) {\n            _emergencyExitConvex();\n        } else if (buildingBlockId == 1) {\n            _emergencyExitBalancer();\n        } else if (buildingBlockId == 2) {\n            _emergencyExitGHO();\n        } else {\n            revert WrongBuildingBlockId(buildingBlockId);\n        }\n    }\n\n    function accountLiquidity(\n        address account\n    ) public view override returns (uint256) {\n        return IRewardPool(REWARD_POOL).balanceOf(account);\n    }\n\n    function _emergencyExitConvex() internal {\n        uint256 totalLiquidity = accountLiquidity(address(this));\n        IRewardPool(REWARD_POOL).withdrawAndUnwrap(totalLiquidity, true);\n    }\n\n    function _emergencyExitBalancer() internal {\n        uint256 totalLiquidity = accountLiquidity(address(this));\n        IRewardPool(REWARD_POOL).withdrawAndUnwrap(totalLiquidity, true);\n        _removeLiquidityGHOUSDCUSDT();\n    }\n\n    function _emergencyExitGHO() internal {\n        uint256 totalLiquidity = accountLiquidity(address(this));\n        IRewardPool(REWARD_POOL).withdrawAndUnwrap(totalLiquidity, true);\n        _removeLiquidityUSDC();\n    }\n\n    function _removeLiquidityGHOUSDCUSDT() internal {\n        uint256 amountBPT = IERC20(POOL).balanceOf(address(this));\n\n        address[] memory assets = new address[](4);\n        assets[0] = GHO;\n        assets[1] = POOL;\n        assets[2] = USDC;\n        assets[3] = USDT;\n\n        uint256[] memory minAmountsOut = new uint256[](4);\n\n        IBalancerVault.ExitPoolRequest memory exitRequest = IBalancerVault\n            .ExitPoolRequest(\n                assets,\n                minAmountsOut,\n                // 2 - EXACT_BPT_IN_FOR_ALL_TOKENS_OUT;\n                // https://docs.balancer.fi/reference/joins-and-exits/pool-exits.html#userdata\n                abi.encode(uint256(2), amountBPT),\n                false\n            );\n        bytes32 poolId = IComposableStablePool(POOL).getPoolId();\n        _approveIfNeeded(POOL, VAULT);\n        IBalancerVault(VAULT).exitPool(\n            poolId,\n            address(this),\n            payable(address(this)),\n            exitRequest\n        );\n    }\n\n    function _removeLiquidityUSDC() internal {\n        uint256 amountBPT = IERC20(POOL).balanceOf(address(this));\n\n        address[] memory assets = new address[](4);\n        assets[0] = GHO;\n        assets[1] = POOL;\n        assets[2] = USDC;\n        assets[3] = USDT;\n\n        uint256[] memory minAmountsOut = new uint256[](4);\n\n        IBalancerVault.ExitPoolRequest memory exitRequest = IBalancerVault\n            .ExitPoolRequest(\n                assets,\n                minAmountsOut,\n                // 2 - EXACT_BPT_IN_FOR_ALL_TOKENS_OUT;\n                // https://docs.balancer.fi/reference/joins-and-exits/pool-exits.html#userdata\n                abi.encode(uint256(2), amountBPT),\n                false\n            );\n        bytes32 poolId = IComposableStablePool(POOL).getPoolId();\n        _approveIfNeeded(POOL, VAULT);\n        IBalancerVault(VAULT).exitPool(\n            poolId,\n            address(this),\n            payable(address(this)),\n            exitRequest\n        );\n        uint256 ghoAmountAfterLiquidityRemove = IERC20(GHO).balanceOf(\n            address(this)\n        );\n        if (ghoAmountAfterLiquidityRemove > 0) {\n            uint256 usdcProjected = IBalancerQueries(BALANCER_QUERIES)\n                .querySwap(\n                    IBalancerVault.SingleSwap(\n                        poolId,\n                        uint8(0),\n                        GHO,\n                        USDC,\n                        ghoAmountAfterLiquidityRemove,\n                        bytes(\"\")\n                    ),\n                    IBalancerVault.FundManagement(\n                        address(this),\n                        false,\n                        payable(address(this)),\n                        false\n                    )\n                );\n            uint256 usdtProjected = IBalancerQueries(BALANCER_QUERIES)\n                .querySwap(\n                    IBalancerVault.SingleSwap(\n                        poolId,\n                        uint8(0),\n                        GHO,\n                        USDT,\n                        ghoAmountAfterLiquidityRemove,\n                        bytes(\"\")\n                    ),\n                    IBalancerVault.FundManagement(\n                        address(this),\n                        false,\n                        payable(address(this)),\n                        false\n                    )\n                );\n            address swapFor;\n            if (usdcProjected > usdtProjected) {\n                swapFor = USDC;\n            } else {\n                swapFor = USDT;\n            }\n            _approveIfNeeded(GHO, VAULT);\n            IBalancerVault(VAULT).swap(\n                IBalancerVault.SingleSwap(\n                    poolId,\n                    uint8(0),\n                    GHO,\n                    swapFor,\n                    ghoAmountAfterLiquidityRemove,\n                    bytes(\"\")\n                ),\n                IBalancerVault.FundManagement(\n                    address(this),\n                    false,\n                    payable(address(this)),\n                    false\n                ),\n                0,\n                block.timestamp\n            );\n        }\n    }\n}\n\ninterface IBalancerVault {\n    struct JoinPoolRequest {\n        address[] assets;\n        uint256[] maxAmountsIn;\n        bytes userData;\n        bool fromInternalBalance;\n    }\n    struct ExitPoolRequest {\n        address[] assets;\n        uint256[] minAmountsOut;\n        bytes userData;\n        bool toInternalBalance;\n    }\n    struct SingleSwap {\n        bytes32 poolId;\n        uint8 kind;\n        address assetIn;\n        address assetOut;\n        uint256 amount;\n        bytes userData;\n    }\n    struct FundManagement {\n        address sender;\n        bool fromInternalBalance;\n        address payable recipient;\n        bool toInternalBalance;\n    }\n    function joinPool(\n        bytes32 poolId,\n        address sender,\n        address recipient,\n        JoinPoolRequest memory request\n    ) external;\n    function exitPool(\n        bytes32 poolId,\n        address sender,\n        address payable recipient,\n        ExitPoolRequest memory request\n    ) external;\n\n    function swap(\n        SingleSwap memory,\n        FundManagement memory,\n        uint256 limit,\n        uint256 deadline\n    ) external;\n}\n\ninterface IBalancerQueries {\n    function querySwap(\n        IBalancerVault.SingleSwap memory,\n        IBalancerVault.FundManagement memory\n    ) external returns (uint256);\n}\n\ninterface IComposableStablePool {\n    function getPoolId() external view returns (bytes32);\n}\n\ninterface IAsset {}\n\ninterface IBooster {\n    function depositAll(uint256, bool) external;\n    function poolInfo(\n        uint256\n    ) external returns (address, address, address, address, address, bool);\n}\n\ninterface IRewardPool {\n    function withdrawAndUnwrap(uint256, bool) external;\n    function getReward(address, bool) external;\n    function balanceOf(address) external view returns (uint256);\n    function extraRewardsLength() external view returns (uint256);\n    function extraRewards(uint256) external view returns (address);\n    function rewardToken() external view returns (address);\n}\n\ninterface IExtraReward {\n    function rewardToken() external view returns (address);\n}\n\ninterface IStashReward {\n    function baseToken() external view returns (address);\n}\n"
      },
      "contracts/logic/templates/SelfManagedLogicWithUtils.sol": {
        "content": "// SPDX-License-Identifier: SHIFT-1.0\npragma solidity ^0.8.9;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport {SelfManagedLogic} from \"@shift-defi/core/contracts/self-managed/SelfManagedLogic.sol\";\nimport {Constants} from \"@shift-defi/core/contracts/libraries/Constants.sol\";\n\nabstract contract SelfManagedLogicWithUtils is SelfManagedLogic {\n    using SafeERC20 for IERC20;\n\n    function _approveIfNeeded(address token, address recipient) internal {\n        uint256 allowance = IERC20(token).allowance(address(this), recipient);\n        if (allowance < type(uint256).max) {\n            IERC20(token).forceApprove(recipient, type(uint256).max);\n        }\n    }\n\n    function _transferAll(address token, address recipient) internal {\n        uint256 balance = IERC20(token).balanceOf(address(this));\n        if (balance > 0) {\n            IERC20(token).safeTransfer(recipient, balance);\n        }\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 1
      },
      "evmVersion": "paris",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}