@hyperbridge/core 1.0.1 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,6 +17,9 @@ import {PostRequest, PostResponse, GetRequest} from "../libraries/Message.sol";
17
17
  import {DispatchPost, DispatchPostResponse, DispatchGet, IDispatcher} from "../interfaces/IDispatcher.sol";
18
18
  import {IApp, IncomingPostRequest, IncomingPostResponse, IncomingGetResponse} from "../interfaces/IApp.sol";
19
19
 
20
+ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
21
+ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
22
+
20
23
  /**
21
24
  * @dev Uniswap interface for estimating fees in the native token
22
25
  */
@@ -33,6 +36,8 @@ interface IUniswapV2Router02 {
33
36
  * host authorization, and cross-chain message handling. Extend this contract to build your Hyperbridge application.
34
37
  */
35
38
  abstract contract HyperApp is IApp {
39
+ using SafeERC20 for IERC20;
40
+
36
41
  /**
37
42
  * @dev Call was not expected
38
43
  */
@@ -65,19 +70,6 @@ abstract contract HyperApp is IApp {
65
70
  return request.fee + (len * IDispatcher(host()).perByteFee(request.dest));
66
71
  }
67
72
 
68
- /**
69
- * @dev returns the quoted fee in the native token for dispatching a POST request
70
- */
71
- function quoteNative(DispatchPost memory request) public view returns (uint256) {
72
- uint256 fee = quote(request);
73
- address _host = host();
74
- address _uniswap = IDispatcher(_host).uniswapV2Router();
75
- address[] memory path = new address[](2);
76
- path[0] = IUniswapV2Router02(_uniswap).WETH();
77
- path[1] = IDispatcher(_host).feeToken();
78
- return IUniswapV2Router02(_uniswap).getAmountsIn(fee, path)[0];
79
- }
80
-
81
73
  /**
82
74
  * @dev returns the quoted fee in the feeToken for dispatching a GET request
83
75
  */
@@ -90,9 +82,17 @@ abstract contract HyperApp is IApp {
90
82
  }
91
83
 
92
84
  /**
93
- * @dev returns the quoted fee in the native token for dispatching a GET request
85
+ * @dev returns the quoted fee in the feeToken for dispatching a POST response
94
86
  */
95
- function quoteNative(DispatchGet memory request) public view returns (uint256) {
87
+ function quote(DispatchPostResponse memory response) public view returns (uint256) {
88
+ uint256 len = 32 > response.response.length ? 32 : response.response.length;
89
+ return response.fee + (len * IDispatcher(host()).perByteFee(response.request.source));
90
+ }
91
+
92
+ /**
93
+ * @dev returns the quoted fee in the native token for dispatching a POST request
94
+ */
95
+ function quoteNative(DispatchPost memory request) public view returns (uint256) {
96
96
  uint256 fee = quote(request);
97
97
  address _host = host();
98
98
  address _uniswap = IDispatcher(_host).uniswapV2Router();
@@ -103,11 +103,16 @@ abstract contract HyperApp is IApp {
103
103
  }
104
104
 
105
105
  /**
106
- * @dev returns the quoted fee in the feeToken for dispatching a POST response
106
+ * @dev returns the quoted fee in the native token for dispatching a GET request
107
107
  */
108
- function quote(DispatchPostResponse memory response) public view returns (uint256) {
109
- uint256 len = 32 > response.response.length ? 32 : response.response.length;
110
- return response.fee + (len * IDispatcher(host()).perByteFee(response.request.source));
108
+ function quoteNative(DispatchGet memory request) public view returns (uint256) {
109
+ uint256 fee = quote(request);
110
+ address _host = host();
111
+ address _uniswap = IDispatcher(_host).uniswapV2Router();
112
+ address[] memory path = new address[](2);
113
+ path[0] = IUniswapV2Router02(_uniswap).WETH();
114
+ path[1] = IDispatcher(_host).feeToken();
115
+ return IUniswapV2Router02(_uniswap).getAmountsIn(fee, path)[0];
111
116
  }
112
117
 
113
118
  /**
@@ -123,6 +128,54 @@ abstract contract HyperApp is IApp {
123
128
  return IUniswapV2Router02(_uniswap).getAmountsIn(fee, path)[0];
124
129
  }
125
130
 
131
+ /**
132
+ * @notice Dispatches a POST request using the fee token for payment
133
+ * @dev Handles fee token approval and transfer before dispatching the request to the Host.
134
+ * If the payer is not this contract, transfers fee tokens from the payer to this contract first.
135
+ * @param request The POST request to dispatch containing destination, body, timeout, and fee parameters
136
+ * @param payer The address that will pay the fee token. If different from this contract, must have approved this contract to spend the fee amount
137
+ */
138
+ function dispatchWithFeeToken(DispatchPost memory request, address payer) internal {
139
+ address hostAddr = host();
140
+ address feeToken = IDispatcher(hostAddr).feeToken();
141
+ uint256 fee = quote(request);
142
+ if (payer != address(this)) IERC20(feeToken).safeTransferFrom(payer, address(this), fee);
143
+ IERC20(feeToken).safeApprove(hostAddr, fee);
144
+ IDispatcher(hostAddr).dispatch(request);
145
+ }
146
+
147
+ /**
148
+ * @notice Dispatches a POST response using the fee token for payment
149
+ * @dev Handles fee token approval and transfer before dispatching the response to the Host.
150
+ * If the payer is not this contract, transfers fee tokens from the payer to this contract first.
151
+ * @param response The POST response to dispatch containing the original request, response data, timeout, and fee parameters
152
+ * @param payer The address that will pay the fee token. If different from this contract, must have approved this contract to spend the fee amount
153
+ */
154
+ function dispatchWithFeeToken(DispatchPostResponse memory response, address payer) internal {
155
+ address hostAddr = host();
156
+ address feeToken = IDispatcher(hostAddr).feeToken();
157
+ uint256 fee = quote(response);
158
+ if (payer != address(this)) IERC20(feeToken).safeTransferFrom(payer, address(this), fee);
159
+ IERC20(feeToken).safeApprove(hostAddr, fee);
160
+ IDispatcher(hostAddr).dispatch(response);
161
+ }
162
+
163
+ /**
164
+ * @notice Dispatches a GET request using the fee token for payment
165
+ * @dev Handles fee token approval and transfer before dispatching the request to the Host.
166
+ * If the payer is not this contract, transfers fee tokens from the payer to this contract first.
167
+ * @param request The GET request to dispatch containing destination, keys, height, timeout, and fee parameters
168
+ * @param payer The address that will pay the fee token. If different from this contract, must have approved this contract to spend the fee amount
169
+ */
170
+ function dispatchWithFeeToken(DispatchGet memory request, address payer) internal {
171
+ address hostAddr = host();
172
+ address feeToken = IDispatcher(hostAddr).feeToken();
173
+ uint256 fee = quote(request);
174
+ if (payer != address(this)) IERC20(feeToken).safeTransferFrom(payer, address(this), fee);
175
+ IERC20(feeToken).safeApprove(hostAddr, fee);
176
+ IDispatcher(hostAddr).dispatch(request);
177
+ }
178
+
126
179
  /**
127
180
  * @notice Callback for receiving incoming POST requests
128
181
  * @dev Called by the Host when a new POST request is received for this app.
@@ -18,211 +18,273 @@ pragma solidity ^0.8.17;
18
18
  * @notice Tokens that must be received for a valid order fulfillment
19
19
  */
20
20
  struct PaymentInfo {
21
- /// @dev The address of the ERC20 token on the destination chain
22
- /// @dev address(0) used as a sentinel for the native token
23
- bytes32 token;
24
- /// @dev The amount of the token to be sent
25
- uint256 amount;
26
- /// @dev The address to receive the output tokens
27
- bytes32 beneficiary;
21
+ /// @dev The address of the ERC20 token on the destination chain
22
+ /// @dev address(0) used as a sentinel for the native token
23
+ bytes32 token;
24
+ /// @dev The amount of the token to be sent
25
+ uint256 amount;
26
+ /// @dev The address to receive the output tokens
27
+ bytes32 beneficiary;
28
28
  }
29
29
 
30
30
  /**
31
31
  * @notice Tokens that must be escrowed for an order
32
32
  */
33
33
  struct TokenInfo {
34
- /// @dev The address of the ERC20 token on the destination chain
35
- /// @dev address(0) used as a sentinel for the native token
36
- bytes32 token;
37
- /// @dev The amount of the token to be sent
38
- uint256 amount;
34
+ /// @dev The address of the ERC20 token on the destination chain
35
+ /// @dev address(0) used as a sentinel for the native token
36
+ bytes32 token;
37
+ /// @dev The amount of the token to be sent
38
+ uint256 amount;
39
+ }
40
+
41
+ /**
42
+ * @dev Struct for predispatch information
43
+ */
44
+ struct PredispatchInfo {
45
+ /// @dev Assets to execute a predispatch call with
46
+ TokenInfo[] assets;
47
+ /// @dev The actual call data to be executed
48
+ bytes call;
39
49
  }
40
50
 
41
51
  /**
42
52
  * @dev Represents an order in the IntentGateway module.
43
- * @param Order The structure defining an order.
44
53
  */
45
54
  struct Order {
46
- /// @dev The address of the user who is initiating the transfer
47
- bytes32 user;
48
- /// @dev The state machine identifier of the origin chain
49
- bytes sourceChain;
50
- /// @dev The state machine identifier of the destination chain
51
- bytes destChain;
52
- /// @dev The block number by which the order must be filled on the destination chain
53
- uint256 deadline;
54
- /// @dev The nonce of the order
55
- uint256 nonce;
56
- /// @dev Represents the dispatch fees associated with the IntentGateway.
57
- uint256 fees;
58
- /// @dev The tokens that the filler will provide.
59
- PaymentInfo[] outputs;
60
- /// @dev The tokens that are escrowed for the filler.
61
- TokenInfo[] inputs;
62
- /// @dev A bytes array to store the calls if any.
63
- bytes callData;
55
+ /// @dev The address of the user who is initiating the transfer
56
+ bytes32 user;
57
+ /// @dev The state machine identifier of the origin chain
58
+ bytes sourceChain;
59
+ /// @dev The state machine identifier of the destination chain
60
+ bytes destChain;
61
+ /// @dev The block number by which the order must be filled on the destination chain
62
+ uint256 deadline;
63
+ /// @dev The nonce of the order
64
+ uint256 nonce;
65
+ /// @dev Represents the dispatch fees associated with the IntentGateway.
66
+ uint256 fees;
67
+ /// @dev The tokens that the filler will provide.
68
+ PaymentInfo[] outputs;
69
+ /// @dev The tokens that are escrowed for the filler.
70
+ TokenInfo[] inputs;
71
+ /// @dev The predispatch information for the order
72
+ PredispatchInfo predispatch;
73
+ /// @dev A bytes array to store the calls if any.
74
+ bytes callData;
64
75
  }
65
76
 
66
77
  /**
67
78
  * @dev Struct to define the parameters for the IntentGateway module.
68
79
  */
69
80
  struct Params {
70
- /// @dev The address of the host contract
71
- address host;
72
- /// @dev Address of the dispatcher contract responsible for handling intents.
73
- address dispatcher;
81
+ /// @dev The address of the host contract
82
+ address host;
83
+ /// @dev Address of the dispatcher contract responsible for handling intents.
84
+ address dispatcher;
85
+ /// @dev Protocol fee in basis points (BPS) deducted from filler-provided tokens
86
+ uint256 protocolFeeBps;
74
87
  }
75
88
 
76
89
  /**
77
90
  * @notice A struct representing the options for filling an intent.
78
- * @dev This struct is used to specify various parameters and options
79
- * when filling an intent in the IntentGateway contract.
80
91
  */
81
92
  struct FillOptions {
82
- /// @dev The fee paid to the relayer for processing transactions.
83
- uint256 relayerFee;
93
+ /// @dev The fee paid to the relayer for processing transactions.
94
+ uint256 relayerFee;
84
95
  }
85
96
 
86
97
  /**
87
98
  * @dev Struct representing the options for canceling an intent.
88
99
  */
89
100
  struct CancelOptions {
90
- /// @dev The fee paid to the relayer for processing transactions.
91
- uint256 relayerFee;
92
- /// @dev Stores the height value.
93
- uint256 height;
101
+ /// @dev The fee paid to the relayer for processing transactions.
102
+ uint256 relayerFee;
103
+ /// @dev Stores the height value.
104
+ uint256 height;
94
105
  }
95
106
 
96
107
  /**
97
- * @title IIntentGateway
108
+ * @title IIntentGatewayV2
98
109
  * @author Polytope Labs (hello@polytope.technology)
99
- *
100
- * @dev Interface for the IntentGateway that allows for the creation and fulfillment of cross-chain orders.
110
+ * @notice Interface for the IntentGatewayV2 contract
111
+ * @dev The IntentGateway allows for the creation and fulfillment of cross-chain orders.
101
112
  */
102
113
  interface IIntentGateway {
103
- /**
104
- * @dev Emitted when an order is placed.
105
- */
106
- event OrderPlaced(
107
- /// @dev The address of the user who is initiating the transfer
108
- bytes32 user,
109
- /// @dev The state machine identifier of the origin chain
110
- bytes sourceChain,
111
- /// @dev The state machine identifier of the destination chain
112
- bytes destChain,
113
- /// @dev The block number by which the order must be filled on the destination chain
114
- uint256 deadline,
115
- /// @dev The nonce of the order
116
- uint256 nonce,
117
- /// @dev Represents the dispatch fees associated with the IntentGateway.
118
- uint256 fees,
119
- /// @dev The tokens that the filler will provide.
120
- PaymentInfo[] outputs,
121
- /// @dev The tokens that are escrowed for the filler.
122
- TokenInfo[] inputs,
123
- /// @dev A bytes array to store the calls if any.
124
- bytes callData
125
- );
126
-
127
- /**
128
- * @dev Emitted when an order is filled.
129
- * @param commitment The unique identifier of the order.
130
- * @param filler The address of the entity that filled the order.
131
- */
132
- event OrderFilled(bytes32 indexed commitment, address filler);
133
-
134
- /**
135
- * @dev Emitted when an escrow is released.
136
- * @param commitment The unique identifier of the order.
137
- */
138
- event EscrowReleased(bytes32 indexed commitment);
139
-
140
- /**
141
- * @dev Emitted when an escrow is refunded.
142
- * @param commitment The unique identifier of the order.
143
- */
144
- event EscrowRefunded(bytes32 indexed commitment);
145
-
146
- /// @notice Thrown when an unauthorized action is attempted.
147
- error Unauthorized();
148
-
149
- /// @notice Thrown when an invalid input is provided.
150
- error InvalidInput();
151
-
152
- /// @notice Thrown when an action is attempted on an expired order.
153
- error Expired();
154
-
155
- /// @notice Thrown when there are insufficient native tokens to complete an action.
156
- error InsufficientNativeToken();
157
-
158
- /// @notice Thrown when an action is attempted on an order that has not yet expired.
159
- error NotExpired();
160
-
161
- /// @notice Thrown when an action is attempted on an order that has already been filled.
162
- error Filled();
163
-
164
- /// @notice Thrown when an action is attempted on the wrong chain.
165
- error WrongChain();
166
-
167
- /// @notice Thrown when an action is attempted on an unknown order.
168
- error UnknownOrder();
169
-
170
- /**
171
- * @notice Fallback function to receive ether
172
- * @dev This function is called when ether is sent to the contract without data
173
- * @custom:note The function is marked payable to allow receiving ether
174
- */
175
- receive() external payable;
176
-
177
- /**
178
- * @dev Should return the `IsmpHost` address for the current chain.
179
- * The `IsmpHost` is an immutable contract that will never change.
180
- */
181
- function host() external view returns (address);
182
-
183
- /**
184
- * @dev Fetch the IntentGateway contract instance for a chain.
185
- */
186
- function instance(bytes calldata stateMachineId) external view returns (bytes32);
187
-
188
- /**
189
- * @notice Retrieves the current parameter settings for the IntentGateway module
190
- * @dev Returns a struct containing all configurable parameters
191
- * @return Params A struct containing the module's current parameters
192
- */
193
- function params() external view returns (Params memory);
194
-
195
- /**
196
- * @notice Calculates the commitment slot hash required for storage queries.
197
- * @dev The commitment slot hash is used as part of the proof verification process
198
- * @param commitment The commitment value as a bytes32 hash
199
- * @return bytes The calculated commitment slot hash
200
- */
201
- function calculateCommitmentSlotHash(bytes32 commitment) external pure returns (bytes memory);
202
-
203
- /**
204
- * @notice Places an order with the given order details.
205
- * @dev This function allows users to place an order by providing the order details.
206
- * @param order The order details to be placed.
207
- * @param graffiti Additional data that can be attached to the order
208
- */
209
- function placeOrder(Order memory order, bytes32 graffiti) external payable;
210
-
211
- /**
212
- * @notice Fills an order with the specified options.
213
- * @param order The order to be filled.
214
- * @param options The options to be used when filling the order.
215
- * @dev This function is payable and can accept Ether.
216
- */
217
- function fillOrder(Order calldata order, FillOptions memory options) external payable;
218
-
219
- /**
220
- * @notice Cancels an existing order.
221
- * @param order The order to be canceled.
222
- * @param options Additional options for the cancellation process.
223
- * @dev This function can only be called by the order owner and requires a payment.
224
- * It will initiate a storage query on the source chain to verify the order has not
225
- * yet been filled. If the order has not been filled, the tokens will be released.
226
- */
227
- function cancelOrder(Order calldata order, CancelOptions memory options) external payable;
114
+ /**
115
+ * @dev Enum representing the different kinds of incoming requests that can be executed.
116
+ */
117
+ enum RequestKind {
118
+ /// @dev Identifies a request for redeeming an escrow.
119
+ RedeemEscrow,
120
+ /// @dev Identifies a request for recording new contract deployments
121
+ NewDeployment,
122
+ /// @dev Identifies a request for updating parameters.
123
+ UpdateParams,
124
+ /// @dev Identifies a request for refunding an escrow.
125
+ RefundEscrow,
126
+ /// @dev Identifies a request for collecting fees.
127
+ CollectFees
128
+ }
129
+
130
+ /// @notice Thrown when an unauthorized action is attempted.
131
+ error Unauthorized();
132
+
133
+ /// @notice Thrown when an invalid input is provided.
134
+ error InvalidInput();
135
+
136
+ /// @notice Thrown when an action is attempted on an expired order.
137
+ error Expired();
138
+
139
+ /// @notice Thrown when there are insufficient native tokens to complete an action.
140
+ error InsufficientNativeToken();
141
+
142
+ /// @notice Thrown when an action is attempted on an order that has not yet expired.
143
+ error NotExpired();
144
+
145
+ /// @notice Thrown when an action is attempted on an order that has already been filled.
146
+ error Filled();
147
+
148
+ /// @notice Thrown when an action is attempted on an order that has been cancelled.
149
+ error Cancelled();
150
+
151
+ /// @notice Thrown when an action is attempted on the wrong chain.
152
+ error WrongChain();
153
+
154
+ /// @notice Thrown when an action is attempted on an unknown order.
155
+ error UnknownOrder();
156
+
157
+ /**
158
+ * @dev Emitted when an order is placed.
159
+ */
160
+ event OrderPlaced(
161
+ /// @dev The address of the user who is initiating the transfer
162
+ bytes32 user,
163
+ /// @dev The state machine identifier of the origin chain
164
+ bytes sourceChain,
165
+ /// @dev The state machine identifier of the destination chain
166
+ bytes destChain,
167
+ /// @dev The block number by which the order must be filled on the destination chain
168
+ uint256 deadline,
169
+ /// @dev The nonce of the order
170
+ uint256 nonce,
171
+ /// @dev Represents the dispatch fees associated with the IntentGateway.
172
+ uint256 fees,
173
+ /// @dev Assets that were used to execute a predispatch call
174
+ TokenInfo[] predispatch,
175
+ /// @dev The tokens that are escrowed for the filler.
176
+ TokenInfo[] inputs,
177
+ /// @dev The tokens that the filler will provide.
178
+ PaymentInfo[] outputs
179
+ );
180
+
181
+ /**
182
+ * @notice Event emitted when an order is filled.
183
+ * @param commitment The order commitment hash
184
+ * @param filler The address of the filler
185
+ */
186
+ event OrderFilled(bytes32 commitment, address filler);
187
+
188
+ /**
189
+ * @notice Event emitted when escrow is released.
190
+ * @param commitment The order commitment hash
191
+ */
192
+ event EscrowReleased(bytes32 commitment);
193
+
194
+ /**
195
+ * @notice Event emitted when escrow is refunded.
196
+ * @param commitment The order commitment hash
197
+ */
198
+ event EscrowRefunded(bytes32 commitment);
199
+
200
+ /**
201
+ * @notice Event emitted when parameters are updated.
202
+ * @param previous The previous parameters
203
+ * @param current The new parameters
204
+ */
205
+ event ParamsUpdated(Params previous, Params current);
206
+
207
+ /**
208
+ * @notice Event emitted when a new deployment is added.
209
+ * @param stateMachineId The state machine identifier
210
+ * @param gateway The gateway address
211
+ */
212
+ event NewDeploymentAdded(bytes stateMachineId, bytes32 gateway);
213
+
214
+ /**
215
+ * @dev Emitted when dust is collected from predispatch swaps.
216
+ * @param token The token contract address of the dust, address(0) for native currency.
217
+ * @param amount The amount of dust collected.
218
+ */
219
+ event DustCollected(address token, uint256 amount);
220
+
221
+ /**
222
+ * @dev Emitted when protocol fee is collected from a filler.
223
+ * @param token The token contract address of the fee, address(0) for native currency.
224
+ * @param amount The amount of protocol fee collected.
225
+ * @param chain The chain where the funds are stored.
226
+ */
227
+ event FeeCollected(address token, uint256 amount, bytes chain);
228
+
229
+ /**
230
+ * @dev Emitted when protocol revenue is withdrawn.
231
+ * @param token The token contract address of the fee, address(0) for native currency.
232
+ * @param amount The amount of protocol revenue collected.
233
+ * @param beneficiary The beneficiary of the funds
234
+ */
235
+ event RevenueWithdrawn(address token, uint256 amount, address beneficiary);
236
+
237
+ /**
238
+ * @notice Returns the host address.
239
+ * @return The host contract address
240
+ */
241
+ function host() external view returns (address);
242
+
243
+ /**
244
+ * @notice Returns the instance address for a given state machine.
245
+ * @param stateMachineId The state machine identifier
246
+ * @return The instance address
247
+ */
248
+ function instance(bytes calldata stateMachineId) external view returns (bytes32);
249
+
250
+ /**
251
+ * @notice Returns the current gateway parameters.
252
+ * @return The current parameters
253
+ */
254
+ function params() external view returns (Params memory);
255
+
256
+ /**
257
+ * @notice Calculates the commitment slot hash for an order.
258
+ * @param commitment The order commitment
259
+ * @return The slot hash
260
+ */
261
+ function calculateCommitmentSlotHash(bytes32 commitment) external pure returns (bytes32);
262
+
263
+ /**
264
+ * @notice Places a new order.
265
+ * @param order The order details
266
+ * @param graffiti Additional data
267
+ */
268
+ function placeOrder(Order memory order, bytes32 graffiti) external payable;
269
+
270
+ /**
271
+ * @notice Fills an existing order.
272
+ * @param order The order to fill
273
+ * @param options Fill options including relayer fee
274
+ */
275
+ function fillOrder(Order calldata order, FillOptions memory options) external payable;
276
+
277
+ /**
278
+ * @notice Cancels an order (for expired orders).
279
+ * @param order The order to cancel
280
+ * @param options Cancel options including height and relayer fee
281
+ */
282
+ function cancelOrder(Order calldata order, CancelOptions memory options) external payable;
283
+
284
+ /**
285
+ * @notice Cancels a limit order (for orders with deadline = 0).
286
+ * @param order The order to cancel
287
+ * @param options Cancel options including relayer fee
288
+ */
289
+ function cancelLimitOrder(Order calldata order, CancelOptions memory options) external payable;
228
290
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperbridge/core",
3
- "version": "1.0.1",
3
+ "version": "1.1.1",
4
4
  "description": "Hyperbridge Solidity SDK for dispatching & receiving cross-chain messages",
5
5
  "author": "Polytope Labs <hello@polytope.technology>",
6
6
  "license": "Apache-2.0",