GenericDecoderAndSanitizer

Description:

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

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "src/base/DecodersAndSanitizers/GenericDecoderAndSanitizer.sol": {
      "content": "// SPDX-License-Identifier: MIT

pragma solidity 0.8.21;

import {
    PendleRouterDecoderAndSanitizer,
    BaseDecoderAndSanitizer
} from "src/base/DecodersAndSanitizers/Protocols/PendleRouterDecoderAndSanitizer.sol";
import {
    UniswapV3DecoderAndSanitizer
} from "src/base/DecodersAndSanitizers/Protocols/UniswapV3DecoderAndSanitizer.sol";
import { OneInchDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/Protocols/OneInchDecoderAndSanitizer.sol";
import { CurveDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/Protocols/CurveDecoderAndSanitizer.sol";
import {
    NativeWrapperDecoderAndSanitizer
} from "src/base/DecodersAndSanitizers/Protocols/NativeWrapperDecoderAndSanitizer.sol";
import { ERC4626DecoderAndSanitizer } from "src/base/DecodersAndSanitizers/Protocols/ERC4626DecoderAndSanitizer.sol";
import { EigenpieDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/Protocols/EigenpieDecoderAndSanitizer.sol";
import { PirexEthDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/Protocols/PirexEthDecoderAndSanitizer.sol";
import { AaveV3DecoderAndSanitizer } from "src/base/DecodersAndSanitizers/Protocols/AaveV3DecoderAndSanitizer.sol";
import {
    VelodromeV1DecoderAndSanitizer
} from "src/base/DecodersAndSanitizers/Protocols/VelodromeV1DecoderAndSanitizer.sol";
import {
    FlashHypeDecoderAndSanitizer
} from "src/base/DecodersAndSanitizers/Protocols/FlashHypeDecoderAndSanitizer.sol";
import { CircleDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/Protocols/CircleDecoderAndSanitizer.sol";
import {
    BalancerV2DecoderAndSanitizer
} from "src/base/DecodersAndSanitizers/Protocols/BalancerV2DecoderAndSanitizer.sol";
import {
    MorphoBlueDecoderAndSanitizer
} from "src/base/DecodersAndSanitizers/Protocols/MorphoBlueDecoderAndSanitizer.sol";
import { EtherFiDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/Protocols/EtherFiDecoderAndSanitizer.sol";
import {
    LayerZeroOFTDecoderAndSanitizer
} from "src/base/DecodersAndSanitizers/Protocols/LayerZeroOFTDecoderAndSanitizer.sol";
import { NucleusDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/Protocols/NucleusDecoderAndSanitizer.sol";

contract GenericDecoderAndSanitizer is
    PendleRouterDecoderAndSanitizer,
    UniswapV3DecoderAndSanitizer,
    OneInchDecoderAndSanitizer,
    CurveDecoderAndSanitizer,
    NativeWrapperDecoderAndSanitizer,
    ERC4626DecoderAndSanitizer,
    EigenpieDecoderAndSanitizer,
    PirexEthDecoderAndSanitizer,
    AaveV3DecoderAndSanitizer,
    VelodromeV1DecoderAndSanitizer,
    FlashHypeDecoderAndSanitizer,
    CircleDecoderAndSanitizer,
    BalancerV2DecoderAndSanitizer,
    MorphoBlueDecoderAndSanitizer,
    EtherFiDecoderAndSanitizer,
    LayerZeroOFTDecoderAndSanitizer,
    NucleusDecoderAndSanitizer
{

    constructor(
        address _boringVault,
        address _uniswapV3NonFungiblePositionManager
    )
        BaseDecoderAndSanitizer(_boringVault)
        UniswapV3DecoderAndSanitizer(_uniswapV3NonFungiblePositionManager)
    { }

    function deposit(
        uint256,
        address receiver
    )
        external
        pure
        override(CurveDecoderAndSanitizer, ERC4626DecoderAndSanitizer, BalancerV2DecoderAndSanitizer)
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(receiver);
    }

    function withdraw(uint256)
        external
        pure
        override(CurveDecoderAndSanitizer, NativeWrapperDecoderAndSanitizer, BalancerV2DecoderAndSanitizer)
        returns (bytes memory addressesFound)
    {
        // Nothing to sanitize or return
        return addressesFound;
    }

    function deposit()
        external
        pure
        virtual
        override(NativeWrapperDecoderAndSanitizer, EtherFiDecoderAndSanitizer)
        returns (bytes memory addressesFound)
    {
        // Nothing to sanitize or return
        return addressesFound;
    }

}
"
    },
    "src/base/DecodersAndSanitizers/Protocols/PendleRouterDecoderAndSanitizer.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import {
    BaseDecoderAndSanitizer,
    DecoderCustomTypes
} from "src/base/DecodersAndSanitizers/BaseDecoderAndSanitizer.sol";

abstract contract PendleRouterDecoderAndSanitizer is BaseDecoderAndSanitizer {

    //============================== ERRORS ===============================

    error PendleRouterDecoderAndSanitizer__AggregatorSwapsNotPermitted();
    error PendleRouterDecoderAndSanitizer__LimitOrderSwapsNotPermitted();

    //============================== PENDLEROUTER ===============================

    // @desc Function to mint Pendle Sy using some token, will revert if using aggregator swaps
    // @tag user:address:The user to mint to
    // @tag sy:address:The sy token to mint
    // @tag input:address:The input token to mint from
    function mintSyFromToken(
        address user,
        address sy,
        uint256,
        DecoderCustomTypes.TokenInput calldata input
    )
        external
        pure
        virtual
        returns (bytes memory addressesFound)
    {
        if (
            input.swapData.swapType != DecoderCustomTypes.SwapType.NONE || input.swapData.extRouter != address(0)
                || input.pendleSwap != address(0) || input.tokenIn != input.tokenMintSy
        ) revert PendleRouterDecoderAndSanitizer__AggregatorSwapsNotPermitted();

        addressesFound = abi.encodePacked(user, sy, input.tokenIn);
    }

    // @desc Function to mint Pendle Py using the Sy
    // @tag user:address:The user to mint to
    // @tag yt:address:The yt token to mint
    function mintPyFromSy(
        address user,
        address yt,
        uint256,
        uint256
    )
        external
        pure
        virtual
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(user, yt);
    }

    // @desc Function to swap exact Pendle Pt for Pendle Yt
    // @tag user:address:The user to swap from
    // @tag market:address:The pendle market address
    function swapExactPtForYt(
        address user,
        address market,
        uint256,
        uint256,
        DecoderCustomTypes.ApproxParams calldata
    )
        external
        pure
        virtual
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(user, market);
    }

    // @desc Function to withdraw from Pendle PT tokens, does not support limit orders or aggregator swaps.
    // @param receiver:address
    // @param market:address
    // @param tokenOut:address
    function swapExactPtForToken(
        address receiver,
        address market,
        uint256 minPtOut,
        DecoderCustomTypes.TokenOutput calldata output,
        DecoderCustomTypes.LimitOrderData calldata limit
    )
        external
        pure
        virtual
        returns (bytes memory addressesFound)
    {
        if (limit.limitRouter != address(0)) {
            revert PendleRouterDecoderAndSanitizer__LimitOrderSwapsNotPermitted();
        }

        if (
            output.swapData.swapType != DecoderCustomTypes.SwapType.NONE || output.swapData.extRouter != address(0)
                || output.pendleSwap != address(0) || output.tokenOut != output.tokenRedeemSy
        ) revert PendleRouterDecoderAndSanitizer__AggregatorSwapsNotPermitted();

        addressesFound = abi.encodePacked(receiver, market, output.tokenOut);
    }

    // @desc Function to swap exact Pendle Yt for Pendle Pt
    // @tag user:address:The user to swap from
    // @tag market:address:The pendle market address
    function swapExactYtForPt(
        address user,
        address market,
        uint256,
        uint256,
        DecoderCustomTypes.ApproxParams calldata
    )
        external
        pure
        virtual
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(user, market);
    }

    // @desc Function to add Pendle liquidity with Sy and Pt
    // @tag user:address:The user to add liquidity from
    // @tag market:address:The pendle market address
    function addLiquidityDualSyAndPt(
        address user,
        address market,
        uint256,
        uint256,
        uint256
    )
        external
        pure
        virtual
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(user, market);
    }

    // @desc Function to remove Pendle liquidity to Sy and Pt
    // @tag user:address:The user to remove liquidity from
    // @tag market:address:The pendle market address
    function removeLiquidityDualSyAndPt(
        address user,
        address market,
        uint256,
        uint256,
        uint256
    )
        external
        pure
        virtual
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(user, market);
    }

    // @desc Function to redeem Pendle Py to Sy
    // @tag user:address:The user to redeem from
    // @tag yt:address:The yt token to redeem
    function redeemPyToSy(
        address user,
        address yt,
        uint256,
        uint256
    )
        external
        pure
        virtual
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(user, yt);
    }

    // @desc Function to redeem Pendle Sy to some token, will revert if using aggregator swaps
    // @tag user:address:The user to redeem from
    // @tag sy:address:The sy token to redeem
    // @tag output:address:The token to redeem to
    function redeemSyToToken(
        address user,
        address sy,
        uint256,
        DecoderCustomTypes.TokenOutput calldata output
    )
        external
        pure
        virtual
        returns (bytes memory addressesFound)
    {
        if (
            output.swapData.swapType != DecoderCustomTypes.SwapType.NONE || output.swapData.extRouter != address(0)
                || output.pendleSwap != address(0) || output.tokenOut != output.tokenRedeemSy
        ) revert PendleRouterDecoderAndSanitizer__AggregatorSwapsNotPermitted();

        addressesFound = abi.encodePacked(user, sy, output.tokenOut);
    }

    // @desc Function to swap exact token for Pendle Pt, will revert if using aggregator swaps or limit orders
    // @tag receiver:address:The receiver of the Pendle Pt
    // @tag market:address:The pendle market address
    // @tag input:address:The token to swap from
    function swapExactTokenForPt(
        address receiver,
        address market,
        uint256 minPtOut,
        DecoderCustomTypes.ApproxParams calldata guessPtOut,
        DecoderCustomTypes.TokenInput calldata input,
        DecoderCustomTypes.LimitOrderData calldata limit
    )
        external
        pure
        virtual
        returns (bytes memory addressFound)
    {
        if (
            input.swapData.swapType != DecoderCustomTypes.SwapType.NONE || input.swapData.extRouter != address(0)
                || input.pendleSwap != address(0) || input.tokenIn != input.tokenMintSy
        ) {
            revert PendleRouterDecoderAndSanitizer__AggregatorSwapsNotPermitted();
        }

        if (limit.limitRouter != address(0)) {
            revert PendleRouterDecoderAndSanitizer__LimitOrderSwapsNotPermitted();
        }

        addressFound = abi.encodePacked(receiver, market, input.tokenIn);
    }

    // @desc function to claim PENDLE token rewards and interest from LPing
    // @tag packedArgs:bytes:packed all sys,yts, and markets in order
    function redeemDueInterestAndRewards(
        address user,
        address[] calldata sys,
        address[] calldata yts,
        address[] calldata markets
    )
        external
        pure
        virtual
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(user);
        uint256 sysLength = sys.length;
        for (uint256 i; i < sysLength; ++i) {
            addressesFound = abi.encodePacked(addressesFound, sys[i]);
        }
        uint256 ytsLength = yts.length;
        for (uint256 i; i < ytsLength; ++i) {
            addressesFound = abi.encodePacked(addressesFound, yts[i]);
        }
        uint256 marketsLength = markets.length;
        for (uint256 i; i < marketsLength; ++i) {
            addressesFound = abi.encodePacked(addressesFound, markets[i]);
        }
    }

    // @desc function to add liquidity with a single token and keep the yt, will revert if using aggregator swaps
    // @tag receiver:address:The receiver of the Pendle Yt and lp
    // @tag market:address:The pendle market address
    // @tag input:address:The token to add liquidity from
    function addLiquiditySingleTokenKeepYt(
        address receiver,
        address market,
        uint256 minLpOut,
        uint256 minYtOut,
        DecoderCustomTypes.TokenInput calldata input
    )
        external
        pure
        virtual
        returns (bytes memory addressesFound)
    {
        if (
            input.swapData.swapType != DecoderCustomTypes.SwapType.NONE || input.swapData.extRouter != address(0)
                || input.pendleSwap != address(0) || input.tokenIn != input.tokenMintSy
        ) {
            revert PendleRouterDecoderAndSanitizer__AggregatorSwapsNotPermitted();
        }

        addressesFound = abi.encodePacked(receiver, market, input.tokenIn);
    }

    // @desc Function to add liquidity with a single token, does not keep the yt, will revert if using aggregator swaps
    // or limit orders
    // @tag receiver:address:The receiver of the Pendle Yt and lp
    // @tag market:address:The pendle market address
    // @tag input:address:The token to add liquidity from
    function addLiquiditySingleToken(
        address receiver,
        address market,
        uint256 minLpOut,
        DecoderCustomTypes.ApproxParams calldata guessPtReceivedFromSy,
        DecoderCustomTypes.TokenInput calldata input,
        DecoderCustomTypes.LimitOrderData calldata limit
    )
        external
        pure
        returns (bytes memory addressesFound)
    {
        if (
            input.swapData.swapType != DecoderCustomTypes.SwapType.NONE || input.swapData.extRouter != address(0)
                || input.pendleSwap != address(0) || input.tokenIn != input.tokenMintSy
        ) {
            revert PendleRouterDecoderAndSanitizer__AggregatorSwapsNotPermitted();
        }

        if (limit.limitRouter != address(0)) {
            revert PendleRouterDecoderAndSanitizer__LimitOrderSwapsNotPermitted();
        }

        addressesFound = abi.encodePacked(receiver, market, input.tokenIn);
    }

    // @desc Function to remove liquidity into a single token, will revert if using aggregator swaps or limit orders
    // @tag receiver:address:The receiver of the token to remove liquidity into
    // @tag market:address:The pendle market address
    // @tag output:address:The token to receive after removing liquidity
    function removeLiquiditySingleToken(
        address receiver,
        address market,
        uint256 netLpToRemove,
        DecoderCustomTypes.TokenOutput calldata output,
        DecoderCustomTypes.LimitOrderData calldata limit
    )
        external
        pure
        virtual
        returns (bytes memory addressFound)
    {
        if (
            output.swapData.swapType != DecoderCustomTypes.SwapType.NONE || output.swapData.extRouter != address(0)
                || output.pendleSwap != address(0) || output.tokenOut != output.tokenRedeemSy
        ) {
            revert PendleRouterDecoderAndSanitizer__AggregatorSwapsNotPermitted();
        }

        if (limit.limitRouter != address(0)) {
            revert PendleRouterDecoderAndSanitizer__LimitOrderSwapsNotPermitted();
        }

        addressFound = abi.encodePacked(receiver, market, output.tokenOut);
    }

    function exitPostExpToToken(
        address receiver,
        address market,
        uint256 netPtIn,
        uint256 netLpIn,
        DecoderCustomTypes.TokenOutput calldata output
    )
        external
        pure
        returns (bytes memory addressFound)
    {
        if (
            output.swapData.swapType != DecoderCustomTypes.SwapType.NONE || output.swapData.extRouter != address(0)
                || output.pendleSwap != address(0)
        ) {
            revert PendleRouterDecoderAndSanitizer__AggregatorSwapsNotPermitted();
        }

        addressFound = abi.encodePacked(receiver, market, output.tokenOut, output.tokenRedeemSy);
    }

}
"
    },
    "src/base/DecodersAndSanitizers/Protocols/UniswapV3DecoderAndSanitizer.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import { INonFungiblePositionManager } from "src/interfaces/RawDataDecoderAndSanitizerInterfaces.sol";
