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

Script for verification + gas bound caller disclaimer #447

Open
wants to merge 9 commits into
base: release-v23
Choose a base branch
from
Open
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
97 changes: 97 additions & 0 deletions .github/workflows/gas-bound-caller-ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
name: GasBoundCaller CI

on:
pull_request:

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout the repository
uses: actions/checkout@v4

- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: 18.18.0
cache: yarn

- name: Install dependencies
run: yarn

- name: Build L1 artifacts
run: yarn gas-bound-caller build

- name: Check the correcntess of the canonical bytecode
run: yarn gas-bound-caller calculate-canonical-bytecode:check

- name: Create cache
uses: actions/cache/save@v3
with:
key: artifacts-gas-bound-caller-${{ github.sha }}
path: |
gas-bound-caller/artifacts-zk
gas-bound-caller/cache-zk
gas-bound-caller/typechain

lint:
runs-on: ubuntu-latest

steps:
- name: Checkout the repository
uses: actions/checkout@v4

- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: 18.18.0
cache: yarn

- name: Install dependencies
run: yarn

- name: Lint
run: yarn lint:check

test:
needs: [build, lint]
runs-on: ubuntu-latest

steps:
- name: Checkout the repository
uses: actions/checkout@v4
with:
submodules: recursive

- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: 18.18.0
cache: yarn

- name: Install dependencies
run: yarn

- name: Restore artifacts cache
uses: actions/cache/restore@v3
with:
fail-on-cache-miss: true
key: artifacts-gas-bound-caller-${{ github.sha }}
path: |
gas-bound-caller/artifacts-zk
gas-bound-caller/cache-zk
gas-bound-caller/typechain

- name: Use era-test-node for testing
uses: dutterbutter/[email protected]
with:
releaseTag: v0.0.1-vm1.5.0

# The tests of GasBoundCaller reuse utility methods of the system contracts tests,
# so we need to deploy those also.
- name: Build system contracts
run: yarn sc build

- name: Run tests
run: yarn gas-bound-caller test
70 changes: 70 additions & 0 deletions .github/workflows/l1-contracts-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,73 @@ jobs:

- name: Compare
run: diff tools/data/Verifier.sol l1-contracts/contracts/state-transition/Verifier.sol

coverage:
defaults:
run:
working-directory: l1-contracts
needs: [build, lint]
runs-on: ubuntu-latest

steps:
- name: Checkout the repository
uses: actions/checkout@v4
with:
submodules: recursive

- name: Use Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: 18.18.0
cache: yarn

- name: Install dependencies
run: yarn

- name: Restore artifacts cache
uses: actions/cache/restore@v3
with:
fail-on-cache-miss: true
key: artifacts-l1-${{ github.sha }}
path: |
l1-contracts/artifacts
l1-contracts/cache
l1-contracts/typechain

- name: Run coverage
run: FOUNDRY_PROFILE=default yarn test:foundry && FOUNDRY_PROFILE=default yarn coverage:foundry --report summary --report lcov

# To ignore coverage for certain directories modify the paths in this step as needed. The
# below default ignores coverage results for the test and script directories. Alternatively,
# to include coverage in all directories, comment out this step. Note that because this
# filtering applies to the lcov file, the summary table generated in the previous step will
# still include all files and directories.
# The `--rc lcov_branch_coverage=1` part keeps branch info in the filtered report, since lcov
# defaults to removing branch info.
- name: Filter directories
run: |
sudo apt update && sudo apt install -y lcov
lcov --remove lcov.info 'test/*' 'contracts/dev-contracts/*' 'lib/*' --output-file lcov.info --rc lcov_branch_coverage=1

# This step posts a detailed coverage report as a comment and deletes previous comments on
# each push. The below step is used to fail coverage if the specified coverage threshold is
# not met. The below step can post a comment (when it's `github-token` is specified) but it's
# not as useful, and this action cannot fail CI based on a minimum coverage threshold, which
# is why we use both in this way.
- name: Post coverage report
if: github.event_name == 'pull_request' # This action fails when ran outside of a pull request.
uses: romeovs/[email protected]
with:
delete-old-comments: true
lcov-file: ./l1-contracts/lcov.info
github-token: ${{ secrets.GITHUB_TOKEN }} # Adds a coverage summary comment to the PR.

