-
Notifications
You must be signed in to change notification settings - Fork 409
basic contracts #1800
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: draft-v31
Are you sure you want to change the base?
basic contracts #1800
Changes from 1 commit
7c0a2b7
ee1205d
c6d18cb
f24e144
b32524e
ba60c62
aea34c8
7ac9441
6e6d849
85350f9
f1d128e
5c54719
191b846
d489db2
2cf3811
eeecb94
831ebe4
0c89daa
b183a11
24cdb4d
0d38d3d
71673ac
8de412e
616e068
6b458da
b5e4633
ebef355
8567b0d
d0033af
2222a14
63a587c
8307029
92be3dd
c106c01
ed9b54c
3c712c6
6eec1de
c60e6b0
b2512c3
e2ac3e8
9458351
8097804
4349eed
72c182a
6673bd4
a5d3ce1
d23ddce
eca1b5b
5371636
9562f56
1111fa6
c4943fe
1e7b960
be956f2
a5b15f6
7879945
ffc603b
fa26fb0
9abc1fc
19ad7f7
8934b46
c4be9c5
ff33726
cecce69
edc6418
76cc6fe
be73d2d
87acc97
e4c1930
d5d1e6d
1e55b2f
ffb1b13
2efe252
f9e9261
ea05b90
0a63088
6b35266
39b98b9
a44ed0e
487f501
a39ffdd
104321a
10bbd13
e802b36
f9498c5
578ba46
8748252
7aec612
68a169c
d79e087
e4ae8ca
43ac018
4d49456
ac13d7e
133f674
f9d3fa6
0b875d6
c18c1ad
d27e121
d1a2280
3dd0b04
89ed957
4403097
95a9c9d
e15cc51
4e0ae48
707c703
cbf22fb
31c986f
3b0abde
94d2723
55e457c
e1864ce
6573240
024e8eb
6f1da2b
72047aa
8547bcc
a8b4362
e64b837
fbc4180
6ef6d39
2c56e35
db3bd15
308c997
e77e86e
4421880
c6a5244
24e13e2
554d096
21d6f40
e84cf10
709cefd
01a6ae9
c624a99
b870553
46ae089
ef888ff
5a2a7f4
a6a26cb
9fa9e2f
0d2a4e0
90865fc
312f02a
35c94ec
c0a2cc2
f68672f
322fa1d
fb6a11d
f64c0ef
25b20d9
4c36eb4
a5cc118
ebb95f6
1065567
00ba368
ce365aa
ec71a1b
b08496e
1a32cf2
10cd713
005d439
508a518
83369c6
1b26555
1ed4348
f01dde5
c022c57
34f3a5d
b7d1f05
44c3997
9a4e523
cea5177
e954643
10c283a
5b5b9a1
c6c17b1
c5983ae
48f64de
4c1e38d
22afe1e
1129bc7
7831684
f32677e
5e1200e
d8c9cc5
bf00aad
5ddc2b5
11fe14b
f1e259f
d0f1bec
d12dc60
e7947c8
166ec4e
ada702b
a531675
907cfef
7e82465
f894e11
ca7ac52
f7065f7
639f7e2
f33b264
6ad872d
92d56bf
7fcd5f2
227955a
313c35a
1d3452c
923f5bd
a290ce1
4b0c50e
884d5bd
2f88afe
be61bd9
21e0ad4
a6c9e56
a2c706a
ed31c01
b56fcb4
d5a5e31
20f2dbe
6915321
68ab974
8691f05
4b08f5b
524c0cd
3d96c70
5190830
1079469
d86014c
43496f7
7cdf58b
899b659
39c0970
f631ebd
fd84f92
68f79ed
0741356
3fcd17d
9efcb94
51af655
0bc7cf0
cee7e54
f9447b5
8f13871
7199f9a
4b71920
b59987d
0e96ac2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,159 @@ | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| pragma solidity 0.8.28; | ||
|
|
||
|
|
||
| import {L2_BRIDGEHUB_ADDR} from "../common/l2-helpers/L2ContractAddresses.sol"; | ||
|
Check failure on line 6 in l1-contracts/contracts/dummy-interop/L1InteropHandler.sol
|
||
| import {FinalizeL1DepositParams} from "../bridge/interfaces/IL1Nullifier.sol"; | ||
|
|
||
| /// @author Matter Labs | ||
| /// @custom:security-contact security@matterlabs.dev | ||
| /// @dev The L1InteropHandler contract is responsible for handling interops from L2. | ||
| contract L1InteropHandler { | ||
|
|
||
| address public l2InteropCenterAddress; | ||
|
|
||
| address public l1BridgehubAddress; | ||
|
|
||
| function receiveInteropFromL2( | ||
|
Check failure on line 18 in l1-contracts/contracts/dummy-interop/L1InteropHandler.sol
|
||
| FinalizeL1DepositParams memory _tokenWithdrawalParams, | ||
| FinalizeL1DepositParams memory _bundleWithdrawalParams | ||
| ) external returns (address l1Receiver, address l1Token, uint256 amount) { | ||
| (l1Receiver, l1Token, amount) = _parseL2WithdrawalMessage(_tokenWithdrawalParams.message); | ||
|
|
||
| // deploy shadow account if needed | ||
| address shadowAccount = _deployShadowAccount(_tokenWithdrawalParams.l2Sender); | ||
|
Check failure on line 25 in l1-contracts/contracts/dummy-interop/L1InteropHandler.sol
|
||
|
|
||
| // execute bundle withdrawal | ||
| _executeBundleWithdrawal(_bundleWithdrawalParams); | ||
kelemeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| /// @notice Verifies the validity of a withdrawal message from L2 and returns withdrawal details. | ||
| /// @param _finalizeWithdrawalParams The structure that holds all necessary data to finalize withdrawal | ||
| /// @return assetId The ID of the bridged asset. | ||
| /// @return transferData The transfer data used to finalize withdawal. | ||
| function _verifyWithdrawal( | ||
| FinalizeL1DepositParams memory _finalizeWithdrawalParams, | ||
| bool overrideL2Sender | ||
|
Check failure on line 37 in l1-contracts/contracts/dummy-interop/L1InteropHandler.sol
|
||
| ) internal returns (bytes32 assetId, bytes memory transferData) { | ||
| (assetId, transferData) = _parseL2WithdrawalMessage( | ||
| _finalizeWithdrawalParams.chainId, | ||
| _finalizeWithdrawalParams.message | ||
| ); | ||
| L2Message memory l2ToL1Message; | ||
| { | ||
| address l2Sender = _finalizeWithdrawalParams.l2Sender; | ||
| bool baseTokenWithdrawal = (assetId == BRIDGE_HUB.baseTokenAssetId(_finalizeWithdrawalParams.chainId)); | ||
|
|
||
| bool isL2SenderCorrect = l2Sender == L2_ASSET_ROUTER_ADDR || | ||
| l2Sender == L2_BASE_TOKEN_SYSTEM_CONTRACT_ADDR || | ||
| l2Sender == __DEPRECATED_l2BridgeAddress[_finalizeWithdrawalParams.chainId]; | ||
| if (!isL2SenderCorrect) { | ||
| revert WrongL2Sender(l2Sender); | ||
| } | ||
|
|
||
| l2ToL1Message = L2Message({ | ||
| txNumberInBatch: _finalizeWithdrawalParams.l2TxNumberInBatch, | ||
| sender: baseTokenWithdrawal ? L2_BASE_TOKEN_SYSTEM_CONTRACT_ADDR : l2Sender, | ||
| data: _finalizeWithdrawalParams.message | ||
| }); | ||
| } | ||
|
|
||
| bool success = BRIDGE_HUB.proveL2MessageInclusion({ | ||
| _chainId: _finalizeWithdrawalParams.chainId, | ||
| _batchNumber: _finalizeWithdrawalParams.l2BatchNumber, | ||
| _index: _finalizeWithdrawalParams.l2MessageIndex, | ||
| _message: l2ToL1Message, | ||
| _proof: _finalizeWithdrawalParams.merkleProof | ||
| }); | ||
| // withdrawal wrong proof | ||
| if (!success) { | ||
| revert InvalidProof(); | ||
| } | ||
kelemeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| /// @notice Parses the withdrawal message and returns withdrawal details. | ||
| /// @dev Currently, 3 different encoding versions are supported: legacy mailbox withdrawal, ERC20 bridge withdrawal, | ||
| /// @dev and the latest version supported by shared bridge. Selectors are used for versioning. | ||
| /// @param _chainId The ZK chain ID. | ||
| /// @param _l2ToL1message The encoded L2 -> L1 message. | ||
| /// @return assetId The ID of the bridged asset. | ||
| /// @return transferData The transfer data used to finalize withdawal. | ||
| function _parseL2WithdrawalMessage( | ||
| uint256 _chainId, | ||
| bytes memory _l2ToL1message | ||
| ) internal returns (bytes32 assetId, bytes memory transferData) { | ||
| // Please note that there are three versions of the message: | ||
| // 1. The message that is sent from `L2BaseToken` to withdraw base token. | ||
| // 2. The message that is sent from L2 Legacy Shared Bridge to withdraw ERC20 tokens or base token. | ||
| // 3. The message that is sent from L2 Asset Router to withdraw ERC20 tokens or base token. | ||
|
|
||
| uint256 amount; | ||
| address l1Receiver; | ||
|
|
||
| (uint32 functionSignature, uint256 offset) = UnsafeBytes.readUint32(_l2ToL1message, 0); | ||
| if (bytes4(functionSignature) == IMailboxImpl.finalizeEthWithdrawal.selector) { | ||
| // The data is expected to be at least 56 bytes long. | ||
| if (_l2ToL1message.length < 56) { | ||
| revert L2WithdrawalMessageWrongLength(_l2ToL1message.length); | ||
| } | ||
| // this message is a base token withdrawal | ||
| (l1Receiver, offset) = UnsafeBytes.readAddress(_l2ToL1message, offset); | ||
| // slither-disable-next-line unused-return | ||
| (amount, ) = UnsafeBytes.readUint256(_l2ToL1message, offset); | ||
| assetId = BRIDGE_HUB.baseTokenAssetId(_chainId); | ||
| transferData = DataEncoding.encodeBridgeMintData({ | ||
| _originalCaller: address(0), | ||
| _remoteReceiver: l1Receiver, | ||
| // Note, that `assetId` could belong to a token native to an L2, and so | ||
| // the logic for determining the correct origin token address will be complex. | ||
| // It is expected that this value won't be used in the NativeTokenVault and so providing | ||
| // any value is acceptable here. | ||
| _originToken: address(0), | ||
| _amount: amount, | ||
| _erc20Metadata: new bytes(0) | ||
| }); | ||
| } else if (bytes4(functionSignature) == IL1ERC20Bridge.finalizeWithdrawal.selector) { | ||
| // this message is a token withdrawal | ||
|
|
||
| // Check that the message length is correct. | ||
| // It should be equal to the length of the function signature + address + address + uint256 = 4 + 20 + 20 + 32 = | ||
| // 76 (bytes). | ||
| if (_l2ToL1message.length != 76) { | ||
| revert L2WithdrawalMessageWrongLength(_l2ToL1message.length); | ||
| } | ||
| (l1Receiver, offset) = UnsafeBytes.readAddress(_l2ToL1message, offset); | ||
| // We use the IL1ERC20Bridge for backward compatibility with old withdrawals. | ||
| address l1Token; | ||
| (l1Token, offset) = UnsafeBytes.readAddress(_l2ToL1message, offset); | ||
| // slither-disable-next-line unused-return | ||
| (amount, ) = UnsafeBytes.readUint256(_l2ToL1message, offset); | ||
|
|
||
| assetId = l1NativeTokenVault.ensureTokenIsRegistered(l1Token); | ||
| bytes32 expectedAssetId = DataEncoding.encodeNTVAssetId(block.chainid, l1Token); | ||
| // This method is only expected to use L1-based tokens. | ||
| if (assetId != expectedAssetId) { | ||
| revert TokenNotLegacy(); | ||
| } | ||
| transferData = DataEncoding.encodeBridgeMintData({ | ||
| _originalCaller: address(0), | ||
| _remoteReceiver: l1Receiver, | ||
| _originToken: l1Token, | ||
| _amount: amount, | ||
| _erc20Metadata: new bytes(0) | ||
| }); | ||
| } else if (bytes4(functionSignature) == IAssetRouterBase.finalizeDeposit.selector) { | ||
| // The data is expected to be at least 68 bytes long to contain assetId. | ||
| if (_l2ToL1message.length < 68) { | ||
| revert WrongMsgLength(68, _l2ToL1message.length); | ||
| } | ||
| // slither-disable-next-line unused-return | ||
| (, offset) = UnsafeBytes.readUint256(_l2ToL1message, offset); // originChainId, not used for L2->L1 txs | ||
| (assetId, offset) = UnsafeBytes.readBytes32(_l2ToL1message, offset); | ||
| transferData = UnsafeBytes.readRemainingBytes(_l2ToL1message, offset); | ||
| } else { | ||
| revert InvalidSelector(bytes4(functionSignature)); | ||
| } | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| pragma solidity 0.8.28; | ||
|
|
||
|
|
||
| import {L2_BRIDGEHUB_ADDR} from "../common/l2-helpers/L2ContractAddresses.sol"; | ||
|
Check failure on line 6 in l1-contracts/contracts/dummy-interop/L1ShadowAccount.sol
|
||
|
|
||
| /// @author Matter Labs | ||
| /// @custom:security-contact security@matterlabs.dev | ||
| /// @dev The L1ShadowAccount contract. | ||
| contract L1ShadowAccount { | ||
|
|
||
| address public l1InteropHandlerAddress; | ||
|
|
||
| constructor() { | ||
| l1InteropHandlerAddress = msg.sender; | ||
| } | ||
|
|
||
| function executeFromIH( | ||
| address target, | ||
| uint256 value, | ||
| bytes calldata data | ||
| ) external { | ||
| require(msg.sender == l1InteropHandlerAddress, "L1ShadowAccount: not authorized"); | ||
| (bool success, ) = target.call{value: value}(data); | ||
| require(success, "L1ShadowAccount: call failed"); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| pragma solidity 0.8.28; | ||
|
|
||
|
|
||
| import {L2_BRIDGEHUB_ADDR} from "../common/l2-helpers/L2ContractAddresses.sol"; | ||
|
|
||
| /// @author Matter Labs | ||
| /// @custom:security-contact security@matterlabs.dev | ||
| /// @dev The L2InteropCenter contract is responsible for sending interops to L1. | ||
| contract L2InteropCenter { | ||
|
|
||
| address public l1InteropHandlerAddress; | ||
|
|
||
| /// send bundle to L1 | ||
| /// 1. withdraw token to L1 shadow account | ||
| /// 2. deploy shadow account if needed on L1. | ||
| /// 3+. arbitrary calls from shadow account to arbitrary L1 contracts. | ||
|
|
||
|
|
||
| function sendTokenWithdrawalAndBundleToL1( | ||
| bytes32 assetId, | ||
| uint256 amount, | ||
| ShadowAccountOp[] memory shadowAccountOps | ||
kelemeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ) external { | ||
|
|
||
| } | ||
|
|
||
| function l1ShadowAccount( | ||
| address _l2CallerAddress | ||
| ) returns (address) { | ||
| // get create2 address from l1 interop handler and shadow account bytecode | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.