-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathL2ContractHelper.sol
88 lines (68 loc) · 3.26 KB
/
L2ContractHelper.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8.0;
interface IL2Messenger {
function sendToL1(bytes memory _message) external returns (bytes32);
}
interface IContractDeployer {
struct ForceDeployment {
bytes32 bytecodeHash;
address newAddress;
uint256 value;
bytes input;
}
function forceDeployOnAddresses(ForceDeployment[] calldata _deployParams) external;
function create2(
bytes32 _salt,
bytes32 _bytecodeHash,
bytes calldata _input
) external;
}
uint160 constant SYSTEM_CONTRACTS_OFFSET = 0x8000; // 2^15
address constant BOOTLOADER_ADDRESS = address(SYSTEM_CONTRACTS_OFFSET + 0x01);
address constant DEPLOYER_SYSTEM_CONTRACT_ADDRESS = address(SYSTEM_CONTRACTS_OFFSET + 0x06);
// A contract that is allowed to deploy any codehash
// on any address. To be used only during an upgrade.
address constant FORCE_DEPLOYER = address(SYSTEM_CONTRACTS_OFFSET + 0x07);
IL2Messenger constant L2_MESSENGER = IL2Messenger(address(SYSTEM_CONTRACTS_OFFSET + 0x08));
address constant VALUE_SIMULATOR_SYSTEM_CONTRACT_ADDRESS = address(SYSTEM_CONTRACTS_OFFSET + 0x09);
library L2ContractHelper {
bytes32 constant CREATE2_PREFIX = keccak256("zksyncCreate2");
function sendMessageToL1(bytes memory _message) internal returns (bytes32) {
return L2_MESSENGER.sendToL1(_message);
}
function hashL2Bytecode(bytes memory _bytecode) internal pure returns (bytes32 hashedBytecode) {
// Note that the length of the bytecode
// must be provided in 32-byte words.
require(_bytecode.length % 32 == 0, "po");
uint256 bytecodeLenInWords = _bytecode.length / 32;
require(bytecodeLenInWords < 2**16, "pp"); // bytecode length must be less than 2^16 words
require(bytecodeLenInWords % 2 == 1, "pr"); // bytecode length in words must be odd
hashedBytecode = sha256(_bytecode) & 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
// Setting the version of the hash
hashedBytecode = (hashedBytecode | bytes32(uint256(1 << 248)));
// Setting the length
hashedBytecode = hashedBytecode | bytes32(bytecodeLenInWords << 224);
}
/// @notice Validates the bytecodehash
function validateBytecodeHash(bytes32 _bytecodeHash) internal pure {
uint8 version = uint8(_bytecodeHash[0]);
require(version == 1 && _bytecodeHash[1] == bytes1(0), "zf"); // Incorrectly formatted bytecodeHash
require(bytecodeLen(_bytecodeHash) % 2 == 1, "uy"); // Code length in words must be odd
}
/// @notice returns the length of the bytecode
function bytecodeLen(bytes32 _bytecodeHash) internal pure returns (uint256 codeLengthInWords) {
codeLengthInWords = uint256(uint8(_bytecodeHash[2])) * 256 + uint256(uint8(_bytecodeHash[3]));
}
function computeCreate2Address(
address _sender,
bytes32 _salt,
bytes32 _bytecodeHash,
bytes32 _constructorInputHash
) internal pure returns (address) {
bytes32 senderBytes = bytes32(uint256(uint160(_sender)));
bytes32 data = keccak256(
bytes.concat(CREATE2_PREFIX, senderBytes, _salt, _bytecodeHash, _constructorInputHash)
);
return address(uint160(uint256(data)));
}
}