EmptyWrapper

Description:

Proxy contract enabling upgradeable smart contract patterns. Delegates calls to an implementation contract.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "test/EmptyWrapper.sol": {
      "content": "// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8;
pragma abicoder v2;

import "../src/vendor/CowWrapper.sol";

contract EmptyWrapper is CowWrapper {
    constructor(CowSettlement settlement_) CowWrapper(settlement_) {}

    function _wrap(
        bytes calldata settleData,
        bytes calldata wrappedData
    ) internal override {
        _internalSettle(settleData, wrappedData);
    }

    function parseWrapperData(bytes calldata wrapperData) external pure override returns (bytes calldata remainingWrapperData) {
        // EmptyWrapper doesn't consume any wrapper data
        return wrapperData;
    }
}
"
    },
    "src/vendor/CowWrapper.sol": {
      "content": "// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.7.6 <0.9.0;
pragma abicoder v2;

/// @title CoW Protocol Authentication Interface
/// @author CoW DAO developers
interface CowAuthentication {
    /// @dev determines whether the provided address is an authenticated solver.
    /// @param prospectiveSolver the address of prospective solver.
    /// @return true when prospectiveSolver is an authenticated solver, otherwise false.
    function isSolver(address prospectiveSolver) external view returns (bool);
}

/// @title CoW Protocol Settlement Interface
/// @notice Minimal interface for CoW Protocol's settlement contract
/// @dev Used for type-safe calls to the settlement contract's settle function
interface CowSettlement {
    /// @notice Trade data structure matching GPv2Settlement
    struct CowTradeData {
        uint256 sellTokenIndex;
        uint256 buyTokenIndex;
        address receiver;
        uint256 sellAmount;
        uint256 buyAmount;
        uint32 validTo;
        bytes32 appData;
        uint256 feeAmount;
        uint256 flags;
        uint256 executedAmount;
        bytes signature;
    }

    /// @notice Interaction data structure for pre/intra/post-settlement hooks
    struct CowInteractionData {
        address target;
        uint256 value;
        bytes callData;
    }

    /// @notice Returns the authentication contract used by the settlement contract.
    function authenticator() external returns (CowAuthentication);

    /// @notice Settles a batch of trades atomically
    /// @param tokens Array of token addresses involved in the settlement
    /// @param clearingPrices Array of clearing prices for each token
    /// @param trades Array of trades to execute
    /// @param interactions Array of three interaction arrays (pre, intra, post-settlement)
    function settle(
        address[] calldata tokens,
        uint256[] calldata clearingPrices,
        CowTradeData[] calldata trades,
        CowInteractionData[][3] calldata interactions
    ) external;
}

/// @title CoW Protocol Wrapper Interface
/// @notice Interface for wrapper contracts that add custom logic around CoW settlements
/// @dev Wrappers can be chained together to compose multiple settlement operations
interface ICowWrapper {
    /// @notice The settlement contract used by this wrapper
    /// @return The CowSettlement contract address
    function SETTLEMENT() external view returns (CowSettlement);

    /// @notice Initiates a wrapped settlement call
    /// @dev This is the entry point for wrapped settlements. The wrapper will execute custom logic
    ///      before calling the next wrapper or settlement contract in the chain.
    /// @param settleData ABI-encoded call to CowSettlement.settle()
    /// @param wrapperData Encoded chain of wrapper-specific data followed by addresses of next wrappers/settlement
    function wrappedSettle(bytes calldata settleData, bytes calldata wrapperData) external;

    /// @notice Parses and validates wrapper-specific data
    /// @dev Used by CowWrapperHelpers to validate wrapper data before execution.
    ///      Implementations should consume their portion of wrapperData and return the rest.
    /// @param wrapperData The wrapper-specific data to parse
    /// @return remainingWrapperData Any wrapper data that was not consumed by this wrapper
    function parseWrapperData(bytes calldata wrapperData) external view returns (bytes calldata remainingWrapperData);
}

/// @title CoW Protocol Wrapper Base Contract
/// @notice Abstract base contract for creating wrapper contracts around CoW Protocol settlements
/// @dev A wrapper enables custom pre/post-settlement and context-setting logic and can be chained with other wrappers.
///      Wrappers must:
///      - Be approved by the CowAuthentication contract
///      - Verify the caller is an authenticated solver
///      - Eventually call settle() on the approved CowSettlement contract
///      - Implement _wrap() for custom logic
///      - Implement parseWrapperData() for validation of implementation-specific wrapperData
abstract contract CowWrapper is ICowWrapper {
    /// @notice Thrown when the caller is not an authenticated solver
    /// @param unauthorized The address that attempted to call wrappedSettle
    error NotASolver(address unauthorized);

    /// @notice Thrown when settle data doesn't contain the correct function selector
    /// @param invalidSettleData The invalid settle data that was provided
    error InvalidSettleData(bytes invalidSettleData);

    /// @notice The settlement contract
    CowSettlement public immutable SETTLEMENT;

    /// @notice The authentication contract used to verify solvers
    /// @dev This is derived from `SETTLEMENT.authenticator()`.
    CowAuthentication public immutable AUTHENTICATOR;

    /// @notice Constructs a new CowWrapper
    /// @param settlement_ The CowSettlement contract to use at the end of the wrapper chain. Also used for wrapper authentication.
    constructor(CowSettlement settlement_) {
        SETTLEMENT = settlement_;
        AUTHENTICATOR = settlement_.authenticator();
    }

    /// @notice Initiates a wrapped settlement call
    /// @dev Entry point for solvers to execute wrapped settlements. Verifies the caller is a solver,
    ///      validates wrapper data, then delegates to _wrap() for custom logic.
    /// @param settleData ABI-encoded call to CowSettlement.settle() containing trade data
    /// @param wrapperData Encoded data for this wrapper and the chain of next wrappers/settlement.
    ///                    Format: [wrapper-specific-data][next-address][remaining-wrapper-data]
    ///                    Must be at least 20 bytes to contain the next settlement target address.
    function wrappedSettle(bytes calldata settleData, bytes calldata wrapperData) external {
        // Revert if not a valid solver
        require(AUTHENTICATOR.isSolver(msg.sender), NotASolver(msg.sender));

        // Delegate to the wrapper's custom logic
        _wrap(settleData, wrapperData);
    }

    /// @notice Parses and validates wrapper-specific data
    /// @dev Must be implemented by concrete wrapper contracts. Used for pre-execution validation.
    ///      The implementation should consume its wrapper-specific data and return the remainder.
    /// @param wrapperData The full wrapper data to parse
    /// @return remainingWrapperData The portion of wrapper data not consumed by this wrapper
    function parseWrapperData(bytes calldata wrapperData) external virtual view returns (bytes calldata remainingWrapperData);

    /// @notice Internal function containing the wrapper's custom logic
    /// @dev Must be implemented by concrete wrapper contracts. Should execute custom logic
    ///      then eventually call _internalSettle() to continue the settlement chain.
    /// @param settleData ABI-encoded call to CowSettlement.settle()
    /// @param wrapperData The wrapper data, which may be parsed and consumed as needed
    function _wrap(bytes calldata settleData, bytes calldata wrapperData) internal virtual;

    /// @notice Continues the settlement chain by calling the next wrapper or settlement contract
    /// @dev Extracts the next target address from wrapperData and either:
    ///      - Calls CowSettlement.settle() directly if no more wrappers remain, or
    ///      - Calls the next CowWrapper.wrappedSettle() to continue the chain
    /// @param settleData ABI-encoded call to CowSettlement.settle()
    /// @param wrapperData Remaining wrapper data starting with the next target address (20 bytes)
    function _internalSettle(bytes calldata settleData, bytes calldata wrapperData) internal {
        if (wrapperData.length == 0) {
            // No more wrapper data - we're calling the final settlement contract
            // Verify the settle data has the correct function selector
            require(bytes4(settleData[:4]) == CowSettlement.settle.selector, InvalidSettleData(settleData));

            // Call the settlement contract directly with the settle data
            (bool success, bytes memory returnData) = address(SETTLEMENT).call(settleData);

            if (!success) {
                // Bubble up the revert reason from the settlement contract
                assembly {
                    revert(add(returnData, 0x20), mload(returnData))
                }
            }
        } else {
            // Extract the next wrapper address from the first 20 bytes of wrapperData
            address nextWrapper = address(bytes20(wrapperData[:20]));

            // Skip past the address we just read
            wrapperData = wrapperData[20:];

            // More wrapper data remains - call the next wrapper in the chain
            CowWrapper(nextWrapper).wrappedSettle(settleData, wrapperData);
        }
    }
}
"
    }
  },
  "settings": {
    "remappings": [
      "cow/=lib/cow/src/contracts/",
      "evc/=lib/euler-vault-kit/lib/ethereum-vault-connector/src/",
      "ethereum-vault-connector/=lib/euler-vault-kit/lib/ethereum-vault-connector/src/",
      "openzeppelin/=lib/euler-vault-kit/lib/ethereum-vault-connector/lib/openzeppelin-contracts/contracts/",
      "@openzeppelin/contracts/=lib/euler-vault-kit/lib/openzeppelin-contracts/contracts/",
      "ds-test/=lib/evc/lib/forge-std/lib/ds-test/src/",
      "erc4626-tests/=lib/evc/lib/openzeppelin-contracts/lib/erc4626-tests/",
      "euler-vault-kit/=lib/euler-vault-kit/",
      "forge-gas-snapshot/=lib/euler-vault-kit/lib/permit2/lib/forge-gas-snapshot/src/",
      "forge-std/=lib/forge-std/src/",
      "openzeppelin-contracts/=lib/evc/lib/openzeppelin-contracts/",
      "permit2/=lib/euler-vault-kit/lib/permit2/",
      "solmate/=lib/euler-vault-kit/lib/permit2/lib/solmate/"
    ],
    "optimizer": {
      "enabled": false,
      "runs": 200
    },
    "metadata": {
      "useLiteralContent": false,
      "bytecodeHash": "ipfs",
      "appendCBOR": true
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    },
    "evmVersion": "prague",
    "viaIR": false
  }
}}

Tags:
Proxy, Upgradeable, Factory|addr:0x2aa326f09834de1cc3637e9e37eb5c10c75c2a94|verified:true|block:23595593|tx:0xc87c6ef192e343f50f8865f25b8d0b4bcb4058a7e4e287373882a09705e7fe89|first_check:1760693170

Submitted on: 2025-10-17 11:26:11

Comments

Log in to comment.

No comments yet.