Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use fillerData for indicating settle receivers #22

Open
wants to merge 2 commits into
base: deploy-router
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 13 additions & 15 deletions solidity/src/Base7683.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ abstract contract Base7683 is IOriginSettler, IDestinationSettler {

mapping(bytes32 orderId => OrderData orderData) public orders;

mapping(bytes32 orderId => address filler) public orderFiller;
mapping(bytes32 orderId => bytes fillerData) public orderFillerData;

mapping(bytes32 orderId => OrderStatus status) public orderStatus;

Expand All @@ -57,7 +57,7 @@ abstract contract Base7683 is IOriginSettler, IDestinationSettler {
// ============ Events ============

event Filled(bytes32 orderId, bytes originData, bytes fillerData);
event Settle(bytes32[] orderIds, bytes32[] receivers);
event Settle(bytes32[] orderIds, bytes[] ordersFillerData);
event Refund(bytes32[] orderIds);
event Settled(bytes32 orderId, address receiver);
event Refunded(bytes32 orderId, address receiver);
Expand All @@ -73,10 +73,8 @@ abstract contract Base7683 is IOriginSettler, IDestinationSettler {
error InvalidOrderDomain();
error InvalidOrderStatus();
error InvalidSenderNonce();
error InvalidOrderFiller();
error OrderFillNotExpired();
error InvalidDomain();
error InvalidOrdersLength();
error InvalidSender();

// ============ Constructor ============
Expand Down Expand Up @@ -182,8 +180,9 @@ abstract contract Base7683 is IOriginSettler, IDestinationSettler {
/// @notice Fills a single leg of a particular order on the destination chain
/// @param _orderId Unique order identifier for this order
/// @param _originData Data emitted on the origin to parameterize the fill
/// NOT USED fillerData Data provided by the filler to inform the fill or express their preferences
function fill(bytes32 _orderId, bytes calldata _originData, bytes calldata) external virtual {
/// @param _fillerData Data provided by the filler to inform the fill or express their preferences. It should
/// contain the bytes32 encoded address of the receiver which is the used at settlement time
function fill(bytes32 _orderId, bytes calldata _originData, bytes calldata _fillerData) external virtual {
OrderData memory orderData = OrderEncoder.decode(_originData);

if (_orderId != _getOrderId(orderData)) revert InvalidOrderId();
Expand All @@ -194,30 +193,29 @@ abstract contract Base7683 is IOriginSettler, IDestinationSettler {

orders[_orderId] = orderData;
orderStatus[_orderId] = OrderStatus.FILLED;
orderFiller[_orderId] = msg.sender;
orderFillerData[_orderId] = _fillerData;

emit Filled(_orderId, _originData, new bytes(0));
emit Filled(_orderId, _originData, _fillerData);

IERC20(TypeCasts.bytes32ToAddress(orderData.outputToken)).safeTransferFrom(
msg.sender, TypeCasts.bytes32ToAddress(orderData.recipient), orderData.amountOut
);
}

function settle(bytes32[] calldata _orderIds, bytes32[] calldata _receivers) external payable {
if (_orderIds.length != _receivers.length) revert InvalidOrdersLength();

function settle(bytes32[] calldata _orderIds) external payable {
bytes[] memory ordersFillerData = new bytes[](_orderIds.length);
for (uint256 i = 0; i < _orderIds.length; i += 1) {
if (orderStatus[_orderIds[i]] != OrderStatus.FILLED) revert InvalidOrderStatus();
if (orderFiller[_orderIds[i]] != msg.sender) revert InvalidOrderFiller();

// not necessary to check the localDomain and counterpart since the fill function already did it

orderStatus[_orderIds[i]] = OrderStatus.SETTLED;
ordersFillerData[i] = orderFillerData[_orderIds[i]];
}

_handleSettlement(_orderIds, _receivers);
_handleSettlement(_orderIds, ordersFillerData);

emit Settle(_orderIds, _receivers);
emit Settle(_orderIds, ordersFillerData);
}
function refund(OrderData[] memory _ordersData) external payable {
bytes32[] memory orderIds = new bytes32[](_ordersData.length);
Expand Down Expand Up @@ -397,7 +395,7 @@ abstract contract Base7683 is IOriginSettler, IDestinationSettler {
* @dev This function is called during `settle` to handle the settlement of the orders, it is meant to be
* implemented by the inheriting contract with specific settlement logic. i.e. sending a cross-chain message
*/
function _handleSettlement(bytes32[] memory _orderIds, bytes32[] memory _receivers) internal virtual;
function _handleSettlement(bytes32[] memory _orderIds, bytes[] memory _ordersFillerData) internal virtual;

/**
* @dev This function is called during `refund` to handle the refund of the orders, it is meant to be
Expand Down
8 changes: 4 additions & 4 deletions solidity/src/Router7683.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,24 +45,24 @@ contract Router7683 is GasRouter, Base7683 {
// ============ Internal Functions ============

function _handle(uint32 _origin, bytes32, bytes calldata _message) internal virtual override {
(bool _settle, bytes32[] memory _orderIds, bytes32[] memory _receivers) = Router7683Message.decode(_message);
(bool _settle, bytes32[] memory _orderIds, bytes[] memory _ordersFillerData) = Router7683Message.decode(_message);

for (uint i = 0; i < _orderIds.length; i++) {
// check if the order is opened to ensure it belongs to this domain, skip otherwise
if (orderStatus[_orderIds[i]] != OrderStatus.OPENED) continue;

if (_settle) {
_settleOrder(_orderIds[i], _receivers[i], _origin);
_settleOrder(_orderIds[i], abi.decode(_ordersFillerData[i], (bytes32)), _origin);
} else {
_refundOrder(_orderIds[i], _origin);

}
}
}

function _handleSettlement(bytes32[] memory _orderIds, bytes32[] memory _receivers) internal virtual override {
function _handleSettlement(bytes32[] memory _orderIds, bytes[] memory _ordersFillerData) internal virtual override {
uint32 originDomain = orders[_orderIds[0]].originDomain;
_GasRouter_dispatch(originDomain, msg.value, Router7683Message.encodeSettle(_orderIds, _receivers), address(hook));
_GasRouter_dispatch(originDomain, msg.value, Router7683Message.encodeSettle(_orderIds, _ordersFillerData), address(hook));
}

function _handleRefund(bytes32[] memory _orderIds) internal virtual override {
Expand Down
16 changes: 8 additions & 8 deletions solidity/src/libs/Route7683Message.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ library Router7683Message {
* @dev This function should only be used in memory message construction.
* @param _settle Flag to indicate if the message is a settlement or refund
* @param _orderIds The orderIds to settle or refund
* @param _receivers The address of the receivers when settling
* @param _ordersFillerData Each element should contain the bytes32 encoded address of the settlement receiver.
* @return Formatted message body
*/
function encode(
bool _settle,
bytes32[] memory _orderIds,
bytes32[] memory _receivers
bytes[] memory _ordersFillerData
)
internal
pure
returns (bytes memory)
{
return abi.encode(_settle, _orderIds, _receivers);
return abi.encode(_settle, _orderIds, _ordersFillerData);
}

/**
Expand All @@ -32,20 +32,20 @@ library Router7683Message {
function decode(bytes calldata _message)
internal
pure
returns (bool, bytes32[] memory, bytes32[] memory)
returns (bool, bytes32[] memory, bytes[] memory)
{
return abi.decode(_message, (bool, bytes32[], bytes32[]));
return abi.decode(_message, (bool, bytes32[], bytes[]));
}

function encodeSettle(
bytes32[] memory _orderIds,
bytes32[] memory _receivers
bytes[] memory _ordersFillerData
)
internal
pure
returns (bytes memory)
{
return encode(true, _orderIds, _receivers);
return encode(true, _orderIds, _ordersFillerData);
}

function encodeRefund(
Expand All @@ -55,6 +55,6 @@ library Router7683Message {
pure
returns (bytes memory)
{
return encode(false, _orderIds, new bytes32[](0));
return encode(false, _orderIds, new bytes[](0));
}
}
28 changes: 16 additions & 12 deletions solidity/test/Base7683.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { Base7683 } from "../src/Router7683.sol";

event Open(bytes32 indexed orderId, ResolvedCrossChainOrder resolvedOrder);
event Filled(bytes32 orderId, bytes originData, bytes fillerData);
event Settle(bytes32[] orderIds, bytes32[] receivers);
event Settle(bytes32[] orderIds, bytes[] ordersFillerData);
event Refund(bytes32[] orderIds);
event Settled(bytes32 orderId, address receiver);
event Refunded(bytes32 orderId, address receiver);
Expand All @@ -31,7 +31,7 @@ contract Base7683ForTest is Base7683 {

bytes32[] public refundedOrderIds;
bytes32[] public settledOrderIds;
bytes32[] public settledReceivers;
bytes[] public settledReceivers;

uint32 internal immutable _origin;
uint32 internal immutable _destination;
Expand All @@ -53,7 +53,7 @@ contract Base7683ForTest is Base7683 {
_refundOrder(_orderId, _destination);
}

function _handleSettlement(bytes32[] memory _orderIds, bytes32[] memory receivers) internal override {
function _handleSettlement(bytes32[] memory _orderIds, bytes[] memory receivers) internal override {
settledOrderIds = _orderIds;
settledReceivers = receivers;
}
Expand Down Expand Up @@ -462,13 +462,15 @@ contract Base7683Test is Test, DeployPermit2 {
vm.startPrank(vegeta);
outputToken.approve(address(base), amount);

bytes memory fillerData = abi.encode(TypeCasts.addressToBytes32(vegeta));

vm.expectEmit(false, false, false, true);
emit Filled(orderId, OrderEncoder.encode(orderData), new bytes(0));
emit Filled(orderId, OrderEncoder.encode(orderData), fillerData);

base.fill(orderId, OrderEncoder.encode(orderData), new bytes(0));
base.fill(orderId, OrderEncoder.encode(orderData), fillerData);

assertOrder(orderId, orderData, balancesBefore, outputToken, vegeta, karpincho, Base7683.OrderStatus.FILLED);
assertEq(base.orderFiller(orderId), vegeta);
assertEq(base.orderFillerData(orderId), fillerData);

vm.stopPrank();
}
Expand All @@ -481,23 +483,25 @@ contract Base7683Test is Test, DeployPermit2 {

bytes32 orderId = OrderEncoder.id(orderData);

bytes memory fillerData = abi.encode(TypeCasts.addressToBytes32(karpincho));

vm.startPrank(vegeta);
outputToken.approve(address(base), amount);
base.fill(orderId, OrderEncoder.encode(orderData), new bytes(0));
base.fill(orderId, OrderEncoder.encode(orderData), fillerData);

bytes32[] memory orderIds = new bytes32[](1);
orderIds[0] = orderId;
bytes32[] memory receivers = new bytes32[](1);
receivers[0] = TypeCasts.addressToBytes32(karpincho);
bytes[] memory ordersFillerData = new bytes[](1);
ordersFillerData[0] = fillerData;

vm.expectEmit(false, false, false, true);
emit Settle(orderIds, receivers);
emit Settle(orderIds, ordersFillerData);

base.settle(orderIds, receivers);
base.settle(orderIds);

assertTrue(base.orderStatus(orderId) == Base7683.OrderStatus.SETTLED);
assertEq(base.settledOrderIds(0), orderId);
assertEq(base.settledReceivers(0), TypeCasts.addressToBytes32(karpincho));
assertEq(base.settledReceivers(0), fillerData);

vm.stopPrank();
}
Expand Down
20 changes: 10 additions & 10 deletions solidity/test/Router7683.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { Base7683 } from "../src/Router7683.sol";

event Open(bytes32 indexed orderId, ResolvedCrossChainOrder resolvedOrder);
event Filled(bytes32 orderId, bytes originData, bytes fillerData);
event Settle(bytes32[] orderIds, bytes32[] receivers);
event Settle(bytes32[] orderIds, bytes[] ordersFillerData);
event Refund(bytes32[] orderIds);
event Settled(bytes32 orderId, address receiver);
event Refunded(bytes32 orderId, address receiver);
Expand Down Expand Up @@ -145,8 +145,6 @@ contract Router7683BaseTest is Test, DeployPermit2 {

testIsm = new TestIsm();

uint32[] memory domains = new uint32[](0);

originRouter = deployProxiedRouter(
environment.mailboxes(origin),
owner
Expand Down Expand Up @@ -322,28 +320,30 @@ contract Router7683Test is Router7683BaseTest {
vm.recordLogs();
originRouter.open(order);

(bytes32 orderId, ResolvedCrossChainOrder memory resolvedOrder) = getOrderIDFromLogs();
(bytes32 orderId,) = getOrderIDFromLogs();

vm.stopPrank();

bytes memory fillerData = abi.encode(TypeCasts.addressToBytes32(vegeta));

vm.startPrank(vegeta);
outputToken.approve(address(destinationRouter), amount);
destinationRouter.fill(orderId, OrderEncoder.encode(orderData), new bytes(0));
destinationRouter.fill(orderId, OrderEncoder.encode(orderData), fillerData);

bytes32[] memory orderIds = new bytes32[](1);
orderIds[0] = orderId;
bytes32[] memory receivers = new bytes32[](1);
receivers[0] = TypeCasts.addressToBytes32(vegeta);
bytes[] memory ordersFillerData = new bytes[](1);
ordersFillerData[0] = fillerData;

uint256[] memory balancesBefore = balances(inputToken);

vm.expectEmit(false, false, false, true, address(destinationRouter));
emit Settle(orderIds, receivers);
emit Settle(orderIds, ordersFillerData);

vm.deal(vegeta, gasPaymentQuote);
uint256 balanceBefore = address(vegeta).balance;

destinationRouter.settle{value: gasPaymentQuote}(orderIds, receivers);
destinationRouter.settle{value: gasPaymentQuote}(orderIds);

vm.expectEmit(false, false, false, true, address(originRouter));
emit Settled(orderId, vegeta);
Expand Down Expand Up @@ -375,7 +375,7 @@ contract Router7683Test is Router7683BaseTest {
vm.recordLogs();
originRouter.open(order);

(bytes32 orderId, ResolvedCrossChainOrder memory resolvedOrder) = getOrderIDFromLogs();
(bytes32 orderId,) = getOrderIDFromLogs();

vm.warp(orderData.fillDeadline + 1);

Expand Down