Skip to content

Commit

Permalink
Merge pull request #678 from matter-labs/zk-sync-main-dev
Browse files Browse the repository at this point in the history
Merge Main into Dev
  • Loading branch information
StanislavBreadless authored Aug 6, 2024
2 parents bc98e4b + c808b1f commit 5b8d6ae
Show file tree
Hide file tree
Showing 14 changed files with 318 additions and 52 deletions.
2 changes: 2 additions & 0 deletions CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
* @vladbochok @StanislavBreadless
l1-contracts/deploy-scripts @Deniallugo
l1-contracts/deploy-script-config-template @Deniallugo
6 changes: 2 additions & 4 deletions gas-bound-caller/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,10 @@ If the call to the `_to` address succeeds, the `GasBoundCaller` will ensure that

Summing up the information from the previous chapter, the `GasBoundCaller` should be used in the following way:

TODO(EVM-585): switch `addr` with address.

```solidity
uint256 computeGasBefore = gasleft();
(bool success, bytes memory returnData) = address(this).call{gas: _gasToPass}(abi.encodeWithSelector(GasBoundCaller.gasBoundCall.selector, _to, _maxTotalGas, _data));
(bool success, bytes memory returnData) = address(0xc706EC7dfA5D4Dc87f29f859094165E8290530f5).call{gas: _gasToPass}(abi.encodeWithSelector(GasBoundCaller.gasBoundCall.selector, _to, _maxTotalGas, _data));
uint256 pubdataGasSpent;
if (success) {
Expand All @@ -48,4 +46,4 @@ Since `GasBoundCaller` would be the contract that calls the `_to` contract, the

It should be deployed via a built-in CREATE2 factory on each individual chain.

TODO(EVM-585)
The current address on both sepolia testnet and mainnet for zkSync Era is `0xc706EC7dfA5D4Dc87f29f859094165E8290530f5`.
2 changes: 1 addition & 1 deletion gas-bound-caller/canonical-bytecodes/GasBoundCaller

Large diffs are not rendered by default.

33 changes: 16 additions & 17 deletions gas-bound-caller/hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,15 @@
import "@matterlabs/hardhat-zksync-chai-matchers";
import "@matterlabs/hardhat-zksync-node";
import "@matterlabs/hardhat-zksync-solc";
import "@matterlabs/hardhat-zksync-verify";
import "@nomiclabs/hardhat-ethers";
import "hardhat-typechain";

// This version of system contracts requires a pre release of the compiler
const COMPILER_VERSION = "1.5.0";
const PRE_RELEASE_VERSION = "prerelease-a167aa3-code4rena";
function getZksolcUrl(): string {
// @ts-ignore
const platform = { darwin: "macosx", linux: "linux", win32: "windows" }[process.platform];
// @ts-ignore
const toolchain = { linux: "-musl", win32: "-gnu", darwin: "" }[process.platform];
const arch = process.arch === "x64" ? "amd64" : process.arch;
const ext = process.platform === "win32" ? ".exe" : "";

return `https://github.com/matter-labs/era-compiler-solidity/releases/download/${PRE_RELEASE_VERSION}/zksolc-${platform}-${arch}${toolchain}-v${COMPILER_VERSION}${ext}`;
}

console.log(`Using zksolc from ${getZksolcUrl()}`);

