You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Starknet's ability to interact with L1 is crucial. _Messaging_ is the mechanism that enables this interaction.
3
+
== Overview
4
+
Starknet's ability to interact with L1 is crucial, and is used by bridges (e.g., for depositing your tokens in the L1 bridge contract, and automatically triggers the minting of the same token on L2), link:https://starkware.co/resource/defi-pooling/[DeFi pooling^] and https://www.starknet.io/en/ecosystem/dapps[more^]. Messaging — both xref:l2_l1_messages[from L1 to L2] and from xref:l1_l2_message_protocol[L2 to L1] — is the mechanism that enables this interaction.
5
5
6
-
For example, you can perform computations on L2 and use the result on L1.
7
-
8
-
Bridges on Starknet use the L1-L2 messaging mechanism. Consider that you want to bridge tokens from Ethereum to Starknet. You deposit your tokens in the L1 bridge contract, which automatically triggers the minting of the same token on L2. Another good use case for L1-L2 messaging is Defi pooling. For more information, see link:https://starkware.co/resource/defi-pooling/[DeFi pooling] on StarkWare's site and link:https://www.starknet.io/en/ecosystem/dapps[dApps] on https://www.starknet.io.
9
-
10
-
Be aware that the messaging mechanism is _asynchronous_ and _asymmetric_.
6
+
[IMPORTANT]
7
+
====
8
+
Starknet's messaging mechanism is both _asynchronous_ and _asymmetric_.
11
9
12
10
* _Asynchronous_: Your contract code, whether Cairo or Solidity, cannot await the result of the message being sent on the other layer within your contract code's execution.
13
11
* _Asymmetric_: Sending a message from Ethereum to Starknet, L1->L2, is fully automated by the Starknet sequencer, so the message is automatically delivered to the target contract on L2. However, when sending a message from Starknet to Ethereum, L2->L1, the sequencer only sends the hash of the message. You must then consume the message manually using a transaction on L1.
* https://book.cairo-lang.org/ch16-04-L1-L2-messaging.html[L1-L2 Messaging in the Cairo Book^]
14
19
15
-
[id="l2-l1_messages"]
16
20
== L2 -> L1 messages
17
21
18
-
Contracts on L2 can interact asynchronously with contracts on L1 using the L2->L1 messaging protocol.
22
+
=== L2 -> L1 message protocol
19
23
20
-
The protocol consists of the following stages:
24
+
The L2 -> L1 message protocol consists of the following stages:
21
25
22
26
. During the execution of a transaction, a contract on Starknet sends a message from L2 to L1 by calling the `send_message_to_L1` syscall.
23
27
. The sequencer attaches the message parameters to the block that includes the syscall invocation. The message parameters include the address of the sender on L2, the address of the recipient contract on L1, and the message data.
@@ -44,27 +48,21 @@ This function, which is part of the Starknet Core Contract, verifies the followi
44
48
* The hashes of the L2 sent message parameters, now stored on the Core Contract, and the L1 received message parameters, are the same.
45
49
* The entity calling the function is indeed the recipient on L1.
46
50
+
47
-
// We need to separate out these functions into a reference.
48
51
In such a case, the counter corresponding to the message hash in the Starknet Core Contract decreases by one. For more information, see the link:https://github.com/starkware-libs/cairo-lang/blob/4e233516f52477ad158bc81a86ec2760471c1b65/src/starkware/starknet/eth/StarknetMessaging.sol#L130C7-L130C7#[`consumeMessageFromL2`] function in `StarknetMessaging.sol`.
49
52
50
-
xref:#diagram_l2-l1_messaging_mechanism[] illustrates this flow:
53
+
The protocol is summarized in the following illustration:
51
54
52
-
[#diagram_l2-l1_messaging_mechanism]
53
-
.L2->L1 Messaging mechanism
54
55
image::l2l1.png[L2->L1 message mechanism]
55
56
56
57
=== L2 -> L1 message structure
57
58
58
-
// xref:#structure_l2-l1[] illustrates the structure of an L2 -> L1 message.
59
-
60
-
The structure of an L2 -> L1 message is described as follows under `MSG_TO_L1` in the link:https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json[Starknet API JSON RPC] specification:
59
+
The structure of an L2 -> L1 message is defined under `MSG_TO_L1` in the https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json[Starknet API JSON RPC^] specification as follows:
61
60
62
-
[horizontal,labelwidth="30",role="stripes-odd"]
61
+
[horizontal,labelwidth="30"]
63
62
`from_address` (`felt252`):: The address of the L2 contract sending the message.
64
63
`to_address` (`EthAddress`):: The target L1 address the message is sent to.
65
-
`payload` (`Array<felt252>`):: The payload of the message.
64
+
`payload` (`Array<felt252>`):: The payload of the message.
66
65
67
-
[#hashing_l2-l1]
68
66
=== L2 -> L1 message hashing
69
67
70
68
The hash of an L2 -> L1 message is computed on L1 as follows:
@@ -86,12 +84,11 @@ keccak256(
86
84
Sending an L2 to L1 message always incurs a fixed cost of 20,000 L1 gas, because the hash of the message being sent must be written to L1 storage in the Starknet Core Contract.
87
85
====
88
86
89
-
[id="l1-l2-messages"]
90
87
== L1 -> L2 messages
91
88
92
-
Contracts on L1 can interact asynchronously with contracts on L2 using the _L1->L2_ messaging protocol.
89
+
=== L1 -> L2 message protocol
93
90
94
-
The protocol consists of the following stages:
91
+
The L1 -> L2 message protocol consists of the following stages:
95
92
96
93
. An L1 contract induces a message to an L2 contract on Starknet by calling the link:https://github.com/starkware-libs/cairo-lang/blob/54d7e92a703b3b5a1e07e9389608178129946efc/src/starkware/starknet/solidity/IStarknetMessaging.sol#L13[`sendMessageToL2`] function on the Starknet Core Contract with the message parameters.
97
94
+
@@ -108,11 +105,6 @@ The Starknet Core Contract hashes the message parameters and updates the L1->L2
108
105
109
106
At this point, the message is handled.
110
107
111
-
// The above flow is illustrated in the following diagram:
112
-
// #THIS IMAGE IS WRONG & MISLEADING#
113
-
114
-
// image::l1l2.png[l1l2]
115
-
116
108
An L1->L2 message consists of the following:
117
109
118
110
* L1 sender's address
@@ -128,7 +120,37 @@ The message nonce is maintained on the Starknet Core Contract on L1, and is incr
128
120
For more information, see xref:#l1_l2_message_structure[L1->L2 structure].
129
121
====
130
122
131
-
[id="l2-l1_message_cancellation"]
123
+
=== L1 -> L2 message structure
124
+
125
+
126
+
For completeness, the following table describes the precise structure of both the message as it appears on L1 and the induced transaction as it appears on L2:
The hash of the message is computed on L1 as follows:
138
+
139
+
[source,js]
140
+
----
141
+
keccak256(
142
+
abi.encodePacked(
143
+
uint256(FromAddress),
144
+
ToAddress,
145
+
Nonce,
146
+
Selector,
147
+
Payload.length,
148
+
Payload
149
+
)
150
+
);
151
+
----
152
+
153
+
132
154
=== L1 -> L2 message cancellation
133
155
134
156
[NOTE]
@@ -148,7 +170,6 @@ The steps in this flow are as follows:
148
170
149
171
150
172
151
-
[id="l1-l2-message-fees"]
152
173
=== L1 -> L2 message fees
153
174
154
175
An L1 -> L2 message induces a transaction on L2, which, unlike regular transactions, is not sent by an account. This calls for a different mechanism for paying the transaction's fee, for otherwise the sequencer has no incentive of including L1 handler transactions inside a block.
@@ -160,60 +181,34 @@ The sequencer takes this fee in exchange for handling the message. The sequencer
160
181
The fee itself is calculated in the xref:architecture:fees.adoc#overall_fee[same manner] as
161
182
"regular" L2 transactions.
162
183
163
-
[id="structure_and_hashing_l1-l2"]
164
-
[#l1_l2_message_structure]
165
-
=== L1 -> L2 structure
166
-
167
-
For completeness, xref:#l1_l2_message_structure[] describes the precise structure of both the message as it appears on L1 and the induced transaction as it appears on L2.
In an L1 handler transaction, the first element of the calldata is always the sender's Ethereum address.
198
+
====
199
+
200
+
==== Hash calculation
201
+
207
202
The hash of the corresponding L1 handler transaction on L2 is computed as follows:
208
203
209
204
[source,cairo]
210
205
----
211
-
l1_handler_tx_hash = _h_(
206
+
l1_handler_tx_hash = h(
212
207
"l1_handler",
213
208
version,
214
209
contract_address,
215
210
entry_point_selector,
216
-
_h_(calldata),
211
+
h(calldata),
217
212
0,
218
213
chain_id,
219
214
nonce
@@ -228,26 +223,19 @@ Where:
228
223
* _h_ is the xref:architecture:cryptography.adoc#hash-functions#pedersen_hash[Pedersen] hash (note that since we're hashing an array, the # of inputs needs to be appended to the hash).
229
224
* `0` indicates that L1 to L2 message fees are charged on L1.
230
225
231
-
[NOTE]
232
-
====
233
-
In an L1 handler transaction, the first element of the calldata is always the sender's Ethereum address.
234
-
====
226
+
==== Caveats and limitations
235
227
236
-
[NOTE]
237
-
====
238
-
Since L1 handler transactions are not initiated by an account, invoking link:https://github.com/starkware-libs/cairo/blob/2203a47f8a098cd4718d03bd109ca014049419e7/corelib/src/starknet/info.cairo#L49[`get_caller_address()`] or similar account-related functions returns the address `0x0`.
239
-
====
228
+
* Since L1 handler transactions are not initiated by an account, invoking https://github.com/starkware-libs/cairo/blob/2203a47f8a098cd4718d03bd109ca014049419e7/corelib/src/starknet/info.cairo#L49[`get_caller_address`^] or similar account-related functions returns the address `0x0`.
229
+
* Starting from Starknet version 0.14.0:
230
+
** L1 handlers that fail execution will appear in a block as `REVERTED`, instead of only be written in the feeder gateway's database as `REJECTED`. The purpose of this change is to simplify the tracking of messages L1 -> L2, and the implementation of `getMessageStatus` in particular.
231
+
** The `l1_gas`, `l2_gas`, and `l1_data_gas` execution resources of L1 handlers will be bounded as follows:
232
+
*** `l2_gas` will bounded by stem:[10^8] (the same as ``++__validate__++``'s)
233
+
*** `l1_gas` and `l1_data_gas` will be bounded by stem:[4*10^4] and stem:[2*10^4], respectively (to allow for sending one L2 -> L1 message)
240
234
241
-
.Supported versions of the `L1HandlerTransaction` transaction type
235
+
==== Supported versions
242
236
[cols=",,",]
243
237
|===
244
238
|Current version |Deprecated versions | Unsupported versions
* link:https://github.com/starkware-libs/cairo-lang/blob/54d7e92a703b3b5a1e07e9389608178129946efc/src/starkware/starknet/solidity/IStarknetMessaging.sol#L13[`sendMessageToL2`] function on the Starknet Core Contract
253
-
* For more information on how messaging works within the Starknet Core Contract, including details on coding, see link:https://book.cairo-lang.org/ch16-04-L1-L2-messaging.html[L1-L2 Messaging] in _The Cairo Book: The Cairo Programming Language_
Copy file name to clipboardExpand all lines: components/Starknet/modules/architecture/pages/os.adoc
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -43,7 +43,7 @@ Contract calls are in fact done non-deterministically, i.e. the contract's respo
43
43
44
44
* State updates are accumulated in the global state updates dictionary
45
45
. Verifying that the new commitment corresponds to applying the updates accumulated in the global state updates dictionary to the old commitment (for more details, see the link:https://github.com/starkware-libs/cairo-lang/blob/8e11b8cc65ae1d0959328b1b4a40b92df8b58595/src/starkware/starknet/core/os/state/state.cairo#L40[`state_update` function in `state.cairo`^]).
46
-
. Encoding the state diff and adding it to the output segment for xref:network-architecture/data-availability.adoc[data availability] purposes (for more details, see the link:https://github.com/starkware-libs/cairo-lang/blob/8e11b8cc65ae1d0959328b1b4a40b92df8b58595/src/starkware/starknet/core/os/output.cairo#L71[`serialize_os_output` function in `output.cairo`^])
46
+
. Encoding the state diff and adding it to the output segment for xref:data-availability.adoc[data availability] purposes (for more details, see the link:https://github.com/starkware-libs/cairo-lang/blob/8e11b8cc65ae1d0959328b1b4a40b92df8b58595/src/starkware/starknet/core/os/output.cairo#L71[`serialize_os_output` function in `output.cairo`^])
0 commit comments