import {
    BaseDecoderAndSanitizer,
    DecoderCustomTypes
} from "src/base/DecodersAndSanitizers/BaseDecoderAndSanitizer.sol";

abstract contract UniswapV3DecoderAndSanitizer is BaseDecoderAndSanitizer {

    //============================== ERRORS ===============================

    error UniswapV3DecoderAndSanitizer__BadPathFormat();
    error UniswapV3DecoderAndSanitizer__BadTokenId();

    //============================== IMMUTABLES ===============================

    /**
     * @notice The networks uniswapV3 nonfungible position manager.
     */
    INonFungiblePositionManager internal immutable uniswapV3NonFungiblePositionManager;

    constructor(address _uniswapV3NonFungiblePositionManager) {
        uniswapV3NonFungiblePositionManager = INonFungiblePositionManager(_uniswapV3NonFungiblePositionManager);
    }

    //============================== UNISWAP V3 ===============================

    // @desc Uniswap V3 function to swap by exactInput, will revert if the path is not valid
    // @tag packedArgs:bytes:The path ADDRESSES ONLY of the swap followed by the recipient
    function exactInput(DecoderCustomTypes.ExactInputParams calldata params)
        external
        pure
        virtual
        returns (bytes memory addressesFound)
    {
        // Nothing to sanitize
        // Return addresses found
        // Determine how many addresses are in params.path.
        uint256 chunkSize = 23; // 3 bytes for uint24 fee, and 20 bytes for address token
        uint256 pathLength = params.path.length;
        if (pathLength % chunkSize != 20) revert UniswapV3DecoderAndSanitizer__BadPathFormat();
        uint256 pathAddressLength = 1 + (pathLength / chunkSize);
        uint256 pathIndex;
        for (uint256 i; i < pathAddressLength; ++i) {
            addressesFound = abi.encodePacked(addressesFound, params.path[pathIndex:pathIndex + 20]);
            pathIndex += chunkSize;
        }
        addressesFound = abi.encodePacked(addressesFound, params.recipient);
    }

    // @desc Uniswap V3 function to mint LP
    // @tag token0:address:The first token in the pair
    // @tag token1:address:The second token in the pair
    // @tag recipient:address:The recipient of the LP token
    function mint(DecoderCustomTypes.MintParams calldata params)
        external
        pure
        virtual
        returns (bytes memory addressesFound)
    {
        // Nothing to sanitize
        // Return addresses found
        addressesFound = abi.encodePacked(params.token0, params.token1, params.recipient);
    }

    // @desc Uniswap V3 function to increase liquidity, will revert if the tokenId is not owned by the boring vault
    // @tag operator:address:The operator/owner of the liquidity
    // @tag token0:address:The first token in the pair
    // @tag token1:address:The second token in the pair
    function increaseLiquidity(DecoderCustomTypes.IncreaseLiquidityParams calldata params)
        external
        view
        virtual
        returns (bytes memory addressesFound)
    {
        // Sanitize raw data
        if (uniswapV3NonFungiblePositionManager.ownerOf(params.tokenId) != boringVault) {
            revert UniswapV3DecoderAndSanitizer__BadTokenId();
        }
        // Extract addresses from uniswapV3NonFungiblePositionManager.positions(params.tokenId).
        (, address operator, address token0, address token1,,,,,,,,) =
            uniswapV3NonFungiblePositionManager.positions(params.tokenId);
        addressesFound = abi.encodePacked(operator, token0, token1);
    }

    // @desc Uniswap V3 function to decrease liquidity, will revert if the tokenId is not owned by the boring vault
    function decreaseLiquidity(DecoderCustomTypes.DecreaseLiquidityParams calldata params)
        external
        view
        virtual
        returns (bytes memory addressesFound)
    {
        // Sanitize raw data
        // NOTE ownerOf check is done in PositionManager contract as well, but it is added here
        // just for completeness.
        if (uniswapV3NonFungiblePositionManager.ownerOf(params.tokenId) != boringVault) {
            revert UniswapV3DecoderAndSanitizer__BadTokenId();
        }

        // No addresses in data
        return addressesFound;
    }

    // @desc Uniswap V3 function to collect fees, will revert if the tokenId is not owned by the boring vault
    // @tag recipient:address:The recipient of the fees
    function collect(DecoderCustomTypes.CollectParams calldata params)
        external
        view
        virtual
        returns (bytes memory addressesFound)
    {
        // Sanitize raw data
        // NOTE ownerOf check is done in PositionManager contract as well, but it is added here
        // just for completeness.
        if (uniswapV3NonFungiblePositionManager.ownerOf(params.tokenId) != boringVault) {
            revert UniswapV3DecoderAndSanitizer__BadTokenId();
        }

        // Return addresses found
        addressesFound = abi.encodePacked(params.recipient);
    }

    // @desc Uniswap V3 function to burn empty LP NFTs, will revert if the tokenId is not owned by the boring vault
    function burn(uint256 tokenId) external view virtual returns (bytes memory addressesFound) {
        // Sanitize raw data
        // NOTE ownerOf check is done in PositionManager contract as well, but it is added here
        // just for completeness.
        if (uniswapV3NonFungiblePositionManager.ownerOf(tokenId) != boringVault) {
            revert UniswapV3DecoderAndSanitizer__BadTokenId();
        }
    }

    // @desc Uniswap V3 function to safeTransferFrom ERC721s
    // @tag to:address:The recipient of the ERC721
    function safeTransferFrom(address, address to, uint256)
        external
        pure
        virtual
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(to);
    }

}
"
    },
    "src/base/DecodersAndSanitizers/Protocols/OneInchDecoderAndSanitizer.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import {
    BaseDecoderAndSanitizer,
    DecoderCustomTypes
} from "src/base/DecodersAndSanitizers/BaseDecoderAndSanitizer.sol";

