Skip to content

Commit 6dde82f

Browse files
committed
feat: fill multiple Outputs at once
1 parent 5e32da8 commit 6dde82f

File tree

1 file changed

+40
-23
lines changed

1 file changed

+40
-23
lines changed

src/Orders.sol

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,29 @@ pragma solidity ^0.8.24;
33

44
import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
55

6+
/// @notice Tokens sent by the swapper as inputs to the order
7+
/// @dev From ERC-7683
8+
struct Input {
9+
/// @dev The address of the ERC20 token on the origin chain
10+
address token;
11+
/// @dev The amount of the token to be sent
12+
uint256 amount;
13+
}
14+
15+
/// @notice Tokens that must be receive for a valid order fulfillment
16+
/// @dev From ERC-7683
17+
struct Output {
18+
/// @dev The address of the ERC20 token on the destination chain
19+
/// @dev address(0) used as a sentinel for the native token
20+
address token;
21+
/// @dev The amount of the token to be sent
22+
uint256 amount;
23+
/// @dev The address to receive the output tokens
24+
address recipient;
25+
/// @dev The destination chain for this output
26+
uint32 chainId;
27+
}
28+
629
/// @notice Contract capable of processing fulfillment of intent-based Orders.
730
abstract contract OrderDestination {
831
/// @notice Emitted when an Order's Output is sent to the recipient.
@@ -30,33 +53,27 @@ abstract contract OrderDestination {
3053
}
3154
emit OutputFilled(originChainId, recipient, token, amount);
3255
}
56+
57+
/// @notice Send multiple Output(s) of Order(s).
58+
/// @custom:emits OutputFilled for each output
59+
/// @param outputs - The array of Outputs to fill.
60+
function fill(uint256 originChainId, Output[] memory outputs) external payable {
61+
uint256 value = msg.value;
62+
for (uint256 i; i < outputs.length; i++) {
63+
if (outputs[i].token == address(0)) {
64+
// this line should underflow if there's an attempt to spend more ETH than is attached to the transaction
65+
value -= outputs[i].amount;
66+
payable(outputs[i].recipient).transfer(outputs[i].amount);
67+
} else {
68+
IERC20(outputs[i].token).transferFrom(msg.sender, outputs[i].recipient, outputs[i].amount);
69+
}
70+
emit OutputFilled(originChainId, outputs[i].recipient, outputs[i].token, outputs[i].amount);
71+
}
72+
}
3373
}
3474

3575
/// @notice Contract capable of registering initiation of intent-based Orders.
3676
abstract contract OrderOrigin {
37-
/// @notice Tokens sent by the swapper as inputs to the order
38-
/// @dev From ERC-7683
39-
struct Input {
40-
/// @dev The address of the ERC20 token on the origin chain
41-
address token;
42-
/// @dev The amount of the token to be sent
43-
uint256 amount;
44-
}
45-
46-
/// @notice Tokens that must be receive for a valid order fulfillment
47-
/// @dev From ERC-7683
48-
struct Output {
49-
/// @dev The address of the ERC20 token on the destination chain
50-
/// @dev address(0) used as a sentinel for the native token
51-
address token;
52-
/// @dev The amount of the token to be sent
53-
uint256 amount;
54-
/// @dev The address to receive the output tokens
55-
address recipient;
56-
/// @dev The destination chain for this output
57-
uint32 chainId;
58-
}
59-
6077
/// @notice Thrown when an Order is submitted with a deadline that has passed.
6178
error OrderExpired();
6279

0 commit comments

Comments
 (0)