Skip to content

Commit

Permalink
Add order deletion (#7)
Browse files Browse the repository at this point in the history
* Add order deletion

* Add parameter test to dedicated test contract

* Remove time check from test

* Fix usage of vm.startPrank and vm.prank

* Use .send to transfer ETH
  • Loading branch information
fedgiac authored Aug 31, 2022
1 parent e512d2b commit b51eb3a
Show file tree
Hide file tree
Showing 7 changed files with 344 additions and 18 deletions.
52 changes: 48 additions & 4 deletions src/CoWSwapEthFlow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,20 @@
pragma solidity ^0.8;

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

/// @title CoW Swap ETH Flow
/// @author CoW Swap Developers
contract CoWSwapEthFlow is CoWSwapOnchainOrders, 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).
Expand All @@ -21,11 +28,13 @@ contract CoWSwapEthFlow is CoWSwapOnchainOrders, ICoWSwapEthFlow {
/// onchain data.
mapping(bytes32 => EthFlowOrder.OnchainData) public orders;

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

Expand Down Expand Up @@ -68,4 +77,39 @@ contract CoWSwapEthFlow is CoWSwapOnchainOrders, ICoWSwapEthFlow {

orders[orderHash] = onchainData;
}

/// @inheritdoc ICoWSwapEthFlow
function deleteOrder(EthFlowOrder.Data calldata order) external {
GPv2Order.Data memory cowSwapOrder = order.toCoWSwapOrder(
wrappedNativeToken
);
bytes32 orderHash = cowSwapOrder.hash(cowSwapDomainSeparator);

EthFlowOrder.OnchainData memory orderData = orders[orderHash];

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

orders[orderHash].owner = EthFlowOrder.INVALIDATED_OWNER;

bytes memory orderUid = new bytes(GPv2Order.UID_LENGTH);
orderUid.packOrderUidParams(
orderHash,
address(this),
cowSwapOrder.validTo
);
uint256 freedAmount = cowSwapOrder.sellAmount -
cowSwapSettlement.filledAmount(orderUid);

if (!payable(orderData.owner).send(freedAmount)) {
revert EthTransferFailed();
}
}
}
12 changes: 12 additions & 0 deletions src/interfaces/ICoWSwapEthFlow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ interface ICoWSwapEthFlow {
/// @dev Error thrown when trying to create an order without sending the expected amount of ETH to this contract.
error IncorrectEthAmount();

/// @dev Error thrown if trying to delete an order while not allowed.
error NotAllowedToDeleteOrder(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.
///
Expand All @@ -23,4 +29,10 @@ interface ICoWSwapEthFlow {
external
payable
returns (bytes32 orderHash);

/// @dev Marks an existing ETH flow order as invalid and refunds the trader of all ETH that hasn't been traded yet.
/// Note that some parameters of the order are ignored, as for example the order expiration date and the quote id.
///
/// @param order The order to be deleted.
function deleteOrder(EthFlowOrder.Data calldata order) external;
}
16 changes: 16 additions & 0 deletions src/interfaces/ICoWSwapSettlement.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// 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.
function filledAmount(bytes memory orderUid) external returns (uint256);
}
4 changes: 4 additions & 0 deletions src/libraries/EthFlowOrder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ library EthFlowOrder {
/// @dev An order that is owned by this address is an order that has not yet been assigned.
address public 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 public 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();

Expand Down
Loading

0 comments on commit b51eb3a

Please sign in to comment.