export default {
zksolc: {
version: "1.5.0",
compilerSource: "binary",
settings: {
compilerPath: getZksolcUrl(),
isSystem: true,
},
},
Expand Down Expand Up @@ -55,6 +40,20 @@ export default {
ethNetwork: "localhost",
zksync: true,
},
zkSyncTestnet: {
url: "https://sepolia.era.zksync.dev",
ethNetwork: "sepolia",
zksync: true,
// contract verification endpoint
verifyURL: "https://explorer.sepolia.era.zksync.dev/contract_verification",
},
zkSyncMainnet: {
url: "https://mainnet.era.zksync.io",
ethNetwork: "mainnet",
zksync: true,
// contract verification endpoint
verifyURL: "https://zksync2-mainnet-explorer.zksync.io/contract_verification",
},
},
paths: {
sources: "./contracts",
Expand Down
3 changes: 3 additions & 0 deletions gas-bound-caller/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"devDependencies": {
"@matterlabs/hardhat-zksync-chai-matchers": "^0.2.0",
"@matterlabs/hardhat-zksync-node": "^0.0.1-beta.7",
"@matterlabs/hardhat-zksync-verify": "0.6.1",
"@nomicfoundation/hardhat-chai-matchers": "^1.0.3",
"@nomiclabs/hardhat-ethers": "^2.0.0",
"@typechain/ethers-v5": "^2.0.0",
Expand Down Expand Up @@ -53,6 +54,8 @@
"clean": "yarn clean:bootloader && yarn clean:system-contracts",
"test": "yarn build && hardhat test --network zkSyncTestNode",
"test-node": "hardhat node-zksync --tag v0.0.1-vm1.5.0",
"check-canonical-bytecode": "ts-node ./scripts/check-canonical-bytecode.ts",
"verify": "hardhat run scripts/verify.ts",
"deploy-on-hyperchain": "ts-node ./scripts/deploy-on-hyperchain.ts",
"deploy-on-localhost": "hardhat deploy --network localhost"
}
Expand Down
31 changes: 31 additions & 0 deletions gas-bound-caller/scripts/verify.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// hardhat import should be the first import in the file
import * as hardhat from "hardhat";

const EXPECTED_ADDRESS = "0xc706EC7dfA5D4Dc87f29f859094165E8290530f5";

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function verifyPromise(address: string, constructorArguments?: Array<any>, libraries?: object): Promise<any> {
return new Promise((resolve, reject) => {
hardhat
.run("verify:verify", { address, constructorArguments, libraries })
.then(() => resolve(`Successfully verified ${address}`))
.catch((e) => reject(`Failed to verify ${address}\nError: ${e.message}`));
});
}

async function main() {
if (process.env.CHAIN_ETH_NETWORK == "localhost") {
console.log("Skip contract verification on localhost");
return;
}

const message = await verifyPromise(EXPECTED_ADDRESS);
console.log(message.status == "fulfilled" ? message.value : message.reason);
}

main()
.then(() => process.exit(0))
.catch((err) => {
console.error("Error:", err.message || err);
process.exit(1);
});
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
additional_addresses_for_minting = []

[tokens.DAI]
name = "DAI"
symbol = "DAI"
Expand Down
20 changes: 8 additions & 12 deletions l1-contracts/deploy-scripts/AcceptAdmin.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
pragma solidity ^0.8.0;

import {Script} from "forge-std/Script.sol";
import {stdToml} from "forge-std/StdToml.sol";

import {Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol";
import {IZkSyncHyperchain} from "contracts/state-transition/chain-interfaces/IZkSyncHyperchain.sol";
Expand All @@ -27,28 +26,25 @@ contract AcceptAdmin is Script {
}

// This function should be called by the owner to accept the admin role
function acceptOwner() public {
initConfig();

Ownable2Step adminContract = Ownable2Step(config.admin);
function acceptOwner(address governor, address target) public {
Ownable2Step adminContract = Ownable2Step(target);
Utils.executeUpgrade({
_governor: config.governor,
_governor: governor,
_salt: bytes32(0),
_target: config.admin,
_target: target,
_data: abi.encodeCall(adminContract.acceptOwnership, ()),
_value: 0,
_delay: 0
});
}

// This function should be called by the owner to accept the admin role
function acceptAdmin() public {
initConfig();
IZkSyncHyperchain adminContract = IZkSyncHyperchain(config.admin);
function acceptAdmin(address governor, address target) public {
IZkSyncHyperchain adminContract = IZkSyncHyperchain(target);
Utils.executeUpgrade({
_governor: config.governor,
_governor: governor,
_salt: bytes32(0),
_target: config.admin,
_target: target,
_data: abi.encodeCall(adminContract.acceptAdmin, ()),
_value: 0,
_delay: 0
Expand Down
29 changes: 20 additions & 9 deletions l1-contracts/deploy-scripts/DeployErc20.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ pragma solidity 0.8.24;
import {Script, console2 as console} from "forge-std/Script.sol";
import {stdToml} from "forge-std/StdToml.sol";

// It's required to disable lints to force the compiler to compile the contracts
// solhint-disable no-unused-import
import {TestnetERC20Token} from "contracts/dev-contracts/TestnetERC20Token.sol";
// solhint-disable no-unused-import
import {WETH9} from "contracts/dev-contracts/WETH9.sol";

import {Utils} from "./Utils.sol";
import {MintFailed} from "./ZkSyncScriptErrors.sol";

Expand All @@ -15,6 +21,7 @@ contract DeployErc20Script is Script {
struct Config {
TokenDescription[] tokens;
address deployerAddress;
address[] additionalAddressesForMinting;
address create2FactoryAddr;
bytes32 create2FactorySalt;
}
Expand Down Expand Up @@ -56,6 +63,7 @@ contract DeployErc20Script is Script {
// Grab config from custom config file
path = string.concat(root, "/script-config/config-deploy-erc20.toml");
toml = vm.readFile(path);
config.additionalAddressesForMinting = vm.parseTomlAddressArray(toml, "$.additional_addresses_for_minting");

string[] memory tokens = vm.parseTomlKeys(toml, "$.tokens");

Expand All @@ -68,7 +76,6 @@ contract DeployErc20Script is Script {
token.decimals = toml.readUint(string.concat(key, ".decimals"));
token.implementation = toml.readString(string.concat(key, ".implementation"));
token.mint = toml.readUint(string.concat(key, ".mint"));

config.tokens.push(token);
}
}
Expand All @@ -83,7 +90,8 @@ contract DeployErc20Script is Script {
symbol: token.symbol,
decimals: token.decimals,
implementation: token.implementation,
mint: token.mint
mint: token.mint,
additionalAddressesForMinting: config.additionalAddressesForMinting
});
console.log("Token deployed at:", tokenAddress);
token.addr = tokenAddress;
Expand All @@ -95,7 +103,8 @@ contract DeployErc20Script is Script {
string memory symbol,
uint256 decimals,
string memory implementation,
uint256 mint
uint256 mint,
address[] storage additionalAddressesForMinting
) internal returns (address) {
bytes memory args;
// WETH9 constructor has no arguments
Expand All @@ -109,11 +118,13 @@ contract DeployErc20Script is Script {

if (mint > 0) {
vm.broadcast();
(bool success, ) = tokenAddress.call(
abi.encodeWithSignature("mint(address,uint256)", config.deployerAddress, mint)
);
if (!success) {
revert MintFailed();
additionalAddressesForMinting.push(config.deployerAddress);
for (uint256 i = 0; i < additionalAddressesForMinting.length; i++) {

Check failure on line 122 in l1-contracts/deploy-scripts/DeployErc20.s.sol

View workflow job for this annotation

GitHub Actions / lint

GC: Found [ .length ] property in Loop condition. Suggestion: assign it to a variable

Check failure on line 122 in l1-contracts/deploy-scripts/DeployErc20.s.sol

View workflow job for this annotation

GitHub Actions / lint

GC: For [ i ] variable, increment/decrement by 1 using: [ ++variable ] to save gas

Check failure on line 122 in l1-contracts/deploy-scripts/DeployErc20.s.sol

View workflow job for this annotation

GitHub Actions / lint

GC: Found [ .length ] property in Loop condition. Suggestion: assign it to a variable

Check failure on line 122 in l1-contracts/deploy-scripts/DeployErc20.s.sol

View workflow job for this annotation

GitHub Actions / lint

GC: For [ i ] variable, increment/decrement by 1 using: [ ++variable ] to save gas

Check failure on line 122 in l1-contracts/deploy-scripts/DeployErc20.s.sol

View workflow job for this annotation

GitHub Actions / lint

GC: Found [ .length ] property in Loop condition. Suggestion: assign it to a variable

Check failure on line 122 in l1-contracts/deploy-scripts/DeployErc20.s.sol

View workflow job for this annotation

GitHub Actions / lint

GC: For [ i ] variable, increment/decrement by 1 using: [ ++variable ] to save gas
(bool success, ) = tokenAddress.call(
abi.encodeWithSignature("mint(address,uint256)", additionalAddressesForMinting[i], mint)
);
require(success, "Mint failed");

Check failure on line 126 in l1-contracts/deploy-scripts/DeployErc20.s.sol

View workflow job for this annotation

GitHub Actions / lint

GC: Use Custom Errors instead of require statements

Check failure on line 126 in l1-contracts/deploy-scripts/DeployErc20.s.sol

View workflow job for this annotation

GitHub Actions / lint

GC: Use Custom Errors instead of require statements

Check failure on line 126 in l1-contracts/deploy-scripts/DeployErc20.s.sol

View workflow job for this annotation

GitHub Actions / lint

GC: Use Custom Errors instead of require statements
console.log("Minting to:", additionalAddressesForMinting[i]);
}
}

Expand All @@ -129,7 +140,7 @@ contract DeployErc20Script is Script {
vm.serializeString(token.symbol, "symbol", token.symbol);
vm.serializeUint(token.symbol, "decimals", token.decimals);
vm.serializeString(token.symbol, "implementation", token.implementation);
vm.serializeUint(token.symbol, "mint", token.mint);
vm.serializeUintToHex(token.symbol, "mint", token.mint);
string memory tokenInfo = vm.serializeAddress(token.symbol, "address", token.addr);

tokens = vm.serializeString("tokens", token.symbol, tokenInfo);
Expand Down
16 changes: 13 additions & 3 deletions system-contracts/hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import "@matterlabs/hardhat-zksync-chai-matchers";
import "@matterlabs/hardhat-zksync-node";
import "@matterlabs/hardhat-zksync-solc";
import "@matterlabs/hardhat-zksync-verify";
import "@nomiclabs/hardhat-ethers";
import "hardhat-typechain";

Expand Down Expand Up @@ -50,6 +51,18 @@ export default {
hardhat: {
zksync: true,
},
mainnet: {
url: "https://mainnet.era.zksync.io",
ethNetwork: "mainnet",
zksync: true,
verifyURL: "https://mainnet.zksync.io/contract_verification",
},
sepolia: {
url: "https://sepolia.era.zksync.dev",
ethNetwork: "sepolia",
zksync: true,
verifyURL: "https://sepolia.zksync.io/contract_verification",
},
zkSyncTestNode: {
url: "http://127.0.0.1:8011",
ethNetwork: "localhost",
Expand All @@ -60,9 +73,6 @@ export default {
ethNetwork: "sepolia",
zksync: true,
},
sepolia: {
url: "", // add your sepolia node url
},
},
paths: {
sources: "./contracts-preprocessed",
Expand Down
4 changes: 3 additions & 1 deletion system-contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"dependencies": {
"@matterlabs/hardhat-zksync-deploy": "^0.7.0",
"@matterlabs/hardhat-zksync-solc": "^1.1.4",
"@matterlabs/hardhat-zksync-verify": "^1.4.3",
"commander": "^9.4.1",
"eslint": "^8.51.0",
"eslint-plugin-import": "^2.29.0",
Expand Down Expand Up @@ -61,7 +62,8 @@
"compile-zasm": "ts-node scripts/compile-zasm.ts",
"deploy-preimages": "ts-node scripts/deploy-preimages.ts",
"preprocess:bootloader": "rm -rf ./bootloader/build && yarn ts-node scripts/preprocess-bootloader.ts",
"preprocess:system-contracts": "ts-node scripts/preprocess-system-contracts.ts",
"preprocess:system-contracts": "rm -rf ./contracts-preprocessed && ts-node scripts/preprocess-system-contracts.ts",
"verify-on-explorer": "hardhat run scripts/verify-on-explorer.ts",
"test": "yarn build:test-system-contracts && hardhat test --network zkSyncTestNode",
"test-node": "hardhat node-zksync --tag v0.0.1-vm1.5.0",
"test:bootloader": "cd bootloader/test_infra && cargo run"
Expand Down
46 changes: 46 additions & 0 deletions system-contracts/scripts/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import path from "path";
import { spawn as _spawn } from "child_process";
import { createHash } from "crypto";
import { CompilerDownloader } from "hardhat/internal/solidity/compiler/downloader";
import fetch from "node-fetch";

export type HttpMethod = "POST" | "GET";

export interface Dependency {
name: string;
Expand Down Expand Up @@ -326,3 +329,46 @@ export async function isFolderEmpty(folderPath: string): Promise<boolean> {
return true; // Return true if an error, as folder doesn't exist.
}
}
/**
* Performs an API call to the Contract verification API.
*
* @param endpoint API endpoint to call.
* @param queryParams Parameters for a query string.
* @param requestBody Request body. If provided, a POST request would be met and body would be encoded to JSON.
* @returns API response parsed as a JSON.
*/
export async function query(
method: HttpMethod,
endpoint: string,
queryParams?: { [key: string]: string },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
requestBody?: any
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): Promise<any> {
const url = new URL(endpoint);
// Iterate through query params and add them to URL.
if (queryParams) {
Object.entries(queryParams).forEach(([key, value]) => url.searchParams.set(key, value));
}

const init = {
method,
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(requestBody),
};
if (requestBody) {
init.body = JSON.stringify(requestBody);
}

const response = await fetch(url, init);
try {
return await response.json();
} catch (e) {
throw {
error: "Could not decode JSON in response",
status: `${response.status} ${response.statusText}`,
};
}
}
Loading

0 comments on commit 5b8d6ae

Please sign in to comment.