Skip to content

Commit 9318d44

Browse files
committed
Merge branch 'main' into test/state-structure/prover
2 parents 9acb0fa + 3306b7a commit 9318d44

36 files changed

Lines changed: 1579 additions & 86 deletions

.github/workflows/gas.yml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,11 @@ jobs:
3232
run: |
3333
forge --version
3434
35-
- name: Install Just
36-
uses: taiki-e/install-action@just
37-
3835
# Do not count negative and fuzz tests toward gas calculations since they can add noise
3936
# (https://book.getfoundry.sh/guides/best-practices?highlight=best%20pr#general-test-guidance)
4037
- name: Run Forge tests
4138
run: |
42-
forge test --no-match-test "(RevertWhen|testFuzz)" --no-match-path "test/signal/**" --gas-report --color never | tee gasreport.ansi
39+
forge test --no-match-test "(RevertWhen|testFuzz)" --gas-report --color never | tee gasreport.ansi
4340
id: test
4441

4542
- name: Compare gas reports

.github/workflows/test.yml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,7 @@ jobs:
3636
forge build --sizes
3737
id: build
3838

39-
- name: Install Just
40-
uses: taiki-e/install-action@just
41-
4239
- name: Run Forge tests
4340
run: |
44-
just test -vvv
41+
forge test -vvv
4542
id: test

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,7 @@ docs/
1414
.env
1515

1616
# Added by cargo
17+
1718
/target
19+
20+
.DS_Store

Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
[package]
2+
23
name = "minimal-rollup"
34
version = "0.1.0"
45
edition = "2021"
@@ -19,6 +20,15 @@ path = "offchain/deposit_signal_proof.rs"
1920
name = "utils"
2021
path = "offchain/utils.rs"
2122

23+
[[bin]]
24+
name = "sample_signal_proof"
25+
path = "offchain/sample_signal_proof.rs"
26+
27+
[[bin]]
28+
name = "sample_deposit_proof"
29+
path = "offchain/sample_deposit_proof.rs"
30+
31+
2232
[dependencies]
2333
alloy = { version = "0.13.0", features = ["node-bindings"] }
2434
eyre = "0.6.12"

foundry.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@ src = "src"
33
out = "out"
44
libs = ["lib"]
55
evm_version = "cancun"
6-
always_use_create_2_factory = true # Use Foundry's create2 factory in tests(https://github.com/foundry-rs/foundry/pull/6656)
7-
rpc_endpoints = { L1 = "http://localhost:8545", L2 = "http://localhost:8546" }
6+
always_use_create_2_factory = true
87
sender = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
98

10-
gas_reports_ignore = ["MockDelayedInclusionStore", "MockCheckpointTracker", ""]
9+
gas_reports_ignore = ["MockDelayedInclusionStore", "MockCheckpointTracker", "SampleDepositProof", "SampleProof"]
1110

