Skip to content

Commit e08d7e4

Browse files
avilagaston9gianbelincheilitteriilitteritomip01
authored
feat(l2)!: shared bridge (#5192)
**Motivation** We want to be able to send funds and call contracts from one L2 to another without having to pass through the L1 **Description** This PR adds the necessary changes to send funds and call contracts between 2 L2s. You can find details under `shared_bridge_steps.md` and `shared_bridge.md`. <!-- A clear and concise general description of the changes this PR introduces --> <!-- Link to issues: Resolves #111, Resolves #222 --> --------- Co-authored-by: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Co-authored-by: ilitteri <ilitteri@fi.uba.ar> Co-authored-by: Ivan Litteri <67517699+ilitteri@users.noreply.github.com> Co-authored-by: Tomás Paradelo <112426153+tomip01@users.noreply.github.com>
1 parent 7fad543 commit e08d7e4

Some content is hidden

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

74 files changed

+3005
-413
lines changed

.github/workflows/pr-main_l2.yaml

Lines changed: 167 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,166 @@ jobs:
599599
cd crates/l2
600600
make state-diff-test
601601
602+
integration-test-shared-bridge:
603+
name: Integration Test Shared Bridge
604+
runs-on: ubuntu-latest
605+
needs: [detect-changes, build-docker, build-docker-l2]
606+
if: ${{ needs.detect-changes.outputs.run_tests == 'true' }}
607+
steps:
608+
- name: Checkout sources
609+
uses: actions/checkout@v4
610+
- name: Setup Rust Environment
611+
uses: ./.github/actions/setup-rust
612+
613+
- name: Install solc
614+
uses: lambdaclass/get-solc@master
615+
with:
616+
version: v0.8.29
617+
token: ${{ secrets.GITHUB_TOKEN || '' }}
618+
619+
- name: Build prover
620+
run: |
621+
cd crates/l2
622+
make build-prover-exec
623+
mkdir -p prover/src/guest_program/src/sp1/out && touch prover/src/guest_program/src/sp1/out/riscv32im-succinct-zkvm-vk-bn254 && touch prover/src/guest_program/src/sp1/out/riscv32im-succinct-zkvm-vk-u32
624+
625+
- name: Build test
626+
run: |
627+
cargo test l2 --features l2 --no-run --release
628+
629+
- name: Download ethrex image artifact
630+
uses: actions/download-artifact@v4
631+
with:
632+
name: ethrex_image
633+
path: /tmp
634+
635+
- name: Load ethrex image
636+
run: |
637+
docker load --input /tmp/ethrex_image.tar
638+
639+
- name: Download ethrex L2 image artifact
640+
uses: actions/download-artifact@v4
641+
with:
642+
name: ethrex_image_l2
643+
path: /tmp
644+
645+
- name: Load ethrex L2 image
646+
run: |
647+
docker load --input /tmp/ethrex_image_l2.tar
648+
649+
- name: Start L1
650+
run: |
651+
cd crates/l2
652+
docker compose up --detach ethrex_l1
653+
654+
- name: Deploy contracts L2A
655+
run: |
656+
#
657+
# If this job fails due to connection refused to ethrex_l1 consider increasing the failure retries
658+
# in the contract_deployer service in crates/l2/docker-compose.yaml
659+
#
660+
touch cmd/.env
661+
cd crates/l2
662+
DOCKER_ETHREX_WORKDIR=/usr/local/bin \
663+
ETHREX_DEPLOYER_DEPLOY_RICH=true \
664+
ETHREX_SHARED_BRIDGE_DEPLOY_ROUTER=true \
665+
docker compose up contract_deployer
666+
667+
DEPLOYER_EXIT_CODE=$(docker inspect -f '{{.State.ExitCode}}' contract_deployer)
668+
if [ "$DEPLOYER_EXIT_CODE" != "0" ]; then
669+
echo "If this job fails due to connection refused to ethrex_l1 consider increasing the failure retries in the contract_deployer service in crates/l2/docker-compose.yaml"
670+
docker logs contract_deployer
671+
exit 1
672+
fi
673+
674+
- name: Copy env to host
675+
run: |
676+
docker cp contract_deployer:/env/.env cmd/.env_l2a
677+
cat cmd/.env_l2a
678+
679+
- name: Deploy contracts L2B
680+
run: |
681+
jq '.config.chainId = 1730' fixtures/genesis/l2.json > fixtures/genesis/l2b.json
682+
#
683+
# If this job fails due to connection refused to ethrex_l1 consider increasing the failure retries
684+
# in the contract_deployer service in crates/l2/docker-compose.yaml
685+
#
686+
touch cmd/.env
687+
cd crates/l2
688+
export $(grep -v '^#' ../../cmd/.env_l2a | xargs)
689+
DOCKER_ETHREX_WORKDIR=/usr/local/bin \
690+
ETHREX_DEPLOYER_DEPLOY_RICH=true \
691+
ETHREX_SHARED_BRIDGE_ROUTER_ADDRESS=$ETHREX_SHARED_BRIDGE_ROUTER_ADDRESS \
692+
docker compose -f docker-compose.yaml -f docker-compose-l2-shared-bridge.overrides.yaml up contract_deployer
693+
694+
DEPLOYER_EXIT_CODE=$(docker inspect -f '{{.State.ExitCode}}' contract_deployer)
695+
if [ "$DEPLOYER_EXIT_CODE" != "0" ]; then
696+
echo "If this job fails due to connection refused to ethrex_l1 consider increasing the failure retries in the contract_deployer service in crates/l2/docker-compose.yaml"
697+
docker logs contract_deployer
698+
exit 1
699+
fi
700+
701+
- name: Copy env to host
702+
run: |
703+
docker cp contract_deployer:/env/.env cmd/.env_l2b
704+
cat cmd/.env_l2b
705+
706+
- name: Start Sequencer L2A
707+
run: |
708+
cp cmd/.env_l2a cmd/.env
709+
export ETHREX_BLOCK_PRODUCER_BASE_FEE_VAULT_ADDRESS=0x000c0d6b7c4516a5b274c51ea331a9410fe69127
710+
export ETHREX_BLOCK_PRODUCER_OPERATOR_FEE_VAULT_ADDRESS=0xd5d2a85751b6F158e5b9B8cD509206A865672362
711+
export ETHREX_BLOCK_PRODUCER_OPERATOR_FEE_PER_GAS=1000000000
712+
export ETHREX_BLOCK_PRODUCER_L1_FEE_VAULT_ADDRESS=0x45681AE1768a8936FB87aB11453B4755e322ceec
713+
cd crates/l2
714+
export $(xargs < ../../cmd/.env_l2a)
715+
DOCKER_ETHREX_WORKDIR=/usr/local/bin \
716+
ETHREX_WATCHER_BLOCK_DELAY=0 \
717+
ETHREX_COMMITTER_COMMIT_TIME=15000 \
718+
ETHREX_WATCHER_WATCH_INTERVAL=1000 \
719+
ETHREX_WATCHER_L2_RPCS=http://ethrex_l2_b:1730 \
720+
ETHREX_WATCHER_L2_CHAIN_IDS=1730 \
721+
ETHREX_WATCHER_ROUTER_ADDRESS=$ETHREX_SHARED_BRIDGE_ROUTER_ADDRESS \
722+
docker compose -f docker-compose.yaml up --detach --no-deps ethrex_l2
723+
724+
- name: Start Sequencer L2B
725+
run: |
726+
cp cmd/.env_l2b cmd/.env
727+
export ETHREX_BLOCK_PRODUCER_BASE_FEE_VAULT_ADDRESS=0x000c0d6b7c4516a5b274c51ea331a9410fe69127
728+
export ETHREX_BLOCK_PRODUCER_OPERATOR_FEE_VAULT_ADDRESS=0xd5d2a85751b6F158e5b9B8cD509206A865672362
729+
export ETHREX_BLOCK_PRODUCER_OPERATOR_FEE_PER_GAS=1000000000
730+
export ETHREX_BLOCK_PRODUCER_L1_FEE_VAULT_ADDRESS=0x45681AE1768a8936FB87aB11453B4755e322ceec
731+
cd crates/l2
732+
export $(xargs < ../../cmd/.env_l2b)
733+
DOCKER_ETHREX_WORKDIR=/usr/local/bin \
734+
ETHREX_WATCHER_BLOCK_DELAY=0 \
735+
ETHREX_COMMITTER_COMMIT_TIME=15000 \
736+
ETHREX_WATCHER_WATCH_INTERVAL=1000 \
737+
ETHREX_WATCHER_L2_RPCS=http://ethrex_l2:1729 \
738+
ETHREX_WATCHER_L2_CHAIN_IDS=65536999 \
739+
ETHREX_WATCHER_ROUTER_ADDRESS=$ETHREX_SHARED_BRIDGE_ROUTER_ADDRESS \
740+
docker compose -f docker-compose.yaml -f docker-compose-l2-shared-bridge.overrides.yaml up --detach --no-deps ethrex_l2_b
741+
742+
- name: Run tests
743+
run: |
744+
sudo chmod -R a+rw crates/l2
745+
cd crates/l2
746+
cargo run --release --features "l2,l2-sql" --manifest-path ../../Cargo.toml -- \
747+
l2 prover \
748+
--proof-coordinators tcp://127.0.0.1:3900 tcp://127.0.0.1:3901 \
749+
--backend exec &
750+
docker logs --follow ethrex_l2 &
751+
docker logs --follow ethrex_l2_b &
752+
docker logs --follow ethrex_l1 &
753+
cargo test shared_bridge --release -- --nocapture --test-threads=1
754+
cp ../../cmd/.env_l2a ../../cmd/.env
755+
PROPOSER_COINBASE_ADDRESS=0x0007a881CD95B1484fca47615B64803dad620C8d INTEGRATION_TEST_SKIP_TEST_TOTAL_ETH=true cargo test l2 --release -- --nocapture --test-threads=1
756+
cp ../../cmd/.env_l2b ../../cmd/.env
757+
PROPOSER_COINBASE_ADDRESS=0x0007a881CD95B1484fca47615B64803dad620C8d INTEGRATION_TEST_SKIP_TEST_TOTAL_ETH=true INTEGRATION_TEST_L2_RPC=http://localhost:1730 cargo test l2 --release -- --nocapture --test-threads=1
758+
cargo test shared_bridge --release -- --nocapture --test-threads=1
759+
killall ethrex -s SIGINT
760+
761+
602762
# The purpose of this job is to add it as a required check in GitHub so that we don't have to add every individual job as a required check
603763
all-tests:
604764
# "Integration Test L2" is a required check, don't change the name
@@ -611,9 +771,10 @@ jobs:
611771
state-diff-test,
612772
integration-test-tdx,
613773
uniswap-swap,
774+
integration-test-shared-bridge,
614775
]
615776
# Make sure this job runs even if the previous jobs failed or were skipped
616-
if: ${{ needs.detect-changes.outputs.run_tests == 'true' && always() && needs.integration-test.result != 'skipped' && needs.state-diff-test.result != 'skipped' && needs.integration-test-tdx.result != 'skipped' && needs.uniswap-swap.result != 'skipped' }}
777+
if: ${{ needs.detect-changes.outputs.run_tests == 'true' && always() && needs.integration-test.result != 'skipped' && needs.state-diff-test.result != 'skipped' && needs.integration-test-tdx.result != 'skipped' && needs.uniswap-swap.result != 'skipped' && needs.integration-test-shared-bridge.result != 'skipped' }}
617778
steps:
618779
- name: Check if any job failed
619780
run: |
@@ -631,3 +792,8 @@ jobs:
631792
echo "Job Uniswap Swap Token Flow failed"
632793
exit 1
633794
fi
795+
796+
if [ "${{ needs.integration-test-shared-bridge.result }}" != "success" ]; then
797+
echo "Job Integration test shared bridge failed"
798+
exit 1
799+
fi

