Skip to content

Commit 1683770

Browse files
committed
more doc changes
1 parent bff96fd commit 1683770

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+688
-673
lines changed

docs/src/SUMMARY.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181
- [System Contracts](specs/zk_evm/system_contracts.md)
8282
- [Interop](specs/interop/overview.md)
8383
- [Interop Messages](specs/interop/interopmessages.md)
84-
- [Bundles and Calls](specs/interop/bundlesandcalls.md)
84+
- [Bundles and Calls](specs/interop/bundles_calls.md)
8585
- [Interop Transactions](specs/interop/interoptransactions.md)
8686

8787
# Announcements

docs/src/specs/contracts/bridging/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,9 @@
22

33
- [Overview](./overview.md)
44
- [Interop](./interop/interop.md)
5+
- [Interop](./overview.md)
6+
- [Interop Messages](./interopmessages.md)
7+
- [Bundles and Calls](./bundles_calls.md)
8+
- [Interop Transactions](./interoptransactions.md)
9+
510
- [Interop](./interop/forms_of_finality.md)

docs/src/specs/contracts/bridging/asset_router_and_ntv/asset_router.md

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,16 @@
22

33
[back to readme](../../README.md)
44

5-
The main job of the asset router is to be the central point of coordination for bridging. All crosschain token bridging is done between asset routers only and once the message reaches asset router, it then routes it to the corresponding asset handler.
5+
<!-- ## Asset router as the main asset bridging entrypoint
6+
7+
The main entry for passing value between chains is the AssetRouter, it is responsible for facilitating bridging between multiple asset types. To read more in detail on how it works, please refer to custom [asset bridging documentation](./asset_router_and_ntv/overview.md).
8+
9+
For the purpose of this document, it is enough to treat the Asset Router as a blackbox that is responsible for processing escrowing funds on the source chain and minting them on the destination chain.
10+
11+
> For those that are aware of the [previous ZKsync architecture](https://github.com/code-423n4/2024-03-zksync/blob/main/docs/Smart%20contract%20Section/L1%20ecosystem%20contracts.md), its role is similar to L1SharedBridge that we had before. Note, however, that it is a different contract with much enhanced functionality. Also, note that the L1SharedBridge will NOT be upgraded to the L1AssetRouter. For more details about migration, please check out [the migration doc](../../upgrade_history/gateway_upgrade/gateway_diff_review.md). -->
12+
13+
14+
The main job of the asset router is to be the central point of coordination for asset bridging. All crosschain token bridging is done between asset routers only and once the message reaches asset router, it then routes it to the corresponding asset handler.
615

716
In order to make this easier, all L2 chains have the asset router located on the same address on every chain. It is `0x10003` and it is pre-deployed contract. More on how it is deployed can be seen in the [Chain Genesis](../../chain_management/chain_genesis.md) section.
817

@@ -22,26 +31,4 @@ While the endgoal is to unify L1 and L2 asset routers, in reality, it may not be
2231

2332
_This is the contract the previous L1SharedBridge will be upgraded to, so it should have the backwards compatible storage._
2433

25-
### NativeTokenVault (L1/L2)
26-
27-
NativeTokenVault is an asset handler that is available on all chains and is also predeployed. It is provides the functionality of the most basic bridging: locking funds on one chain and minting the bridged equivalent on the other one. On L2 chains NTV is predeployed at the `0x10004` address.
28-
29-
The L1 and L2 versions of the NTV are almost identical in functionality, the main differences come from the differences of the deployment functionality in L1 and L2 envs, where the former uses standard CREATE2 and the latter uses low level calls to `CONTRACT_DEPLOYER`system contract.
30-
31-
Also, the L1NTV has the following specifics:
32-
33-
<!-- - It operates the `chainBalance` mapping, ensuring that the chains do not go beyond their balances. -->
34-
- It allows recovering from failed L1→L2 transfers.
35-
- It needs to both be able to retrieve funds from the former L1SharedBridge (now this contract has L1Nullifier in its place), but also needs to support the old SDK that gives out allowance to the “l1 shared bridge” value returned from the API, i.e. in our case this is will the L1AssetRouter.
36-
37-
### L2SharedBridgeLegacy
38-
39-
L2AssetRouter has to be pre-deployed onto a specific address. The old L2SharedBridge will be upgraded to L2SharedBridgeLegacy contract. The main purpose of this contract is to ensure compatibility with the incoming deposits and re-route them to the shared bridge.
40-
41-
This contract is never deployed for new chains.
42-
43-
### Summary
44-
45-
![image.png](./img/bridge_contracts.png)
46-
4734
> New bridge contracts
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Native Token Vault
2+
3+
### NativeTokenVault (L1/L2)
4+
5+
NativeTokenVault is an asset handler that is available on all chains and is also predeployed. It is provides the functionality of the most basic bridging: locking funds on one chain and minting the bridged equivalent on the other one. On L2 chains NTV is predeployed at the `0x10004` address.
6+
7+
The L1 and L2 versions of the NTV are almost identical in functionality, the main differences come from the differences of the deployment functionality in L1 and L2 envs, where the former uses standard CREATE2 and the latter uses low level calls to `CONTRACT_DEPLOYER`system contract.
8+
9+
Also, the L1NTV has the following specifics:
10+
11+
<!-- - It operates the `chainBalance` mapping, ensuring that the chains do not go beyond their balances. -->
12+
- It allows recovering from failed L1→L2 transfers.
13+
- It needs to both be able to retrieve funds from the former L1SharedBridge (now this contract has L1Nullifier in its place), but also needs to support the old SDK that gives out allowance to the “l1 shared bridge” value returned from the API, i.e. in our case this is will the L1AssetRouter.
14+
15+
### L2SharedBridgeLegacy
16+
17+
L2AssetRouter has to be pre-deployed onto a specific address. The old L2SharedBridge will be upgraded to L2SharedBridgeLegacy contract. The main purpose of this contract is to ensure compatibility with the incoming deposits and re-route them to the shared bridge.
18+
19+
This contract is never deployed for new chains.
20+
21+
### Summary
22+
23+
![image.png](./img/bridge_contracts.png)
1.13 KB
Loading
9.59 KB
Loading

docs/src/specs/contracts/bridging/interop_for_devs/bundlesandcalls.md renamed to docs/src/specs/contracts/bridging/interop/bundles_calls.md

Lines changed: 1 addition & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ contract InteropCenter {
5454
5555
```
5656

57-
You can retrieve the `interopMessage` (which contains your entire payload) from the Gateway, or you can construct it
57+
You can retrieve the `interopMessage` (which contains your entire payload) from the chain, or you can construct it
5858
yourself using L1 data.
5959

6060
Under the hood, this process calls the `destinationAddress` with the specified calldata.
@@ -76,46 +76,6 @@ sending interop messages from the `0x5bFF1...` account on chain A.
7676

7777
![msgdotsender.png](./img/msgdotsender.png)
7878

79-
## Simple Example
80-
81-
Imagine you have contracts on chains B, C, and D, and you’d like them to send "reports" to the Headquarters (HQ)
82-
contract on chain A every time a customer makes a purchase.
83-
84-
```solidity
85-
// Deployed on chains B, C, D.
86-
contract Shop {
87-
/// Called by the customers when they buy something.
88-
function buy(uint256 itemPrice) {
89-
// handle payment etc.
90-
...
91-
// report to HQ
92-
InteropCenter(INTEROP_ADDRESS).sendCall(
93-
324, // chain id of chain A,
94-
0xc425.., // HQ contract on chain A,
95-
createCalldata("reportSales(uint256)", itemPrice), // calldata
96-
0, // no value
97-
);
98-
}
99-
}
100-
101-
// Deployed on chain A
102-
contract HQ {
103-
// List of shops
104-
mapping (address => bool) shops;
105-
mapping (address => uint256) sales;
106-
function addShop(address addressOnChain, uint256 chainId) onlyOwner {
107-
// Adding aliased accounts.
108-
shops[address(keccak(addressOnChain || chainId))] = true;
109-
}
110-
111-
function reportSales(uint256 itemPrice) {
112-
// only allow calls from our shops (their aliased accounts).
113-
require(shops[msg.sender]);
114-
sales[msg.sender] += itemPrice;
115-
}
116-
}
117-
```
118-
11979
#### Who is paying for gas? How does this Call get to the destination chain
12080

12181
At this level, the **InteropCall** acts like a hitchhiker — it relies on someone (anyone) to pick it up, execute it, and
@@ -177,58 +137,6 @@ contract InteropCenter {
177137
}
178138
```
179139

180-
### Cross Chain Swap Example
181-
182-
Imagine you want to perform a swap on chain B, exchanging USDC for PEPE, but all your assets are currently on chain A.
183-
184-
This process would typically involve four steps:
185-
186-
1. Transfer USDC from chain A to chain B.
187-
2. Set allowance for the swap.
188-
3. Execute the swap.
189-
4. Transfer PEPE back to chain A.
190-
191-
Each of these steps is a separate "call," but you need them to execute in exactly this order and, ideally, atomically.
192-
If the swap fails, you wouldn’t want the allowance to remain set on the destination chain.
193-
194-
Below is an example of how this process could look (note that the code is pseudocode; we’ll explain the helper methods
195-
required to make it work in a later section).
196-
197-
```solidity
198-
bundleId = InteropCenter(INTEROP_CENTER).startBundle(chainD);
199-
// This will 'burn' the 1k USDC, create the special interopCall
200-
// when this call is executed on chainD, it will mint 1k USDC there.
201-
// BUT - this interopCall is tied to this bundle id.
202-
USDCBridge.transferWithBundle(
203-
bundleId,
204-
chainD,
205-
aliasedAccount(this(account), block.chain_id),
206-
1000);
207-
208-
209-
// This will create interopCall to set allowance.
210-
InteropCenter.addToBundle(bundleId,
211-
USDCOnDestinationChain,
212-
createCalldata("approve", 1000, poolOnDestinationChain),
213-
0);
214-
// This will create interopCall to do the swap.
215-
InteropCenter.addToBundle(bundleId,
216-
poolOnDestinationChain,
217-
createCalldata("swap", "USDC_PEPE", 1000, ...),
218-
0)
219-
// And this will be the interopcall to transfer all the assets back.
220-
InteropCenter.addToBundle(bundleId,
221-
pepeBridgeOnDestinationChain,
222-
createCalldata("transferAll", block.chain_id, this(account)),
223-
0)
224-
225-
226-
bundleHash = interopCenter.finishAndSendBundle(bundleId);
227-
```
228-
229-
In the code above, we created a bundle that anyone can execute on the destination chain. This bundle will handle the
230-
entire process: minting, approving, swapping, and transferring back.
231-
232140
### Bundle Restrictions
233141

234142
When starting a bundle, if you specify the `executionAddress`, only that account will be able to execute the bundle on

docs/src/specs/contracts/bridging/interop_for_devs/cross_chain_paymaster.md renamed to docs/src/specs/contracts/bridging/interop/examples/cross_chain_paymaster.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Cross Chain Paymaster
22

33
[back to readme](../../README.md)
4+
45
We want to allow the automatic execution of cross-chain txs. I.e. the user should not have to interact with the destination chain. We use triggers for this. The cross chain txs can be triggered on the origin chain, if this is the case then there is a feePaymentBundle and an execution bundle this is a general solution, that allows multiple options for paying for gas.
56

67
- Easiest. Pay a required baseTokenAmount on the sender chain (in the baseToken on the destination chain). The same amount will be minted on the destination chain. e.g. [here](../../../../../../core/tests/ts-integration/tests/interop.test.ts#L526)
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
## Simple Example
2+
3+
Imagine you have contracts on chains B, C, and D, and you’d like them to send "reports" to the Headquarters (HQ)
4+
contract on chain A every time a customer makes a purchase.
5+
6+
```solidity
7+
// Deployed on chains B, C, D.
8+
contract Shop {
9+
/// Called by the customers when they buy something.
10+
function buy(uint256 itemPrice) {
11+
// handle payment etc.
12+
...
13+
// report to HQ
14+
InteropCenter(INTEROP_ADDRESS).sendCall(
15+
324, // chain id of chain A,
16+
0xc425.., // HQ contract on chain A,
17+
createCalldata("reportSales(uint256)", itemPrice), // calldata
18+
0, // no value
19+
);
20+
}
21+
}
22+
23+
// Deployed on chain A
24+
contract HQ {
25+
// List of shops
26+
mapping (address => bool) shops;
27+
mapping (address => uint256) sales;
28+
function addShop(address addressOnChain, uint256 chainId) onlyOwner {
29+
// Adding aliased accounts.
30+
shops[address(keccak(addressOnChain || chainId))] = true;
31+
}
32+
33+
function reportSales(uint256 itemPrice) {
34+
// only allow calls from our shops (their aliased accounts).
35+
require(shops[msg.sender]);
36+
sales[msg.sender] += itemPrice;
37+
}
38+
}
39+
```
40+
41+
### Cross Chain Swap Example
42+
43+
Imagine you want to perform a swap on chain B, exchanging USDC for PEPE, but all your assets are currently on chain A.
44+
45+
This process would typically involve four steps:
46+
47+
1. Transfer USDC from chain A to chain B.
48+
2. Set allowance for the swap.
49+
3. Execute the swap.
50+
4. Transfer PEPE back to chain A.
51+
52+
Each of these steps is a separate "call," but you need them to execute in exactly this order and, ideally, atomically.
53+
If the swap fails, you wouldn’t want the allowance to remain set on the destination chain.
54+
55+
Below is an example of how this process could look (note that the code is pseudocode; we’ll explain the helper methods
56+
required to make it work in a later section).
57+
58+
```solidity
59+
bundleId = InteropCenter(INTEROP_CENTER).startBundle(chainD);
60+
// This will 'burn' the 1k USDC, create the special interopCall
61+
// when this call is executed on chainD, it will mint 1k USDC there.
62+
// BUT - this interopCall is tied to this bundle id.
63+
USDCBridge.transferWithBundle(
64+
bundleId,
65+
chainD,
66+
aliasedAccount(this(account), block.chain_id),
67+
1000);
68+
69+
70+
// This will create interopCall to set allowance.
71+
InteropCenter.addToBundle(bundleId,
72+
USDCOnDestinationChain,
73+
createCalldata("approve", 1000, poolOnDestinationChain),
74+
0);
75+
// This will create interopCall to do the swap.
76+
InteropCenter.addToBundle(bundleId,
77+
poolOnDestinationChain,
78+
createCalldata("swap", "USDC_PEPE", 1000, ...),
79+
0)
80+
// And this will be the interopcall to transfer all the assets back.
81+
InteropCenter.addToBundle(bundleId,
82+
pepeBridgeOnDestinationChain,
83+
createCalldata("transferAll", block.chain_id, this(account)),
84+
0)
85+
86+
87+
bundleHash = interopCenter.finishAndSendBundle(bundleId);
88+
```
89+
90+
In the code above, we created a bundle that anyone can execute on the destination chain. This bundle will handle the
91+
entire process: minting, approving, swapping, and transferring back.

0 commit comments

Comments
 (0)