Forkchoice Ethereum Mainnet

Address Contract Verified

Address 0xbA3cB449bD2B4ADddBc894D8697F5170800EAdeC
Balance 0 ETH
Nonce 1
Code Size 6177 bytes
Last Active
Indexed Transactions 6 (24,585,84024,585,891)
Value (indexed) ↓ 32.5082 ETH
Gas Used (indexed) 321,494
External Etherscan · Sourcify

Contract Bytecode

6177 bytes
0x6080604052600436106100b55760003560e01c80637bc41b9611610069578063de0e9a3e1161004e578063de0e9a3e1461027c578063ea598cb01461029c578063ec30bb88146102bc57600080fd5b80637bc41b96146101c85780639c3f1e90146101e857600080fd5b8063322bba211161009a578063322bba21146101705780634c84c1c8146101915780634cb76498146101a857600080fd5b80631626ba7e146100c157806317fcb39b1461011757600080fd5b366100bc57005b600080fd5b3480156100cd57600080fd5b506100e16100dc36600461126e565b6102f0565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020015b60405180910390f35b34801561012357600080fd5b5061014b7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161010e565b61018361017e36600461132b565b6103de565b60405190815260200161010e565b34801561019d57600080fd5b506101a6610720565b005b3480156101b457600080fd5b506101a66101c3366004611344565b61072b565b3480156101d457600080fd5b506101a66101e336600461132b565b610770565b3480156101f457600080fd5b5061024b6102033660046113ba565b60006020819052908152604090205473ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900463ffffffff1682565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835263ffffffff90911660208301520161010e565b34801561028857600080fd5b506101a66102973660046113ba565b61077e565b3480156102a857600080fd5b506101a66102b73660046113ba565b610821565b3480156102c857600080fd5b5061014b7f0000000000000000000000009008d19f58aabd9ed0d60971565aa8510560ab4181565b60008281526020818152604080832081518083019092525473ffffffffffffffffffffffffffffffffffffffff81168083527401000000000000000000000000000000000000000090910463ffffffff1692820192909252901580159061036f5750805173ffffffffffffffffffffffffffffffffffffffff90811614155b8015610385575042816020015163ffffffff1610155b156103b357507f1626ba7e0000000000000000000000000000000000000000000000000000000090506103d8565b507fffffffff0000000000000000000000000000000000000000000000000000000090505b92915050565b60006103f260a08301356040840135611402565b341461042a576040517f8b6ebb4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160400135600003610468576040517feaec5c9d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4261047960e0840160c0850161142e565b63ffffffff1610156104b7576040517f89bb260100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051808201909152338152600090602081016104db60e0860160c0870161142e565b63ffffffff169052604080518082019091529091506000908082815260200130604051602001610536919060609190911b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016815260140190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905290529050600061057c61012086016101008701611462565b6020808501516040516105c393920160c09290921b825260e01b7fffffffff00000000000000000000000000000000000000000000000000000000166008820152600c0190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052835190915061063a906106337f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc261062d368a90038a018a6114b1565b9061095b565b8484610b2a565b60008181526020819052604090205490945073ffffffffffffffffffffffffffffffffffffffff16156106a1576040517f56a1d2b2000000000000000000000000000000000000000000000000000000008152600481018590526024015b60405180910390fd5b505060008281526020818152604090912082518154929093015163ffffffff1674010000000000000000000000000000000000000000027fffffffffffffffff00000000000000000000000000000000000000000000000090921673ffffffffffffffffffffffffffffffffffffffff90931692909217179055919050565b61072947610821565b565b60005b8181101561076b5761075983838381811061074b5761074b61154b565b905061012002016000610c2c565b806107638161157a565b91505061072e565b505050565b61077b816001610c2c565b50565b6040517f2e1a7d4d000000000000000000000000000000000000000000000000000000008152600481018290527f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff1690632e1a7d4d90602401600060405180830381600087803b15801561080657600080fd5b505af115801561081a573d6000803e3d6000fd5b5050505050565b60007f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461081a576040519150601f19603f3d011682016040523d82523d6000602084013e61081a565b604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f6c85c0337eba1661327f94f3bf46c8a7f9311a563f4d5c948362567f5d8ed60c918101919091527ff9446b8e937d86f0bc87cac73923491692b123ca5f8761908494703758206adf6060820152466080820181905273ffffffffffffffffffffffffffffffffffffffff831660a083015260009160c00160405160208183030381529060405280519060200120915050919050565b604080516101808101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e082018190526101008201819052610120820181905261014082018190526101608201529083015173ffffffffffffffffffffffffffffffffffffffff16610a0a576040517fefc9ccdf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040518061018001604052808373ffffffffffffffffffffffffffffffffffffffff168152602001846000015173ffffffffffffffffffffffffffffffffffffffff168152602001846020015173ffffffffffffffffffffffffffffffffffffffff168152602001846040015181526020018460600151815260200163ffffffff80168152602001846080015181526020018460a0015181526020017ff3b277728b3fee749481eb3e0b3b48980dbbab78658fc419025cb16eee34677581526020018460e00151151581526020017f5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc981526020017f5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc9815250905092915050565b60008473ffffffffffffffffffffffffffffffffffffffff167fcf5f9de2984132265203b5c335b25727702ca77262ff622e136baa7362bf1da9858585604051610b7693929190611676565b60405180910390a25050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00180517fd5a25ba2e97094ad7d83dc28a6572da797d6b3e7fc6663bd93efb789fc17e48982526101a0822091526040517f190100000000000000000000000000000000000000000000000000000000000081527fc078f884a2676e1345748b1feace7b0abee5d00ecadb6e574dcdd109a63e89436002820152602281019190915260429020919050565b6000610c617f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc261062d368690038601866114b1565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810180517fd5a25ba2e97094ad7d83dc28a6572da797d6b3e7fc6663bd93efb789fc17e48982526101a082209152604080517f190100000000000000000000000000000000000000000000000000000000000081527fc078f884a2676e1345748b1feace7b0abee5d00ecadb6e574dcdd109a63e8943600282015260228101929092526042909120600081815260208181529083902083518085019094525473ffffffffffffffffffffffffffffffffffffffff8082168086527401000000000000000000000000000000000000000090920463ffffffff1692850183905294955091934290911015911480610d8d5750815173ffffffffffffffffffffffffffffffffffffffff16155b80610db75750808015610db75750815173ffffffffffffffffffffffffffffffffffffffff163314155b15610dff578415610df7576040517ff8cc70ce00000000000000000000000000000000000000000000000000000000815260048101849052602401610698565b505050505050565b60008381526020818152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff1790558051603880825260608201909252918201818036833750505060a0860151909150610e7a90829086903090611149565b8115610ebc577fb8bad102ac8bbacfef31ff1c906ec6d951c230b4dce750bb0376b812ad35852a81604051610eaf9190611790565b60405180910390a1610f0b565b3373ffffffffffffffffffffffffffffffffffffffff167f195271068a288191e4b265c641a56b9832919f69e9e7d6c2f31ba40278aeb85a82604051610f029190611790565b60405180910390a25b6040517f2479fb6e00000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000009008d19f58aabd9ed0d60971565aa8510560ab411690632479fb6e90610f80908590600401611790565b6020604051808303816000875af1158015610f9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc391906117a3565b90506000808760600151838960e001510281610fe157610fe16117bc565b048860e00151039050808389606001510301915050804710156110a4576040517f2e1a7d4d00000000000000000000000000000000000000000000000000000000815247820360048201819052907f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff1690632e1a7d4d90602401600060405180830381600087803b15801561108a57600080fd5b505af115801561109e573d6000803e3d6000fd5b50505050505b845160405160009173ffffffffffffffffffffffffffffffffffffffff169083908381818185875af1925050503d80600081146110fd576040519150601f19603f3d011682016040523d82523d6000602084013e611102565b606091505b505090508061113d576040517f6d963f8800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050505050565b60388451146111b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f475076323a2075696420627566666572206f766572666c6f77000000000000006044820152606401610698565b60388401526034830152602090910152565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715611219576112196111c6565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611266576112666111c6565b604052919050565b6000806040838503121561128157600080fd5b8235915060208084013567ffffffffffffffff808211156112a157600080fd5b818601915086601f8301126112b557600080fd5b8135818111156112c7576112c76111c6565b6112f7847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161121f565b9150808252878482850101111561130d57600080fd5b80848401858401376000848284010152508093505050509250929050565b6000610120828403121561133e57600080fd5b50919050565b6000806020838503121561135757600080fd5b823567ffffffffffffffff8082111561136f57600080fd5b818501915085601f83011261138357600080fd5b81358181111561139257600080fd5b866020610120830285010111156113a857600080fd5b60209290920196919550909350505050565b6000602082840312156113cc57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156103d8576103d86113d3565b803563ffffffff8116811461142957600080fd5b919050565b60006020828403121561144057600080fd5b61144982611415565b9392505050565b8035600781900b811461142957600080fd5b60006020828403121561147457600080fd5b61144982611450565b803573ffffffffffffffffffffffffffffffffffffffff8116811461142957600080fd5b8035801515811461142957600080fd5b600061012082840312156114c457600080fd5b6114cc6111f5565b6114d58361147d565b81526114e36020840161147d565b602082015260408301356040820152606083013560608201526080830135608082015260a083013560a082015261151c60c08401611415565b60c082015261152d60e084016114a1565b60e0820152610100611540818501611450565b908201529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036115ab576115ab6113d3565b5060010190565b6000815180845260005b818110156115d8576020818501810151868301820152016115bc565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6000815160028110611651577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8084525060208201516040602085015261166e60408501826115b2565b949350505050565b835173ffffffffffffffffffffffffffffffffffffffff16815260006101c060208601516116bc602085018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408601516116e4604085018273ffffffffffffffffffffffffffffffffffffffff169052565b50606086015160608401526080860151608084015260a086015161171060a085018263ffffffff169052565b5060c086015160c084015260e086015160e0840152610100808701518185015250610120808701516117458286018215159052565b505061014086810151908401526101608087015190840152610180830181905261177181840186611616565b90508281036101a084015261178681856115b2565b9695505050505050565b60208152600061144960208301846115b2565b6000602082840312156117b557600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea2646970667358221220ef8802913dc7f390c98427b120eee077bb04d92ea672807f56839d2e432db81764736f6c63430008100033

