Skip to content

Commit

Permalink
Add v2 version of the functions with makeRecipient
Browse files Browse the repository at this point in the history
  • Loading branch information
wojciech-turek committed Sep 6, 2024
1 parent 3b0a941 commit 20b07a2
Show file tree
Hide file tree
Showing 7 changed files with 519 additions and 24 deletions.
26 changes: 26 additions & 0 deletions packages/marketplace/contracts/Exchange.sol
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ contract Exchange is
_matchOrders(_msgSender(), matchedOrders);
}

/// @notice Match orders and transact.
/// @param matchedOrders A list of left/right orders that match each other.
function matchOrdersV2(ExchangeMatchV2[] calldata matchedOrders) external whenNotPaused {
_matchOrdersV2(_msgSender(), matchedOrders);
}

/// @notice Match orders and transact.
/// @param sender The original sender of the transaction.
/// @param matchedOrders A list of left/right orders that match each other.
Expand All @@ -92,6 +98,18 @@ contract Exchange is
_matchOrders(sender, matchedOrders);
}

/// @notice Match orders and transact.
/// @param sender The original sender of the transaction.
/// @param matchedOrders A list of left/right orders that match each other.
/// @dev This method supports ERC1776 native meta transactions.
function matchOrdersFromV2(
address sender,
ExchangeMatchV2[] calldata matchedOrders
) external onlyRole(ERC1776_OPERATOR_ROLE) whenNotPaused {
require(sender != address(0), "invalid sender");
_matchOrdersV2(sender, matchedOrders);
}

/// @notice Cancel an order.
/// @param order The order to be canceled.
/// @param orderKeyHash Used as a checksum to avoid mistakes in the order values.
Expand All @@ -100,6 +118,14 @@ contract Exchange is
_cancel(order, orderKeyHash);
}

/// @notice Cancel an order.
/// @param order The order to be canceled.
/// @param orderKeyHash Used as a checksum to avoid mistakes in the order values.
function cancelV2(LibOrder.OrderV2 calldata order, bytes32 orderKeyHash) external {
require(_msgSender() == order.maker, "not maker");
_cancelV2(order, orderKeyHash);
}

/// @notice Set the royalty registry.
/// @param newRoyaltiesRegistry Address of the new royalties registry.
function setRoyaltiesRegistry(IRoyaltiesProvider newRoyaltiesRegistry) external onlyRole(DEFAULT_ADMIN_ROLE) {
Expand Down
152 changes: 152 additions & 0 deletions packages/marketplace/contracts/ExchangeCore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ abstract contract ExchangeCore is Initializable, ITransferManager {
bytes signatureRight; // Signature of the right order
}

struct ExchangeMatchV2 {
LibOrder.OrderV2 orderLeft; // Left order details
bytes signatureLeft; // Signature of the left order
LibOrder.OrderV2 orderRight; // Right order details
bytes signatureRight; // Signature of the right order
}

/// @dev Address of the OrderValidator contract.
IOrderValidator public orderValidator;

Expand All @@ -38,6 +45,11 @@ abstract contract ExchangeCore is Initializable, ITransferManager {
/// @param order The details of the order being canceled.
event Cancel(bytes32 indexed orderKeyHash, LibOrder.Order order);

/// @notice Event emitted when an order is canceled.
/// @param orderKeyHash The hash of the order being canceled.
/// @param order The details of the order being canceled.
event CancelV2(bytes32 indexed orderKeyHash, LibOrder.OrderV2 order);

/// @notice Event emitted when two orders are matched.
/// @param from Address that initiated the match.
/// @param orderKeyHashLeft Hash of the left order.
Expand All @@ -58,6 +70,26 @@ abstract contract ExchangeCore is Initializable, ITransferManager {
uint256 totalFillRight
);

/// @notice Event emitted when two orders are matched.
/// @param from Address that initiated the match.
/// @param orderKeyHashLeft Hash of the left order.
/// @param orderKeyHashRight Hash of the right order.
/// @param orderLeft Details of the left order.
/// @param orderRight Details of the right order.
/// @param newFill Fill details resulting from the order match.
/// @param totalFillLeft Total fill amount for the left order.
/// @param totalFillRight Total fill amount for the right order.
event MatchV2(
address indexed from,
bytes32 indexed orderKeyHashLeft,
bytes32 indexed orderKeyHashRight,
LibOrder.OrderV2 orderLeft,
LibOrder.OrderV2 orderRight,
LibOrder.FillResult newFill,
uint256 totalFillLeft,
uint256 totalFillRight
);

/// @notice Event emitted when a new OrderValidator contract is set.
/// @param contractAddress Address of the new OrderValidator contract.
event OrderValidatorSet(IOrderValidator indexed contractAddress);
Expand Down Expand Up @@ -111,6 +143,17 @@ abstract contract ExchangeCore is Initializable, ITransferManager {
emit Cancel(orderKeyHash, order);
}

/// @notice Cancels a specified order.
/// @param order Details of the order to be canceled.
/// @param orderKeyHash The hash of the order, used for verification.
function _cancelV2(LibOrder.OrderV2 calldata order, bytes32 orderKeyHash) internal {
require(order.salt != 0, "0 salt can't be used");
bytes32 _orderKeyHash = LibOrder.hashKeyV2(order);
require(_orderKeyHash == orderKeyHash, "invalid orderHash");
fills[orderKeyHash] = type(uint256).max;
emit CancelV2(orderKeyHash, order);
}

/// @notice Matches provided orders and performs the transaction.
/// @param sender The original sender of the transaction.
/// @param matchedOrders Array of orders that are matched with each other.
Expand All @@ -125,6 +168,20 @@ abstract contract ExchangeCore is Initializable, ITransferManager {
}
}

/// @notice Matches provided orders and performs the transaction.
/// @param sender The original sender of the transaction.
/// @param matchedOrders Array of orders that are matched with each other.
function _matchOrdersV2(address sender, ExchangeMatchV2[] calldata matchedOrders) internal {
uint256 len = matchedOrders.length;
require(len > 0, "ExchangeMatch cannot be empty");
require(len <= matchOrdersLimit, "too many ExchangeMatch");
for (uint256 i; i < len; i++) {
ExchangeMatchV2 calldata m = matchedOrders[i];
_validateOrdersV2(sender, m.orderLeft, m.signatureLeft, m.orderRight, m.signatureRight);
_matchAndTransferV2(sender, m.orderLeft, m.orderRight);
}
}

/// @dev Validates the provided orders.
/// @param sender Address of the sender.
/// @param orderLeft Details of the left order.
Expand All @@ -149,6 +206,30 @@ abstract contract ExchangeCore is Initializable, ITransferManager {
}
}

