Skip to content

Commit

Permalink
feat: refactor forcedExit script
Browse files Browse the repository at this point in the history
  • Loading branch information
franciscotobar committed Oct 6, 2023
1 parent fe61bdd commit 55b391e
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 79 deletions.
2 changes: 1 addition & 1 deletion core/lib/wallet_creator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ zk test i wallet-generator

Or to do it manually:

Navigate to `ri-aggregation/core/lib/wallet_creator` and run:
Navigate to `./core/lib/wallet_creator` and run:

Unit tests

Expand Down
2 changes: 1 addition & 1 deletion infrastructure/zk/src/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ async function createVolumes() {

export const initCommand = new Command('init')
.description('perform zksync network initialization for development')
.option('--no-crypto', 'not include sdk packages')
.option('--no-crypto', 'not include crypto packages')
.option('--with-docker', 'use docker container instead of local environment')
.action(async (cmd: Command) => {
const { crypto, withDocker } = cmd;
Expand Down
129 changes: 129 additions & 0 deletions infrastructure/zk/src/run/forced-exit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import { Command } from 'commander';
import fetch from 'node-fetch';
import * as utils from '../utils';
import { BigNumber, BigNumberish, ethers } from 'ethers';

type State = {
balances: {
[token: string]: BigNumberish;
};
nonce: number;
pubKeyHash: string;
};

type RestAccountState = {
finalized: State | undefined;
};

type RpcAccountState = {
verified: State;
};

async function checkForcedExitSenderAccountBalance(nodeUrl: string, nodeType: 'REST' | 'JSONRPC') {
const forcedExitAccount = process.env.FORCED_EXIT_REQUESTS_SENDER_ACCOUNT_ADDRESS as string;
let state: State | undefined;
if (nodeType === 'REST') {
({ finalized: state } = await processRestRequest(nodeUrl, forcedExitAccount));
} else {
({ verified: state } = await processJsonRpcRequest(nodeUrl, forcedExitAccount));
}

if (!state || state.pubKeyHash === 'sync:0000000000000000000000000000000000000000') {
if (state?.balances['RBTC']) {
const balance = BigNumber.from(state.balances['RBTC']);
if (!balance.isZero()) {
console.log(`Forced exit sender account balance is ${balance.toString()} RBTC`);
console.log('wait until the preparation of the forced exit sender account is completed');
}
}
console.log('Forced exit sender account balance is not ready');
return;
}

console.log('Forced exit sender account balance is ready');
}

async function processRestRequest(nodeUrl: string, forcedExitAccount: string): Promise<RestAccountState> {
const response = await fetch(`${nodeUrl}/accounts/${forcedExitAccount}`);
const { result } = await response.json();

return result;
}

async function processJsonRpcRequest(nodeUrl: string, forcedExitAccount: string): Promise<RpcAccountState> {
const body = {
jsonrpc: '2.0',
method: 'account_info',
params: [forcedExitAccount],
id: 1
};
const response = await fetch(nodeUrl, {
method: 'POST',
body: JSON.stringify(body),
headers: {
Accept: 'application/json',
'Content-type': 'application/json'
}
});
const { result } = await response.json();

return result;
}

async function depositToForcedExitSenderAccount(
l1Address: string,
privateKey: string,
amount: string,
mnemonic: boolean
) {
const forcedExitAccount = process.env.FORCED_EXIT_REQUESTS_SENDER_ACCOUNT_ADDRESS as string;
const provider = new ethers.providers.JsonRpcProvider(
process.env.FORCED_EXIT_REQUESTS_WEB3_URL ?? process.env.ETH_CLIENT_WEB3_URL
);
const wallet = mnemonic
? ethers.Wallet.fromMnemonic(privateKey).connect(provider)
: new ethers.Wallet(privateKey).connect(provider);

if (l1Address.toLowerCase() !== wallet.address.toLowerCase()) {
console.log('L1 address does not match the provided private key or mnemonic');
return;
}

const mainZkSyncContract = new ethers.Contract(
process.env.CONTRACTS_CONTRACT_ADDR as string,
await utils.readZkSyncAbi(),
wallet
);

const depositTransaction = (await mainZkSyncContract.depositRBTC(forcedExitAccount, {
value: ethers.utils.parseEther(amount)
})) as ethers.ContractTransaction;

await depositTransaction.wait();

console.log('Deposit to the forced exit sender account has been successfully completed');
}

export const command = new Command('forced-exit').description('prepare forced exit sender account');

command
.command('check')
.description('check forced exit sender account balance')
.arguments('<nodeUrl> <nodeType>')
.action(async (nodeUrl: string, nodeType: string) => {
if (nodeType !== 'REST' && nodeType !== 'JSONRPC') {
console.log('Node type must be either REST or JSONRPC');
return;
}
await checkForcedExitSenderAccountBalance(nodeUrl, nodeType);
});

command
.command('prepare')
.description('deposit to forced exit sender account')
.arguments('<l1Address> <privateKey> [amount]')
.option('-m --mnemonic', 'Is mnemonic')
.action(async (l1Address: string, privateKey: string, amount = '0.0001', cmd: Command) => {
const { mnemonic } = cmd;
await depositToForcedExitSenderAccount(l1Address, privateKey, amount, !!mnemonic);
});
12 changes: 7 additions & 5 deletions infrastructure/zk/src/run/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import * as eventListener from './event-listener';
import * as dataRestore from './data-restore';
import * as docker from '../docker';
import * as walletGenerator from './generate-wallet';
import * as forcedExit from './forced-exit';

export { verifyKeys, dataRestore };

Expand Down Expand Up @@ -96,7 +97,7 @@ export async function tokenInfo(address: string) {
}

// installs all dependencies and builds our js packages
export async function yarn(crypto = true) {
export async function yarn(crypto: boolean) {
await utils.spawn('yarn');
if (crypto) {
await utils.spawn('yarn build:crypto');
Expand Down Expand Up @@ -240,17 +241,18 @@ export const command = new Command('run')
.addCommand(verifyKeys.command)
.addCommand(dataRestore.command)
.addCommand(eventListener.command)
.addCommand(walletGenerator.command);
.addCommand(walletGenerator.command)
.addCommand(forcedExit.command);

command.command('test-accounts').description('print rootstock test accounts').action(testAccounts);
command.command('explorer').description('run zksync explorer locally').action(explorer);
command
.command('yarn')
.description('install all JS dependencies')
.option('--no-sdk', 'not include sdk packages')
.option('--no-crypto', 'not include crypto packages')
.action(async (cmd: Command) => {
const { sdk } = cmd;
await yarn(!!sdk);
const { crypto } = cmd;
await yarn(!!crypto);
});
command.command('test-upgrade <main_contract> <gatekeeper_contract>').action(testUpgrade);
command.command('cat-logs [exit_code]').description('print server and prover logs').action(catLogs);
Expand Down
72 changes: 0 additions & 72 deletions infrastructure/zk/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ import fs from 'fs';
import * as db from './db/db';
import * as docker from './docker';

import { ethers } from 'ethers';

export async function core(withDocker = false) {
prepareForcedExitRequestAccount();

if (withDocker) {
await docker.deployUp('server-core');
return;
Expand Down Expand Up @@ -41,11 +37,6 @@ export async function apiNode(withDocker = false) {
}

export async function server(withDocker = false) {
// By the time this function is run the server is most likely not be running yet
// However, it does not matter, since the only thing the function does is depositing
// to the forced exit sender account, and server should be capable of recognizing
// priority operaitons that happened before it was booted
prepareForcedExitRequestAccount();
if (withDocker) {
await docker.deployUp('server');
return;
Expand Down Expand Up @@ -79,64 +70,6 @@ export async function genesis(withDocker = false) {
env.modify_contracts_toml('CONTRACTS_GENESIS_ROOT', genesisRoot);
}

// This functions deposits funds onto the forced exit sender account
// This is needed to make sure that it has the account id
async function prepareForcedExitRequestAccount() {
console.log('Depositing to the forced exit sender account');
const forcedExitAccount = process.env.FORCED_EXIT_REQUESTS_SENDER_ACCOUNT_ADDRESS as string;

const ethProvider = getEthProvider();

// This is the private key of the first test account ()
const ethRichWallet = new ethers.Wallet(
'0x20e4a6381bd3826a14f8da63653d94e7102b38eb5f929c7a94652f41fa7ba323',
ethProvider
);

const gasPrice = await ethProvider.getGasPrice();

const topupTransaction = await ethRichWallet.sendTransaction({
to: forcedExitAccount,
// The amount for deposit should be enough to send at least
// one transaction to retrieve the funds form the forced exit smart contract
value: ethers.utils.parseEther('100.0'),
gasPrice
});

await topupTransaction.wait();

const mainZkSyncContract = new ethers.Contract(
process.env.CONTRACTS_CONTRACT_ADDR as string,
await utils.readZkSyncAbi(),
ethRichWallet
);

const depositTransaction = (await mainZkSyncContract.depositRBTC(forcedExitAccount, {
// Here the amount to deposit does not really matter, as it is done purely
// to guarantee that the account exists in the network
value: ethers.utils.parseEther('1.0'),
gasLimit: ethers.BigNumber.from('200000'),
gasPrice
})) as ethers.ContractTransaction;

await depositTransaction.wait();

console.log('Deposit to the forced exit sender account has been successfully completed');
}

function getEthProvider() {
return new ethers.providers.JsonRpcProvider(
process.env.FORCED_EXIT_REQUESTS_WEB3_URL ?? process.env.ETH_CLIENT_WEB3_URL
);
}

async function testWeb3Network() {
const ethProvider = getEthProvider();

const network = await ethProvider.getNetwork();
console.log(`current network chain id ${network.chainId}`);
}

export const command = new Command('server')
.description('start zksync server')
.option('--genesis', 'generate genesis data via server')
Expand Down Expand Up @@ -178,8 +111,3 @@ command
} = cmd;
await core(withDocker);
});

command
.command('test-web3-network')
.description('test if web3 node can be reached to prepare the forced exit requests account')
.action(testWeb3Network);

0 comments on commit 55b391e

Please sign in to comment.