Verified Source Code Full Match

Compiler: v0.8.16+commit.07a7930e EVM: london Optimization: Yes (1000000 runs)
CoWSwapEthFlow.sol 270 lines
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.8;

import "./libraries/EthFlowOrder.sol";
import "./interfaces/ICoWSwapSettlement.sol";
import "./interfaces/ICoWSwapEthFlow.sol";
import "./interfaces/IWrappedNativeToken.sol";
import "./mixins/CoWSwapOnchainOrders.sol";
import "./vendored/GPv2EIP1271.sol";

/// @title CoW Swap ETH Flow
/// @author CoW Swap Developers
contract CoWSwapEthFlow is
    CoWSwapOnchainOrders,
    EIP1271Verifier,
    ICoWSwapEthFlow
{
    using EthFlowOrder for EthFlowOrder.Data;
    using GPv2Order for GPv2Order.Data;
    using GPv2Order for bytes;

    /// @dev The address of the CoW Swap settlement contract that will be used to settle orders created by this
    /// contract.
    ICoWSwapSettlement public immutable cowSwapSettlement;

    /// @dev The address of the contract representing the default native token in the current chain (e.g., WETH for
    /// Ethereum mainnet).
    IWrappedNativeToken public immutable wrappedNativeToken;

    /// @dev Each ETH flow order as described in [`EthFlowOrder.Data`] can be converted to a CoW Swap order. Distinct
    /// CoW Swap orders have non-colliding order hashes. This mapping associates some extra data to a specific CoW Swap
    /// order. This data is stored onchain and is used to verify the ownership and validity of an ETH flow order.
    /// An ETH flow order can be settled onchain only if converting it to a CoW Swap order and hashing yields valid
    /// onchain data.
    mapping(bytes32 => EthFlowOrder.OnchainData) public orders;

    /// @param _cowSwapSettlement The CoW Swap settlement contract.
    /// @param _wrappedNativeToken The default native token in the current chain (e.g., WETH on mainnet).
    constructor(
        ICoWSwapSettlement _cowSwapSettlement,
        IWrappedNativeToken _wrappedNativeToken
    ) CoWSwapOnchainOrders(address(_cowSwapSettlement)) {
        cowSwapSettlement = _cowSwapSettlement;
        wrappedNativeToken = _wrappedNativeToken;

        _wrappedNativeToken.approve(
            cowSwapSettlement.vaultRelayer(),
            type(uint256).max
        );
    }

    // The contract needs to be able to receive native tokens when unwrapping.
    // solhint-disable-next-line no-empty-blocks
    receive() external payable {}

    /// @inheritdoc ICoWSwapEthFlow
    function wrapAll() external {
        wrap(address(this).balance);
    }

    /// @inheritdoc ICoWSwapEthFlow
    function wrap(uint256 amount) public {
        // The fallback implementation of the standard WETH9 contract just calls `deposit`. Using the fallback instead
        // of directly calling `deposit` is slightly cheaper in terms of gas.
        // solhint-disable-next-line avoid-low-level-calls
        (bool success, ) = payable(address(wrappedNativeToken)).call{
            value: amount
        }("");
        // The success value is intentionally disregarded. The callback of the standard WETH9 contract has no revert
        // path in the code, so it could only revert if the internal call runs out of gas. This is not considered a
        // security risk since a reverting internal call would just mean that calling this function has no effect.
        success;
    }

    /// @inheritdoc ICoWSwapEthFlow
    function unwrap(uint256 amount) external {
        wrappedNativeToken.withdraw(amount);
    }

    /// @inheritdoc ICoWSwapEthFlow
    function createOrder(EthFlowOrder.Data calldata order)
        external
        payable
        returns (bytes32 orderHash)
    {
        if (msg.value != order.sellAmount + order.feeAmount) {
            revert IncorrectEthAmount();
        }

        if (0 == order.sellAmount) {
            revert NotAllowedZeroSellAmount();
        }

        // solhint-disable-next-line not-rely-on-time
        if (order.validTo < block.timestamp) {
            revert OrderIsAlreadyExpired();
        }

        EthFlowOrder.OnchainData memory onchainData = EthFlowOrder.OnchainData(
            msg.sender,
            order.validTo
        );

        OnchainSignature memory signature = OnchainSignature(
            OnchainSigningScheme.Eip1271,
            abi.encodePacked(address(this))
        );

        // The data event field includes extra information needed to settle orders with the CoW Swap API.
        bytes memory data = abi.encodePacked(
            order.quoteId,
            onchainData.validTo
        );

        orderHash = broadcastOrder(
            onchainData.owner,
            order.toCoWSwapOrder(wrappedNativeToken),
            signature,
            data
        );

        if (orders[orderHash].owner != EthFlowOrder.NO_OWNER) {
            revert OrderIsAlreadyOwned(orderHash);
        }

        orders[orderHash] = onchainData;
    }

    /// @inheritdoc ICoWSwapEthFlow
    function invalidateOrdersIgnoringNotAllowed(
        EthFlowOrder.Data[] calldata orderArray
    ) external {
        for (uint256 i = 0; i < orderArray.length; i++) {
            _invalidateOrder(orderArray[i], false);
        }
    }

    /// @inheritdoc ICoWSwapEthFlow
    function invalidateOrder(EthFlowOrder.Data calldata order) public {
        _invalidateOrder(order, true);
    }

    /// @dev Performs the same tasks as `invalidateOrder` (see documentation in `ICoWSwapEthFlow`), but also allows the
    /// caller to ignore the revert condition `NotAllowedToInvalidateOrder`. Instead of reverting, it stops execution
    /// without causing any state change.
    ///
    /// @param order order to be invalidated.
    /// @param revertOnInvalidDeletion controls whether the function call should revert or just return.
    function _invalidateOrder(
        EthFlowOrder.Data calldata order,
        bool revertOnInvalidDeletion
    ) internal {
        GPv2Order.Data memory cowSwapOrder = order.toCoWSwapOrder(
            wrappedNativeToken
        );
        bytes32 orderHash = cowSwapOrder.hash(cowSwapDomainSeparator);

        EthFlowOrder.OnchainData memory orderData = orders[orderHash];

        // solhint-disable-next-line not-rely-on-time
        bool isTradable = orderData.validTo >= block.timestamp;
        if (
            orderData.owner == EthFlowOrder.INVALIDATED_OWNER ||
            orderData.owner == EthFlowOrder.NO_OWNER ||
            (isTradable && orderData.owner != msg.sender)
        ) {
            if (revertOnInvalidDeletion) {
                revert NotAllowedToInvalidateOrder(orderHash);
            } else {
                return;
            }
        }

        orders[orderHash].owner = EthFlowOrder.INVALIDATED_OWNER;

        bytes memory orderUid = new bytes(GPv2Order.UID_LENGTH);
        orderUid.packOrderUidParams(
            orderHash,
            address(this),
            cowSwapOrder.validTo
        );

        // solhint-disable-next-line not-rely-on-time
        if (isTradable) {
            // Order is valid but its owner decided to invalidate it.
            emit OrderInvalidation(orderUid);
        } else {
            // The order cannot be traded anymore, so this transaction is likely triggered to get back the ETH. We are
            // interested in knowing who is the source of the refund.
            emit OrderRefund(orderUid, msg.sender);
        }

        uint256 filledAmount = cowSwapSettlement.filledAmount(orderUid);

        // This comment argues that a CoW Swap trader does not pay more fees if a partially fillable order is
        // (partially) settled in multiple batches rather than in one single batch of the combined size.
        // This also means that we can refund the user assuming the worst case of settling the filled amount in a single
        // batch without risking giving out more funds than available in the contract because of rounding issues.
        // A CoW Swap trader is always charged exactly the amount of fees that is proportional to the filled amount
        // rounded down to the smaller integer. The code is here:
        // https://github.com/cowprotocol/contracts/blob/d4e0fcd58367907bf1aff54d182222eeaee793dd/src/contracts/GPv2Settlement.sol#L385-L387
        // We show that a trader pays less in fee to CoW Swap when settiling a partially fillable order in two
        // executions rather than a single one for the combined amount; by induction this proves our original statement.
        // Our previous statement is equivalent to `floor(a/c) + floor(b/c) ≤ floor((a+b)/c)`. Writing a and b in terms
        // of reminders (`a = ad*c+ar`, `b = bd*c+br`) the equation becomes `ad + bd ≤ ad + bd + floor((ar+br)/c)`,
        // which is immediately true.
        uint256 refundAmount;
        unchecked {
            // - Multiplication overflow: since this smart contract never invalidates orders on CoW Swap,
            //   `filledAmount <= sellAmount`. Also, `feeAmount + sellAmount` is an amount of native tokens that was
            //   originally sent by the user. As such, it cannot be larger than the amount of native tokens available,
            //   which is smaller than 2¹²⁸/10¹⁸ ≈ 10²⁰ in all networks supported by CoW Swap so far. Since both values
            //    are smaller than 2¹²⁸, their product does not overflow a uint256.
            // - Subtraction underflow: again `filledAmount ≤ sellAmount`, meaning:
            //   feeAmount * filledAmount / sellAmount ≤ feeAmount
            uint256 feeRefundAmount = cowSwapOrder.feeAmount -
                ((cowSwapOrder.feeAmount * filledAmount) /
                    cowSwapOrder.sellAmount);

            // - Subtraction underflow: as noted before, filledAmount ≤ sellAmount.
            // - Addition overflow: as noted before, the user already sent feeAmount + sellAmount native tokens, which
            //   did not overflow.
            refundAmount =
                cowSwapOrder.sellAmount -
                filledAmount +
                feeRefundAmount;
        }

        // If not enough native token is available in the contract, unwrap the needed amount.
        if (address(this).balance < refundAmount) {
            uint256 withdrawAmount;
            unchecked {
                withdrawAmount = refundAmount - address(this).balance;
            }
            wrappedNativeToken.withdraw(withdrawAmount);
        }

        // Using low level calls to perform the transfer avoids setting arbitrary limits to the amount of gas used in a
        // call. Reentrancy is avoided thanks to the `nonReentrant` function modifier.
        // solhint-disable-next-line avoid-low-level-calls
        (bool success, ) = payable(orderData.owner).call{value: refundAmount}(
            ""
        );
        if (!success) {
            revert EthTransferFailed();
        }
    }

    /// @inheritdoc ICoWSwapEthFlow
    function isValidSignature(bytes32 orderHash, bytes memory)
        external
        view
        override(EIP1271Verifier, ICoWSwapEthFlow)
        returns (bytes4)
    {
        // Note: the signature parameter is ignored since all information needed to verify the validity of the order is
        // already available onchain.
        EthFlowOrder.OnchainData memory orderData = orders[orderHash];
        if (
            (orderData.owner != EthFlowOrder.NO_OWNER) &&
            (orderData.owner != EthFlowOrder.INVALIDATED_OWNER) &&
            // solhint-disable-next-line not-rely-on-time
            (orderData.validTo >= block.timestamp)
        ) {
            return GPv2EIP1271.MAGICVALUE;
        } else {
            return bytes4(type(uint32).max);
        }
    }
}
IERC20.sol 95 lines
// SPDX-License-Identifier: MIT

