Skip to content

Commit

Permalink
add deploy erc20 bridge
Browse files Browse the repository at this point in the history
  • Loading branch information
zkbenny committed Feb 11, 2024
1 parent 1aa05f3 commit 718db99
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 5 deletions.
30 changes: 30 additions & 0 deletions contracts/ZkLink.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ import {Merkle} from "./zksync/l1-contracts/zksync/libraries/Merkle.sol";
import {L2Log, L2Message, PubdataPricingMode, FeeParams, SecondaryChainSyncStatus} from "./zksync/l1-contracts/zksync/Storage.sol";
import {REQUIRED_L2_GAS_PRICE_PER_PUBDATA, MAX_NEW_FACTORY_DEPS, L1_GAS_PER_PUBDATA_BYTE, L2_L1_LOGS_TREE_DEFAULT_LEAF_HASH} from "./zksync/l1-contracts/zksync/Config.sol";
import {L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR, L2_BOOTLOADER_ADDRESS} from "./zksync/l1-contracts/common/L2ContractAddresses.sol";
import {IGetters} from "./zksync/l1-contracts/zksync/interfaces/IGetters.sol";

/// @title ZkLink contract
/// @author zk.link
contract ZkLink is
IZkLink,
IMailbox,
IAdmin,
IGetters,
OwnableUpgradeable,
UUPSUpgradeable,
ReentrancyGuardUpgradeable,
Expand Down Expand Up @@ -104,6 +106,34 @@ contract ZkLink is
_unpause();
}

function getGateway() external view returns (IL2Gateway) {
return gateway;
}

function getGovernor() external view returns (address) {
return owner();
}

function getTotalBatchesExecuted() external view returns (uint256) {
return totalBatchesExecuted;
}

function getTotalPriorityTxs() external view returns (uint256) {
return totalPriorityTxs;
}

function isValidator(address _address) external view returns (bool) {
return validators[_address];
}

function l2LogsRootHash(uint256 _batchNumber) external view returns (bytes32 merkleRoot) {
return l2LogsRootHashes[_batchNumber];
}

function getPriorityTxMaxGasLimit() external pure returns (uint256) {
return 72000000;
}

/// @dev Init gateway, can only be called by the owner
function setGateway(IL2Gateway _gateway) external onlyOwner {
require(address(gateway) == address(0), "Duplicate init gateway");
Expand Down
6 changes: 6 additions & 0 deletions contracts/zksync/l1-contracts/zksync/interfaces/IGetters.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ interface IGetters {
/// @return The gateway on local chain
function getGateway() external view returns (IL2Gateway);

/// @return The address of the current governor
function getGovernor() external view returns (address);

/// @return The total number of batches that were committed & verified & executed
function getTotalBatchesExecuted() external view returns (uint256);

Expand All @@ -26,4 +29,7 @@ interface IGetters {

/// @return merkleRoot Merkle root of the tree with L2 logs for the selected batch
function l2LogsRootHash(uint256 _batchNumber) external view returns (bytes32 merkleRoot);

/// @return The maximum number of L2 gas that a user can request for L1 -> L2 transactions
function getPriorityTxMaxGasLimit() external view returns (uint256);
}
2 changes: 1 addition & 1 deletion examples/scroll/scripts/1_initConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,6 @@ task('initConfig', 'Init config')
await zkLink.setGateway(scrollL2GatewayAddr, { gasLimit: 1000000, gasPrice: 100000000 });
console.log(`The zkLink set gateway to ${scrollL2GatewayAddr}`);

const gateway = await zkLink.gateway();
const gateway = await zkLink.getGateway();
console.log(`The gateway address: ${gateway}`);
});
1 change: 1 addition & 0 deletions hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ require('./script/deploy_arbitrator');
require('./script/deploy_l1_gateway');
require('./script/deploy_l2_gateway');
require('./script/deploy_eth_gateway');
require('./script/deploy_erc20_bridge');

const BaseConfig = require('./hardhat.base.config');

Expand Down
86 changes: 86 additions & 0 deletions script/deploy_erc20_bridge.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
const fs = require('fs');
const { getImplementationAddress } = require('@openzeppelin/upgrades-core');
const {
verifyContractCode,
createOrGetDeployLog,
ChainContractDeployer,
getDeployTx,
readDeployLogField,
} = require('./utils');
const logName = require('./deploy_log_name');
const { task, types } = require('hardhat/config');