abstract contract OneInchDecoderAndSanitizer is BaseDecoderAndSanitizer {

    //============================== ERRORS ===============================

    error OneInchDecoderAndSanitizer__PermitNotSupported();

    //============================== ONEINCH ===============================

    // @desc swap tokens with 1inch, will revert if the permit is not empty
    // @tag executor:address:executor
    // @tag srcToken:address:source token
    // @tag dstToken:address:destination token
    // @tag srcReceiver:address:source receiver
    // @tag dstReceiver:address:destination receiver
    function swap(
        address executor,
        DecoderCustomTypes.SwapDescription calldata desc,
        bytes calldata permit,
        bytes calldata
    )
        external
        pure
        returns (bytes memory addressesFound)
    {
        if (permit.length > 0) revert OneInchDecoderAndSanitizer__PermitNotSupported();
        addressesFound = abi.encodePacked(executor, desc.srcToken, desc.dstToken, desc.srcReceiver, desc.dstReceiver);
    }

    // @desc use uniswapV3Swap on OneInch
    // @tag packedArgs:bytes:packed arguments
    function uniswapV3Swap(
        uint256,
        uint256,
        uint256[] calldata pools
    )
        external
        pure
        returns (bytes memory addressesFound)
    {
        for (uint256 i; i < pools.length; ++i) {
            addressesFound = abi.encodePacked(addressesFound, uint160(pools[i]));
        }
    }

}
"
    },
    "src/base/DecodersAndSanitizers/Protocols/CurveDecoderAndSanitizer.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import { BaseDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/BaseDecoderAndSanitizer.sol";