- name: Verify minimum coverage
uses: zgosalvez/github-actions-report-lcov@v2
with:
coverage-files: ./l1-contracts/lcov.info
working-directory: l1-contracts
minimum-coverage: 85 # Set coverage threshold.
4 changes: 2 additions & 2 deletions .github/workflows/slither.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,5 @@ jobs:

- name: Run Slither
run: |
cd l1-contracts
slither --config ./slither.config.json .
cd l1-contracts
slither --config ./slither.config.json .
4 changes: 4 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ system-contracts/contracts/Constants.sol
system-contracts/artifacts-zk
system-contracts/cache-zk
system-contracts/contracts-preprocessed
system-contracts/typechain
gas-bound-caller/artifacts-zk
gas-bound-caller/cache-zk
gas-bound-caller/typechain
l1-contracts/cache
l1-contracts/cache-forge
l1-contracts/artifacts
Expand Down
17 changes: 14 additions & 3 deletions gas-bound-caller/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# GasBoundCaller

> ⚠️⚠️ The GasBoundCaller's bytecode is not yet finalized, this version is for testnet trial only ⚠️⚠️

Starting from v24 On Era, the gas for pubdata is charged at the end of the execution of the entire transaction. This means that if a subcall is not trusted, it can consume a significant amount of pubdata during the process. While this may not be an issue for most contracts, there are use cases, e.g., for relayers, where it is crucial to ensure that the subcall will not spend more money than intended.

The `GasBoundCaller` is a contract with the following interface:
Expand Down Expand Up @@ -44,8 +46,17 @@ uint256 totalGasConsumed = computeGasBefore - computeGasAfter + pubdataGasSpent;

Since `GasBoundCaller` would be the contract that calls the `_to` contract, the `msg.sender` will be equal to the `GasBoundCaller`'s address. To preserve the current `msg.sender`, this contract can be inherited from and used the same way, but instead of calling `GasBoundCaller.gasBoundCall`, `this.gasBoundCall` could be called.

## Deployed Address
## Deploying on a zkSync-based chain

Note, that it requires the v1.5.0 version of the contracts to be active on the network, i.e. the protocol version should be at least v24.

```
yarn deploy-on-hyperchain --private-key <private-key> --l2-rpc <rpc>
```

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

