Skip to content

Commit c60a348

Browse files
koloz193DeniallugoStanislavBreadless
authored
feat(contracts)!: integrate protocol defense changes (#2737)
## What ❔ The work done in the protocol defense project introduced a number of changes, namely custom errors in our solidity contracts. We need to update the server code to handle these new errors. ## Why ❔ <!-- Why are these changes done? What goal do they contribute to? What are the principles behind them? --> <!-- Example: PR templates ensure PR reviewers, observers, and future iterators are in context about the evolution of repos. --> ## Checklist <!-- Check your PR fulfills the following items. --> <!-- For draft PRs check the boxes as you complete them. --> - [ ] PR title corresponds to the body of PR (we generate changelog entries from PRs). - [ ] Tests for the changes have been added / updated. - [ ] Documentation comments have been added / updated. - [ ] Code has been formatted via `zk fmt` and `zk lint`. --------- Signed-off-by: Danil <deniallugo@gmail.com> Co-authored-by: Danil <deniallugo@gmail.com> Co-authored-by: Stanislav Breadless <stanislavbezkor@gmail.com>
1 parent c1cb30e commit c60a348

File tree

59 files changed

+1856
-452
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+1856
-452
lines changed

.github/workflows/build-core-template.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ jobs:
128128
ci_run git config --global --add safe.directory /usr/src/zksync/contracts
129129
ci_run ./bin/zk || true
130130
ci_run run_retried curl -LO https://storage.googleapis.com/matterlabs-setup-keys-us/setup-keys/setup_2\^26.key
131-
131+
132132
- name: Install zkstack
133133
run: |
134134
ci_run ./zkstack_cli/zkstackup/install -g --path ./zkstack_cli/zkstackup/zkstackup || true

.github/workflows/new-build-contract-verifier-template.yml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,13 @@ jobs:
103103
crate: sqlx-cli
104104
tag: 0.8.1
105105

106-
- name: Install Foundry
107-
uses: foundry-rs/foundry-toolchain@8f1998e9878d786675189ef566a2e4bf24869773 # v1.2.0
106+
- name: Install foundry-zksync
107+
run: |
108+
mkdir ./foundry-zksync
109+
curl -LO https://github.com/matter-labs/foundry-zksync/releases/download/nightly-15bec2f861b3b4c71e58f85e2b2c9dd722585aa8/foundry_nightly_linux_amd64.tar.gz
110+
tar zxf foundry_nightly_linux_amd64.tar.gz -C ./foundry-zksync
111+
chmod +x ./foundry-zksync/forge ./foundry-zksync/cast
112+
echo "$PWD/foundry-zksync" >> $GITHUB_PATH
108113
109114
- name: Pre-download compilers
110115
shell: bash
@@ -131,7 +136,7 @@ jobs:
131136
docker compose up -d postgres
132137
133138
- name: Install zkstack
134-
run: |
139+
run: |
135140
./zkstack_cli/zkstackup/install --path ./zkstack_cli/zkstackup/zkstackup
136141
zkstackup --local || true
137142

.github/workflows/new-build-core-template.yml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,13 @@ jobs:
108108
crate: sqlx-cli
109109
tag: 0.8.1
110110

111-
- name: Install Foundry
112-
uses: foundry-rs/foundry-toolchain@8f1998e9878d786675189ef566a2e4bf24869773 # v1.2.0
111+
- name: Install foundry-zksync
112+
run: |
113+
mkdir ./foundry-zksync
114+
curl -LO https://github.com/matter-labs/foundry-zksync/releases/download/nightly-15bec2f861b3b4c71e58f85e2b2c9dd722585aa8/foundry_nightly_linux_amd64.tar.gz
115+
tar zxf foundry_nightly_linux_amd64.tar.gz -C ./foundry-zksync
116+
chmod +x ./foundry-zksync/forge ./foundry-zksync/cast
117+
echo "$PWD/foundry-zksync" >> $GITHUB_PATH
113118
114119
- name: Pre-download compilers
115120
shell: bash
@@ -136,10 +141,10 @@ jobs:
136141
docker compose up -d postgres
137142
138143
- name: Install zkstack
139-
run: |
144+
run: |
140145
./zkstack_cli/zkstackup/install --path ./zkstack_cli/zkstackup/zkstackup
141146
zkstackup --local || true
142-
147+
143148
- name: build contracts
144149
shell: bash
145150
run: |

contracts

Submodule contracts updated 333 files

core/bin/system-constants-generator/src/utils.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::{cell::RefCell, rc::Rc};
33
use once_cell::sync::Lazy;
44
use zksync_contracts::{
55
load_sys_contract, read_bootloader_code, read_bytecode_from_path, read_sys_contract_bytecode,
6-
BaseSystemContracts, ContractLanguage, SystemContractCode,
6+
read_zbin_bytecode, BaseSystemContracts, ContractLanguage, SystemContractCode,
77
};
88
use zksync_multivm::{
99
interface::{
@@ -171,9 +171,16 @@ pub(super) fn get_l1_txs(number_of_txs: usize) -> (Vec<Transaction>, Vec<Transac
171171
}
172172

173173
fn read_bootloader_test_code(test: &str) -> Vec<u8> {
174-
read_bytecode_from_path(format!(
174+
if let Some(contract) = read_bytecode_from_path(format!(
175175
"contracts/system-contracts/zkout/{test}.yul/contracts-preprocessed/bootloader/{test}.yul.json",
176-
))
176+
)){
177+
contract
178+
} else {
179+
read_zbin_bytecode(format!(
180+
"contracts/system-contracts/bootloader/tests/artifacts/{}.yul.zbin",
181+
test
182+
))
183+
}
177184
}
178185

179186
fn default_l1_batch() -> L1BatchEnv {

core/lib/basic_types/src/protocol_version.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,16 @@ pub enum ProtocolVersionId {
6868
Version23,
6969
Version24,
7070
Version25,
71+
Version26,
7172
}
7273

7374
impl ProtocolVersionId {
7475
pub const fn latest() -> Self {
75-
Self::Version24
76+
Self::Version25
7677
}
7778

7879
pub const fn next() -> Self {
79-
Self::Version25
80+
Self::Version26
8081
}
8182

8283
pub fn try_from_packed_semver(packed_semver: U256) -> Result<Self, String> {
@@ -120,6 +121,7 @@ impl ProtocolVersionId {
120121
ProtocolVersionId::Version23 => VmVersion::Vm1_5_0SmallBootloaderMemory,
121122
ProtocolVersionId::Version24 => VmVersion::Vm1_5_0IncreasedBootloaderMemory,
122123
ProtocolVersionId::Version25 => VmVersion::Vm1_5_0IncreasedBootloaderMemory,
124+
ProtocolVersionId::Version26 => VmVersion::Vm1_5_0IncreasedBootloaderMemory,
123125
}
124126
}
125127

@@ -275,6 +277,7 @@ impl From<ProtocolVersionId> for VmVersion {
275277
ProtocolVersionId::Version23 => VmVersion::Vm1_5_0SmallBootloaderMemory,
276278
ProtocolVersionId::Version24 => VmVersion::Vm1_5_0IncreasedBootloaderMemory,
277279
ProtocolVersionId::Version25 => VmVersion::Vm1_5_0IncreasedBootloaderMemory,
280+
ProtocolVersionId::Version26 => VmVersion::Vm1_5_0IncreasedBootloaderMemory,
278281
}
279282
}
280283
}

core/lib/contracts/src/lib.rs

Lines changed: 96 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -69,20 +69,21 @@ fn home_path() -> PathBuf {
6969
Workspace::locate().core()
7070
}
7171

72-
fn read_file_to_json_value(path: impl AsRef<Path> + std::fmt::Debug) -> serde_json::Value {
72+
fn read_file_to_json_value(path: impl AsRef<Path> + std::fmt::Debug) -> Option<serde_json::Value> {
7373
let zksync_home = home_path();
7474
let path = Path::new(&zksync_home).join(path);
75-
let file =
76-
File::open(&path).unwrap_or_else(|e| panic!("Failed to open file {:?}: {}", path, e));
77-
serde_json::from_reader(BufReader::new(file))
78-
.unwrap_or_else(|e| panic!("Failed to parse file {:?}: {}", path, e))
75+
let file = File::open(&path).ok()?;
76+
Some(
77+
serde_json::from_reader(BufReader::new(file))
78+
.unwrap_or_else(|e| panic!("Failed to parse file {:?}: {}", path, e)),
79+
)
7980
}
8081

8182
fn load_contract_if_present<P: AsRef<Path> + std::fmt::Debug>(path: P) -> Option<Contract> {
8283
let zksync_home = home_path();
8384
let path = Path::new(&zksync_home).join(path);
8485
path.exists().then(|| {
85-
serde_json::from_value(read_file_to_json_value(&path)["abi"].take())
86+
serde_json::from_value(read_file_to_json_value(&path).unwrap()["abi"].take())
8687
.unwrap_or_else(|e| panic!("Failed to parse contract abi from file {:?}: {}", path, e))
8788
})
8889
}
@@ -114,17 +115,26 @@ pub fn load_contract<P: AsRef<Path> + std::fmt::Debug>(path: P) -> Contract {
114115
}
115116

116117
pub fn load_sys_contract(contract_name: &str) -> Contract {
117-
load_contract(format!(
118+
if let Some(contract) = load_contract_if_present(format!(
118119
"contracts/system-contracts/artifacts-zk/contracts-preprocessed/{0}.sol/{0}.json",
119120
contract_name
120-
))
121+
)) {
122+
contract
123+
} else {
124+
load_contract(format!(
125+
"contracts/system-contracts/zkout/{0}.sol/{0}.json",
126+
contract_name
127+
))
128+
}
121129
}
122130

123-
pub fn read_contract_abi(path: impl AsRef<Path> + std::fmt::Debug) -> String {
124-
read_file_to_json_value(path)["abi"]
125-
.as_str()
126-
.expect("Failed to parse abi")
127-
.to_string()
131+
pub fn read_contract_abi(path: impl AsRef<Path> + std::fmt::Debug) -> Option<String> {
132+
Some(
133+
read_file_to_json_value(path)?["abi"]
134+
.as_str()
135+
.expect("Failed to parse abi")
136+
.to_string(),
137+
)
128138
}
129139

130140
pub fn bridgehub_contract() -> Contract {
@@ -200,7 +210,7 @@ pub fn l1_messenger_contract() -> Contract {
200210

201211
/// Reads bytecode from the path RELATIVE to the Cargo workspace location.
202212
pub fn read_bytecode(relative_path: impl AsRef<Path> + std::fmt::Debug) -> Vec<u8> {
203-
read_bytecode_from_path(relative_path)
213+
read_bytecode_from_path(relative_path).expect("Exists")
204214
}
205215

206216
pub fn eth_contract() -> Contract {
@@ -212,25 +222,33 @@ pub fn known_codes_contract() -> Contract {
212222
}
213223

214224
/// Reads bytecode from a given path.
215-
pub fn read_bytecode_from_path(artifact_path: impl AsRef<Path> + std::fmt::Debug) -> Vec<u8> {
216-
let artifact = read_file_to_json_value(&artifact_path);
217-
218-
let bytecode = artifact["bytecode"]
219-
.as_str()
220-
.unwrap_or_else(|| panic!("Bytecode not found in {:?}", artifact_path))
221-
.strip_prefix("0x")
222-
.unwrap_or_else(|| panic!("Bytecode in {:?} is not hex", artifact_path));
225+
pub fn read_bytecode_from_path(
226+
artifact_path: impl AsRef<Path> + std::fmt::Debug,
227+
) -> Option<Vec<u8>> {
228+
let artifact = read_file_to_json_value(&artifact_path)?;
229+
230+
let bytecode = if let Some(bytecode) = artifact["bytecode"].as_str() {
231+
bytecode
232+
.strip_prefix("0x")
233+
.unwrap_or_else(|| panic!("Bytecode in {:?} is not hex", artifact_path))
234+
} else {
235+
artifact["bytecode"]["object"]
236+
.as_str()
237+
.unwrap_or_else(|| panic!("Bytecode not found in {:?}", artifact_path))
238+
};
223239

224-
hex::decode(bytecode)
225-
.unwrap_or_else(|err| panic!("Can't decode bytecode in {:?}: {}", artifact_path, err))
240+
Some(
241+
hex::decode(bytecode)
242+
.unwrap_or_else(|err| panic!("Can't decode bytecode in {:?}: {}", artifact_path, err)),
243+
)
226244
}
227245

228246
pub fn read_sys_contract_bytecode(directory: &str, name: &str, lang: ContractLanguage) -> Vec<u8> {
229247
DEFAULT_SYSTEM_CONTRACTS_REPO.read_sys_contract_bytecode(directory, name, lang)
230248
}
231249

232250
static DEFAULT_SYSTEM_CONTRACTS_REPO: Lazy<SystemContractsRepo> =
233-
Lazy::new(SystemContractsRepo::from_env);
251+
Lazy::new(SystemContractsRepo::default);
234252

235253
/// Structure representing a system contract repository - that allows
236254
/// fetching contracts that are located there.
@@ -240,38 +258,65 @@ pub struct SystemContractsRepo {
240258
pub root: PathBuf,
241259
}
242260

243-
impl SystemContractsRepo {
261+
impl Default for SystemContractsRepo {
244262
/// Returns the default system contracts repository with directory based on the Cargo workspace location.
245-
pub fn from_env() -> Self {
263+
fn default() -> Self {
246264
SystemContractsRepo {
247265
root: home_path().join("contracts/system-contracts"),
248266
}
249267
}
268+
}
250269

270+
impl SystemContractsRepo {
251271
pub fn read_sys_contract_bytecode(
252272
&self,
253273
directory: &str,
254274
name: &str,
255275
lang: ContractLanguage,
256276
) -> Vec<u8> {
257277
match lang {
258-
ContractLanguage::Sol => read_bytecode_from_path(self.root.join(format!(
259-
"artifacts-zk/contracts-preprocessed/{0}{1}.sol/{1}.json",
260-
directory, name
261-
))),
278+
ContractLanguage::Sol => {
279+
if let Some(contracts) = read_bytecode_from_path(
280+
self.root
281+
.join(format!("zkout/{0}{1}.sol/{1}.json", directory, name)),
282+
) {
283+
contracts
284+
} else {
285+
read_bytecode_from_path(self.root.join(format!(
286+
"artifacts-zk/contracts-preprocessed/{0}{1}.sol/{1}.json",
287+
directory, name
288+
)))
289+
.expect("One of the outputs should exists")
290+
}
291+
}
262292
ContractLanguage::Yul => {
263-
let artifacts_path = self
264-
.root
265-
.join(format!("contracts-preprocessed/{}artifacts/", directory));
266-
read_yul_bytecode_by_path(artifacts_path, name)
293+
if let Some(contract) = read_bytecode_from_path(self.root.join(format!(
294+
"zkout/{name}.yul/contracts-preprocessed/{directory}/{name}.yul.json",
295+
))) {
296+
contract
297+
} else {
298+
read_zbin_bytecode_from_path(self.root.join(format!(
299+
"contracts-preprocessed/{0}artifacts/{1}.yul.zbin",
300+
directory, name
301+
)))
302+
}
267303
}
268304
}
269305
}
270306
}
271307

272308
pub fn read_bootloader_code(bootloader_type: &str) -> Vec<u8> {
273-
let artifacts_path = "contracts/system-contracts/bootloader/build/artifacts/";
274-
read_yul_bytecode(artifacts_path, bootloader_type)
309+
if let Some(contract) =
310+
read_bytecode_from_path(home_path().join("contracts/system-contracts").join(format!(
311+
"zkout/{bootloader_type}.yul/contracts-preprocessed/bootloader/{bootloader_type}.yul.json",
312+
)))
313+
{
314+
return contract;
315+
};
316+
read_zbin_bytecode(format!(
317+
"contracts/system-contracts/bootloader/build/artifacts/{}.yul.zbin",
318+
bootloader_type
319+
))
275320
}
276321

277322
fn read_proved_batch_bootloader_bytecode() -> Vec<u8> {
@@ -463,6 +508,13 @@ impl BaseSystemContracts {
463508
BaseSystemContracts::load_with_bootloader(bootloader_bytecode)
464509
}
465510

511+
pub fn playground_post_protocol_defense() -> Self {
512+
let bootloader_bytecode = read_zbin_bytecode(
513+
"etc/multivm_bootloaders/vm_protocol_defense/playground_batch.yul/playground_batch.yul.zbin",
514+
);
515+
BaseSystemContracts::load_with_bootloader(bootloader_bytecode)
516+
}
517+
466518
pub fn estimate_gas_pre_virtual_blocks() -> Self {
467519
let bootloader_bytecode = read_zbin_bytecode(
468520
"etc/multivm_bootloaders/vm_1_3_2/fee_estimate.yul/fee_estimate.yul.zbin",
@@ -526,6 +578,13 @@ impl BaseSystemContracts {
526578
BaseSystemContracts::load_with_bootloader(bootloader_bytecode)
527579
}
528580

581+
pub fn estimate_gas_post_protocol_defense() -> Self {
582+
let bootloader_bytecode = read_zbin_bytecode(
583+
"etc/multivm_bootloaders/vm_protocol_defense/fee_estimate.yul/fee_estimate.yul.zbin",
584+
);
585+
BaseSystemContracts::load_with_bootloader(bootloader_bytecode)
586+
}
587+
529588
pub fn hashes(&self) -> BaseSystemContractsHashes {
530589
BaseSystemContractsHashes {
531590
bootloader: self.bootloader.hash,

core/lib/multivm/src/versions/vm_fast/tests/l1_tx_execution.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,8 @@ fn test_l1_tx_execution() {
117117
let res = vm.vm.execute(VmExecutionMode::OneTx);
118118
let storage_logs = res.logs.storage_logs;
119119
let res = StorageWritesDeduplicator::apply_on_empty_state(&storage_logs);
120-
// We changed one slot inside contract. However, the rewrite of the `basePubdataSpent` didn't happen, since it was the same
121-
// as the start of the previous tx. Thus we have `+1` slot for the changed counter and `-1` slot for base pubdata spent
122-
assert_eq!(res.initial_storage_writes, basic_initial_writes);
120+
// We changed one slot inside contract.
121+
assert_eq!(res.initial_storage_writes - basic_initial_writes, 1);
123122

124123
// No repeated writes
125124
let repeated_writes = res.repeated_storage_writes;
@@ -146,7 +145,7 @@ fn test_l1_tx_execution() {
146145
assert!(result.result.is_failed(), "The transaction should fail");
147146

148147
let res = StorageWritesDeduplicator::apply_on_empty_state(&result.logs.storage_logs);
149-
assert_eq!(res.initial_storage_writes, basic_initial_writes);
148+
assert_eq!(res.initial_storage_writes, basic_initial_writes + 1);
150149
assert_eq!(res.repeated_storage_writes, 1);
151150
}
152151

0 commit comments

Comments
 (0)