// Vendored from OpenZeppelin Contracts v4.4.0, see:
// <https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/v4.4.0/contracts/token/ERC20/IERC20.sol>

// OpenZeppelin Contracts v4.4.0 (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount)
        external
        returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender)
        external
        view
        returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );
}
GPv2Order.sol 254 lines
// SPDX-License-Identifier: LGPL-3.0-or-later

// Vendored from GPv2 contracts v1.0.0, see:
// <https://raw.githubusercontent.com/cowprotocol/contracts/v1.0.0/src/contracts/libraries/GPv2Order.sol>
// The following changes were made:
// - Bumped up Solidity version.
// - Vendored imports.

pragma solidity ^0.8;

import "./IERC20.sol";

/// @title Gnosis Protocol v2 Order Library
/// @author Gnosis Developers
library GPv2Order {
    /// @dev The complete data for a Gnosis Protocol order. This struct contains
    /// all order parameters that are signed for submitting to GP.
    struct Data {
        IERC20 sellToken;
        IERC20 buyToken;
        address receiver;
        uint256 sellAmount;
        uint256 buyAmount;
        uint32 validTo;
        bytes32 appData;
        uint256 feeAmount;
        bytes32 kind;
        bool partiallyFillable;
        bytes32 sellTokenBalance;
        bytes32 buyTokenBalance;
    }

    /// @dev The order EIP-712 type hash for the [`GPv2Order.Data`] struct.
    ///
    /// This value is pre-computed from the following expression:
    /// ```
    /// keccak256(
    ///     "Order(" +
    ///         "address sellToken," +
    ///         "address buyToken," +
    ///         "address receiver," +
    ///         "uint256 sellAmount," +
    ///         "uint256 buyAmount," +
    ///         "uint32 validTo," +
    ///         "bytes32 appData," +
    ///         "uint256 feeAmount," +
    ///         "string kind," +
    ///         "bool partiallyFillable" +
    ///         "string sellTokenBalance" +
    ///         "string buyTokenBalance" +
    ///     ")"
    /// )
    /// ```
    bytes32 internal constant TYPE_HASH =
        hex"d5a25ba2e97094ad7d83dc28a6572da797d6b3e7fc6663bd93efb789fc17e489";

    /// @dev The marker value for a sell order for computing the order struct
    /// hash. This allows the EIP-712 compatible wallets to display a
    /// descriptive string for the order kind (instead of 0 or 1).
    ///
    /// This value is pre-computed from the following expression:
    /// ```
    /// keccak256("sell")
    /// ```
    bytes32 internal constant KIND_SELL =
        hex"f3b277728b3fee749481eb3e0b3b48980dbbab78658fc419025cb16eee346775";

    /// @dev The OrderKind marker value for a buy order for computing the order
    /// struct hash.
    ///
    /// This value is pre-computed from the following expression:
    /// ```
    /// keccak256("buy")
    /// ```
    bytes32 internal constant KIND_BUY =
        hex"6ed88e868af0a1983e3886d5f3e95a2fafbd6c3450bc229e27342283dc429ccc";

    /// @dev The TokenBalance marker value for using direct ERC20 balances for
    /// computing the order struct hash.
    ///
    /// This value is pre-computed from the following expression:
    /// ```
    /// keccak256("erc20")
    /// ```
    bytes32 internal constant BALANCE_ERC20 =
        hex"5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc9";

    /// @dev The TokenBalance marker value for using Balancer Vault external
    /// balances (in order to re-use Vault ERC20 approvals) for computing the
    /// order struct hash.
    ///
    /// This value is pre-computed from the following expression:
    /// ```
    /// keccak256("external")
    /// ```
    bytes32 internal constant BALANCE_EXTERNAL =
        hex"abee3b73373acd583a130924aad6dc38cfdc44ba0555ba94ce2ff63980ea0632";

    /// @dev The TokenBalance marker value for using Balancer Vault internal
    /// balances for computing the order struct hash.
    ///
    /// This value is pre-computed from the following expression:
    /// ```
    /// keccak256("internal")
    /// ```
    bytes32 internal constant BALANCE_INTERNAL =
        hex"4ac99ace14ee0a5ef932dc609df0943ab7ac16b7583634612f8dc35a4289a6ce";

    /// @dev Marker address used to indicate that the receiver of the trade
    /// proceeds should the owner of the order.
    ///
    /// This is chosen to be `address(0)` for gas efficiency as it is expected
    /// to be the most common case.
    address internal constant RECEIVER_SAME_AS_OWNER = address(0);

    /// @dev The byte length of an order unique identifier.
    uint256 internal constant UID_LENGTH = 56;

    /// @dev Returns the actual receiver for an order. This function checks
    /// whether or not the [`receiver`] field uses the marker value to indicate
    /// it is the same as the order owner.
    ///
    /// @return receiver The actual receiver of trade proceeds.
    function actualReceiver(Data memory order, address owner)
        internal
        pure
        returns (address receiver)
    {
        if (order.receiver == RECEIVER_SAME_AS_OWNER) {
            receiver = owner;
        } else {
            receiver = order.receiver;
        }
    }

    /// @dev Return the EIP-712 signing hash for the specified order.
    ///
    /// @param order The order to compute the EIP-712 signing hash for.
    /// @param domainSeparator The EIP-712 domain separator to use.
    /// @return orderDigest The 32 byte EIP-712 struct hash.
    function hash(Data memory order, bytes32 domainSeparator)
        internal
        pure
        returns (bytes32 orderDigest)
    {
        bytes32 structHash;

        // NOTE: Compute the EIP-712 order struct hash in place. As suggested
        // in the EIP proposal, noting that the order struct has 10 fields, and
        // including the type hash `(12 + 1) * 32 = 416` bytes to hash.
        // <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#rationale-for-encodedata>
        // solhint-disable-next-line no-inline-assembly
        assembly {
            let dataStart := sub(order, 32)
            let temp := mload(dataStart)
            mstore(dataStart, TYPE_HASH)
            structHash := keccak256(dataStart, 416)
            mstore(dataStart, temp)
        }

        // NOTE: Now that we have the struct hash, compute the EIP-712 signing
        // hash using scratch memory past the free memory pointer. The signing
        // hash is computed from `"\x19\x01" || domainSeparator || structHash`.
        // <https://docs.soliditylang.org/en/v0.8.16/internals/layout_in_memory.html#layout-in-memory>
        // <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#specification>
        // solhint-disable-next-line no-inline-assembly
        assembly {
            let freeMemoryPointer := mload(0x40)
            mstore(freeMemoryPointer, "\x19\x01")
            mstore(add(freeMemoryPointer, 2), domainSeparator)
            mstore(add(freeMemoryPointer, 34), structHash)
            orderDigest := keccak256(freeMemoryPointer, 66)
        }
    }

    /// @dev Packs order UID parameters into the specified memory location. The
    /// result is equivalent to `abi.encodePacked(...)` with the difference that
    /// it allows re-using the memory for packing the order UID.
    ///
    /// This function reverts if the order UID buffer is not the correct size.
    ///
    /// @param orderUid The buffer pack the order UID parameters into.
    /// @param orderDigest The EIP-712 struct digest derived from the order
    /// parameters.
    /// @param owner The address of the user who owns this order.
    /// @param validTo The epoch time at which the order will stop being valid.
    function packOrderUidParams(
        bytes memory orderUid,
        bytes32 orderDigest,
        address owner,
        uint32 validTo
    ) internal pure {
        require(orderUid.length == UID_LENGTH, "GPv2: uid buffer overflow");

        // NOTE: Write the order UID to the allocated memory buffer. The order
        // parameters are written to memory in **reverse order** as memory
        // operations write 32-bytes at a time and we want to use a packed
        // encoding. This means, for example, that after writing the value of
        // `owner` to bytes `20:52`, writing the `orderDigest` to bytes `0:32`
        // will **overwrite** bytes `20:32`. This is desirable as addresses are
        // only 20 bytes and `20:32` should be `0`s:
        //
        //        |           1111111111222222222233333333334444444444555555
        //   byte | 01234567890123456789012345678901234567890123456789012345
        // -------+---------------------------------------------------------
        //  field | [.........orderDigest..........][......owner.......][vT]
        // -------+---------------------------------------------------------
        // mstore |                         [000000000000000000000000000.vT]
        //        |                     [00000000000.......owner.......]
        //        | [.........orderDigest..........]
        //
        // Additionally, since Solidity `bytes memory` are length prefixed,
        // 32 needs to be added to all the offsets.
        //
        // solhint-disable-next-line no-inline-assembly
        assembly {
            mstore(add(orderUid, 56), validTo)
            mstore(add(orderUid, 52), owner)
            mstore(add(orderUid, 32), orderDigest)
        }
    }

    /// @dev Extracts specific order information from the standardized unique
    /// order id of the protocol.
    ///
    /// @param orderUid The unique identifier used to represent an order in
    /// the protocol. This uid is the packed concatenation of the order digest,
    /// the validTo order parameter and the address of the user who created the
    /// order. It is used by the user to interface with the contract directly,
    /// and not by calls that are triggered by the solvers.
    /// @return orderDigest The EIP-712 signing digest derived from the order
    /// parameters.
    /// @return owner The address of the user who owns this order.
    /// @return validTo The epoch time at which the order will stop being valid.
    function extractOrderUidParams(bytes calldata orderUid)
        internal
        pure
        returns (
            bytes32 orderDigest,
            address owner,
            uint32 validTo
        )
    {
        require(orderUid.length == UID_LENGTH, "GPv2: invalid uid");

        // Use assembly to efficiently decode packed calldata.
        // solhint-disable-next-line no-inline-assembly
        assembly {
            orderDigest := calldataload(orderUid.offset)
            owner := shr(96, calldataload(add(orderUid.offset, 32)))
            validTo := shr(224, calldataload(add(orderUid.offset, 52)))
        }
    }
}
GPv2EIP1271.sol 36 lines
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.8;