1211
remappings = [
1312
"@optimism/=lib/optimism/",

justfile

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,18 @@
1-
# Start two anvil instances
2-
# "🚨WARNING: This starts two background processes🚨"
3-
# "To stop them, run: just stop-anvil"
4-
start-anvil:
5-
anvil --port 8545 &
6-
anvil --port 8546 &
7-
wait
8-
9-
stop-anvil:
10-
lsof -ti:8545 | xargs -r kill
11-
lsof -ti:8546 | xargs -r kill
12-
13-
test +ARGS='':
14-
# Run all unit tests
15-
forge test {{ARGS}} --no-match-path 'test/signal/**'
16-
17-
test-int +ARGS='':
18-
# Run all tests
19-
forge test {{ARGS}}
20-
211
# Get signal proof for a signal and sender
222
get-generic-signal-proof signal sender:
233
cargo run --bin generic_signal_proof {{signal}} {{sender}}
244

255
get-deposit-signal-proof:
266
cargo run --bin deposit_signal_proof
277

28-
# Get signal slot for a signal, sender and namespace (1: default signal , 2: eth deposit)
29-
get-signal-slot signal sender namespace:
30-
cargo run --bin signal_slot {{signal}} {{sender}} {{namespace}}
8+
# Get signal slot for a signal and sender
9+
get-signal-slot signal sender:
10+
cargo run --bin signal_slot {{signal}} {{sender}}
11+
12+
# Create a sample signal proof
13+
create-sample-signal-proof:
14+
cargo run --bin sample_signal_proof > test/SignalService/SampleProof.t.sol
15+
16+
# Create a sample deposit proof
17+
create-sample-deposit-proof:
18+
cargo run --bin sample_deposit_proof > test/ETHBridge/SampleDepositProof.t.sol

offchain/deposit_signal_proof.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use alloy::primitives::{address, bytes, B256, U256};
1+
use alloy::primitives::{address, bytes, Address, U256};
22
use eyre::Result;
33

44
mod utils;
@@ -22,11 +22,9 @@ async fn main() -> Result<()> {
2222
let data = bytes!();
2323
let sender = address!("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266");
2424
let amount = U256::from(4000000000000000000_u128);
25+
let relayer = Address::ZERO;
2526

26-
// This is the checkpoint tracker
27-
let trusted_publisher = address!("0xCafac3dD18aC6c6e92c921884f9E4176737C052c");
28-
29-
let (provider, _anvil) = get_provider()?;
27+
let (provider, _, _) = get_provider()?;
3028

3129
let signal_service = deploy_signal_service(&provider).await?;
3230

@@ -35,23 +33,19 @@ async fn main() -> Result<()> {
3533
signal_service.address()
3634
);
3735

38-
let eth_bridge =
39-
deploy_eth_bridge(&provider, *signal_service.address(), trusted_publisher).await?;
36+
let eth_bridge = deploy_eth_bridge(&provider, *signal_service.address()).await?;
4037

4138
println!("Deployed ETH bridge at address: {}", eth_bridge.address());
4239

4340
println!("Sending ETH deposit...");
44-
let builder = eth_bridge.deposit(sender, data).value(amount);
41+
let builder = eth_bridge.deposit(sender, data, bytes!()).value(amount);
4542
let tx = builder.send().await?.get_receipt().await?;
4643

4744
// Get deposit ID from the transaction receipt logs
4845
// possibly a better way to do this, but this works :)
4946
let receipt_logs = tx.logs().get(0).unwrap().topics();
5047
let deposit_id = receipt_logs.get(1).unwrap();
51-
let depid: B256 =
52-
"0xf9c183d2de58fbeb1a8917170139e980fa1b6e5a358ec83721e11c9f6e25eb18".parse()?;
53-
54-
let slot = get_signal_slot(&depid, &eth_bridge.address());
48+
let slot = get_signal_slot(&deposit_id, &eth_bridge.address());
5549
get_proofs(&provider, slot, &signal_service).await?;
5650

5751
Ok(())

offchain/generic_signal_proof.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ async fn main() -> Result<()> {
3535
println!();
3636
let (signal, sender) = prompt_sender_and_signal()?;
3737

38-
let (provider, _anvil) = get_provider()?;
38+
let (provider, _, _) = get_provider()?;
3939

4040
let signal_service = deploy_signal_service(&provider).await?;
4141

offchain/sample_deposit_proof.rs

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
use eyre::Result;
2+
3+
mod signal_slot;
4+
use signal_slot::get_signal_slot;
5+
6+
mod utils;
7+
use utils::{deploy_eth_bridge, deploy_signal_service, get_proofs, get_provider, SignalProof};
8+
9+
use alloy::hex::decode;
10+
use alloy::primitives::{Address, Bytes, FixedBytes, U256};
11+
use std::fs;
12+
13+
fn expand_vector(vec: Vec<Bytes>, name: &str) -> String {
14+
let mut expanded = String::new();
15+
for (i, item) in vec.iter().enumerate() {
16+
expanded += format!("\t\t{}[{}] = hex\"{}\";\n", name, i, item)
17+
.replace("0x", "")
18+
.as_str();
19+
}
20+
return expanded;
21+
}
22+
23+
fn create_deposit_call(
24+
proof: SignalProof,
25+
nonce: usize,
26+
signer: Address,
27+
recipient: Address,
28+
amount: U256,
29+
data: &str,
30+
context: &str,
31+
id: &FixedBytes<32>,
32+
) -> String {
33+
let mut result = String::new();
34+
result += format!("\n\t\t// Populate proof {}\n", nonce).as_str();
35+
result += format!(
36+
"\t\taccountProof = new bytes[]({});\n",
37+
proof.account_proof.len()
38+
)
39+
.as_str();
40+
result += expand_vector(proof.account_proof, "accountProof").as_str();
41+
result += format!(
42+
"\t\tstorageProof = new bytes[]({});\n",
43+
proof.storage_proof.len()
44+
)
45+
.as_str();
46+
result += expand_vector(proof.storage_proof, "storageProof").as_str();
47+
result += format!("\t\tdeposit.nonce = {};\n", nonce).as_str();
48+
result += format!("\t\tdeposit.from = address({});\n", signer).as_str();
49+
result += format!("\t\tdeposit.to = address({});\n", recipient).as_str();
50+
result += format!("\t\tdeposit.amount = {};\n", amount).as_str();
51+
result += format!("\t\tdeposit.data = bytes(hex\"{}\");\n", data).as_str();
52+
result += format!("\t\tdeposit.context = bytes(hex\"{}\");\n", context).as_str();
53+
result += format!("\t\t_createDeposit(\n\t\t\taccountProof,\n\t\t\tstorageProof,\n\t\t\tdeposit,\n\t\t\tbytes32({}),\n\t\t\tbytes32({})\n\t\t);\n", proof.slot, id).as_str();
54+
return result;
55+
}
56+
57+
pub struct DepositSpecification {
58+
pub recipient: Address,
59+
pub amount: U256,
60+
pub data: String,
61+
pub context: String,
62+
}
63+
64+
fn deposit_specification() -> Vec<DepositSpecification> {
65+
// This is an address on the destination chain, so it seems natural to use one generated there
66+
// In this case, the CrossChainDepositExists.sol test case defines _randomAddress("recipient");
67+
let recipient = "0x99A270Be1AA5E97633177041859aEEB9a0670fAa";
68+
// Use both zero and non-zero amounts (in this case 4 ether)
69+
let amounts = vec![0_u128, 4000000000000000000_u128];
70+
// Use different calldata to try different functions and inputs
71+
let calldata = vec![
72+
"", // empty
73+
"9b28f6fb00000000000000000000000000000000000000000000000000000000000004d2", // (valid) call to somePayableFunction(1234)
74+
"9b28f6fb00000000000000000000000000000000000000000000000000000000000004d3", // (invalid) call to somePayableFunction(1235)
75+
"5932a71200000000000000000000000000000000000000000000000000000000000004d2", // (valid) call to `someNonPayableFunction(1234)`
76+
];
77+
78+
let mut specifications = vec![];
79+
for amount in amounts {
80+
for data in calldata.iter() {
81+
specifications.push(DepositSpecification {
82+
recipient: recipient.parse().unwrap(),
83+
amount: U256::from(amount),
84+
data: data.to_string(),
85+
context: String::from(""),
86+
});
87+
}
88+
}
89+
return specifications;
90+
}
91+
92+
#[tokio::main]
93+
async fn main() -> Result<()> {
94+
let (provider, _anvil, signer) = get_provider()?;
95+
let signal_service = deploy_signal_service(&provider).await?;
96+
let eth_bridge = deploy_eth_bridge(&provider, *signal_service.address()).await?;
97+
98+
let deposits = deposit_specification();
99+
assert!(deposits.len() > 0, "No deposits to prove");
100+
let mut ids: Vec<FixedBytes<32>> = vec![];
101+
// Perform all deposits
102+
for (_i, spec) in deposits.iter().enumerate() {
103+
let tx = eth_bridge
104+
.deposit(
105+
spec.recipient,
106+
decode(spec.data.clone())?.into(),
107+
decode(spec.context.clone())?.into(),
108+
)
109+
.value(spec.amount)
110+
.send()
111+
.await?
112+
.get_receipt()
113+
.await?;
114+
let id = tx.logs().get(0).unwrap().data().clone().data;
115+
ids.push(FixedBytes::from_slice(&id[..32]));
116+
}
117+
118+
let mut block_hash = FixedBytes::ZERO;
119+
let mut state_root = FixedBytes::ZERO;
120+
121+
let mut populated_proofs = String::new();
122+
for (i, id) in ids.iter().enumerate() {
123+
let slot = get_signal_slot(id, &eth_bridge.address());
124+
let proof = get_proofs(&provider, slot, &signal_service).await?;
125+
126+
if i == 0 {
127+
block_hash = proof.block_hash;
128+
state_root = proof.state_root;
129+
} else {
130+
assert!(proof.block_hash == block_hash);
131+
assert!(proof.state_root == state_root);
132+
}
133+
134+
let d = &deposits[i];
135+
populated_proofs += create_deposit_call(
136+
proof,
137+
i,
138+
signer.address(),
139+
d.recipient,
140+
d.amount,
141+
d.data.as_str(),
142+
d.context.as_str(),
143+
id,
144+
)
145+
.as_str();
146+
}
147+
148+
let template = fs::read_to_string("offchain/sample_deposit_proof.tmpl")?;
149+
let formatted = template
150+
.replace(
151+
"{signal_service_address}",
152+
signal_service.address().to_string().as_str(),
153+
)
154+
.replace(
155+
"{bridge_address}",
156+
eth_bridge.address().to_string().as_str(),
157+
)
158+
.replace("{block_hash}", block_hash.to_string().as_str())
159+
.replace("{state_root}", state_root.to_string().as_str())
160+
.replace("{populate_proofs}", populated_proofs.as_str());
161+
println!("{}", formatted);
162+
Ok(())
163+
}

0 commit comments

Comments
 (0)