abstract contract CurveDecoderAndSanitizer is BaseDecoderAndSanitizer {

    //============================== CURVE ===============================

    // @desc exchange on curve
    function exchange(int128, int128, uint256, uint256) external pure virtual returns (bytes memory addressesFound) {
        // Nothing to sanitize or return
        return addressesFound;
    }

    // @desc add liquidity on curve
    function add_liquidity(uint256[] calldata, uint256) external pure virtual returns (bytes memory addressesFound) {
        // Nothing to sanitize or return
        return addressesFound;
    }

    // @desc remove liquidity on curve
    // @tag user:address:the address of the user receiving rewards
    function remove_liquidity(uint256, uint256[] calldata) external pure virtual returns (bytes memory addressesFound) {
        // Nothing to sanitize or return
        return addressesFound;
    }

    function deposit(uint256, address receiver) external view virtual returns (bytes memory addressesFound) {
        addressesFound = abi.encodePacked(receiver);
    }

    function withdraw(uint256) external pure virtual returns (bytes memory addressesFound) {
        // Nothing to sanitize or return
        return addressesFound;
    }

    // @desc claim rewards on curve
    // @tag user:address:the address of the user receiving rewards
    function claim_rewards(address _addr) external pure virtual returns (bytes memory addressesFound) {
        addressesFound = abi.encodePacked(_addr);
    }

}
"
    },
    "src/base/DecodersAndSanitizers/Protocols/NativeWrapperDecoderAndSanitizer.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import { BaseDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/BaseDecoderAndSanitizer.sol";

abstract contract NativeWrapperDecoderAndSanitizer is BaseDecoderAndSanitizer {

    //============================== ETHERFI ===============================

    // @desc deposit native token for wrapped token
    function deposit() external pure virtual returns (bytes memory addressesFound) {
        // Nothing to sanitize or return
        return addressesFound;
    }

    // @desc withdraw wrapped token for native token
    function withdraw(uint256) external pure virtual returns (bytes memory addressesFound) {
        // Nothing to sanitize or return
        return addressesFound;
    }

}
"
    },
    "src/base/DecodersAndSanitizers/Protocols/ERC4626DecoderAndSanitizer.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import { BaseDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/BaseDecoderAndSanitizer.sol";

abstract contract ERC4626DecoderAndSanitizer is BaseDecoderAndSanitizer {

    //============================== ERC4626 ===============================

    // @desc deposit into the ERC4626 vault
    // @tag receiver:address:the address of the receiver of the vault tokens
    function deposit(uint256, address receiver) external view virtual returns (bytes memory addressesFound) {
        addressesFound = abi.encodePacked(receiver);
    }

    // @desc mint tokens from the ERC4626 vault
    // @tag receiver:address:the address of the receiver of the vault tokens
    function mint(uint256, address receiver) external pure virtual returns (bytes memory addressesFound) {
        addressesFound = abi.encodePacked(receiver);
    }

    // @desc withdraw tokens from the ERC4626 vault
    // @tag receiver:address:the address of the receiver of the vault tokens
    // @tag owner:address:the address of the owner of the vault tokens
    function withdraw(
        uint256,
        address receiver,
        address owner
    )
        external
        view
        virtual
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(receiver, owner);
    }

    // @desc redeem tokens from the ERC4626 vault
    // @tag receiver:address:the address of the receiver of the vault tokens
    // @tag owner:address:the address of the owner of the vault tokens
    function redeem(uint256, address receiver, address owner)
        external
        view
        virtual
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(receiver, owner);
    }

}
"
    },
    "src/base/DecodersAndSanitizers/Protocols/EigenpieDecoderAndSanitizer.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import {
    BaseDecoderAndSanitizer,
    DecoderCustomTypes
} from "src/base/DecodersAndSanitizers/BaseDecoderAndSanitizer.sol";

abstract contract EigenpieDecoderAndSanitizer is BaseDecoderAndSanitizer {

    //============================== ERRORS ===============================

    error EigenpieDecoderAndSanitizer__CanOnlyReceiveAsTokens();

    // @desc withdraw assets from Eigenpie
    function userWithdrawAsset(address[] memory assets) external pure virtual returns (bytes memory addressesFound) {
        return addressesFound;
    }

    // @desc queue withdrawals from Eigenpie
    function userQueuingForWithdraw(
        address asset,
        uint256 mLRTamount
    )
        external
        pure
        virtual
        returns (bytes memory addressesFound)
    {
        return addressesFound;
    }

}
"
    },
    "src/base/DecodersAndSanitizers/Protocols/PirexEthDecoderAndSanitizer.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import { BaseDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/BaseDecoderAndSanitizer.sol";

abstract contract PirexEthDecoderAndSanitizer is BaseDecoderAndSanitizer {

    error PirexEthDecoderAndSanitizer_OnlyBoringVaultAsReceiver();

    // @desc Function to deposit ETH for pxETH, will revert if receiver is not the boring vault
    function deposit(address receiver, bool) external returns (bytes memory) {
        if (receiver != boringVault) {
            revert PirexEthDecoderAndSanitizer_OnlyBoringVaultAsReceiver();
        }
    }

    // @desc Initiate redemption by burning pxETH in return for upxETH, will revert if receiver is not the boring vault
    function initiateRedemption(
        uint256 _assets,
        address _receiver,
        bool _shouldTriggerValidatorExit
    )
        external
        view
        returns (bytes memory)
    {
        if (_receiver != boringVault) {
            revert PirexEthDecoderAndSanitizer_OnlyBoringVaultAsReceiver();
        }
    }

    // @desc function to redeem E with UPXEth, will revert if receiver is not the boring vault
    function redeemWithUpxEth(
        uint256 _tokenId,
        uint256 _assets,
        address _receiver
    )
        external
        view
        returns (bytes memory)
    {
        if (_receiver != boringVault) {
            revert PirexEthDecoderAndSanitizer_OnlyBoringVaultAsReceiver();
        }
    }

    // @desc function to redeem ETH with pxETH, will revert if receiver is not the boring vault
    function instantRedeemWithPxEth(uint256 _assets, address _receiver) external view returns (bytes memory) {
        if (_receiver != boringVault) {
            revert PirexEthDecoderAndSanitizer_OnlyBoringVaultAsReceiver();
        }
    }

}
"
    },
    "src/base/DecodersAndSanitizers/Protocols/AaveV3DecoderAndSanitizer.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import { BaseDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/BaseDecoderAndSanitizer.sol";