task('deployERC20Bridge', 'Deploy erc20 bridge')
.addParam('zklink', 'The zklink address (default get from zkLink deploy log)', undefined, types.string, true)
.addParam('force', 'Fore redeploy all contracts', false, types.boolean, true)
.addParam('skipVerify', 'Skip verify', false, types.boolean, true)
.setAction(async (taskArgs, hardhat) => {
let zklinkAddr = taskArgs.zklink;
if (zklinkAddr === undefined) {
zklinkAddr = readDeployLogField(logName.DEPLOY_ZKLINK_LOG_PREFIX, logName.DEPLOY_LOG_ZKLINK_PROXY);
}
let force = taskArgs.force;
let skipVerify = taskArgs.skipVerify;
console.log('zklink', zklinkAddr);
console.log('force redeploy all contracts?', force);
console.log('skip verify contracts?', skipVerify);

const contractDeployer = new ChainContractDeployer(hardhat);
await contractDeployer.init();
const deployerWallet = contractDeployer.deployerWallet;

const { deployLogPath, deployLog } = createOrGetDeployLog(logName.DEPLOY_ERC20_BRIDGE_LOG_PREFIX);
deployLog[logName.DEPLOY_LOG_GOVERNOR] = deployerWallet.address;
fs.writeFileSync(deployLogPath, JSON.stringify(deployLog, null, 2));

let erc20BridgeAddr;
if (!(logName.DEPLOY_ERC20_BRIDGE in deployLog) || force) {
console.log('deploy erc20 bridge...');
const contract = await contractDeployer.deployProxy('L1ERC20Bridge', [], [zklinkAddr], 'transparent', false);
const transaction = await getDeployTx(contract);
erc20BridgeAddr = await contract.getAddress();
deployLog[logName.DEPLOY_ERC20_BRIDGE] = erc20BridgeAddr;
deployLog[logName.DEPLOY_LOG_DEPLOY_TX_HASH] = transaction.hash;
deployLog[logName.DEPLOY_LOG_DEPLOY_BLOCK_NUMBER] = transaction.blockNumber;
fs.writeFileSync(deployLogPath, JSON.stringify(deployLog, null, 2));
} else {
erc20BridgeAddr = deployLog[logName.DEPLOY_ERC20_BRIDGE];
}
console.log('erc20 bridge', erc20BridgeAddr);

let erc20BridgeTargetAddr;
if (!(logName.DEPLOY_ERC20_BRIDGE_TARGET in deployLog) || force) {
console.log('get erc20 bridge target...');
erc20BridgeTargetAddr = await getImplementationAddress(hardhat.ethers.provider, erc20BridgeAddr);
deployLog[logName.DEPLOY_ERC20_BRIDGE_TARGET] = erc20BridgeTargetAddr;
fs.writeFileSync(deployLogPath, JSON.stringify(deployLog, null, 2));
} else {
erc20BridgeTargetAddr = deployLog[logName.DEPLOY_ERC20_BRIDGE_TARGET];
}
console.log('erc20 bridge target', erc20BridgeTargetAddr);

// set allowance
const zkLink = await hardhat.ethers.getContractAt('ZkLink', zklinkAddr);
const isAllow = await zkLink.allowLists(erc20BridgeAddr);
if (!isAllow) {
console.log('set allow for erc20 bridge...');
await zkLink.setAllowList(erc20BridgeAddr, true);
console.log('set allow success');
} else {
console.log('already allowed');
}

// verify target contract
if ((!(logName.DEPLOY_ERC20_BRIDGE_TARGET_VERIFIED in deployLog) || force) && !skipVerify) {
await verifyContractCode(hardhat, erc20BridgeTargetAddr, [zklinkAddr]);
deployLog[logName.DEPLOY_ERC20_BRIDGE_TARGET_VERIFIED] = true;
fs.writeFileSync(deployLogPath, JSON.stringify(deployLog, null, 2));
}

// verify proxy contract
if ((!(logName.DEPLOY_ERC20_BRIDGE_VERIFIED in deployLog) || force) && !skipVerify) {
await verifyContractCode(hardhat, erc20BridgeAddr, []);
deployLog[logName.DEPLOY_ERC20_BRIDGE_VERIFIED] = true;
fs.writeFileSync(deployLogPath, JSON.stringify(deployLog, null, 2));
}
});
12 changes: 12 additions & 0 deletions script/deploy_log_name.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ const DEPLOY_LOG_ZKLINK_PROXY_VERIFIED = 'zkLinkProxyVerified';
const DEPLOY_LOG_DEPLOY_TX_HASH = 'deployTxHash';
const DEPLOY_LOG_DEPLOY_BLOCK_NUMBER = 'deployBlockNumber';

