forked from zksync-sdk/zksync2-examples
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path06_deploy_create_with_deps.py
More file actions
128 lines (95 loc) · 4.61 KB
/
06_deploy_create_with_deps.py
File metadata and controls
128 lines (95 loc) · 4.61 KB
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import os
from pathlib import Path
from eth_account import Account
from eth_account.signers.local import LocalAccount
from eth_typing import HexStr
from web3 import Web3
from zksync2.core.types import EthBlockParams
from zksync2.manage_contracts.contract_encoder_base import ContractEncoder
from zksync2.manage_contracts.deploy_addresses import ZkSyncAddresses
from zksync2.manage_contracts.precompute_contract_deployer import PrecomputeContractDeployer
from zksync2.manage_contracts.utils import nonce_holder_abi_default
from zksync2.module.module_builder import ZkSyncBuilder
from zksync2.signer.eth_signer import PrivateKeyEthSigner
from zksync2.transaction.transaction_builders import TxCreateContract
def generate_random_salt() -> bytes:
return os.urandom(32)
def deploy_contract(
zk_web3: Web3, account: LocalAccount, compiled_contract: Path
):
"""Deploy compiled contract with dependency on zkSync network using create() opcode
:param zk_web3:
Instance of ZkSyncBuilder that interacts with zkSync network
:param account:
From which account the deployment contract tx will be made
:param compiled_contract:
Compiled contract source.
:return:
Address of deployed contract.
"""
# Get chain id of zkSync network
chain_id = zk_web3.zksync.chain_id
# Signer is used to generate signature of provided transaction
signer = PrivateKeyEthSigner(account, chain_id)
# Get nonce of ETH address on zkSync network
nonce = zk_web3.zksync.get_transaction_count(
account.address, EthBlockParams.PENDING.value
)
# Get deployment nonce
nonce_holder = zk_web3.zksync.contract(address=ZkSyncAddresses.NONCE_HOLDER_ADDRESS.value,
abi=nonce_holder_abi_default())
deployment_nonce = nonce_holder.functions.getDeploymentNonce(account.address).call(
{
"from": account.address
})
# Precompute the address of smart contract
# Use this if there is a case where contract address should be known before deployment
deployer = PrecomputeContractDeployer(zk_web3)
precomputed_address = deployer.compute_l2_create_address(account.address, deployment_nonce)
# Get ABI and bytecode of demo and foo contracts
demo_contract, foo_contract = ContractEncoder.from_json(zk_web3, compiled_contract)
# Get current gas price in Wei
gas_price = zk_web3.zksync.gas_price
# Create deployment contract transaction
create_contract = TxCreateContract(web3=zk_web3,
chain_id=chain_id,
nonce=nonce,
from_=account.address,
gas_price=gas_price,
bytecode=demo_contract.bytecode,
deps=[foo_contract.bytecode])
# ZkSync transaction gas estimation
estimate_gas = zk_web3.zksync.eth_estimate_gas(create_contract.tx)
print(f"Fee for transaction is: {Web3.from_wei(estimate_gas * gas_price, 'ether')} ETH")
# Convert transaction to EIP-712 format
tx_712 = create_contract.tx712(estimate_gas)
# Sign message
signed_message = signer.sign_typed_data(tx_712.to_eip712_struct())
# Encode signed message
msg = tx_712.encode(signed_message)
# Deploy contract
tx_hash = zk_web3.zksync.send_raw_transaction(msg)
# Wait for deployment contract transaction to be included in a block
tx_receipt = zk_web3.zksync.wait_for_transaction_receipt(
tx_hash, timeout=240, poll_latency=0.5
)
print(f"Tx status: {tx_receipt['status']}")
contract_address = tx_receipt["contractAddress"]
print(f"Contract address: {contract_address}")
print(f"Precomputed address: {precomputed_address}")
# Check does precompute address match with deployed address
if precomputed_address.lower() != contract_address.lower():
raise RuntimeError("Precomputed contract address does now match with deployed contract address")
if __name__ == "__main__":
# Set a provider
PROVIDER = "https://sepolia.era.zksync.dev"
# Get the private key from OS environment variables
PRIVATE_KEY = bytes.fromhex(os.environ.get("PRIVATE_KEY"))
# Connect to zkSync network
zk_web3 = ZkSyncBuilder.build(PROVIDER)
# Get account object by providing from private key
account: LocalAccount = Account.from_key(PRIVATE_KEY)
# Provide a compiled JSON source contract
contract_path = Path("../solidity/demo/build/combined.json")
# Perform contract deployment
deploy_contract(zk_web3, account, contract_path)