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
## Generic usage of `BridgeHub.requestL2TransactionTwoBridges`
4
+
5
+
`L1AssetRouter` is the only bridge that can handle base tokens. However, the `BridgeHub.requestL2TransactionTwoBridges` could be used by `secondBridgeAddress` on L1. A notable example of how it is done is how our [CTMDeploymentTracker](../../../l1-contracts/contracts/bridgehub/CTMDeploymentTracker.sol) uses it to register the correct CTM address on Gateway. You can read more about how Gateway works in [its documentation](../../gateway/overview.md).
6
+
7
+
Let’s do a quick recap on how it works:
8
+
9
+
When calling `BridgeHub.requestL2TransactionTwoBridges` the following struct needs to be provided:
10
+
11
+
```solidity
12
+
struct L2TransactionRequestTwoBridgesOuter {
13
+
uint256 chainId;
14
+
uint256 mintValue;
15
+
uint256 l2Value;
16
+
uint256 l2GasLimit;
17
+
uint256 l2GasPerPubdataByteLimit;
18
+
address refundRecipient;
19
+
address secondBridgeAddress;
20
+
uint256 secondBridgeValue;
21
+
bytes secondBridgeCalldata;
22
+
}
23
+
```
24
+
25
+
-`secondBridgeAddress` is the address of the L1 contract that needs to perform the L1->L2 transaction.
26
+
-`secondBridgeValue` is the `msg.value` to be sent to the `secondBridgeAddress`.
27
+
-`secondBridgeCalldata` is the data to pass to the `secondBridgeAddress`. This can be interpreted any way it wants.
28
+
29
+
1. Firstly, the Bridgehub will deposit the `request.mintValue` the same way as during a simple L1→L2 transaction. These funds will be used for funding the `l2Value` and the fee to the operator.
30
+
2. After that, the `secondBridgeAddress.bridgehubDeposit` with the following signature is called
31
+
32
+
```solidity
33
+
struct L2TransactionRequestTwoBridgesInner {
34
+
// Should be equal to a constant `keccak256("TWO_BRIDGES_MAGIC_VALUE")) - 1`
35
+
bytes32 magicValue;
36
+
// The L2 contract to call
37
+
address l2Contract;
38
+
// The calldata to call it with
39
+
bytes l2Calldata;
40
+
// The factory deps to call it with
41
+
bytes[] factoryDeps;
42
+
// Just some 32-byte value that can be used for later processing
43
+
// It is called `txDataHash` as it *should* be used as a way to facilitate
44
+
// reclaiming failed deposits.
45
+
bytes32 txDataHash;
46
+
}
47
+
48
+
function bridgehubDeposit(
49
+
uint256 _chainId,
50
+
// The actual user that does the deposit
51
+
address _prevMsgSender,
52
+
// The msg.value of the L1->L2 transaction to be created
Now the job of the contract will be to “validate” whether they are okay with the transaction to come. For instance, the `CTMDeploymentTracker` checks that the `_prevMsgSender` is the owner of `CTMDeploymentTracker` and has the necessary rights to perform the transaction out of the name of it.
60
+
61
+
Ultimately, the correctly processed `bridgehubDeposit` function basically grants `BridgeHub` the right to create an L1→L2 transaction out of the name of the `secondBridgeAddress`. Since it is so powerful, the first returned value must be a magical constant that is equal to `keccak256("TWO_BRIDGES_MAGIC_VALUE")) - 1`. The fact that it was a somewhat non standard signature and a struct with the magical value is the major defense against “accidental” approvals to start a transaction out of the name of an account.
62
+
63
+
Aside from the magical constant, the method should also return the information an L1→L2 transaction will start its call with: the `l2Contract` , `l2Calldata`, `factoryDeps`. It also should return the `txDataHash` field. The meaning `txDataHash` will be needed in the next paragraphs. But generally it can be any 32-byte value the bridge wants.
64
+
65
+
1. After that, an L1→L2 transaction is invoked. Note, that the “trusted” `L1AssetRouter` has enforced that the baseToken was deposited correctly (again, the step (1) can _only_ be handled by the `L1AssetRouter`), while the second bridge can provide any data to call its L2 counterpart with.
66
+
2. As a final step, following function is called:
67
+
68
+
```solidity
69
+
function bridgehubConfirmL2Transaction(
70
+
// `chainId` of the ZKChain
71
+
uint256 _chainId,
72
+
// the same value that was returned by `bridgehubDeposit`
73
+
bytes32 _txDataHash,
74
+
// the hash of the L1->L2 transaction
75
+
bytes32 _txHash
76
+
) external;
77
+
```
78
+
79
+
This function is needed for whatever actions are needed to be done after the L1→L2 transaction has been invoked.
80
+
81
+
On `L1AssetRouter` it is used to remember the hash of each deposit transaction, so that later on, the funds could be returned to user if the `L1->L2` transaction fails. The `_txDataHash` is stored so that the whenever the users will want to reclaim funds from a failed deposit, they would provide the token and the amount as well as the sender to send the money to.
## Generic usage of `BridgeHub.requestL2TransactionTwoBridges`
62
-
63
-
`L1AssetRouter` is the only bridge that can handle base tokens. However, the `BridgeHub.requestL2TransactionTwoBridges` could be used by `secondBridgeAddress` on L1. A notable example of how it is done is how our [CTMDeploymentTracker](../../../l1-contracts/contracts/bridgehub/CTMDeploymentTracker.sol) uses it to register the correct CTM address on Gateway. You can read more about how Gateway works in [its documentation](../../gateway/overview.md).
64
-
65
-
Let’s do a quick recap on how it works:
66
-
67
-
When calling `BridgeHub.requestL2TransactionTwoBridges` the following struct needs to be provided:
68
-
69
-
```solidity
70
-
struct L2TransactionRequestTwoBridgesOuter {
71
-
uint256 chainId;
72
-
uint256 mintValue;
73
-
uint256 l2Value;
74
-
uint256 l2GasLimit;
75
-
uint256 l2GasPerPubdataByteLimit;
76
-
address refundRecipient;
77
-
address secondBridgeAddress;
78
-
uint256 secondBridgeValue;
79
-
bytes secondBridgeCalldata;
80
-
}
81
-
```
82
-
83
-
-`secondBridgeAddress` is the address of the L1 contract that needs to perform the L1->L2 transaction.
84
-
-`secondBridgeValue` is the `msg.value` to be sent to the `secondBridgeAddress`.
85
-
-`secondBridgeCalldata` is the data to pass to the `secondBridgeAddress`. This can be interpreted any way it wants.
86
-
87
-
1. Firstly, the Bridgehub will deposit the `request.mintValue` the same way as during a simple L1→L2 transaction. These funds will be used for funding the `l2Value` and the fee to the operator.
88
-
2. After that, the `secondBridgeAddress.bridgehubDeposit` with the following signature is called
89
-
90
-
```solidity
91
-
struct L2TransactionRequestTwoBridgesInner {
92
-
// Should be equal to a constant `keccak256("TWO_BRIDGES_MAGIC_VALUE")) - 1`
93
-
bytes32 magicValue;
94
-
// The L2 contract to call
95
-
address l2Contract;
96
-
// The calldata to call it with
97
-
bytes l2Calldata;
98
-
// The factory deps to call it with
99
-
bytes[] factoryDeps;
100
-
// Just some 32-byte value that can be used for later processing
101
-
// It is called `txDataHash` as it *should* be used as a way to facilitate
102
-
// reclaiming failed deposits.
103
-
bytes32 txDataHash;
104
-
}
105
-
106
-
function bridgehubDeposit(
107
-
uint256 _chainId,
108
-
// The actual user that does the deposit
109
-
address _prevMsgSender,
110
-
// The msg.value of the L1->L2 transaction to be created
Now the job of the contract will be to “validate” whether they are okay with the transaction to come. For instance, the `CTMDeploymentTracker` checks that the `_prevMsgSender` is the owner of `CTMDeploymentTracker` and has the necessary rights to perform the transaction out of the name of it.
118
-
119
-
Ultimately, the correctly processed `bridgehubDeposit` function basically grants `BridgeHub` the right to create an L1→L2 transaction out of the name of the `secondBridgeAddress`. Since it is so powerful, the first returned value must be a magical constant that is equal to `keccak256("TWO_BRIDGES_MAGIC_VALUE")) - 1`. The fact that it was a somewhat non standard signature and a struct with the magical value is the major defense against “accidental” approvals to start a transaction out of the name of an account.
120
-
121
-
Aside from the magical constant, the method should also return the information an L1→L2 transaction will start its call with: the `l2Contract` , `l2Calldata`, `factoryDeps`. It also should return the `txDataHash` field. The meaning `txDataHash` will be needed in the next paragraphs. But generally it can be any 32-byte value the bridge wants.
122
-
123
-
1. After that, an L1→L2 transaction is invoked. Note, that the “trusted” `L1AssetRouter` has enforced that the baseToken was deposited correctly (again, the step (1) can _only_ be handled by the `L1AssetRouter`), while the second bridge can provide any data to call its L2 counterpart with.
124
-
2. As a final step, following function is called:
125
-
126
-
```solidity
127
-
function bridgehubConfirmL2Transaction(
128
-
// `chainId` of the ZKChain
129
-
uint256 _chainId,
130
-
// the same value that was returned by `bridgehubDeposit`
131
-
bytes32 _txDataHash,
132
-
// the hash of the L1->L2 transaction
133
-
bytes32 _txHash
134
-
) external;
135
-
```
136
-
137
-
This function is needed for whatever actions are needed to be done after the L1→L2 transaction has been invoked.
138
-
139
-
On `L1AssetRouter` it is used to remember the hash of each deposit transaction, so that later on, the funds could be returned to user if the `L1->L2` transaction fails. The `_txDataHash` is stored so that the whenever the users will want to reclaim funds from a failed deposit, they would provide the token and the amount as well as the sender to send the money to.
0 commit comments