// Vendored from GPv2 contracts v1.0.0, see:
// <https://raw.githubusercontent.com/cowprotocol/contracts/main/src/contracts/interfaces/GPv2EIP1271.sol>
// The following changes were made:
// - Bumped up Solidity version.

library GPv2EIP1271 {
    /// @dev Value returned by a call to `isValidSignature` if the signature
    /// was verified successfully. The value is defined in EIP-1271 as:
    /// bytes4(keccak256("isValidSignature(bytes32,bytes)"))
    bytes4 internal constant MAGICVALUE = 0x1626ba7e;
}

/// @title EIP1271 Interface
/// @dev Standardized interface for an implementation of smart contract
/// signatures as described in EIP-1271. The code that follows is identical to
/// the code in the standard with the exception of formatting and syntax
/// changes to adapt the code to our Solidity version.
interface EIP1271Verifier {
    /// @dev Should return whether the signature provided is valid for the
    /// provided data
    /// @param _hash      Hash of the data to be signed
    /// @param _signature Signature byte array associated with _data
    ///
    /// MUST return the bytes4 magic value 0x1626ba7e when function passes.
    /// MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for
    /// solc > 0.5)
    /// MUST allow external calls
    ///
    function isValidSignature(bytes32 _hash, bytes memory _signature)
        external
        view
        returns (bytes4 magicValue);
}
EthFlowOrder.sol 102 lines
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.8;