abstract contract AaveV3DecoderAndSanitizer is BaseDecoderAndSanitizer {

    //============================== AAVEV3 ===============================

    // @desc Supply to the Aave V3 protocol
    // @tag asset:address:the address of the supply asset
    // @tag onBehalfOf:address:the address to supply on behalf of
    function supply(
        address asset,
        uint256,
        address onBehalfOf,
        uint16
    )
        external
        pure
        virtual
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(asset, onBehalfOf);
    }

    // @desc Withdraw from the Aave V3 protocol
    // @tag asset:address:the address of the withdraw asset
    // @tag to:address:the address to withdraw to
    function withdraw(address asset, uint256, address to) external pure virtual returns (bytes memory addressesFound) {
        addressesFound = abi.encodePacked(asset, to);
    }

    // @desc Borrow from the Aave V3 protocol
    // @tag asset:address:the address of the borrow asset
    // @tag onBehalfOf:address:the address to borrow on behalf of
    function borrow(
        address asset,
        uint256,
        uint256,
        uint16,
        address onBehalfOf
    )
        external
        pure
        virtual
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(asset, onBehalfOf);
    }

    // @desc Repay an Aave V3 loan
    // @tag asset:address:the address of the repay asset
    // @tag onBehalfOf:address:the address to repay on behalf of
    function repay(
        address asset,
        uint256,
        uint256,
        address onBehalfOf
    )
        external
        pure
        virtual
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(asset, onBehalfOf);
    }

    // @desc Required for Aave V3 to enable deposits as collateral
    // @tag asset:address:the address of the collateral asset
    function setUserUseReserveAsCollateral(
        address asset,
        bool useAsCollateral
    )
        external
        pure
        virtual
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(asset);
    }

    // @desc allow higher liquidation threshold for correlated assets
    function setUserEMode(uint8) external pure virtual returns (bytes memory addressesFound) {
        // Nothing to sanitize or return
        return addressesFound;
    }

    // @desc Borrow ETH from the Aave V3 protocol, address is ignored by protocol and WETH is used for internal
    // POOL.borrow
    function borrowETH(address, uint256, uint16) external pure returns (bytes memory addressesFound) {
        // nothing to sanitize or return
        return addressesFound;
    }

}
"
    },
    "src/base/DecodersAndSanitizers/Protocols/VelodromeV1DecoderAndSanitizer.sol": {
      "content": "// SPDX-License-Identifier: MIT

pragma solidity 0.8.21;

import { BaseDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/BaseDecoderAndSanitizer.sol";
import { DecoderCustomTypes } from "src/interfaces/DecoderCustomTypes.sol";

abstract contract VelodromeV1DecoderAndSanitizer is BaseDecoderAndSanitizer {

    error VelodromeV1DecoderAndSanitizer__BadToAddress();

    // @desc velodrome v1 add liquidity for pair of ERC20s
    // @tag tokenA:address
    // @tag tokenB:address
    // @tag to:address:receiver of the liquidity
    function addLiquidity(
        address tokenA,
        address tokenB,
        bool,
        uint256,
        uint256,
        uint256,
        uint256,
        address to,
        uint256
    )
        external
        pure
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(tokenA, tokenB, to);
    }

    // @desc velodrome v1 add liquidity for an ERC20 and ETH
    // @tag token:address:ERC20 token to add liquidity for
    // @tag to:address:receiver of the liquidity
    function addLiquidityETH(
        address token,
        bool,
        uint256,
        uint256,
        uint256,
        address to,
        uint256
    )
        external
        pure
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(token, to);
    }

    // @desc velodrome v1 remove liquidity for pair of ERC20s lp position
    // @tag tokenA:address
    // @tag tokenB:address
    // @tag to:address:receiver of the liquidity
    function removeLiquidity(
        address tokenA,
        address tokenB,
        bool,
        uint256,
        uint256,
        address to,
        uint256
    )
        external
        pure
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(tokenA, tokenB, to);
    }

    // @desc velodrome v1 remove liquidity for an ERC20 and ETH lp position
    // @tag token:address:ERC20 token to remove liquidity for
    // @tag to:address:receiver of the liquidity
    function removeLiquidityETH(
        address token,
        bool,
        uint256,
        uint256,
        address to,
        uint256
    )
        external
        pure
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(token, to);
    }

    // @desc velodrome v1 swap exact tokens for tokens with a single route
    // @tag tokenFrom:address
    // @tag tokenTo:address
    function swapExactTokensForTokensSimple(
        uint256 amountIn,
        uint256 amountOutMin,
        address tokenFrom,
        address tokenTo,
        bool stable,
        address to,
        uint256 deadline
    )
        external
        returns (bytes memory addressesFound)
    {
        if (to != boringVault) revert VelodromeV1DecoderAndSanitizer__BadToAddress();

        addressesFound = abi.encodePacked(tokenFrom, tokenTo);
    }

    // @desc velodrome v1 swap exact tokens for tokens with multiple routes
    // @tag tokenFrom:address
    // @tag tokenTo:address
    function swapExactTokensForTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        DecoderCustomTypes.route[] calldata routes,
        address to,
        uint256 deadline
    )
        external
        returns (bytes memory addressesFound)
    {
        if (to != boringVault) revert VelodromeV1DecoderAndSanitizer__BadToAddress();

        for (uint256 i; i < routes.length; ++i) {
            addressesFound = abi.encodePacked(addressesFound, routes[i].from, routes[i].to);
        }
    }

}
"
    },
    "src/base/DecodersAndSanitizers/Protocols/FlashHypeDecoderAndSanitizer.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import { BaseDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/BaseDecoderAndSanitizer.sol";

abstract contract FlashHypeDecoderAndSanitizer is BaseDecoderAndSanitizer {

    // @desc stake into flash hype, no community code
    function stake(address asset) external pure returns (bytes memory addressesFound) {
        // nothing to decode
    }

    // @desc unstake from flash hype, no community code
    function unstake(uint256) external pure returns (bytes memory addressesFound) {
        // nothing to decode
    }

}
"
    },
    "src/base/DecodersAndSanitizers/Protocols/CircleDecoderAndSanitizer.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import { BaseDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/BaseDecoderAndSanitizer.sol";