/// @dev Validates the provided orders.
/// @param sender Address of the sender.
/// @param orderLeft Details of the left order.
/// @param signatureLeft Signature of the left order.
/// @param orderRight Details of the right order.
/// @param signatureRight Signature of the right order.
function _validateOrdersV2(
address sender,
LibOrder.OrderV2 memory orderLeft,
bytes memory signatureLeft,
LibOrder.OrderV2 memory orderRight,
bytes memory signatureRight
) internal view {
// validate must force order.maker != address(0)
orderValidator.validateV2(orderLeft, signatureLeft, sender);
orderValidator.validateV2(orderRight, signatureRight, sender);
if (orderLeft.taker != address(0)) {
require(orderRight.maker == orderLeft.taker, "leftOrder.taker failed");
}
if (orderRight.taker != address(0)) {
require(orderRight.taker == orderLeft.maker, "rightOrder.taker failed");
}
}

/// @notice Matches valid orders and transfers the associated assets.
/// @param sender Address initiating the match.
/// @param orderLeft The left order.
Expand All @@ -169,6 +250,37 @@ abstract contract ExchangeCore is Initializable, ITransferManager {

LibOrder.FillResult memory newFill = _parseOrdersSetFillEmitMatch(sender, orderLeft, orderRight);

doTransfers(
ITransferManager.DealSide(LibAsset.Asset(makeMatch, newFill.leftValue), orderLeft.maker, orderLeft.maker),
ITransferManager.DealSide(
LibAsset.Asset(takeMatch, newFill.rightValue),
orderRight.maker,
orderRight.maker
),
LibAsset.getFeeSide(makeMatch.assetClass, takeMatch.assetClass)
);
}