import "../vendored/GPv2Order.sol";
import "../vendored/IERC20.sol";

/// @title CoW Swap ETH Flow Order Library
/// @author CoW Swap Developers
library EthFlowOrder {
    /// @dev Struct collecting all parameters of an ETH flow order that need to be stored onchain.
    struct OnchainData {
        /// @dev The address of the user whom the order belongs to.
        address owner;
        /// @dev The latest timestamp in seconds when the order can be settled.
        uint32 validTo;
    }

    /// @dev Data describing all parameters of an ETH flow order.
    struct Data {
        /// @dev The address of the token that should be bought for ETH. It follows the same format as in the CoW Swap
        /// contracts, meaning that the token GPv2Transfer.BUY_ETH_ADDRESS (0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
        /// represents native ETH (and should most likely not be used in this context).
        IERC20 buyToken;
        /// @dev The address that should receive the proceeds from the order. Note that using the address
        /// GPv2Order.RECEIVER_SAME_AS_OWNER (i.e., the zero address) as the receiver is not allowed.
        address receiver;
        /// @dev The exact amount of ETH that should be sold in this order.
        uint256 sellAmount;
        /// @dev The minimum amount of buyToken that should be received to settle this order.
        uint256 buyAmount;
        /// @dev Extra data to include in the order. It is used by the CoW Swap infrastructure as extra information on
        /// the order and has no direct effect on on-chain execution.
        bytes32 appData;
        /// @dev The exact amount of ETH that should be paid by the user to the CoW Swap contract after the order is
        /// settled.
        uint256 feeAmount;
        /// @dev The last timestamp in seconds from which the order can be settled (order cannot resolve after this timestamp).
        uint32 validTo;
        /// @dev Flag indicating whether the order is fill-or-kill or can be filled partially.
        bool partiallyFillable;
        /// @dev quoteId The quote id obtained from the CoW Swap API to lock in the current price. It is not directly
        /// used by any onchain component but is part of the information emitted onchain on order creation and may be
        /// required for an order to be automatically picked up by the CoW Swap orderbook.
        int64 quoteId;
    }

    /// @dev An order that is owned by this address is an order that has not yet been assigned.
    address internal constant NO_OWNER = address(0);

    /// @dev An order that is owned by this address is an order that has been invalidated. Note that this address cannot
    /// be directly used to create orders.
    address internal constant INVALIDATED_OWNER = address(type(uint160).max);

    /// @dev Error returned if the receiver of the ETH flow order is unspecified (`GPv2Order.RECEIVER_SAME_AS_OWNER`).
    error ReceiverMustBeSet();

    /// @dev Transforms an ETH flow order into the CoW Swap order that can be settled by the ETH flow contract.
    ///
    /// @param order The ETH flow order to be converted.
    /// @param wrappedNativeToken The address of the wrapped native token for the current network (e.g., WETH for
    /// Ethereum mainet).
    /// @return The CoW Swap order data that represents the user order in the ETH flow contract.
    function toCoWSwapOrder(Data memory order, IERC20 wrappedNativeToken)
        internal
        pure
        returns (GPv2Order.Data memory)
    {
        if (order.receiver == GPv2Order.RECEIVER_SAME_AS_OWNER) {
            // The receiver field specified which address is going to receive the proceeds from the orders. If using
            // `RECEIVER_SAME_AS_OWNER`, then the receiver is implicitly assumed by the CoW Swap Protocol to be the
            // same as the order owner.
            // However, the owner of an ETH flow order is always the ETH flow smart contract, and any ERC20 tokens sent
            // to this contract would be lost.
            revert ReceiverMustBeSet();
        }

        // Note that not all fields from `order` are used in creating the corresponding CoW Swap order.
        // For example, validTo and quoteId are ignored.
        return
            GPv2Order.Data(
                wrappedNativeToken, // IERC20 sellToken
                order.buyToken, // IERC20 buyToken
                order.receiver, // address receiver
                order.sellAmount, // uint256 sellAmount
                order.buyAmount, // uint256 buyAmount
                // This CoW Swap order is not allowed to expire. If it expired, then any solver of CoW Swap contract
                // would be allowed to clear the `filledAmount` for this order using `freeFilledAmountStorage`, making
                // it impossible to detect if the order has been previously filled.
                // Note that order.validTo is disregarded in building the CoW Swap order.
                type(uint32).max, // uint32 validTo
                order.appData, // bytes32 appData
                order.feeAmount, // uint256 feeAmount
                // Only sell orders are allowed. In a buy order, any leftover ETH would stay in the ETH flow contract
                // and would need to be sent back to the user, whose extra gas cost is usually not worth it.
                GPv2Order.KIND_SELL, // bytes32 kind
                order.partiallyFillable, // bool partiallyFillable
                // We do not currently support interacting with the Balancer vault.
                GPv2Order.BALANCE_ERC20, // bytes32 sellTokenBalance
                GPv2Order.BALANCE_ERC20 // bytes32 buyTokenBalance
            );
    }
}
CoWSwapEip712.sol 50 lines
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.8;