abstract contract CircleDecoderAndSanitizer is BaseDecoderAndSanitizer {

    // @desc Deposit assets into Circle TokenMessengerV1 to burn, in order to bridge to another chain
    // @tag destinationDomain:uint32:the id of the destination chain
    // @tag mintRecipient:bytes32:the address of the recipient on the destination chain in a bytes32 format
    // @tag burnToken:address:the address of the token to burn
    function depositForBurn(
        uint256 amount,
        uint32 destinationDomain,
        bytes32 mintRecipient,
        address burnToken
    )
        external
        view
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(destinationDomain, mintRecipient, burnToken);
    }

    // @desc Deposit assets into Circle TokenMessengerV2 to burn, in order to bridge to another chain
    // @tag destinationDomain:uint32:the id of the destination chain
    // @tag mintRecipient:bytes32:the address of the recipient on the destination chain in a bytes32 format
    // @tag burnToken:address:the address of the token to burn
    // @tag destinationCaller:bytes32:the address as bytes32 which can call receiveMessage on destination domain. If set
    // to bytes32(0), any address can call receiveMessage @tag maxFee:uint256:Max fee paid for fast burn, specified in
    // units of burnToken
    // @tag minFinalityThreshold:uint32:Minimum finality threshold at which burn will be attested
    function depositForBurn(
        uint256 amount,
        uint32 destinationDomain,
        bytes32 mintRecipient,
        address burnToken,
        bytes32 destinationCaller,
        uint256 maxFee,
        uint32 minFinalityThreshold
    )
        external
        view
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(
            destinationDomain, mintRecipient, burnToken, destinationCaller, maxFee, minFinalityThreshold
        );
    }

    // @desc Receive a message from Circle, in order to mint tokens on the destination chain
    function receiveMessage(
        bytes memory message,
        bytes memory attestation
    )
        external
        view
        returns (bytes memory addressesFound)
    {
        // nothing to sanitize
        return addressesFound;
    }

}
"
    },
    "src/base/DecodersAndSanitizers/Protocols/BalancerV2DecoderAndSanitizer.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import {
    BaseDecoderAndSanitizer,
    DecoderCustomTypes
} from "src/base/DecodersAndSanitizers/BaseDecoderAndSanitizer.sol";

abstract contract BalancerV2DecoderAndSanitizer is BaseDecoderAndSanitizer {

    //============================== ERRORS ===============================

    error BalancerV2DecoderAndSanitizer__SingleSwapUserDataLengthNonZero();
    error BalancerV2DecoderAndSanitizer__InternalBalancesNotSupported();

    //============================== BALANCER V2 ===============================

    // @desc Flash loan from the Balancer V2 protocol
    // @tag recipient:address:the address of the recipient
    // @tag tokens:bytes:packed bytes of every token in each address[] tokens input.
    function flashLoan(
        address recipient,
        address[] calldata tokens,
        uint256[] calldata,
        bytes calldata
    )
        external
        pure
        virtual
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(recipient);
        for (uint256 i; i < tokens.length; ++i) {
            addressesFound = abi.encodePacked(addressesFound, tokens[i]);
        }
    }

    // @desc Swap tokens in the Balancer V2 protocol. Reverts if userData is not empty or if internal balances are used
    // @tag pool:address:the address of the pool
    // @tag assetIn:address:the address of the input asset
    // @tag assetOut:address:the address of the output asset
    // @tag sender:address:the address of the sender
    // @tag recipient:address:the address of the recipient
    function swap(
        DecoderCustomTypes.SingleSwap calldata singleSwap,
        DecoderCustomTypes.FundManagement calldata funds,
        uint256,
        uint256
    )
        external
        pure
        virtual
        returns (bytes memory addressesFound)
    {
        // Sanitize raw data
        if (singleSwap.userData.length > 0) revert BalancerV2DecoderAndSanitizer__SingleSwapUserDataLengthNonZero();
        if (funds.fromInternalBalance) revert BalancerV2DecoderAndSanitizer__InternalBalancesNotSupported();
        if (funds.toInternalBalance) revert BalancerV2DecoderAndSanitizer__InternalBalancesNotSupported();

        // Return addresses found
        addressesFound = abi.encodePacked(
            _getPoolAddressFromPoolId(singleSwap.poolId),
            singleSwap.assetIn,
            singleSwap.assetOut,
            funds.sender,
            funds.recipient
        );
    }

    // @desc Join a pool in the Balancer V2 protocol, will revert if internal balances are used
    // @tag pool:address:the address of the pool
    // @tag sender:address:the address of the sender
    // @tag recipient:address:the address of the recipient
    // @tag assets:bytes:packed bytes of every address in the req.assets input.
    function joinPool(
        bytes32 poolId,
        address sender,
        address recipient,
        DecoderCustomTypes.JoinPoolRequest calldata req
    )
        external
        pure
        virtual
        returns (bytes memory addressesFound)
    {
        // Sanitize raw data
        if (req.fromInternalBalance) revert BalancerV2DecoderAndSanitizer__InternalBalancesNotSupported();
        // Return addresses found
        addressesFound = abi.encodePacked(_getPoolAddressFromPoolId(poolId), sender, recipient);
        uint256 assetsLength = req.assets.length;
        for (uint256 i; i < assetsLength; ++i) {
            addressesFound = abi.encodePacked(addressesFound, req.assets[i]);
        }
    }

    // @desc Exit a pool in the Balancer V2 protocol, will revert if internal balances are used
    // @tag pool:address:the address of the pool
    // @tag sender:address:the address of the sender
    // @tag recipient:address:the address of the recipient
    // @tag assets:bytes:packed bytes of every address in the req.assets input.
    function exitPool(
        bytes32 poolId,
        address sender,
        address recipient,
        DecoderCustomTypes.ExitPoolRequest calldata req
    )
        external
        pure
        virtual
        returns (bytes memory addressesFound)
    {
        // Sanitize raw data
        if (req.toInternalBalance) revert BalancerV2DecoderAndSanitizer__InternalBalancesNotSupported();
        // Return addresses found
        addressesFound = abi.encodePacked(_getPoolAddressFromPoolId(poolId), sender, recipient);
        uint256 assetsLength = req.assets.length;
        for (uint256 i; i < assetsLength; ++i) {
            addressesFound = abi.encodePacked(addressesFound, req.assets[i]);
        }
    }

    // @desc Deposit into the Balancer V2 protocol
    // @tag recipient:address:the address of the recipient
    function deposit(uint256, address recipient) external pure virtual returns (bytes memory addressesFound) {
        addressesFound = abi.encodePacked(recipient);
    }

    // @desc Withdraw from the Balancer V2 protocol to msg.sender
    function withdraw(uint256) external pure virtual returns (bytes memory addressesFound) {
        // No addresses in data
        return addressesFound;
    }

    function mint(address gauge) external pure virtual returns (bytes memory addressesFound) {
        addressesFound = abi.encodePacked(gauge);
    }

    // ========================================= INTERNAL HELPER FUNCTIONS =========================================

    /**
     * @notice Internal helper function that converts poolIds to pool addresses.
     */
    function _getPoolAddressFromPoolId(bytes32 poolId) internal pure returns (address) {
        return address(uint160(uint256(poolId >> 96)));
    }

}
"
    },
    "src/base/DecodersAndSanitizers/Protocols/MorphoBlueDecoderAndSanitizer.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import {
    BaseDecoderAndSanitizer,
    DecoderCustomTypes
} from "src/base/DecodersAndSanitizers/BaseDecoderAndSanitizer.sol";