/// @notice Matches valid orders and transfers the associated assets.
/// @param sender Address initiating the match.
/// @param orderLeft The left order.
/// @param orderRight The right order.
function _matchAndTransferV2(
address sender,
LibOrder.OrderV2 calldata orderLeft,
LibOrder.OrderV2 calldata orderRight
) internal {
LibAsset.AssetType memory makeMatch = LibAsset.matchAssets(
orderLeft.makeAsset.assetType,
orderRight.takeAsset.assetType
);
LibAsset.AssetType memory takeMatch = LibAsset.matchAssets(
orderLeft.takeAsset.assetType,
orderRight.makeAsset.assetType
);

LibOrder.FillResult memory newFill = _parseOrdersSetFillEmitMatchV2(sender, orderLeft, orderRight);

doTransfers(
ITransferManager.DealSide(
LibAsset.Asset(makeMatch, newFill.leftValue),
Expand Down Expand Up @@ -224,6 +336,46 @@ abstract contract ExchangeCore is Initializable, ITransferManager {
return newFill;
}

/// @notice Parse orders to get the order data, then create a new fill with setFillEmitMatch()
/// @param sender The message sender
/// @param orderLeft Left order
/// @param orderRight Right order
/// @return newFill Fill result
function _parseOrdersSetFillEmitMatchV2(
address sender,
LibOrder.OrderV2 calldata orderLeft,
LibOrder.OrderV2 calldata orderRight
) internal returns (LibOrder.FillResult memory newFill) {
bytes32 orderKeyHashLeft = LibOrder.hashKeyV2(orderLeft);
bytes32 orderKeyHashRight = LibOrder.hashKeyV2(orderRight);

uint256 leftOrderFill = _getOrderFill(orderLeft.salt, orderKeyHashLeft);
uint256 rightOrderFill = _getOrderFill(orderRight.salt, orderKeyHashRight);
newFill = LibOrder.fillOrderV2(orderLeft, orderRight, leftOrderFill, rightOrderFill);

require(newFill.rightValue > 0 && newFill.leftValue > 0, "nothing to fill");

if (orderLeft.salt != 0) {
fills[orderKeyHashLeft] = leftOrderFill + newFill.rightValue;
}

if (orderRight.salt != 0) {
fills[orderKeyHashRight] = rightOrderFill + newFill.leftValue;
}

emit MatchV2({
from: sender,
orderKeyHashLeft: orderKeyHashLeft,
orderKeyHashRight: orderKeyHashRight,
orderLeft: orderLeft,
orderRight: orderRight,
newFill: newFill,
totalFillLeft: fills[orderKeyHashLeft],
totalFillRight: fills[orderKeyHashRight]
});
return newFill;
}

/// @notice Return fill corresponding to order hash
/// @param salt If salt 0, fill = 0
/// @param hash Order hash
Expand Down
27 changes: 26 additions & 1 deletion packages/marketplace/contracts/OrderValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ contract OrderValidator is IOrderValidator, Initializable, EIP712Upgradeable, Wh
/// @param sender Address of the order sender.
function validate(LibOrder.Order calldata order, bytes memory signature, address sender) external view {
require(order.maker != address(0), "no maker");
require(order.makeRecipient != address(0), "no recipient");

LibOrder.validateOrderTime(order);
_verifyWhitelists(order.makeAsset);
Expand All @@ -62,6 +61,32 @@ contract OrderValidator is IOrderValidator, Initializable, EIP712Upgradeable, Wh
require(order.maker.isValidSignatureNow(_hashTypedDataV4(hash), signature), "signature verification error");
}

/// @notice Validates the given order.
/// @param order The order details to be validated.
/// @param signature The signature associated with the order.
/// @param sender Address of the order sender.
function validateV2(LibOrder.OrderV2 calldata order, bytes memory signature, address sender) external view {
require(order.maker != address(0), "no maker");
require(order.makeRecipient != address(0), "no recipient");

LibOrder.validateOrderTimeV2(order);
_verifyWhitelists(order.makeAsset);

if (order.salt == 0) {
require(sender == order.maker, "maker is not tx sender");
// No partial fill, the order is reusable forever
return;
}

if (sender == order.maker) {
return;
}

bytes32 hash = LibOrder.hashV2(order);

require(order.maker.isValidSignatureNow(_hashTypedDataV4(hash), signature), "signature v2 verification error");
}

/// @notice Verifies if the asset exchange is affected by the whitelist.
/// @param asset Details of the asset to be verified.
/// @dev If the asset type is ERC20, the ERC20_ROLE is checked.
Expand Down
6 changes: 6 additions & 0 deletions packages/marketplace/contracts/interfaces/IOrderValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,10 @@ interface IOrderValidator {
/// @param signature Signature of order
/// @param sender Order sender
function validate(LibOrder.Order memory order, bytes memory signature, address sender) external view;

/// @notice Verifies order
/// @param order Order to be validated
/// @param signature Signature of order
/// @param sender Order sender
function validateV2(LibOrder.OrderV2 memory order, bytes memory signature, address sender) external view;
}
Loading

0 comments on commit 20b07a2

Please sign in to comment.