Skip to content

Commit

Permalink
Merge pull request #14 from matter-labs/anastasiia-add-watchdog-address
Browse files Browse the repository at this point in the history
[don't merge] Support Watchdog top up on L2
  • Loading branch information
AnastasiiaVashchuk authored Jun 7, 2023
2 parents 1c890d4 + bb2fb27 commit 0dac520
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 12 deletions.
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ RUN yarn install
# ENV UPPER_BOUND_WITHDRAWER_THRESHOLD
# ENV NOTIFICATION_WEBHOOK_URL
# optional env
# ENV ETH_TRANSFER_THRESHOLD
# ENV L1_ETH_TRANSFER_THRESHOLD
# ENV L2_ETH_TRANSFER_THRESHOLD
CMD ["yarn", "start"]
61 changes: 50 additions & 11 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const OPERATOR_ADDRESS = process.env.OPERATOR_ADDRESS;
const WITHDRAWAL_FINALIZER_ETH_ADDRESS = process.env.WITHDRAWAL_FINALIZER_ETH_ADDRESS;
const RESERVE_FEE_ACCUMULATOR_ADDRESS = process.env.MISC_RESERVE_FEE_ACCUMULATOR_ADDRESS;
const TESTNET_PAYMASTER_ADDRESS = process.env.CONTRACTS_L2_TESTNET_PAYMASTER_ADDR;
const WATCHDOG_ADDRESS = process.env.WATCHDOG_ADDRESS;

/** API URLs */
const L1_WEB3_API_URL = process.env.L1_RPC_ADDRESS;
Expand All @@ -31,6 +32,9 @@ const UPPER_BOUND_WITHDRAWER_THRESHOLD = ethers.utils.parseEther(process.env.UPP
const LOWER_BOUND_PAYMASTER_THRESHOLD = ethers.utils.parseEther(process.env.LOWER_BOUND_PAYMASTER_THRESHOLD);
const UPPER_BOUND_PAYMASTER_THRESHOLD = ethers.utils.parseEther(process.env.UPPER_BOUND_PAYMASTER_THRESHOLD);

const LOWER_BOUND_WATCHDOG_THRESHOLD = ethers.utils.parseEther(process.env.LOWER_BOUND_WATCHDOG_THRESHOLD);
const UPPER_BOUND_WATCHDOG_THRESHOLD = ethers.utils.parseEther(process.env.UPPER_BOUND_WATCHDOG_THRESHOLD);

const L1_ETH_TRANSFER_THRESHOLD = process.env.L1_ETH_TRANSFER_THRESHOLD
? ethers.utils.parseEther(process.env.L1_ETH_TRANSFER_THRESHOLD)
: ethers.utils.parseEther('3.0');
Expand Down Expand Up @@ -86,13 +90,13 @@ async function withdrawForL1TopUps(wallet: zkweb3.Wallet) {
}
}

async function topUpPaymaster(wallet: zkweb3.Wallet, amount: BigNumber) {
async function L2topUp(wallet: zkweb3.Wallet, amount: BigNumber, l2AccountAddress: string, l2AccountName: string) {
// Estimate withdrawal fee.
const tx = await wallet.provider.getTransferTx({
token: zkweb3.utils.ETH_ADDRESS,
amount,
from: wallet.address,
to: TESTNET_PAYMASTER_ADDRESS
to: l2AccountAddress
});
const gasLimit = (await wallet.provider.estimateGas(tx)).mul(2);
const gasPrice = await wallet.provider.getGasPrice();
Expand All @@ -101,23 +105,23 @@ async function topUpPaymaster(wallet: zkweb3.Wallet, amount: BigNumber) {
const transferHandle = await wallet.transfer({
token: zkweb3.utils.ETH_ADDRESS,
amount,
to: TESTNET_PAYMASTER_ADDRESS,
to: l2AccountAddress,
overrides: {
gasPrice,
gasLimit
}
});
const hash = transferHandle.hash;
console.log(
`ETH transfer to paymaster, amount: ${ethers.utils.formatEther(amount)}, fee: ${ethers.utils.formatEther(
`ETH transfer to ${l2AccountName}, amount: ${ethers.utils.formatEther(amount)}, fee: ${ethers.utils.formatEther(
fee
)}, tx hash: ${hash}`
);

await transferHandle.wait();
console.log(`Transfer to paymaster has succeeded, tx hash: ${hash}`);
console.log(`Transfer to ${l2AccountName} has succeeded, tx hash: ${hash}`);
} else {
console.log('Skipping transfering, fee slippage is too big');
console.log(`Skipping transferring to ${l2AccountName}, fee slippage is too big`);
}
}

Expand Down Expand Up @@ -183,6 +187,7 @@ async function sendETH(ethWallet: ethers.Wallet, to: string, amount: BigNumber)
throw new Error('Testnet paymaster should not be present on mainnet deployments');
}

console.log(`----------------------------------------------------------------------------`);
// get initial balances
let l1feeAccountBalance = await ethProvider.getBalance(wallet.address);
console.log(`Fee account L1 balance before top-up: ${ethers.utils.formatEther(l1feeAccountBalance)}`);
Expand All @@ -201,6 +206,11 @@ async function sendETH(ethWallet: ethers.Wallet, to: string, amount: BigNumber)
: BigNumber.from(0);
console.log(`Paymaster L2 balance before top-up: ${ethers.utils.formatEther(paymasterL2Balance)}`);

const watchdogBalance = await zksyncProvider.getBalance(WATCHDOG_ADDRESS);
console.log(`Watchdog L2 balance before top-up: ${ethers.utils.formatEther(watchdogBalance)}`);

console.log(`----------------------------------------------------------------------------`);

let transferAmount;

// calculate amounts for top ups on L2
Expand All @@ -220,10 +230,33 @@ async function sendETH(ethWallet: ethers.Wallet, to: string, amount: BigNumber)
);

console.log('Step 1 - send ETH to paymaster');
await topUpPaymaster(wallet, transferAmount);
await L2topUp(wallet, transferAmount, TESTNET_PAYMASTER_ADDRESS, 'paymaster');
}

console.log('Step 2 - withdrawing tokens from ZkSync');
console.log(`----------------------------------------------------------------------------`);

if (!WATCHDOG_ADDRESS) {
console.log('Skipping step 2 -- send ETH to era-watchdog');
} else {
[transferAmount, l2feeAccountBalance] = await calculateTransferAmount(
l2feeAccountBalance,
watchdogBalance,
UPPER_BOUND_WATCHDOG_THRESHOLD,
LOWER_BOUND_WATCHDOG_THRESHOLD,
L2_ETH_TRANSFER_THRESHOLD
);
console.log(
`Amount which fee account can send to era-watchdog: ${ethers.utils.formatEther(transferAmount)} ETH;
fee account l2 balance in this case will be ${ethers.utils.formatEther(l2feeAccountBalance)} ETH`
);

console.log('Step 2 - send ETH to era-watchdog');
await L2topUp(wallet, transferAmount, WATCHDOG_ADDRESS, 'watchdog');
}

console.log(`----------------------------------------------------------------------------`);

console.log('Step 3 - withdrawing tokens from ZkSync');
await withdrawForL1TopUps(wallet);

l2feeAccountBalance = await wallet.getBalance(wallet.address);
Expand All @@ -232,6 +265,8 @@ async function sendETH(ethWallet: ethers.Wallet, to: string, amount: BigNumber)
l1feeAccountBalance = await ethProvider.getBalance(wallet.address);
console.log(`L1 fee account balance after withdraw: ${ethers.utils.formatEther(l1feeAccountBalance)} ETH`);

console.log(`----------------------------------------------------------------------------`);

// calculate amounts for top ups on L1
[transferAmount, l1feeAccountBalance] = await calculateTransferAmount(
l1feeAccountBalance,
Expand All @@ -245,9 +280,11 @@ async function sendETH(ethWallet: ethers.Wallet, to: string, amount: BigNumber)
fee account l1 balance in this case will be ${ethers.utils.formatEther(l1feeAccountBalance)} ETH`
);

console.log('Step 3 - send ETH to operator');
console.log('Step 4 - send ETH to operator');
await sendETH(ethWallet, OPERATOR_ADDRESS, transferAmount);

console.log(`----------------------------------------------------------------------------`);

[transferAmount, l1feeAccountBalance] = await calculateTransferAmount(
l1feeAccountBalance,
withdrawerBalance,
Expand All @@ -260,15 +297,17 @@ async function sendETH(ethWallet: ethers.Wallet, to: string, amount: BigNumber)
fee account l1 balance in this case will be ${ethers.utils.formatEther(l1feeAccountBalance)} ETH`
);

console.log('Step 4 - send ETH to withdrawal finalizer');
console.log('Step 5 - send ETH to withdrawal finalizer');
await sendETH(ethWallet, WITHDRAWAL_FINALIZER_ETH_ADDRESS, transferAmount);

console.log(`----------------------------------------------------------------------------`);

transferAmount = l1feeAccountBalance.sub(L1_ETH_TRANSFER_THRESHOLD);
console.log(
`Amount which fee account can send to reserve accumulator: ${ethers.utils.formatEther(transferAmount)} ETH;
fee account l1 balance in this case will be ${ethers.utils.formatEther(L1_ETH_TRANSFER_THRESHOLD)} ETH`
);
console.log('Step 5 - send ETH to reserve address');
console.log('Step 6 - send ETH to reserve address');
await sendETH(ethWallet, RESERVE_FEE_ACCUMULATOR_ADDRESS, transferAmount);
} catch (e) {
console.error('Failed to proceed with fee withdrawal: ', e);
Expand Down

0 comments on commit 0dac520

Please sign in to comment.