abstract contract MorphoBlueDecoderAndSanitizer is BaseDecoderAndSanitizer {

    //============================== ERRORS ===============================

    error MorphoBlueDecoderAndSanitizer__CallbackNotSupported();

    //============================== MORPHO BLUE ===============================

    // @desc supply to morpho blue, will revert if the data is not empty
    // @tag loanToken:address
    // @tag collateralToken:address
    // @tag oracle:address
    // @tag irm:address
    // @tag onBehalf:address:on behalf of the user
    function supply(
        DecoderCustomTypes.MarketParams calldata params,
        uint256,
        uint256,
        address onBehalf,
        bytes calldata data
    )
        external
        pure
        returns (bytes memory addressesFound)
    {
        // Sanitize raw data
        if (data.length > 0) revert MorphoBlueDecoderAndSanitizer__CallbackNotSupported();
        // Return addresses found
        addressesFound = abi.encodePacked(params.loanToken, params.collateralToken, params.oracle, params.irm, onBehalf);
    }

    // @desc withdraw from morpho blue
    // @tag loanToken:address
    // @tag collateralToken:address
    // @tag oracle:address
    // @tag irm:address
    // @tag onBehalf:address:on behalf of the user
    // @tag receiver:address:receiver of the withdrawn tokens
    function withdraw(
        DecoderCustomTypes.MarketParams calldata params,
        uint256,
        uint256,
        address onBehalf,
        address receiver
    )
        external
        pure
        returns (bytes memory addressesFound)
    {
        // Nothing to sanitize
        // Return addresses found
        addressesFound =
            abi.encodePacked(params.loanToken, params.collateralToken, params.oracle, params.irm, onBehalf, receiver);
    }

    // @desc borrow from morpho blue
    // @tag loanToken:address
    // @tag collateralToken:address
    // @tag oracle:address
    // @tag irm:address
    // @tag onBehalf:address:on behalf of the user
    // @tag receiver:address:receiver of the borrowed tokens
    function borrow(
        DecoderCustomTypes.MarketParams calldata params,
        uint256,
        uint256,
        address onBehalf,
        address receiver
    )
        external
        pure
        returns (bytes memory addressesFound)
    {
        addressesFound =
            abi.encodePacked(params.loanToken, params.collateralToken, params.oracle, params.irm, onBehalf, receiver);
    }

    // @desc repay a borrow from morpho blue, will revert if the data is not empty
    // @tag loanToken:address
    // @tag collateralToken:address
    // @tag oracle:address
    // @tag irm:address
    // @tag onBehalf:address:on behalf of the user
    function repay(
        DecoderCustomTypes.MarketParams calldata params,
        uint256,
        uint256,
        address onBehalf,
        bytes calldata data
    )
        external
        pure
        returns (bytes memory addressesFound)
    {
        // Sanitize raw data
        if (data.length > 0) revert MorphoBlueDecoderAndSanitizer__CallbackNotSupported();

        // Return addresses found
        addressesFound = abi.encodePacked(params.loanToken, params.collateralToken, params.oracle, params.irm, onBehalf);
    }

    // @desc supply collateral to morpho blue, will revert if the data is not empty
    // @tag loanToken:address
    // @tag collateralToken:address
    // @tag oracle:address
    // @tag irm:address
    // @tag onBehalf:address:on behalf of the user
    function supplyCollateral(
        DecoderCustomTypes.MarketParams calldata params,
        uint256,
        address onBehalf,
        bytes calldata data
    )
        external
        pure
        returns (bytes memory addressesFound)
    {
        // Sanitize raw data
        if (data.length > 0) revert MorphoBlueDecoderAndSanitizer__CallbackNotSupported();

        // Return addresses found
        addressesFound = abi.encodePacked(params.loanToken, params.collateralToken, params.oracle, params.irm, onBehalf);
    }

    // @desc withdraw collateral from morpho blue
    // @tag loanToken:address
    // @tag collateralToken:address
    // @tag oracle:address
    // @tag irm:address
    // @tag onBehalf:address:on behalf of the user
    // @tag receiver:address:receiver of the withdrawn tokens
    function withdrawCollateral(
        DecoderCustomTypes.MarketParams calldata params,
        uint256,
        address onBehalf,
        address receiver
    )
        external
        pure
        returns (bytes memory addressesFound)
    {
        // Nothing to sanitize
        // Return addresses found
        addressesFound =
            abi.encodePacked(params.loanToken, params.collateralToken, params.oracle, params.irm, onBehalf, receiver);
    }

}
"
    },
    "src/base/DecodersAndSanitizers/Protocols/EtherFiDecoderAndSanitizer.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import { BaseDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/BaseDecoderAndSanitizer.sol";

abstract contract EtherFiDecoderAndSanitizer is BaseDecoderAndSanitizer {

    //============================== ETHERFI ===============================

    // @desc deposit into EtherFi
    function deposit() external pure virtual returns (bytes memory addressesFound) {
        // Nothing to sanitize or return
        return addressesFound;
    }

    // @desc wrap EtherFi
    function wrap(uint256) external pure virtual returns (bytes memory addressesFound) {
        // Nothing to sanitize or return
        return addressesFound;
    }

    // @desc unwrap EtherFi
    function unwrap(uint256) external pure virtual returns (bytes memory addressesFound) {
        // Nothing to sanitize or return
        return addressesFound;
    }

    // @desc request withdraw from EtherFi
    // @tag _addr:address:the address of the user requesting the withdraw
    function requestWithdraw(address _addr, uint256) external pure virtual returns (bytes memory addressesFound) {
        addressesFound = abi.encodePacked(_addr);
    }

    // @desc claim withdraw from EtherFi
    // @tag _addr:address:the address of the user claiming the withdraw
    function claimWithdraw(address _addr, uint256) external pure virtual returns (bytes memory addressesFound) {
        addressesFound = abi.encodePacked(_addr);
    }

}
"
    },
    "src/base/DecodersAndSanitizers/Protocols/LayerZeroOFTDecoderAndSanitizer.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import { BaseDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/BaseDecoderAndSanitizer.sol";
import { SendParam } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/interfaces/IOFT.sol";
import { MessagingFee } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/OFTCore.sol";

