diff --git a/.github/workflows/label-external-contributions.yaml b/.github/workflows/label-external-contributions.yaml new file mode 100644 index 000000000..de9f2439c --- /dev/null +++ b/.github/workflows/label-external-contributions.yaml @@ -0,0 +1,38 @@ +name: Workflow to label external contributions + +on: + pull_request_target: + types: [opened, ready_for_review] + +permissions: + contents: read + pull-requests: write + +jobs: + label: + runs-on: ubuntu-latest + steps: + - name: Add external-contribution label + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + PR_NUMBER=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH") + REPO_FULL_NAME=$(jq --raw-output .repository.full_name "$GITHUB_EVENT_PATH") + IS_FORK=$(jq --raw-output .pull_request.head.repo.fork "$GITHUB_EVENT_PATH") + + if [[ "$IS_FORK" == "true" ]]; then + echo "This PR is created from a fork." + HTTP_STATUS=$(curl -o /dev/null -s -w "%{http_code}\n" \ + -X POST \ + -H "Authorization: Bearer $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github.v3+json" \ + "https://api.github.com/repos/$REPO_FULL_NAME/issues/$PR_NUMBER/labels" \ + -d '{"labels": ["external-contribution"]}') + + if [[ $HTTP_STATUS -ge 300 ]]; then + echo "Failed to add label to PR, exiting." + exit 1 + fi + else + echo "This PR is not created from a fork." + fi diff --git a/README.md b/README.md index 3a795a2f4..5f74ec617 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ used on msg.sender, when it calls other contracts. ## Building -This repository is used as a submodule of the [zksync-2-dev](https://github.com/matter-labs/zksync-2-dev). +This repository is used as a submodule of the [zksync-era](https://github.com/matter-labs/zksync-era). Compile the solidity and yul contracts: `yarn build` @@ -84,9 +84,11 @@ See [LICENSE-MIT](LICENSE-MIT) for details. - [Website](https://zksync.io/) - [GitHub](https://github.com/matter-labs) +- [ZK Credo](https://github.com/zksync/credo) - [Twitter](https://twitter.com/zksync) - [Twitter for Devs](https://twitter.com/zkSyncDevs) -- [Discord](https://discord.gg/nMaPGrDDwk) +- [Discord](https://join.zksync.dev/) +- [Mirror](https://zksync.mirror.xyz/) ## Disclaimer diff --git a/SystemContractsHashes.json b/SystemContractsHashes.json index e123d0e6c..78e00ae21 100644 --- a/SystemContractsHashes.json +++ b/SystemContractsHashes.json @@ -143,35 +143,35 @@ "contractName": "bootloader_test", "bytecodePath": "bootloader/build/artifacts/bootloader_test.yul/bootloader_test.yul.zbin", "sourceCodePath": "bootloader/build/bootloader_test.yul", - "bytecodeHash": "0x01000385425e3ddcaa5a6780f2463c8aa71b844d914b61471f468173d7eaff0d", - "sourceCodeHash": "0xda28bc1ac0cd1e0a34ea99bb70cde15fd0edbacffe7491186620f46fc821c201" + "bytecodeHash": "0x0100038548508a2a29b0c6e8a86fc0ec5c512baf563155e8171afd1a060c81fa", + "sourceCodeHash": "0x8a2f1171cb02b1500e75e607a7a16ea8782b54800fb3396d0aea241117539265" }, { "contractName": "fee_estimate", "bytecodePath": "bootloader/build/artifacts/fee_estimate.yul/fee_estimate.yul.zbin", "sourceCodePath": "bootloader/build/fee_estimate.yul", - "bytecodeHash": "0x0100096bebcd3abfed25138ff97587a5783c0294c25627aa4166bd1c91913a2d", - "sourceCodeHash": "0x6732aa11175c77394065e586f123d10a844335bc57a58ef47291de32583de225" + "bytecodeHash": "0x01000989a967ab5b446c084adf05e13399a24e5cf37e9cf7db05a5dd6d7c5e0b", + "sourceCodeHash": "0xf8d6ef018c46d562d4473628c4b13af322320a4c24015c884083bf5654ce7408" }, { "contractName": "gas_test", "bytecodePath": "bootloader/build/artifacts/gas_test.yul/gas_test.yul.zbin", "sourceCodePath": "bootloader/build/gas_test.yul", - "bytecodeHash": "0x0100094b78d8a52b54f82e4f1007a1c0c9ae7e2d54e73321549d7a70bb320bbf", - "sourceCodeHash": "0x68f07a46c3179705047c41b63b03e157fa48b0f06427801bedc8d45e335ea7c3" + "bytecodeHash": "0x0100096912f983649836f812c6db81c814cc0a5ff24b80ecffbf79ca01e7946c", + "sourceCodeHash": "0xc130da5db5af59763a518394dddf96358664eef53b11260d4c4f86ae967c454d" }, { "contractName": "playground_batch", "bytecodePath": "bootloader/build/artifacts/playground_batch.yul/playground_batch.yul.zbin", "sourceCodePath": "bootloader/build/playground_batch.yul", - "bytecodeHash": "0x0100097500c0f3cc64c09339b8215f35ebdf155f2c7188b4b9426cd8d58b80cc", - "sourceCodeHash": "0x5a121577cd4335105a6b9864196ecb5796890299fac95e7003d9f23bd210e907" + "bytecodeHash": "0x0100099308cc5367de190e240aa355df7d0cfacb6a752726bad8f3100044629f", + "sourceCodeHash": "0x7fd1d118ecb97b79a2bb9d66e132638344d6ad333486f8ee520455679ae5aaaa" }, { "contractName": "proved_batch", "bytecodePath": "bootloader/build/artifacts/proved_batch.yul/proved_batch.yul.zbin", "sourceCodePath": "bootloader/build/proved_batch.yul", - "bytecodeHash": "0x010009657432df24acfe7950b2d1a0707520ca6b7acb699e58c0f378c0ed7a11", - "sourceCodeHash": "0x2469138639d133005f6d3b7fad3d7404db5b4088b2649e9f5167d2a22df3b1de" + "bytecodeHash": "0x01000983d4ac4f797cf5c077e022f72284969b13248c2a8e9846f574bdeb5b88", + "sourceCodeHash": "0x444b9dad3a29511c5a80d6f50e1ccf4500031452d2ef3edb4f63593b7070a24d" } ] diff --git a/bootloader/bootloader.yul b/bootloader/bootloader.yul index 89a2c0500..eba58c936 100644 --- a/bootloader/bootloader.yul +++ b/bootloader/bootloader.yul @@ -634,6 +634,36 @@ object "Bootloader" { } } + /// @dev Checks whether the code hash of the system context contract is correct and updates it if needed. + /// @dev The L1 contracts expect all the system logs to be present in the first boojum upgrade batch already. + /// However, the old system context did not send the same system logs. Usually we upgrade system context + /// via an upgrade transaction, but in this case the transaction won't be even processed, because of failure to create an L2 block. + function upgradeSystemContextIfNeeded() { + let expectedCodeHash := {{SYSTEM_CONTEXT_EXPECTED_CODE_HASH}} + + let actualCodeHash := extcodehash(SYSTEM_CONTEXT_ADDR()) + if iszero(eq(expectedCodeHash, actualCodeHash)) { + // Preparing the calldata to upgrade the SystemContext contract + {{UPGRADE_SYSTEM_CONTEXT_CALLDATA}} + + // We'll use a mimicCall to simulate the correct sender. + let success := mimicCallOnlyResult( + CONTRACT_DEPLOYER_ADDR(), + FORCE_DEPLOYER(), + 0, + 0, + 0, + 0, + 0, + 0 + ) + + if iszero(success) { + assertionError("system context upgrade fail") + } + } + } + /// @dev Calculates the canonical hash of the L1->L2 transaction that will be /// sent to L1 as a message to the L1 contract that a certain operation has been processed. function getCanonicalL1TxHash(txDataOffset) -> ret { @@ -3697,6 +3727,11 @@ object "Bootloader" { + // This implementation of the bootloader relies on the correct version of the SystemContext + // and it can not be upgraded via a standard upgrade transaction, but needs to ensure + // correctness itself before any transaction is executed. + upgradeSystemContextIfNeeded() + // Only for the proved batch we enforce that the baseFee proposed // by the operator is equal to the expected one. For the playground batch, we allow // the operator to provide any baseFee the operator wants. @@ -3716,6 +3751,8 @@ object "Bootloader" { baseFee, GAS_PRICE_PER_PUBDATA := getBaseFee(L1_GAS_PRICE, FAIR_L2_GAS_PRICE) let SHOULD_SET_NEW_BATCH := mload(224) + + upgradeSystemContextIfNeeded() switch SHOULD_SET_NEW_BATCH case 0 { diff --git a/scripts/constants.ts b/scripts/constants.ts index dd089d97c..1483d4693 100644 --- a/scripts/constants.ts +++ b/scripts/constants.ts @@ -46,6 +46,18 @@ export const SYSTEM_CONTRACTS: ISystemContracts = { lang: Language.Yul, path: "precompiles", }, + ecAdd: { + address: "0x0000000000000000000000000000000000000006", + codeName: "EcAdd", + lang: Language.Yul, + path: "precompiles", + }, + ecMul: { + address: "0x0000000000000000000000000000000000000007", + codeName: "EcMul", + lang: Language.Yul, + path: "precompiles", + }, bootloader: { // Bootloader has EmptyContract code address: "0x0000000000000000000000000000000000008001", diff --git a/scripts/deploy-preimages.ts b/scripts/deploy-preimages.ts index 716533c7d..20cc86114 100644 --- a/scripts/deploy-preimages.ts +++ b/scripts/deploy-preimages.ts @@ -256,8 +256,11 @@ async function main() { wallet.connect(providerL2); wallet.connectToL1(providerL1); - const deployer = new Deployer(hre, wallet); - deployer.zkWallet = deployer.zkWallet.connect(providerL2).connectToL1(providerL1); + // TODO(EVM-392): refactor to avoid `any` here. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const deployer = new Deployer(hre, wallet as any); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + deployer.zkWallet = deployer.zkWallet.connect(providerL2 as any).connectToL1(providerL1); deployer.ethWallet = deployer.ethWallet.connect(providerL1); const ethWallet = deployer.ethWallet; diff --git a/test/shared/utils.ts b/test/shared/utils.ts index 448f505e4..168957427 100644 --- a/test/shared/utils.ts +++ b/test/shared/utils.ts @@ -34,7 +34,9 @@ const RICH_WALLETS = [ export const provider = new Provider((hre.network.config as any).url); const wallet = new Wallet(RICH_WALLETS[0].privateKey, provider); -const deployer = new Deployer(hre, wallet); +// TODO(EVM-392): refactor to avoid `any` here. +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const deployer = new Deployer(hre, wallet as any); export async function callFallback(contract: Contract, data: string) { // `eth_Call` revert is not parsed by ethers, so we send