/// @title CoW Swap EIP-712 Encoding Library
/// @author CoW Swap Developers
/// @dev The code in this contract was largely taken from:
/// <https://raw.githubusercontent.com/cowprotocol/contracts/v1.0.0/src/contracts/mixins/GPv2Signing.sol>
library CoWSwapEip712 {
    /// @dev The EIP-712 domain type hash used for computing the domain separator.
    bytes32 private constant DOMAIN_TYPE_HASH =
        keccak256(
            "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
        );

    /// @dev The EIP-712 domain name used for computing the domain separator.
    bytes32 private constant DOMAIN_NAME = keccak256("Gnosis Protocol");

    /// @dev The EIP-712 domain version used for computing the domain separator.
    bytes32 private constant DOMAIN_VERSION = keccak256("v2");

    /// @dev Computes the EIP-712 domain separator of the CoW Swap settlement contract on the current network.
    ///
    /// @param cowSwapAddress The address of the CoW Swap settlement contract for which to compute the domain separator.
    /// Note that there are no checks to verify that the input address points to an actual contract.
    /// @return The domain separator of the settlement contract for the input address as computed by the settlement
    /// contract internally.
    function domainSeparator(address cowSwapAddress)
        internal
        view
        returns (bytes32)
    {
        // NOTE: Currently, the only way to get the chain ID in solidity is using assembly.
        uint256 chainId;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            chainId := chainid()
        }

        return
            keccak256(
                abi.encode(
                    DOMAIN_TYPE_HASH,
                    DOMAIN_NAME,
                    DOMAIN_VERSION,
                    chainId,
                    cowSwapAddress
                )
            );
    }
}
ICoWSwapEthFlow.sol 98 lines
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.8;