abstract contract LayerZeroOFTDecoderAndSanitizer is BaseDecoderAndSanitizer {

    error LayerZeroOFTDecoderAndSanitizer_ComposedMsgNotSupported();
    error LayerZeroOFTDecoderAndSanitizer_OnlyBoringVault();
    /**
     * @dev _sendParam:
     *     uint32 dstEid; // Destination endpoint ID.
     * [VERIFY]
     *     bytes32 to; // Recipient address.
     * [VERIFY]
     *     uint256 amountLD; // Amount to send in local decimals.
     *     uint256 minAmountLD; // Minimum amount to send in local decimals.
     *     bytes extraOptions; // Additional options supplied by the caller to be used in the LayerZero message.
     *     bytes composeMsg; // The composed message for the send() operation.
     * [NONE]
     *     bytes oftCmd; // The OFT command to be executed, unused in default OFT implementations. 0 for Taxi (faster,
     * expensive) 1 for Bus (slower, cheaper)
     * @dev _fee:
     *     uint256 nativeFee;
     *     uint256 lzTokenFee;
     */
    // @desc send a layerzero bridge, will revert if sendParam.to or the refundReceiver is not the boring vault, or the
    // _sendParam.composeMsg length is 0
    // @tag dstEid:uint32:destination endpoint eid

    function send(
        SendParam calldata _sendParam,
        MessagingFee calldata,
        address refundReceiver
    )
        external
        view
        returns (bytes memory)
    {
        if (bytes32ToAddress(_sendParam.to) != boringVault || refundReceiver != boringVault) {
            revert LayerZeroOFTDecoderAndSanitizer_OnlyBoringVault();
        }
        if (_sendParam.composeMsg.length > 0) {
            revert LayerZeroOFTDecoderAndSanitizer_ComposedMsgNotSupported();
        }

        return abi.encodePacked(_sendParam.dstEid);
    }

    function bytes32ToAddress(bytes32 b) internal pure returns (address) {
        return address(uint160(uint256(b)));
    }

}
"
    },
    "src/base/DecodersAndSanitizers/Protocols/NucleusDecoderAndSanitizer.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import { BaseDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/BaseDecoderAndSanitizer.sol";
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { BridgeData } from "src/base/Roles/CrossChain/CrossChainTellerBase.sol";
import { DecoderCustomTypes } from "src/interfaces/DecoderCustomTypes.sol";
import { PredicateMessage } from "@predicate/src/interfaces/IPredicateClient.sol";

abstract contract NucleusDecoderAndSanitizer is BaseDecoderAndSanitizer {

    error NucleusDecoderAndSanitizer__ExitFunctionForInternalBurnUseOnly();

    // @desc deposit into nucleus via the teller
    // @tag depositAsset:address:ERC20 to deposit, must be supported and approved
    function deposit(
        ERC20 depositAsset,
        uint256 depositAmount,
        uint256 minimumMint
    )
        external
        pure
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(depositAsset);
    }

    // @desc deposit into nucleus via the predicate proxy
    // @tag depositAsset:address:ERC20 to deposit, must be supported and approved
    // @tag recipient:address:receiver of shares
    // @tag teller:address:teller contract to deposit with
    function deposit(
        ERC20 depositAsset,
        uint256 depositAmount,
        uint256 minimumMint,
        address recipient,
        address teller,
        PredicateMessage calldata predicateMessage
    )
        external
        pure
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(depositAsset, recipient, teller);
    }

    // add the deposit with receiver for forward compatibility with audited teller
    // @desc teller deposit with receiver (post-Feb 2025 audits)
    // @tag depositAsset:address:ERC20 to deposit
    // @tag to:address:receiver
    function deposit(
        ERC20 depositAsset,
        uint256 depositAmount,
        uint256 minimumMint,
        address to
    )
        external
        pure
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(depositAsset, to);
    }

    // @desc bridge shares using teller
    // @tag chainSelector:uint32:chain selector
    // @tag destinationChainReceiver:address:receiver
    // @tag bridgeFeeToken:address:fee token
    // @tag messageGas:uint64:gas for message
    function bridge(
        uint256 shareAmount,
        BridgeData calldata data
    )
        external
        pure
        returns (bytes memory addressesFound)
    {
        addressesFound =
            abi.encodePacked(data.chainSelector, data.destinationChainReceiver, data.bridgeFeeToken, data.messageGas);
    }

    // @desc teller deposit and bridge
    // @tag depositAsset:address:ERC20 to deposit
    // @tag chainSelector:uint32:chain selector
    // @tag destinationChainReceiver:address:receiver
    // @tag bridgeFeeToken:address:fee token
    // @tag messageGas:uint64:gas for message
    function depositAndBridge(
        ERC20 depositAsset,
        uint256 depositAmount,
        uint256 minimumMint,
        BridgeData calldata data
    )
        external
        pure
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(
            depositAsset, data.chainSelector, data.destinationChainReceiver, data.bridgeFeeToken, data.messageGas
        );
    }

    // @desc updateAtomicRequest to withdraw from vault using newer UCP
    // @tag offer:address:ERC20 to withdraw
    // @tag want:address:ERC20 to withdraw into
    // @tag recipient:address:receiver
    function updateAtomicRequest(
        ERC20 offer,
        ERC20 want,
        DecoderCustomTypes.AtomicRequestUCP calldata userRequest
    )
        external
        pure
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(offer, want, userRequest.recipient);
    }

    // @desc claim fees from a nucleus vault, must be authorized to call
    // @tag token:address:ERC20 to claim fees with
    function claimFees(ERC20 token) external pure returns (bytes memory addressesFound) {
        addressesFound = abi.encodePacked(token);
    }

    // @desc Allows burner to burn shares, in exchange for assets, only supports burning with all but share amount 0
    function exit(
        address to,
        ERC20 asset,
        uint256 assetAmount,
        address from,
        uint256
    )
        external
        view
        returns (bytes memory addressesFound)
    {
        if (to != address(0) || address(asset) != address(0) || assetAmount != 0 || from != boringVault) {
            revert NucleusDecoderAndSanitizer__ExitFunctionForInternalBurnUseOnly();
        }
    }

    // @desc bulk withdraw from teller
    // @tag withdrawAsset:address:ERC20 to withdraw
    // @tag to:address:receiver
    function bulkWithdraw(
        ERC20 withdrawAsset,
        uint256 shareAmount,
        uint256 minimumAssets,
        address to
    )
        external
        pure
        returns (bytes memory addressesFound)
    {
        addressesFound = abi.encodePacked(withdrawAsset, to);
    }

    // @desc deleverage using the LHYPEDeleverage contract
    function deleverage(
        uint256,
        uint256,
        uint256,
        bytes32[] memory,
        address
    )
        external
        pure
        returns (bytes memory addressesFound)
    {
        // Nothing to decode
    }

}
"
    },
    "src/base/DecodersAndSanitizers/BaseDecoderAndSanitizer.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

// solhint-disable-next-line no-unused-import
import { DecoderCustomTypes } from "src/interfaces/DecoderCustomTypes.sol";

contract BaseDecoderAndSanitizer {

    //============================== IMMUTABLES ===============================

    /**
     * @notice The BoringVault contract address.
     */
    address internal immutable boringVault;

    error BaseDecoderAndSanitizer__FunctionNotImplemented(bytes _calldata);

    constructor(address _boringVault) {
        boringVault = _boringVault;
    }

    // @desc The spender address to approve
    // @tag spender:address
    function approve(address spender, uint256) external pure returns (bytes memory addressesFound) {
        addressesFound = abi.encodePacked(spender);
    }

    function acceptOwnership() external pure returns (bytes memory addressesFound) {
        // Nothing to decode
    }

    // @desc The new owner address
    // @tag newOwner:address
    function transferOwnership(address newOwner) external pure returns (bytes memory addressesFound) {
        addressesFound = abi.encodePacked(newOwner);
    }

    // @desc transfer an ERC20
    // @tag to:address:T

Tags:
ERC20, ERC165, Multisig, Mintable, Burnable, Pausable, Swap, Liquidity, Voting, Upgradeable, Multi-Signature, Factory, Oracle|addr:0x2cbf096f5df3f86ec1c5b11318d20a22cba022ef|verified:true|block:23728977|tx:0x52ea0df2dce115ad6c901476a3747616719937314461cd9c4797816c754f0c1b|first_check:1762337871

Submitted on: 2025-11-05 11:17:52

Comments

Log in to comment.

No comments yet.