TODO(EVM-585)
| Network | Address |
| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| Era Testnet | [0xDaAD9137Deec2FCbB8C4aB3820553E0da60328b6](https://sepolia.explorer.zksync.io/address/0xDaAD9137Deec2FCbB8C4aB3820553E0da60328b6#contract) |
| Era Mainnet | TODO |
2 changes: 1 addition & 1 deletion gas-bound-caller/canonical-bytecodes/GasBoundCaller

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions gas-bound-caller/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 @@ -55,6 +56,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
8 changes: 6 additions & 2 deletions gas-bound-caller/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
"devDependencies": {
"@matterlabs/hardhat-zksync-chai-matchers": "^0.1.4",
"@matterlabs/hardhat-zksync-node": "^0.0.1-beta.7",
"@matterlabs/hardhat-zksync-verify": "^1.4.2",
"@nomicfoundation/hardhat-chai-matchers": "^1.0.3",
"@nomicfoundation/hardhat-verify": "^2.0.6",
"@nomiclabs/hardhat-ethers": "^2.0.0",
"@typechain/ethers-v5": "^2.0.0",
"@types/chai": "^4.2.21",
Expand Down Expand Up @@ -51,10 +53,12 @@
},
"scripts": {
"build": "hardhat compile",
"clean": "yarn clean:bootloader && yarn clean:system-contracts",
"clean": "yarn hardhat clean",
"test": "yarn build && hardhat test --network zkSyncTestNode",
"test-node": "hardhat node-zksync --tag v0.0.1-vm1.5.0",
"deploy-on-hyperchain": "ts-node ./scripts/deploy-on-hyperchain.ts",
"deploy-on-localhost": "hardhat deploy --network localhost"
"calculate-canonical-bytecode:check": "ts-node ./scripts/calculate-canonical-bytecode.ts check",
"calculate-canonical-bytecode:fix": "ts-node ./scripts/calculate-canonical-bytecode.ts fix",
"verify": "hardhat run ./scripts/verify.ts"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ async function main() {

program
.version("0.1.0")
.name("check canonical bytecode")
.description("Checks that the locally built artifacts match the canonical bytecode");
.name("calculate canonical bytecode")
.description("A script that is used to check that the locally built artifacts match the canonical bytecode");

program.command("check").action(async () => {
const compiledBytecode = (await hre.artifacts.readArtifact("GasBoundCaller")).bytecode;
Expand Down
20 changes: 5 additions & 15 deletions gas-bound-caller/scripts/deploy-on-hyperchain.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
// hardhat import should be the first import in the file
import { ethers } from "ethers";
import { Command } from "commander";
import { readCanonicalArtifact } from "./utils";
import { Wallet, Provider, Contract, utils } from "zksync-ethers";

// This factory should be predeployed on each post-v24 zksync network
const PREDEPLOYED_CREATE2_ADDRESS = "0x0000000000000000000000000000000000010000";
import { PREDEPLOYED_CREATE2_ADDRESS, getCreate2DeploymentInfo } from "./utils";
import { Wallet, Provider, Contract } from "zksync-ethers";

const singletonFactoryAbi = [
{
Expand Down Expand Up @@ -47,23 +44,16 @@ async function main() {
.name("Deploy on hyperchain")
.description("Deploys the GasBoundCaller on a predetermined Hyperchain network")
.option("--private-key <private-key>")
.option("--l2Rpc <l2Rpc>")
.option("--l2-rpc <l2Rpc>")
.action(async (cmd) => {
console.log("Reading the canonical bytecode of the GasBoundCaller");
const bytecode = readCanonicalArtifact();

const { bytecode, bytecodeHash, expectedAddress } = getCreate2DeploymentInfo();

const wallet = new Wallet(cmd.privateKey, new Provider(cmd.l2Rpc));

const singleTonFactory = new Contract(PREDEPLOYED_CREATE2_ADDRESS, singletonFactoryAbi, wallet);

const bytecodeHash = ethers.utils.hexlify(utils.hashBytecode(bytecode));

const expectedAddress = utils.create2Address(
PREDEPLOYED_CREATE2_ADDRESS,
bytecodeHash,
ethers.constants.HashZero,
"0x"
);
console.log("Expected address:", expectedAddress);

const currentCode = await wallet.provider.getCode(expectedAddress);
Expand Down
28 changes: 28 additions & 0 deletions gas-bound-caller/scripts/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { ethers } from "ethers";
import * as fs from "fs";
import { utils } from "zksync-ethers";

// This factory should be predeployed on each post-v24 zksync network
export const PREDEPLOYED_CREATE2_ADDRESS = "0x0000000000000000000000000000000000010000";

const CANONICAL_BYTECODES_PATH = "./canonical-bytecodes/GasBoundCaller";

Expand All @@ -9,3 +14,26 @@ export function writeCanonicalArtifact(newBytecode: string) {
export function readCanonicalArtifact() {
return fs.readFileSync(CANONICAL_BYTECODES_PATH).toString();
}

export interface Create2DeploymentInfo {
bytecode: string;
bytecodeHash: string;
expectedAddress: string;
}

export function getCreate2DeploymentInfo(): Create2DeploymentInfo {
const bytecode = readCanonicalArtifact();
const bytecodeHash = ethers.utils.hexlify(utils.hashBytecode(bytecode));
const expectedAddress = utils.create2Address(
PREDEPLOYED_CREATE2_ADDRESS,
bytecodeHash,
ethers.constants.HashZero,
"0x"
);

return {
bytecode,
bytecodeHash,
expectedAddress,
};
}
Loading
Loading