Skip to content

Commit d65977d

Browse files
committed
evm: add EQ02 body and quote vs execution method
1 parent 202a3f4 commit d65977d

File tree

6 files changed

+68
-22
lines changed

6 files changed

+68
-22
lines changed

design/02_On_Chain_Quotes.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -160,14 +160,14 @@ uint64 expiryTime; // The unix time, in seconds, after which this quote s
160160

161161
### Quote - Version 2
162162

163-
This introduces a new Quote version to the [Executor spec](../README.md#api--database-schema).
164-
165-
<aside>
166-
⚠️ TBD if the `baseFee`, `destinationGasPrice`, `sourcePrice`, and `destinationPrice` fields should be required akin to `EQ01`. We are assessing the additional cost to implement this or provide an equivalent way to gather this data off-chain.
167-
</aside>
163+
This introduces a new Quote version to the [Executor spec](../README.md#api--database-schema). It has the same body as `EQ01` sans signature. This is useful for parsing and validating off-chain.
168164

169165
```solidity
170166
Header header // prefix = "EQ02"
167+
uint64 baseFee // The base fee, in sourceChain native currency, required by the quoter to perform an execution on the destination chain
168+
uint64 destinationGasPrice // The current gas price on the destination chain
169+
uint64 sourcePrice // The USD price, in 10^10, of the sourceChain native currency
170+
uint64 destinationPrice // The USD price, in 10^10, of the destinationChain native currency
171171
```
172172

173173
# **Caveats**

evm/src/ExecutorQuoter.sol

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,16 @@ contract ExecutorQuoter is IExecutorQuoter {
1717

1818
/// This is the same as an EQ01 quote body
1919
/// It fits into a single bytes32 storage slot
20+
/// It is listed in reverse order so that it is stored in the correct order (EVM stores right to left)
2021
struct OnChainQuoteBody {
21-
/// The base fee, in sourceChain native currency, required by the quoter to perform an execution on the destination chain
22-
uint64 baseFee;
23-
/// The current gas price on the destination chain
24-
uint64 dstGasPrice;
25-
/// The USD price, in 10^10, of the sourceChain native currency
26-
uint64 srcPrice;
2722
/// The USD price, in 10^10, of the destinationChain native currency
2823
uint64 dstPrice;
24+
/// The USD price, in 10^10, of the sourceChain native currency
25+
uint64 srcPrice;
26+
/// The current gas price on the destination chain
27+
uint64 dstGasPrice;
28+
/// The base fee, in sourceChain native currency, required by the quoter to perform an execution on the destination chain
29+
uint64 baseFee;
2930
}
3031

3132
struct ChainInfo {
@@ -193,16 +194,37 @@ contract ExecutorQuoter is IExecutorQuoter {
193194
address, //refundAddr,
194195
bytes calldata, //requestBytes,
195196
bytes calldata relayInstructions
196-
) external view returns (bytes32, uint256) {
197+
) external view returns (uint256 requiredPayment) {
198+
ChainInfo storage dstChainInfo = chainInfos[dstChain];
199+
if (!dstChainInfo.enabled) {
200+
revert ChainDisabled(dstChain);
201+
}
202+
(uint256 gasLimit, uint256 msgValue) = totalGasLimitAndMsgValue(relayInstructions);
203+
// NOTE: this does not include any maxGasLimit or maxMsgValue checks
204+
requiredPayment = estimateQuote(quoteByDstChain[dstChain], dstChainInfo, gasLimit, msgValue);
205+
206+
return requiredPayment;
207+
}
208+
209+
function requestExecutionQuote(
210+
uint16 dstChain,
211+
bytes32, //dstAddr,
212+
address, //refundAddr,
213+
bytes calldata, //requestBytes,
214+
bytes calldata relayInstructions
215+
) external view returns (uint256 requiredPayment, bytes32, bytes32 quoteBody) {
197216
ChainInfo storage dstChainInfo = chainInfos[dstChain];
198217
if (!dstChainInfo.enabled) {
199218
revert ChainDisabled(dstChain);
200219
}
201220
OnChainQuoteBody storage quote = quoteByDstChain[dstChain];
221+
assembly {
222+
quoteBody := sload(quote.slot)
223+
}
202224
(uint256 gasLimit, uint256 msgValue) = totalGasLimitAndMsgValue(relayInstructions);
203225
// NOTE: this does not include any maxGasLimit or maxMsgValue checks
204-
uint256 requiredPayment = estimateQuote(quote, dstChainInfo, gasLimit, msgValue);
226+
requiredPayment = estimateQuote(quote, dstChainInfo, gasLimit, msgValue);
205227

206-
return (PAYEE_ADDRESS, requiredPayment);
228+
return (requiredPayment, PAYEE_ADDRESS, quoteBody);
207229
}
208230
}

evm/src/ExecutorQuoterRouter.sol

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ contract ExecutorQuoterRouter is IExecutorQuoterRouter {
100100
bytes calldata requestBytes,
101101
bytes calldata relayInstructions
102102
) external view returns (uint256 requiredPayment) {
103-
(, requiredPayment) =
103+
requiredPayment =
104104
quoterContract[quoterAddr].requestQuote(dstChain, dstAddr, refundAddr, requestBytes, relayInstructions);
105105
}
106106

@@ -113,8 +113,8 @@ contract ExecutorQuoterRouter is IExecutorQuoterRouter {
113113
bytes calldata relayInstructions
114114
) external payable {
115115
IExecutorQuoter implementation = quoterContract[quoterAddr];
116-
(bytes32 payeeAddress, uint256 requiredPayment) =
117-
implementation.requestQuote(dstChain, dstAddr, refundAddr, requestBytes, relayInstructions);
116+
(uint256 requiredPayment, bytes32 payeeAddress, bytes32 quoteBody) =
117+
implementation.requestExecutionQuote(dstChain, dstAddr, refundAddr, requestBytes, relayInstructions);
118118
if (msg.value < requiredPayment) {
119119
revert Underpaid(msg.value, requiredPayment);
120120
}
@@ -128,7 +128,7 @@ contract ExecutorQuoterRouter is IExecutorQuoterRouter {
128128
dstChain,
129129
dstAddr,
130130
refundAddr,
131-
abi.encodePacked(QUOTE_PREFIX, quoterAddr, payeeAddress, OUR_CHAIN, dstChain, EXPIRY_TIME),
131+
abi.encodePacked(QUOTE_PREFIX, quoterAddr, payeeAddress, OUR_CHAIN, dstChain, EXPIRY_TIME, quoteBody),
132132
requestBytes,
133133
relayInstructions
134134
);

evm/src/interfaces/IExecutorQuoter.sol

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,25 @@
22
pragma solidity ^0.8.19;
33

44
interface IExecutorQuoter {
5+
/// This method is used by on- or off-chain services which need to determine the cost of a relay
6+
/// It only returns the required cost (msg.value)
7+
/// It is explicitly marked view
58
function requestQuote(
69
uint16 dstChain,
710
bytes32 dstAddr,
811
address refundAddr,
912
bytes calldata requestBytes,
1013
bytes calldata relayInstructions
11-
) external view returns (bytes32, uint256);
14+
) external view returns (uint256);
15+
16+
/// This method is used by an ExecutorQuoterRouter during the execution flow
17+
/// It returns the required cost (msg.value) in addition to the payee and EQ02 quote body
18+
/// It is explicitly NOT marked view in order to allow the quoter the flexibility to emit events or update state
19+
function requestExecutionQuote(
20+
uint16 dstChain,
21+
bytes32 dstAddr,
22+
address refundAddr,
23+
bytes calldata requestBytes,
24+
bytes calldata relayInstructions
25+
) external returns (uint256, bytes32, bytes32);
1226
}

evm/test/ExecutorQuoter.t.sol

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ contract ExecutorQuoterTest is Test {
1818
bytes32 constant DST_ADDR = bytes32(0);
1919

2020
function packUint64(uint64 a, uint64 b, uint64 c, uint64 d) public pure returns (bytes32) {
21-
return bytes32((uint256(d) << 192) | (uint256(c) << 128) | (uint256(b) << 64) | uint256(a));
21+
return bytes32((uint256(a) << 192) | (uint256(b) << 128) | (uint256(c) << 64) | uint256(d));
2222
}
2323

2424
function setUp() public {
@@ -69,7 +69,7 @@ contract ExecutorQuoterTest is Test {
6969

7070
function test_quoteUpdate() public {
7171
executorQuoter.quoteUpdate(updates);
72-
(uint64 baseFee,,,) = executorQuoter.quoteByDstChain(10003);
72+
(,,, uint64 baseFee) = executorQuoter.quoteByDstChain(10003);
7373
require(baseFee == 27971);
7474
}
7575

@@ -86,4 +86,14 @@ contract ExecutorQuoterTest is Test {
8686
RelayInstructions.encodeGas(250000, 0)
8787
);
8888
}
89+
90+
function test_requestExecutionQuote() public view {
91+
executorQuoter.requestExecutionQuote(
92+
DST_CHAIN,
93+
DST_ADDR,
94+
UPDATER,
95+
ExecutorMessages.makeVAAv1Request(10002, bytes32(uint256(uint160(address(this)))), 1),
96+
RelayInstructions.encodeGas(250000, 0)
97+
);
98+
}
8999
}

evm/test/ExecutorQuoterRouter.t.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ contract ExecutorQuoterRouterTest is Test {
2828
bytes32 constant DST_ADDR = bytes32(0);
2929

3030
function packUint64(uint64 a, uint64 b, uint64 c, uint64 d) public pure returns (bytes32) {
31-
return bytes32((uint256(d) << 192) | (uint256(c) << 128) | (uint256(b) << 64) | uint256(a));
31+
return bytes32((uint256(a) << 192) | (uint256(b) << 128) | (uint256(c) << 64) | uint256(d));
3232
}
3333

3434
function setUp() public {

0 commit comments

Comments
 (0)