// consumed in deploy_erc20_bridge.js
const DEPLOY_ERC20_BRIDGE_LOG_PREFIX = 'deploy_erc20_bridge';
const DEPLOY_ERC20_BRIDGE = 'erc20Bridge';
const DEPLOY_ERC20_BRIDGE_VERIFIED = 'erc20BridgeVerified';
const DEPLOY_ERC20_BRIDGE_TARGET = 'erc20BridgeTarget';
const DEPLOY_ERC20_BRIDGE_TARGET_VERIFIED = 'erc20BridgeTargetVerified';

// consumed in deploy_l1_gateway.js or deploy_l2_gateway.js or deploy_eth_gateway.js
const DEPLOY_L1_GATEWAY_LOG_PREFIX = 'deploy_l1_gateway';
const DEPLOY_L2_GATEWAY_LOG_PREFIX = 'deploy_l2_gateway';
Expand Down Expand Up @@ -47,4 +54,9 @@ module.exports = {
DEPLOY_LOG_ARBITRATOR_VERIFIED,
DEPLOY_LOG_ARBITRATOR_TARGET,
DEPLOY_LOG_ARBITRATOR_TARGET_VERIFIED,
DEPLOY_ERC20_BRIDGE_LOG_PREFIX,
DEPLOY_ERC20_BRIDGE,
DEPLOY_ERC20_BRIDGE_VERIFIED,
DEPLOY_ERC20_BRIDGE_TARGET,
DEPLOY_ERC20_BRIDGE_TARGET_VERIFIED,
};
2 changes: 1 addition & 1 deletion script/deploy_zklink.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ task('setGateway', 'Set gateway for zkLink').setAction(async (taskArgs, hardhat)
console.log('zkLink', zkLinkAddr);

const zkLink = await hardhat.ethers.getContractAt('ZkLink', zkLinkAddr);
const existGatewayAddr = await zkLink.gateway();
const existGatewayAddr = await zkLink.getGateway();
if (existGatewayAddr !== hardhat.ethers.ZeroAddress) {
console.log('gateway has been set to', existGatewayAddr);
return;
Expand Down
11 changes: 8 additions & 3 deletions script/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,24 +139,29 @@ class ChainContractDeployer {
return contract;
}

async deployProxy(contractName, initArgs, constructorArgs) {
async deployProxy(contractName, initArgs, constructorArgs, kind, initializer) {
if (constructorArgs === undefined) {
constructorArgs = [];
}
if (kind === undefined) {
kind = 'uups';
}
let contract;
if (this.zksync) {
const artifact = await this.zkSyncDeployer.loadArtifact(contractName);
contract = await this.hardhat.zkUpgrades.deployProxy(this.deployerWallet, artifact, initArgs, {
initializer: 'initialize',
kind: kind,
constructorArgs: constructorArgs,
unsafeAllow: ['state-variable-immutable', 'constructor'],
initializer: initializer,
});
} else {
const factory = await this.hardhat.ethers.getContractFactory(contractName, this.deployerWallet);
contract = await this.hardhat.upgrades.deployProxy(factory, initArgs, {
kind: 'uups',
kind: kind,
constructorArgs: constructorArgs,
unsafeAllow: ['state-variable-immutable', 'constructor'],
initializer: initializer,
});
}
await contract.waitForDeployment();
Expand Down
1 change: 1 addition & 0 deletions zksync/hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ if (!fs.existsSync('script')) {

require('./script/deploy_zklink');
require('./script/deploy_l2_gateway');
require('./script/deploy_erc20_bridge');

const BaseConfig = require('../hardhat.base.config');

Expand Down

0 comments on commit 718db99

Please sign in to comment.