import "../libraries/EthFlowOrder.sol";

/// @title CoW Swap ETH Flow Event Interface
/// @author CoW Swap Developers
interface ICoWSwapEthFlowEvents {
    /// @dev Event emitted to notify that an order was refunded. Note that this event is not fired every time the order
    /// is invalidated (even though the user receives all unspent ETH back). This is because we want to differenciate
    /// the case where the user invalidates a valid order and when the user receives back the funds from an expired
    /// order.
    ///
    /// @param orderUid CoW Swap's unique order identifier of the order that has been invalidated (and refunded).
    /// @param refunder The address that triggered the order refund.
    event OrderRefund(bytes orderUid, address indexed refunder);
}

/// @title CoW Swap ETH Flow Interface
/// @author CoW Swap Developers
interface ICoWSwapEthFlow is ICoWSwapEthFlowEvents {
    /// @dev Error thrown when trying to create a new order whose order hash is the same as an order hash that was
    /// already assigned.
    error OrderIsAlreadyOwned(bytes32 orderHash);

    /// @dev Error thrown when trying to create an order that would be expired at the time of creation
    error OrderIsAlreadyExpired();

    /// @dev Error thrown when trying to create an order without sending the expected amount of ETH to this contract.
    error IncorrectEthAmount();

    /// @dev Error thrown when trying to create an order with a sell amount == 0
    error NotAllowedZeroSellAmount();

    /// @dev Error thrown if trying to invalidate an order while not allowed.
    error NotAllowedToInvalidateOrder(bytes32 orderHash);

    /// @dev Error thrown when unsuccessfully sending ETH to an address.
    error EthTransferFailed();

    /// @dev Function that creates and broadcasts an ETH flow order that sells native ETH. The order is paid for when
    /// the caller sends out the transaction. The caller takes ownership of the new order.
    ///
    /// @param order The data describing the order to be created. See [`EthFlowOrder.Data`] for extra information on
    /// each parameter.
    /// @return orderHash The hash of the CoW Swap order that is created to settle the new ETH order.
    function createOrder(EthFlowOrder.Data calldata order)
        external
        payable
        returns (bytes32 orderHash);

    /// @dev Marks existing ETH-flow orders as invalid and, for each order, refunds the ETH that hasn't been traded yet.
    /// The function call will not revert, if some orders are not refundable. It will silently ignore these orders.
    /// Note that some parameters of the orders are ignored, as for example the order expiration date and the quote id.
    ///
    /// @param orderArray Array of orders to be invalidated.
    function invalidateOrdersIgnoringNotAllowed(
        EthFlowOrder.Data[] calldata orderArray
    ) external;

    /// @dev Marks an existing ETH-flow order as invalid and refunds the ETH that hasn't been traded yet.
    /// Note that some parameters of the orders are ignored, as for example the order expiration date and the quote id.
    ///
    /// @param order Order to be invalidated.
    function invalidateOrder(EthFlowOrder.Data calldata order) external;

    /// @dev EIP1271-compliant onchain signature verification function.
    /// This function is used by the CoW Swap settlement contract to determine if an order that is signed with an
    /// EIP1271 signature is valid. As this contract has approved the vault relayer contract, a valid signature for an
    /// order means that the order can be traded on CoW Swap.
    ///
    /// @param orderHash Hash of the order to be signed. This is the EIP-712 signing hash for the specified order as
    /// defined in the CoW Swap settlement contract.
    /// @param signature Signature byte array. This parameter is unused since as all information needed to verify if an
    /// order is already available onchain.
    /// @return magicValue Either the EIP-1271 "magic value" indicating success (0x1626ba7e) or a different value
    /// indicating failure (0xffffffff).
    function isValidSignature(bytes32 orderHash, bytes memory signature)
        external
        view
        returns (bytes4 magicValue);

    /// @dev This function reads the  chain's native token balance of this contract (e.g., ETH for mainnet) and converts
    // the entire amount to its wrapped version (e.g., WETH).
    function wrapAll() external;

    /// @dev This function takes the specified amount of the chain's native token (e.g., ETH for mainnet) stored by this
    /// contract and converts it to its wrapped version (e.g., WETH).
    ///
    /// @param amount The amount of native tokens to convert to wrapped native tokens.
    function wrap(uint256 amount) external;

    /// @dev This function takes the specified amount of the chain's wrapped native token (e.g., WETH for mainnet)
    /// and converts it to its unwrapped version (e.g., ETH).
    ///
    /// @param amount The amount of wrapped native tokens to convert to native tokens.
    function unwrap(uint256 amount) external;
}
CoWSwapOnchainOrders.sol 39 lines
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.8;

import "../vendored/GPv2Order.sol";
import "../interfaces/ICoWSwapOnchainOrders.sol";
import "../libraries/CoWSwapEip712.sol";