cmd/ethrex/build_l2.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ pub fn download_script() {
103103
&Path::new("../../crates/l2/contracts/src/l1/CommonBridge.sol"),
104104
"CommonBridge",
105105
),
106+
(
107+
&Path::new("../../crates/l2/contracts/src/l1/Router.sol"),
108+
"Router",
109+
),
106110
];
107111
for (path, name) in l1_contracts {
108112
compile_contract_to_bytecode(
@@ -122,8 +126,8 @@ pub fn download_script() {
122126
"CommonBridgeL2",
123127
),
124128
(
125-
&Path::new("../../crates/l2/contracts/src/l2/L2ToL1Messenger.sol"),
126-
"L2ToL1Messenger",
129+
&Path::new("../../crates/l2/contracts/src/l2/Messenger.sol"),
130+
"Messenger",
127131
),
128132
(
129133
&Path::new("../../crates/l2/contracts/src/l2/L2Upgradeable.sol"),
@@ -181,8 +185,9 @@ fn write_empty_bytecode_files(output_contracts_path: &Path) {
181185
"SP1Verifier",
182186
"OnChainProposer",
183187
"CommonBridge",
188+
"Router",
184189
"CommonBridgeL2",
185-
"L2ToL1Messenger",
190+
"Messenger",
186191
"UpgradeableSystemContract",
187192
"SequencerRegistry",
188193
"OnChainProposerBased",
@@ -338,9 +343,9 @@ fn common_bridge_l2_runtime(out_dir: &Path) -> Vec<u8> {
338343
fs::read(path).expect("Failed to read bytecode file")
339344
}
340345

341-
/// Bytecode of the L2ToL1Messenger contract.
346+
/// Bytecode of the Messenger contract.
342347
fn l2_to_l1_messenger_runtime(out_dir: &Path) -> Vec<u8> {
343-
let path = out_dir.join("contracts/solc_out/L2ToL1Messenger.bytecode");
348+
let path = out_dir.join("contracts/solc_out/Messenger.bytecode");
344349
fs::read(path).expect("Failed to read bytecode file")
345350
}
346351

0 commit comments

Comments
 (0)