Skip to content
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

feat(zk_toolbox): Minting base token #2571

Merged
merged 5 commits into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 0 additions & 28 deletions core/tests/ts-integration/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ async function loadTestEnvironmentFromFile(chain: string): Promise<TestEnvironme
token = Object.values(tokens.tokens)[1];
}
}
const weth = tokens.tokens['WETH'];
let baseToken;

for (const key in tokens.tokens) {
Expand All @@ -114,12 +113,6 @@ async function loadTestEnvironmentFromFile(chain: string): Promise<TestEnvironme
ethers.getDefaultProvider(l1NodeUrl)
).l2TokenAddress(token.address);

const l2WethAddress = await new zksync.Wallet(
mainWalletPK,
l2Provider,
ethers.getDefaultProvider(l1NodeUrl)
).l2TokenAddress(weth.address);

const baseTokenAddressL2 = L2_BASE_TOKEN_ADDRESS;
const l2ChainId = BigInt(genesisConfig.l2_chain_id);
const l1BatchCommitDataGeneratorMode = genesisConfig.l1_batch_commit_data_generator_mode as DataAvailabityMode;
Expand Down Expand Up @@ -152,13 +145,6 @@ async function loadTestEnvironmentFromFile(chain: string): Promise<TestEnvironme
l1Address: token.address,
l2Address: l2TokenAddress
},
wethToken: {
name: weth.name,
symbol: weth.symbol,
decimals: weth.decimals,
l1Address: weth.address,
l2Address: l2WethAddress
},
baseToken: {
name: baseToken?.name || token.name,
symbol: baseToken?.symbol || token.symbol,
Expand Down Expand Up @@ -213,7 +199,6 @@ export async function loadTestEnvironmentFromEnv(): Promise<TestEnvironment> {
if (!token) {
token = tokens[0];
}
const weth = tokens.find((token: { symbol: string }) => token.symbol == 'WETH')!;
const baseToken = tokens.find((token: { address: string }) =>
zksync.utils.isAddressEq(token.address, baseTokenAddress)
)!;
Expand All @@ -225,12 +210,6 @@ export async function loadTestEnvironmentFromEnv(): Promise<TestEnvironment> {
ethers.getDefaultProvider(l1NodeUrl)
).l2TokenAddress(token.address);

const l2WethAddress = await new zksync.Wallet(
mainWalletPK,
l2Provider,
ethers.getDefaultProvider(l1NodeUrl)
).l2TokenAddress(weth.address);

const baseTokenAddressL2 = L2_BASE_TOKEN_ADDRESS;
const l2ChainId = BigInt(process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID!);
// If the `CHAIN_STATE_KEEPER_L1_BATCH_COMMIT_DATA_GENERATOR_MODE` is not set, the default value is `Rollup`.
Expand Down Expand Up @@ -280,13 +259,6 @@ export async function loadTestEnvironmentFromEnv(): Promise<TestEnvironment> {
l1Address: token.address,
l2Address: l2TokenAddress
},
wethToken: {
name: weth.name,
symbol: weth.symbol,
decimals: weth.decimals,
l1Address: weth.address,
l2Address: l2WethAddress
},
baseToken: {
name: baseToken?.name || token.name,
symbol: baseToken?.symbol || token.symbol,
Expand Down
4 changes: 0 additions & 4 deletions core/tests/ts-integration/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,6 @@ export interface TestEnvironment {
* Description of the "main" ERC20 token used in the tests.
*/
erc20Token: Token;
/**
* Description of the WETH token used in the tests.
*/
wethToken: Token;
/**
* Description of the "base" ERC20 token used in the tests.
*/
Expand Down
40 changes: 39 additions & 1 deletion zk_toolbox/crates/common/src/ethereum.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::{ops::Add, time::Duration};
use std::{ops::Add, sync::Arc, time::Duration};

use ethers::{
contract::abigen,
core::k256::ecdsa::SigningKey,
middleware::MiddlewareBuilder,
prelude::{Http, LocalWallet, Provider, Signer, SignerMiddleware},
Expand Down Expand Up @@ -53,3 +54,40 @@ pub async fn distribute_eth(
futures::future::join_all(pending_txs).await;
Ok(())
}

abigen!(
TokenContract,
r"[
function mint(address to, uint256 amount)
]"
);

pub async fn mint_token(
main_wallet: Wallet,
token_address: Address,
addresses: Vec<Address>,
l1_rpc: String,
chain_id: u64,
amount: u128,
) -> anyhow::Result<()> {
let client = Arc::new(create_ethers_client(
main_wallet.private_key.unwrap(),
l1_rpc,
Some(chain_id),
)?);

let contract = TokenContract::new(token_address, client);
// contract
for address in addresses {
contract
.mint(address, amount.into())
.send()
.await?
// It's safe to set such low number of confirmations and low interval for localhost
.confirmations(1)
.interval(Duration::from_millis(30))
.await?;
}

Ok(())
}
14 changes: 11 additions & 3 deletions zk_toolbox/crates/config/src/ecosystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ use zksync_basic_types::L2ChainId;
use crate::{
consts::{
CONFIGS_PATH, CONFIG_NAME, CONTRACTS_FILE, ECOSYSTEM_PATH, ERA_CHAIN_ID,
ERC20_DEPLOYMENT_FILE, INITIAL_DEPLOYMENT_FILE, L1_CONTRACTS_FOUNDRY, LOCAL_DB_PATH,
WALLETS_FILE,
ERC20_CONFIGS_FILE, ERC20_DEPLOYMENT_FILE, INITIAL_DEPLOYMENT_FILE, L1_CONTRACTS_FOUNDRY,
LOCAL_DB_PATH, WALLETS_FILE,
},
create_localhost_wallets,
forge_interface::deploy_ecosystem::input::{Erc20DeploymentConfig, InitialDeploymentConfig},
forge_interface::deploy_ecosystem::{
input::{Erc20DeploymentConfig, InitialDeploymentConfig},
output::{ERC20Tokens, Erc20Token},
},
traits::{FileConfigWithDefaultName, ReadConfig, SaveConfig, ZkToolboxConfig},
ChainConfig, ChainConfigInternal, ContractsConfig, WalletsConfig,
};
Expand Down Expand Up @@ -169,6 +172,11 @@ impl EcosystemConfig {
pub fn get_erc20_deployment_config(&self) -> anyhow::Result<Erc20DeploymentConfig> {
Erc20DeploymentConfig::read(self.get_shell(), self.config.join(ERC20_DEPLOYMENT_FILE))
}
pub fn get_erc20_tokens(&self) -> Vec<Erc20Token> {
ERC20Tokens::read(self.get_shell(), self.config.join(ERC20_CONFIGS_FILE))
.map(|tokens| tokens.tokens.values().cloned().collect())
.unwrap_or_default()
}

pub fn get_wallets(&self) -> anyhow::Result<WalletsConfig> {
let path = self.config.join(WALLETS_FILE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,6 @@ impl Default for Erc20DeploymentConfig {
implementation: String::from("TestnetERC20Token.sol"),
mint: U256::from_str("9000000000000000000000").unwrap(),
},
Erc20DeploymentTokensConfig {
name: String::from("Wrapped Ether"),
symbol: String::from("WETH"),
decimals: 18,
implementation: String::from("WETH9.sol"),
mint: U256::zero(),
},
],
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ pub struct L1StateTransitionOutput {
}

#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct TokenDeployErc20Output {
pub struct Erc20Token {
pub address: Address,
pub name: String,
pub symbol: String,
Expand All @@ -89,12 +89,12 @@ pub struct TokenDeployErc20Output {
}

#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct DeployErc20Output {
pub tokens: HashMap<String, TokenDeployErc20Output>,
pub struct ERC20Tokens {
pub tokens: HashMap<String, Erc20Token>,
}

impl FileConfigWithDefaultName for DeployErc20Output {
impl FileConfigWithDefaultName for ERC20Tokens {
const FILE_NAME: &'static str = ERC20_CONFIGS_FILE;
}

impl ZkToolboxConfig for DeployErc20Output {}
impl ZkToolboxConfig for ERC20Tokens {}
6 changes: 6 additions & 0 deletions zk_toolbox/crates/config/src/general.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::{
pub struct RocksDbs {
pub state_keeper: PathBuf,
pub merkle_tree: PathBuf,
pub protective_reads: PathBuf,
}

pub fn set_rocks_db_config(config: &mut GeneralConfig, rocks_dbs: RocksDbs) -> anyhow::Result<()> {
Expand All @@ -28,6 +29,11 @@ pub fn set_rocks_db_config(config: &mut GeneralConfig, rocks_dbs: RocksDbs) -> a
.context("DB config is not presented")?
.merkle_tree
.path = rocks_dbs.merkle_tree.to_str().unwrap().to_string();
config
.protective_reads_writer_config
.as_mut()
.context("Protective reads config is not presented")?
.db_path = rocks_dbs.protective_reads.to_str().unwrap().to_string();
Ok(())
}

Expand Down
2 changes: 1 addition & 1 deletion zk_toolbox/crates/types/src/base_token.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use ethers::types::Address;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone)]
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct BaseToken {
pub address: Address,
pub nominator: u64,
Expand Down
26 changes: 19 additions & 7 deletions zk_toolbox/crates/zk_inception/src/commands/chain/args/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::{path::PathBuf, str::FromStr};
use anyhow::{bail, Context};
use clap::{Parser, ValueEnum};
use common::{Prompt, PromptConfirm, PromptSelect};
use config::forge_interface::deploy_ecosystem::output::Erc20Token;
use serde::{Deserialize, Serialize};
use slugify_rs::slugify;
use strum::{Display, EnumIter, IntoEnumIterator};
Expand Down Expand Up @@ -71,6 +72,7 @@ impl ChainCreateArgs {
self,
number_of_chains: u32,
l1_network: &L1Network,
possible_erc20: Vec<Erc20Token>,
) -> anyhow::Result<ChainCreateArgsFinal> {
let mut chain_name = self
.chain_name
Expand Down Expand Up @@ -151,14 +153,24 @@ impl ChainCreateArgs {
&& self.base_token_price_denominator.is_none()
&& self.base_token_price_nominator.is_none()
{
let base_token_selection =
PromptSelect::new(MSG_BASE_TOKEN_SELECTION_PROMPT, BaseTokenSelection::iter())
.ask();
let mut token_selection: Vec<_> =
BaseTokenSelection::iter().map(|a| a.to_string()).collect();

match base_token_selection {
BaseTokenSelection::Eth => BaseToken::eth(),
BaseTokenSelection::Custom => {
let address = Prompt::new(MSG_BASE_TOKEN_ADDRESS_PROMPT).ask();
let erc20_tokens = &mut (possible_erc20
.iter()
.map(|t| format!("{:?}", t.address))
.collect());
token_selection.append(erc20_tokens);
let base_token_selection =
PromptSelect::new(MSG_BASE_TOKEN_SELECTION_PROMPT, token_selection).ask();
match base_token_selection.as_str() {
"Eth" => BaseToken::eth(),
other => {
let address = if other == "Custom" {
Prompt::new(MSG_BASE_TOKEN_ADDRESS_PROMPT).ask()
} else {
H160::from_str(other)?
};
let nominator = Prompt::new(MSG_BASE_TOKEN_PRICE_NOMINATOR_PROMPT)
.validate_with(number_validator)
.ask();
Expand Down
2 changes: 2 additions & 0 deletions zk_toolbox/crates/zk_inception/src/commands/chain/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ fn create(
ecosystem_config: &mut EcosystemConfig,
shell: &Shell,
) -> anyhow::Result<()> {
let tokens = ecosystem_config.get_erc20_tokens();
let args = args
.fill_values_with_prompt(
ecosystem_config.list_of_chains().len() as u32,
&ecosystem_config.l1_network,
tokens,
)
.context(MSG_ARGS_VALIDATOR_ERR)?;

Expand Down
78 changes: 70 additions & 8 deletions zk_toolbox/crates/zk_inception/src/commands/chain/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use config::{
traits::{ReadConfig, SaveConfig, SaveConfigWithBasePath},
update_from_chain_config, ChainConfig, ContractsConfig, EcosystemConfig,
};
use types::{BaseToken, L1Network, WalletCreation};
use xshell::Shell;

use crate::{
Expand All @@ -24,10 +25,11 @@ use crate::{
deploy_l2_contracts, deploy_paymaster,
genesis::genesis,
},
consts::AMOUNT_FOR_DISTRIBUTION_TO_WALLETS,
messages::{
msg_initializing_chain, MSG_ACCEPTING_ADMIN_SPINNER, MSG_CHAIN_INITIALIZED,
MSG_CHAIN_NOT_FOUND_ERR, MSG_GENESIS_DATABASE_ERR, MSG_REGISTERING_CHAIN_SPINNER,
MSG_SELECTED_CONFIG,
MSG_CHAIN_NOT_FOUND_ERR, MSG_DISTRIBUTING_ETH_SPINNER, MSG_GENESIS_DATABASE_ERR,
MSG_MINT_BASE_TOKEN_SPINNER, MSG_REGISTERING_CHAIN_SPINNER, MSG_SELECTED_CONFIG,
},
utils::forge::{check_the_balance, fill_forge_private_key},
};
Expand Down Expand Up @@ -67,12 +69,9 @@ pub async fn init(
contracts_config.l1.base_token_addr = chain_config.base_token.address;
contracts_config.save_with_base_path(shell, &chain_config.configs)?;

crate::commands::ecosystem::init::distribute_eth(
ecosystem_config,
chain_config,
init_args.l1_rpc_url.clone(),
)
.await?;
distribute_eth(ecosystem_config, chain_config, init_args.l1_rpc_url.clone()).await?;
mint_base_token(ecosystem_config, chain_config, init_args.l1_rpc_url.clone()).await?;

let mut secrets = chain_config.get_secrets_config()?;
set_l1_rpc_url(&mut secrets, init_args.l1_rpc_url.clone())?;
secrets.save_with_base_path(shell, &chain_config.configs)?;
Expand Down Expand Up @@ -160,3 +159,66 @@ async fn register_chain(
contracts.set_chain_contracts(&register_chain_output);
Ok(())
}

// Distribute eth to the chain wallets for localhost environment
pub async fn distribute_eth(
ecosystem_config: &EcosystemConfig,
chain_config: &ChainConfig,
l1_rpc_url: String,
) -> anyhow::Result<()> {
if chain_config.wallet_creation == WalletCreation::Localhost
&& ecosystem_config.l1_network == L1Network::Localhost
{
let spinner = Spinner::new(MSG_DISTRIBUTING_ETH_SPINNER);
let wallets = ecosystem_config.get_wallets()?;
let chain_wallets = chain_config.get_wallets_config()?;
let mut addresses = vec![
chain_wallets.operator.address,
chain_wallets.blob_operator.address,
chain_wallets.governor.address,
];
if let Some(deployer) = chain_wallets.deployer {
addresses.push(deployer.address)
}
common::ethereum::distribute_eth(
wallets.operator,
addresses,
l1_rpc_url,
ecosystem_config.l1_network.chain_id(),
AMOUNT_FOR_DISTRIBUTION_TO_WALLETS,
)
.await?;
spinner.finish();
}
Ok(())
}

pub async fn mint_base_token(
ecosystem_config: &EcosystemConfig,
chain_config: &ChainConfig,
l1_rpc_url: String,
) -> anyhow::Result<()> {
if chain_config.wallet_creation == WalletCreation::Localhost
&& ecosystem_config.l1_network == L1Network::Localhost
&& chain_config.base_token != BaseToken::eth()
{
let spinner = Spinner::new(MSG_MINT_BASE_TOKEN_SPINNER);
let wallets = ecosystem_config.get_wallets()?;
let chain_wallets = chain_config.get_wallets_config()?;
let base_token = &chain_config.base_token;
let addresses = vec![wallets.governor.address, chain_wallets.governor.address];
let amount = AMOUNT_FOR_DISTRIBUTION_TO_WALLETS * base_token.nominator as u128
/ base_token.denominator as u128;
common::ethereum::mint_token(
wallets.operator,
base_token.address,
addresses,
l1_rpc_url,
ecosystem_config.l1_network.chain_id(),
amount,
)
.await?;
spinner.finish();
}
Ok(())
}
Loading
Loading