/// @title CoW Swap Onchain Order Creator Event Emitter
/// @author CoW Swap Developers
contract CoWSwapOnchainOrders is ICoWSwapOnchainOrders {
    using GPv2Order for GPv2Order.Data;
    using GPv2Order for bytes;

    /// @dev The domain separator for the CoW Swap settlement contract.
    bytes32 internal immutable cowSwapDomainSeparator;

    /// @param settlementContractAddress The address of CoW Swap's settlement contract on the chain where this contract
    /// is deployed.
    constructor(address settlementContractAddress) {
        cowSwapDomainSeparator = CoWSwapEip712.domainSeparator(
            settlementContractAddress
        );
    }

    /// @dev Emits an event with all information needed to execute an order onchain and returns the corresponding order
    /// hash.
    ///
    /// See [`ICoWSwapOnchainOrders.OrderPlacement`] for details on the meaning of each parameter.
    /// @return The EIP-712 hash of the order data as computed by the CoW Swap settlement contract.
    function broadcastOrder(
        address sender,
        GPv2Order.Data memory order,
        OnchainSignature memory signature,
        bytes memory data
    ) internal returns (bytes32) {
        emit OrderPlacement(sender, order, signature, data);
        return order.hash(cowSwapDomainSeparator);
    }
}
ICoWSwapSettlement.sol 21 lines
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.8;

/// @title CoW Swap Settlement Contract Interface
/// @author CoW Swap Developers
/// @dev This interface collects the functions of the CoW Swap settlement contract that are used by the ETH flow
/// contract.
interface ICoWSwapSettlement {
    /// @dev Map each user order by UID to the amount that has been filled so
    /// far. If this amount is larger than or equal to the amount traded in the
    /// order (amount sold for sell orders, amount bought for buy orders) then
    /// the order cannot be traded anymore. If the order is fill or kill, then
    /// this value is only used to determine whether the order has already been
    /// executed.
    /// @param orderUid The uinique identifier to use to retrieve the filled amount.
    function filledAmount(bytes memory orderUid) external returns (uint256);

    /// @dev The address of the vault relayer: the contract that handles withdrawing tokens from the user to the
    /// settlement contract. A user who wants to sell a token on CoW Swap must approve this contract to spend the token.
    function vaultRelayer() external returns (address);
}
IWrappedNativeToken.sol 15 lines
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.8;

import "../vendored/IERC20.sol";

/// @title CoW Swap Wrapped Native Token Interface
/// @author CoW Swap Developers
interface IWrappedNativeToken is IERC20 {
    /// @dev Deposit native token in exchange for wrapped netive tokens.
    function deposit() external payable;

    /// @dev Burn wrapped native tokens in exchange for native tokens.
    /// @param amount Amount of wrapped tokens to exchange for native tokens.
    function withdraw(uint256 amount) external;
}
ICoWSwapOnchainOrders.sol 50 lines
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.8;

import "../vendored/GPv2Order.sol";

/// @title CoW Swap Onchain Order Creator Interface
/// @author CoW Swap Developers
interface ICoWSwapOnchainOrders {
    /// @dev List of signature schemes that are supported by this contract to create orders onchain.
    enum OnchainSigningScheme {
        Eip1271,
        PreSign
    }

    /// @dev Struct containing information on the signign scheme used plus the corresponding signature.
    struct OnchainSignature {
        /// @dev The signing scheme used by the signature data.
        OnchainSigningScheme scheme;
        /// @dev The data used as an order signature.
        bytes data;
    }

    /// @dev Event emitted to broadcast an order onchain.
    ///
    /// @param sender The user who triggered the creation of the order. Note that this address does *not* need to be
    /// the actual owner of the order and does not need to be related to the order or signature in any way.
    /// For example, if a smart contract creates orders on behalf of the user, then the sender would be the user who
    /// triggers the creation of the order, while the actual owner of the order would be the smart contract that
    /// creates it.
    /// @param order Information on the order that is created in this transacion. The order is expected to be a valid
    /// order for the CoW Swap settlement contract and contain all information needed to settle it in a batch.
    /// @param signature The signature that can be used to verify the newly created order. Note that it is always
    /// possible to recover the owner of the order from a valid signature.
    /// @param data Any extra data that should be passed along with the order. This will be used by the services that
    /// collects onchain orders and no specific encoding is enforced on this field. It is supposed to encode extra
    /// information that is not included in the order data so that it can be passed along when decoding an onchain
    /// order. As an example, a contract that creates orders on behalf of a user could set a different expiration date
    /// than the one specified in the order.
    event OrderPlacement(
        address indexed sender,
        GPv2Order.Data order,
        OnchainSignature signature,
        bytes data
    );

    /// @dev Event emitted to notify that an order was invalidated.
    ///
    /// @param orderUid CoW Swap's unique order identifier of the order that has been invalidated.
    event OrderInvalidation(bytes orderUid);
}

Read Contract

cowSwapSettlement 0xec30bb88 → address
isValidSignature 0x1626ba7e → bytes4
orders 0x9c3f1e90 → address, uint32
wrappedNativeToken 0x17fcb39b → address

Write Contract 6 functions

These functions modify contract state and require a wallet transaction to execute.

createOrder 0xd8b6cc2f
tuple order
returns: bytes32
invalidateOrder 0xa68c3b29
tuple order
invalidateOrdersIgnoringNotAllowed 0x895c9fed
tuple[] orderArray
unwrap 0xde0e9a3e
uint256 amount
wrap 0xea598cb0
uint256 amount
wrapAll 0x4c84c1c8
No parameters

Top Interactions

Recent Transactions

CSV
|
Hash Method Block Age From/To Value Txn Fee Type
0xd08c8134...edc827 0x322bba21 24,585,891 IN 0x17bbBC18...c4d0 1.0000 ETH 0.000065236920 ETH EIP-1559
0x420b7dfa...a680c0 0x7bc41b96 24,585,886 IN 0xA015e4c6...957b 0 ETH 0.000085945453 ETH EIP-1559
0x1afcad69...1b65c9 0x322bba21 24,585,881 IN 0x2482Dc04...91EA 30.0000 ETH 0.000012566663 ETH EIP-1559
0x35dfa4d9...ac0039 0x322bba21 24,585,876 IN 0xc230f4A4...913e 0.254100 ETH 0.000120362415 ETH EIP-1559
0xb3adbeac...5f1eaa 0x322bba21 24,585,855 IN 0x17bbBC18...c4d0 1.0000 ETH 0.000066552401 ETH EIP-1559
0x410eae76...f952fa 0x322bba21 24,585,840 IN 0xc230f4A4...913e 0.254100 ETH 0.000120757957 ETH EIP-1559