diff --git a/.github/workflows/test-bridge.yml b/.github/workflows/test-bridge.yml index 29a1f76..9d1c94f 100644 --- a/.github/workflows/test-bridge.yml +++ b/.github/workflows/test-bridge.yml @@ -10,7 +10,7 @@ env: jobs: test_bridge: - runs-on: macos-latest + runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: @@ -25,15 +25,41 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 - - name: Run anvil + - name: Setup build deps + run: | + sudo apt-get update + sudo apt-get install -y clang llvm libudev-dev protobuf-compiler + - uses: rui314/setup-mold@v1 + - uses: software-mansion/setup-scarb@v1 + with: + scarb-version: "2.8.2" + - uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly + + - name: Checkout Madara + uses: actions/checkout@v4 + with: + repository: madara-alliance/madara + ref: "d188aa91efa78bcc54f92aa1035295fd50e068d2" + path: madara + + - name: Move Madara Devnet config + working-directory: madara run: | - anvil /dev/null & + ls + mv configs/presets/devnet.yaml ../bin/devnet.yaml - - name: Run madara + - name: Build Madara + working-directory: madara + run: | + cargo build + mv target/debug/madara ../bin/madara + cd .. + + - name: Run anvil run: | - cd bin - echo "Running madara...." - ./run_madara.sh + anvil & - uses: taiki-e/install-action@cargo-llvm-cov - uses: taiki-e/install-action@nextest diff --git a/.gitignore b/.gitignore index b427079..598064c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ /target .idea .env -addresses.json \ No newline at end of file +addresses.json +/bin/madara +/bin/devnet.yaml \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index ca5b007..49674f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -337,6 +337,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "base64ct" version = "1.6.0" @@ -349,18 +355,6 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" -[[package]] -name = "bigdecimal" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6773ddc0eafc0e509fb60e48dff7f450f8e674a0686ae8605e8d9901bd5eefa" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits 0.2.19", - "serde", -] - [[package]] name = "bip39" version = "2.0.0" @@ -504,7 +498,7 @@ dependencies = [ [[package]] name = "cairo-felt" version = "0.9.1" -source = "git+https://github.com/bidzyyys/cairo-vm?branch=feature/scale-codec#eb835a9034e208a1756226d64e004cb55e417b96" +source = "git+https://github.com/bidzyyys/cairo-vm.git?branch=feature/scale-codec#eb835a9034e208a1756226d64e004cb55e417b96" dependencies = [ "lazy_static", "num-bigint", @@ -640,7 +634,7 @@ dependencies = [ "serde_json", "sha3", "smol_str", - "starknet-crypto 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "starknet-crypto 0.6.2", "thiserror", ] @@ -833,6 +827,33 @@ dependencies = [ "thiserror", ] +[[package]] +name = "color-eyre" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5" +dependencies = [ + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", +] + +[[package]] +name = "color-spantrace" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" +dependencies = [ + "once_cell", + "owo-colors", + "tracing-core", + "tracing-error", +] + [[package]] name = "colorchoice" version = "1.0.1" @@ -1404,7 +1425,7 @@ dependencies = [ [[package]] name = "ethereum-instance" version = "0.1.0" -source = "git+https://github.com/keep-starknet-strange/zaun?branch=main#dab8928ecdfe1387f8ac0f223378ed36708c8c09" +source = "git+https://github.com/karnotxyz/zaun?rev=782967e5#782967e5e488d447ae989406bf0e1bfc1371493f" dependencies = [ "dirs", "ethers", @@ -2441,6 +2462,7 @@ dependencies = [ "async-trait", "bytes", "clap", + "color-eyre", "dotenv", "env_logger", "ethereum-instance", @@ -2449,6 +2471,7 @@ dependencies = [ "hex", "indexmap 2.2.6", "inline_colorization", + "lazy_static", "log", "num-bigint", "parity-scale-codec", @@ -2457,22 +2480,24 @@ dependencies = [ "scale-info", "serde", "serde_json", - "serde_with", + "serde_with 2.3.3", "starkgate-manager-client", "starkgate-registry-client", - "starknet-accounts", - "starknet-core", + "starknet", + "starknet-accounts 0.11.0", + "starknet-core 0.11.1", "starknet-core-contract-client", - "starknet-crypto 0.6.2 (git+https://github.com/xJonathanLEI/starknet-rs.git?rev=2d59636911628260fa460179010bbd00e89de06e)", + "starknet-crypto 0.7.2", "starknet-erc20-client", "starknet-eth-bridge-client", - "starknet-ff 0.3.7 (git+https://github.com/xJonathanLEI/starknet-rs.git?rev=2d59636911628260fa460179010bbd00e89de06e)", - "starknet-providers", + "starknet-providers 0.11.0", "starknet-proxy-client", - "starknet-signers", + "starknet-signers 0.9.0", "starknet-token-bridge-client", + "starknet-types-core", "starknet_api", "subxt-lightclient", + "tempfile", "thiserror", "tokio", "url", @@ -2519,6 +2544,28 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "lambdaworks-crypto" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fb5d4f22241504f7c7b8d2c3a7d7835d7c07117f10bff2a7d96a9ef6ef217c3" +dependencies = [ + "lambdaworks-math", + "serde", + "sha2 0.10.8", + "sha3", +] + +[[package]] +name = "lambdaworks-math" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "358e172628e713b80a530a59654154bfc45783a6ed70ea284839800cebdf8f97" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -2863,9 +2910,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "oorandom" -version = "11.1.3" +version = "11.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "opaque-debug" @@ -2904,6 +2951,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + [[package]] name = "parity-scale-codec" version = "3.6.12" @@ -3709,9 +3762,9 @@ dependencies = [ [[package]] name = "schemars" -version = "0.8.19" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc6e7ed6919cb46507fb01ff1654309219f62b4d603822501b0b80d42f6f21ef" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" dependencies = [ "dyn-clone", "indexmap 1.9.3", @@ -3722,9 +3775,9 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.19" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "185f2b7aa7e02d418e453790dde16890256bbd2bcd04b7dc5348811052b53f49" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" dependencies = [ "proc-macro2", "quote", @@ -3844,9 +3897,9 @@ dependencies = [ [[package]] name = "serde_derive_internals" -version = "0.29.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330f01ce65a3a5fe59a60c82f3c9a024b573b8a6e875bd233fe5f934e71d54e3" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", @@ -3908,7 +3961,25 @@ dependencies = [ "indexmap 1.9.3", "serde", "serde_json", - "serde_with_macros", + "serde_with_macros 2.3.3", + "time", +] + +[[package]] +name = "serde_with" +version = "3.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9720086b3357bcb44fce40117d769a4d068c70ecfa190850a980a71755f66fcc" +dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.2.6", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros 3.10.0", "time", ] @@ -3924,6 +3995,18 @@ dependencies = [ "syn 2.0.63", ] +[[package]] +name = "serde_with_macros" +version = "3.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f1abbfe725f27678f4663bcacb75a83e829fd464c25d78dd038a3a29e307cec" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.63", +] + [[package]] name = "sha1" version = "0.10.6" @@ -3969,6 +4052,15 @@ dependencies = [ "keccak", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "signature" version = "2.2.0" @@ -4173,7 +4265,7 @@ dependencies = [ [[package]] name = "starkgate-manager-client" version = "0.1.0" -source = "git+https://github.com/keep-starknet-strange/zaun?branch=main#dab8928ecdfe1387f8ac0f223378ed36708c8c09" +source = "git+https://github.com/karnotxyz/zaun?rev=782967e5#782967e5e488d447ae989406bf0e1bfc1371493f" dependencies = [ "async-trait", "ethers", @@ -4187,7 +4279,7 @@ dependencies = [ [[package]] name = "starkgate-registry-client" version = "0.1.0" -source = "git+https://github.com/keep-starknet-strange/zaun?branch=main#dab8928ecdfe1387f8ac0f223378ed36708c8c09" +source = "git+https://github.com/karnotxyz/zaun?rev=782967e5#782967e5e488d447ae989406bf0e1bfc1371493f" dependencies = [ "async-trait", "ethers", @@ -4198,40 +4290,108 @@ dependencies = [ "utils", ] +[[package]] +name = "starknet" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e633a772f59214c296d5037c95c36b72792c9360323818da2b625c7b4ec4b49" +dependencies = [ + "starknet-accounts 0.10.0", + "starknet-contract", + "starknet-core 0.11.1", + "starknet-crypto 0.7.2", + "starknet-macros", + "starknet-providers 0.11.0", + "starknet-signers 0.9.0", +] + [[package]] name = "starknet-accounts" -version = "0.9.0" -source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=2d59636911628260fa460179010bbd00e89de06e#2d59636911628260fa460179010bbd00e89de06e" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eee8a6b588a22c7e79f5d8d4e33413387db63a8beb98be8610138541794cc0a5" dependencies = [ "async-trait", "auto_impl", - "starknet-core", - "starknet-providers", - "starknet-signers", + "starknet-core 0.11.1", + "starknet-crypto 0.7.2", + "starknet-providers 0.11.0", + "starknet-signers 0.9.0", "thiserror", ] [[package]] -name = "starknet-core" +name = "starknet-accounts" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee27ded58ade61da410fccafd57ed5429b0e79a9d62a4ae8b65818cb9d6f400" +dependencies = [ + "async-trait", + "auto_impl", + "starknet-core 0.12.0", + "starknet-crypto 0.7.2", + "starknet-providers 0.12.0", + "starknet-signers 0.10.0", + "thiserror", +] + +[[package]] +name = "starknet-contract" version = "0.10.0" -source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=2d59636911628260fa460179010bbd00e89de06e#2d59636911628260fa460179010bbd00e89de06e" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5f91344f1e0b81873b6dc235c50ae4d084c6ea4dd4a1e3e27ad895803adb610" +dependencies = [ + "serde", + "serde_json", + "serde_with 2.3.3", + "starknet-accounts 0.10.0", + "starknet-core 0.11.1", + "starknet-providers 0.11.0", + "thiserror", +] + +[[package]] +name = "starknet-core" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d506e02a4083290d13b427dfe437fd95aa8b56315c455bb2f9cdeca76620d457" +dependencies = [ + "base64 0.21.7", + "crypto-bigint", + "flate2", + "hex", + "serde", + "serde_json", + "serde_json_pythonic", + "serde_with 2.3.3", + "sha3", + "starknet-crypto 0.7.2", + "starknet-types-core", +] + +[[package]] +name = "starknet-core" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2538240cbe6663c673fe77465f294da707080f39678dd7066761554899e46100" dependencies = [ "base64 0.21.7", + "crypto-bigint", "flate2", "hex", "serde", "serde_json", "serde_json_pythonic", - "serde_with", + "serde_with 3.10.0", "sha3", - "starknet-crypto 0.6.2 (git+https://github.com/xJonathanLEI/starknet-rs.git?rev=2d59636911628260fa460179010bbd00e89de06e)", - "starknet-ff 0.3.7 (git+https://github.com/xJonathanLEI/starknet-rs.git?rev=2d59636911628260fa460179010bbd00e89de06e)", + "starknet-crypto 0.7.2", + "starknet-types-core", ] [[package]] name = "starknet-core-contract-client" version = "0.1.0" -source = "git+https://github.com/keep-starknet-strange/zaun?branch=main#dab8928ecdfe1387f8ac0f223378ed36708c8c09" +source = "git+https://github.com/karnotxyz/zaun?rev=782967e5#782967e5e488d447ae989406bf0e1bfc1371493f" dependencies = [ "async-trait", "ethers", @@ -4256,9 +4416,9 @@ dependencies = [ "num-traits 0.2.19", "rfc6979", "sha2 0.10.8", - "starknet-crypto-codegen 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "starknet-crypto-codegen", "starknet-curve 0.3.0", - "starknet-ff 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "starknet-ff", "zeroize", ] @@ -4276,16 +4436,17 @@ dependencies = [ "num-traits 0.2.19", "rfc6979", "sha2 0.10.8", - "starknet-crypto-codegen 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "starknet-curve 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "starknet-ff 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "starknet-crypto-codegen", + "starknet-curve 0.4.2", + "starknet-ff", "zeroize", ] [[package]] name = "starknet-crypto" -version = "0.6.2" -source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=2d59636911628260fa460179010bbd00e89de06e#2d59636911628260fa460179010bbd00e89de06e" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a5064173a8e8d2675e67744fd07f310de44573924b6b7af225a6bdd8102913" dependencies = [ "crypto-bigint", "hex", @@ -4295,9 +4456,8 @@ dependencies = [ "num-traits 0.2.19", "rfc6979", "sha2 0.10.8", - "starknet-crypto-codegen 0.3.3 (git+https://github.com/xJonathanLEI/starknet-rs.git?rev=2d59636911628260fa460179010bbd00e89de06e)", - "starknet-curve 0.4.2 (git+https://github.com/xJonathanLEI/starknet-rs.git?rev=2d59636911628260fa460179010bbd00e89de06e)", - "starknet-ff 0.3.7 (git+https://github.com/xJonathanLEI/starknet-rs.git?rev=2d59636911628260fa460179010bbd00e89de06e)", + "starknet-curve 0.5.1", + "starknet-types-core", "zeroize", ] @@ -4307,18 +4467,8 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbc159a1934c7be9761c237333a57febe060ace2bc9e3b337a59a37af206d19f" dependencies = [ - "starknet-curve 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "starknet-ff 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 2.0.63", -] - -[[package]] -name = "starknet-crypto-codegen" -version = "0.3.3" -source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=2d59636911628260fa460179010bbd00e89de06e#2d59636911628260fa460179010bbd00e89de06e" -dependencies = [ - "starknet-curve 0.4.2 (git+https://github.com/xJonathanLEI/starknet-rs.git?rev=2d59636911628260fa460179010bbd00e89de06e)", - "starknet-ff 0.3.7 (git+https://github.com/xJonathanLEI/starknet-rs.git?rev=2d59636911628260fa460179010bbd00e89de06e)", + "starknet-curve 0.4.2", + "starknet-ff", "syn 2.0.63", ] @@ -4328,7 +4478,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "252610baff59e4c4332ce3569f7469c5d3f9b415a2240d698fb238b2b4fc0942" dependencies = [ - "starknet-ff 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "starknet-ff", ] [[package]] @@ -4337,21 +4487,22 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1c383518bb312751e4be80f53e8644034aa99a0afb29d7ac41b89a997db875b" dependencies = [ - "starknet-ff 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "starknet-ff", ] [[package]] name = "starknet-curve" -version = "0.4.2" -source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=2d59636911628260fa460179010bbd00e89de06e#2d59636911628260fa460179010bbd00e89de06e" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcde6bd74269b8161948190ace6cf069ef20ac6e79cd2ba09b320efa7500b6de" dependencies = [ - "starknet-ff 0.3.7 (git+https://github.com/xJonathanLEI/starknet-rs.git?rev=2d59636911628260fa460179010bbd00e89de06e)", + "starknet-types-core", ] [[package]] name = "starknet-erc20-client" version = "0.1.0" -source = "git+https://github.com/keep-starknet-strange/zaun?branch=main#dab8928ecdfe1387f8ac0f223378ed36708c8c09" +source = "git+https://github.com/karnotxyz/zaun?rev=782967e5#782967e5e488d447ae989406bf0e1bfc1371493f" dependencies = [ "async-trait", "ethereum-instance", @@ -4366,7 +4517,7 @@ dependencies = [ [[package]] name = "starknet-eth-bridge-client" version = "0.1.0" -source = "git+https://github.com/keep-starknet-strange/zaun?branch=main#dab8928ecdfe1387f8ac0f223378ed36708c8c09" +source = "git+https://github.com/karnotxyz/zaun?rev=782967e5#782967e5e488d447ae989406bf0e1bfc1371493f" dependencies = [ "async-trait", "ethers", @@ -4390,33 +4541,53 @@ dependencies = [ ] [[package]] -name = "starknet-ff" -version = "0.3.7" -source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=2d59636911628260fa460179010bbd00e89de06e#2d59636911628260fa460179010bbd00e89de06e" +name = "starknet-macros" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8986a940af916fc0a034f4e42c6ba76d94f1e97216d75447693dfd7aefaf3ef2" dependencies = [ - "ark-ff", - "bigdecimal", - "crypto-bigint", + "starknet-core 0.12.0", + "syn 2.0.63", +] + +[[package]] +name = "starknet-providers" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59c85e0a0f4563ae95dfeae14ea0f0c70610efc0ec2462505c64eff5765e7b97" +dependencies = [ + "async-trait", + "auto_impl", + "ethereum-types", + "flate2", "getrandom", - "hex", + "log", + "reqwest", "serde", + "serde_json", + "serde_with 2.3.3", + "starknet-core 0.11.1", + "thiserror", + "url", ] [[package]] name = "starknet-providers" -version = "0.10.0" -source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=2d59636911628260fa460179010bbd00e89de06e#2d59636911628260fa460179010bbd00e89de06e" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60e8e69ba7a36dea2d28333be82b4011f8784333d3ae5618482b6587c1ffb66c" dependencies = [ "async-trait", "auto_impl", "ethereum-types", "flate2", + "getrandom", "log", "reqwest", "serde", "serde_json", - "serde_with", - "starknet-core", + "serde_with 3.10.0", + "starknet-core 0.12.0", "thiserror", "url", ] @@ -4424,7 +4595,7 @@ dependencies = [ [[package]] name = "starknet-proxy-client" version = "0.1.0" -source = "git+https://github.com/keep-starknet-strange/zaun?branch=main#dab8928ecdfe1387f8ac0f223378ed36708c8c09" +source = "git+https://github.com/karnotxyz/zaun?rev=782967e5#782967e5e488d447ae989406bf0e1bfc1371493f" dependencies = [ "async-trait", "ethereum-instance", @@ -4438,23 +4609,42 @@ dependencies = [ [[package]] name = "starknet-signers" -version = "0.8.0" -source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=2d59636911628260fa460179010bbd00e89de06e#2d59636911628260fa460179010bbd00e89de06e" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17da2139119dbe3aacf1d5d4338798a5c489d17f424916ceb9d2efd83554f87" +dependencies = [ + "async-trait", + "auto_impl", + "crypto-bigint", + "eth-keystore", + "getrandom", + "rand", + "starknet-core 0.11.1", + "starknet-crypto 0.7.2", + "thiserror", +] + +[[package]] +name = "starknet-signers" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70b9e01b61ae51d722e2b100d6ef913c5a2e70d1ea672733d385f7296d6055ef" dependencies = [ "async-trait", "auto_impl", "crypto-bigint", "eth-keystore", + "getrandom", "rand", - "starknet-core", - "starknet-crypto 0.6.2 (git+https://github.com/xJonathanLEI/starknet-rs.git?rev=2d59636911628260fa460179010bbd00e89de06e)", + "starknet-core 0.12.0", + "starknet-crypto 0.7.2", "thiserror", ] [[package]] name = "starknet-token-bridge-client" version = "0.1.0" -source = "git+https://github.com/keep-starknet-strange/zaun?branch=main#dab8928ecdfe1387f8ac0f223378ed36708c8c09" +source = "git+https://github.com/karnotxyz/zaun?rev=782967e5#782967e5e488d447ae989406bf0e1bfc1371493f" dependencies = [ "async-trait", "ethers", @@ -4465,6 +4655,20 @@ dependencies = [ "utils", ] +[[package]] +name = "starknet-types-core" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b889ee5734db8b3c8a6551135c16764bf4ce1ab4955fffbb2ac5b6706542b64" +dependencies = [ + "lambdaworks-crypto", + "lambdaworks-math", + "num-bigint", + "num-integer", + "num-traits 0.2.19", + "serde", +] + [[package]] name = "starknet_api" version = "0.8.0" @@ -4697,6 +4901,16 @@ dependencies = [ "syn 2.0.63", ] +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + [[package]] name = "time" version = "0.3.36" @@ -4909,6 +5123,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-error" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +dependencies = [ + "tracing", + "tracing-subscriber", ] [[package]] @@ -4921,6 +5146,17 @@ dependencies = [ "tracing", ] +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "sharded-slab", + "thread_local", + "tracing-core", +] + [[package]] name = "try-lock" version = "0.2.5" @@ -5004,9 +5240,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-xid" @@ -5062,7 +5298,7 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "utils" version = "0.1.0" -source = "git+https://github.com/keep-starknet-strange/zaun?branch=main#dab8928ecdfe1387f8ac0f223378ed36708c8c09" +source = "git+https://github.com/karnotxyz/zaun?rev=782967e5#782967e5e488d447ae989406bf0e1bfc1371493f" dependencies = [ "async-trait", "ethers", @@ -5082,6 +5318,12 @@ dependencies = [ "serde", ] +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "version_check" version = "0.9.4" diff --git a/Cargo.toml b/Cargo.toml index 9110913..086abf0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,29 +16,33 @@ serde_with = { version = "2.3.3", default-features = false } url = "2.4.1" # Zaun Deps -ethereum-instance = { git = "https://github.com/keep-starknet-strange/zaun", package = "ethereum-instance", branch = "main" } -starkgate-manager-client = { git = "https://github.com/keep-starknet-strange/zaun", package = "starkgate-manager-client", branch = "main" } -starkgate-registry-client = { git = "https://github.com/keep-starknet-strange/zaun", package = "starkgate-registry-client", branch = "main" } -starknet-core-contract-client = { git = "https://github.com/keep-starknet-strange/zaun", package = "starknet-core-contract-client", branch = "main" } -starknet-erc20-client = { git = "https://github.com/keep-starknet-strange/zaun", package = "starknet-erc20-client", branch = "main" } -starknet-eth-bridge-client = { git = "https://github.com/keep-starknet-strange/zaun", package = "starknet-eth-bridge-client", branch = "main" } -starknet-proxy-client = { git = "https://github.com/keep-starknet-strange/zaun", package = "starknet-proxy-client", branch = "main" } -starknet-token-bridge-client = { git = "https://github.com/keep-starknet-strange/zaun", package = "starknet-token-bridge-client", branch = "main" } -zaun-utils = { git = "https://github.com/keep-starknet-strange/zaun", package = "utils", branch = "main" } +ethereum-instance = { git = "https://github.com/karnotxyz/zaun", package = "ethereum-instance", rev = "782967e5" } +starkgate-manager-client = { git = "https://github.com/karnotxyz/zaun", package = "starkgate-manager-client", rev = "782967e5" } +starkgate-registry-client = { git = "https://github.com/karnotxyz/zaun", package = "starkgate-registry-client", rev = "782967e5" } +starknet-core-contract-client = { git = "https://github.com/karnotxyz/zaun", package = "starknet-core-contract-client", rev = "782967e5" } +starknet-erc20-client = { git = "https://github.com/karnotxyz/zaun", package = "starknet-erc20-client", rev = "782967e5" } +starknet-eth-bridge-client = { git = "https://github.com/karnotxyz/zaun", package = "starknet-eth-bridge-client", rev = "782967e5" } +starknet-proxy-client = { git = "https://github.com/karnotxyz/zaun", package = "starknet-proxy-client", rev = "782967e5" } +starknet-token-bridge-client = { git = "https://github.com/karnotxyz/zaun", package = "starknet-token-bridge-client", rev = "782967e5" } +zaun-utils = { git = "https://github.com/karnotxyz/zaun", package = "utils", rev = "782967e5" } # Starknet Deps -starknet-accounts = { git = "https://github.com/xJonathanLEI/starknet-rs.git", rev = "2d59636911628260fa460179010bbd00e89de06e" } -starknet-core = { git = "https://github.com/xJonathanLEI/starknet-rs.git", rev = "2d59636911628260fa460179010bbd00e89de06e" } -starknet-crypto = { git = "https://github.com/xJonathanLEI/starknet-rs.git", rev = "2d59636911628260fa460179010bbd00e89de06e" } -starknet-ff = { git = "https://github.com/xJonathanLEI/starknet-rs.git", rev = "2d59636911628260fa460179010bbd00e89de06e" } -starknet-providers = { git = "https://github.com/xJonathanLEI/starknet-rs.git", rev = "2d59636911628260fa460179010bbd00e89de06e" } -starknet-signers = { git = "https://github.com/xJonathanLEI/starknet-rs.git", rev = "2d59636911628260fa460179010bbd00e89de06e" } +starknet = "0.11.0" +starknet-accounts = "0.11.0" +starknet-core = "0.11" +starknet-crypto = "0.7" +starknet-providers = "0.11" +starknet-signers = "0.9" +starknet-types-core = { version = "0.1.5", default-features = false, features = [ + "hash", +] } starknet_api = { git = "https://github.com/bidzyyys/starknet-api.git", branch = "feature/scale-codec" } # Third Party assert_matches = "1.5.0" async-trait = "0.1.74" clap = { version = "4.4.11", features = ["derive", "env"] } +color-eyre = "0.6.2" dotenv = "0.15.0" env_logger = "0.11.3" log = "0.4.21" @@ -58,4 +62,6 @@ bytes = "1.6.0" flate2 = "1.0.30" indexmap = "2.2.6" inline_colorization = "0.1.6" +lazy_static = "1.4.0" subxt-lightclient = { version = "0.35.3", optional = true, default-features = false } +tempfile = "3.10.1" diff --git a/bin/madara b/bin/madara deleted file mode 100755 index 5a052ad..0000000 Binary files a/bin/madara and /dev/null differ diff --git a/src/configs/devnet.json b/src/configs/devnet.json new file mode 100644 index 0000000..1a2b2f0 --- /dev/null +++ b/src/configs/devnet.json @@ -0,0 +1,22 @@ +{ + "eth_rpc": "http://127.0.0.1:8545", + "eth_priv_key": "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", + "rollup_seq_url": "http://127.0.0.1:9944", + "rollup_priv_key": "0xabcd", + "eth_chain_id": 31337, + "l1_deployer_address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "l1_wait_time": "15", + "sn_os_program_hash": "0x41fc2a467ef8649580631912517edcab7674173f1dbfa2e9b64fbcd82bc4d79", + "config_hash_version": "StarknetOsConfig2", + "app_chain_id": "MADARA_DEVNET", + "fee_token_address": "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + "native_fee_token_address": "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d", + "cross_chain_wait_time": 20, + "l1_multisig_address": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "l2_multisig_address": "0x556455b8ac8bc00e0ad061d7df5458fa3c372304877663fa21d492a8d5e9435", + "verifier_address": "0x000000000000000000000000000000000000abcd", + "operator_address": "0x000000000000000000000000000000000000abcd", + "dev": false, + "core_contract_address": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512", + "core_contract_implementation_address": "0x5fbdb2315678afecb367f032d93f642f64180aa3" +} diff --git a/src/contract_clients/config.rs b/src/contract_clients/config.rs index 2685404..cfe8997 100644 --- a/src/contract_clients/config.rs +++ b/src/contract_clients/config.rs @@ -1,16 +1,15 @@ use ethereum_instance::EthereumClient; -use starknet_providers::jsonrpc::HttpTransport; -use starknet_providers::JsonRpcClient; -use url::Url; +use starknet::providers::jsonrpc::{HttpTransport, JsonRpcClient}; +use starknet::providers::Url; -use crate::CliArgs; +use crate::ConfigFile; -pub struct Config { +pub struct Clients { eth_client: EthereumClient, provider_l2: JsonRpcClient, } -impl Config { +impl Clients { pub fn provider_l2(&self) -> &JsonRpcClient { &self.provider_l2 } @@ -20,16 +19,31 @@ impl Config { } /// To deploy the instance of ethereum and starknet and returning the struct. - pub async fn init(config: &CliArgs) -> Self { + // pub async fn init(config: &CliArgs) -> Self { + // let client_instance = EthereumClient::attach( + // Option::from(config.eth_rpc.clone()), + // Option::from(config.eth_priv_key.clone()), + // Option::from(config.eth_chain_id), + // ) + // .unwrap(); + // + // let provider_l2 = JsonRpcClient::new(HttpTransport::new( + // Url::parse(&config.rollup_seq_url).expect("Failed to declare provider for app chain"), + // )); + // + // Self { eth_client: client_instance, provider_l2 } + // } + + pub async fn init_from_config(config_file: &ConfigFile) -> Self { let client_instance = EthereumClient::attach( - Option::from(config.eth_rpc.clone()), - Option::from(config.eth_priv_key.clone()), - Option::from(config.eth_chain_id), + Option::from(config_file.eth_rpc.clone()), + Option::from(config_file.eth_priv_key.clone()), + Option::from(config_file.eth_chain_id), ) .unwrap(); let provider_l2 = JsonRpcClient::new(HttpTransport::new( - Url::parse(&config.rollup_seq_url).expect("Failed to declare provider for app chain"), + Url::parse(&config_file.rollup_seq_url).expect("Failed to declare provider for app chain"), )); Self { eth_client: client_instance, provider_l2 } diff --git a/src/contract_clients/core_contract.rs b/src/contract_clients/core_contract.rs index 8468a36..5d85bf6 100644 --- a/src/contract_clients/core_contract.rs +++ b/src/contract_clients/core_contract.rs @@ -5,12 +5,11 @@ use async_trait::async_trait; use ethers::abi::AbiEncode; use ethers::addressbook::Address; use ethers::prelude::{Bytes, I256, U256}; -use starknet_api::hash::{StarkFelt, StarkHash}; -use starknet_ff::FieldElement; +use starknet::core::types::Felt; use starknet_proxy_client::interfaces::proxy::{CoreContractInitData, CoreContractState}; use zaun_utils::LocalWalletSignerMiddleware; -use crate::contract_clients::config::Config; +use crate::contract_clients::config::Clients; use crate::utils::convert_felt_to_u256; #[async_trait] @@ -26,10 +25,11 @@ pub trait CoreContract { #[allow(clippy::too_many_arguments)] async fn add_implementation_core_contract( &self, - block_number: StarkFelt, - state_root: StarkFelt, - program_hash: FieldElement, - config_hash: StarkHash, + block_number: Felt, + state_root: Felt, + block_hash: Felt, + program_hash: Felt, + config_hash: Felt, implementation_address: Address, verifier_address: Address, finalized: bool, @@ -38,10 +38,11 @@ pub trait CoreContract { #[allow(clippy::too_many_arguments)] async fn upgrade_to_core_contract( &self, - block_number: StarkFelt, - state_root: StarkFelt, - program_hash: FieldElement, - config_hash: StarkHash, + block_number: Felt, + state_root: Felt, + block_hash: Felt, + program_hash: Felt, + config_hash: Felt, implementation_address: Address, verifier_address: Address, finalized: bool, @@ -53,41 +54,40 @@ pub trait CoreContract { async fn nominate_governor_core_contract_proxy(&self, l1_governor_address: Address); - async fn initialize(&self, program_hash: StarkFelt, config_hash: StarkFelt); + async fn initialize(&self, program_hash: Felt, config_hash: Felt); async fn initialize_core_contract( &self, - block_number: StarkFelt, - state_root: StarkFelt, - program_hash: FieldElement, - config_hash: StarkHash, + block_number: Felt, + state_root: Felt, + block_hash: Felt, + program_hash: Felt, + config_hash: Felt, verifer_address: Address, ); } pub trait CoreContractDeploy { - fn deploy(config: &Config) -> impl Future + Send; + fn deploy(clients: &Clients) -> impl Future + Send; } pub fn get_init_data_core_contract( - block_number: StarkFelt, - state_root: StarkFelt, - program_hash: StarkFelt, - config_hash: StarkHash, + block_number: Felt, + state_root: Felt, + block_hash: Felt, + program_hash: Felt, + config_hash: Felt, verifier_address: Address, ) -> CoreContractInitData { CoreContractInitData { program_hash: convert_felt_to_u256(program_hash), // zero program hash would be deemed invalid + aggregate_program_hash: U256::zero(), verifier_address, config_hash: convert_felt_to_u256(config_hash), - // TODO : - // Figure out the exact params for production env initial_state: CoreContractState { block_number: I256::from_raw(convert_felt_to_u256(block_number)), state_root: convert_felt_to_u256(state_root), - // TODO : - // Remove hardcoded values. - block_hash: U256::zero(), + block_hash: convert_felt_to_u256(block_hash), }, } } diff --git a/src/contract_clients/eth_bridge.rs b/src/contract_clients/eth_bridge.rs index f6df7ba..23ab326 100644 --- a/src/contract_clients/eth_bridge.rs +++ b/src/contract_clients/eth_bridge.rs @@ -4,13 +4,13 @@ use async_trait::async_trait; use ethers::addressbook::Address; use ethers::providers::Middleware; use ethers::types::{Bytes, U256}; -use starknet_accounts::{Account, ConnectedAccount}; +use starknet::accounts::{Account, ConnectedAccount}; +use starknet::core::types::Felt; use starknet_eth_bridge_client::clients::eth_bridge::StarknetEthBridgeContractClient; use starknet_eth_bridge_client::interfaces::eth_bridge::StarknetEthBridgeTrait; use starknet_eth_bridge_client::{ deploy_starknet_eth_bridge_behind_safe_proxy, deploy_starknet_eth_bridge_behind_unsafe_proxy, }; -use starknet_ff::FieldElement; use starknet_providers::jsonrpc::HttpTransport; use starknet_providers::JsonRpcClient; use starknet_proxy_client::interfaces::proxy::ProxySupport3_0_2Trait; @@ -60,15 +60,15 @@ impl StarknetLegacyEthBridge { pub async fn deploy_l2_contracts( rpc_provider_l2: &JsonRpcClient, - legacy_eth_bridge_class_hash: FieldElement, - legacy_eth_bridge_proxy_address: FieldElement, + legacy_eth_bridge_class_hash: Felt, + legacy_eth_bridge_proxy_address: Felt, account: &RpcAccount<'_>, - ) -> FieldElement { + ) -> Felt { let deploy_tx = account .invoke_contract( account.address(), "deploy_contract", - vec![legacy_eth_bridge_class_hash, FieldElement::ZERO, FieldElement::ZERO, FieldElement::ZERO], + vec![legacy_eth_bridge_class_hash, Felt::ZERO, Felt::ZERO, Felt::ZERO], None, ) .send() @@ -83,12 +83,12 @@ impl StarknetLegacyEthBridge { .unwrap(); let contract_address = get_contract_address_from_deploy_tx(account.provider(), &deploy_tx).await.unwrap(); - log::debug!("🎡 contract address (eth bridge) : {:?}", contract_address); + log::info!("🎡 contract address (eth bridge) : {:?}", contract_address); let add_implementation_txn = invoke_contract( legacy_eth_bridge_proxy_address, "add_implementation", - vec![contract_address, FieldElement::ZERO, FieldElement::ONE, account.address(), FieldElement::ZERO], + vec![contract_address, Felt::ZERO, Felt::ONE, account.address(), Felt::ZERO], account, ) .await; @@ -104,7 +104,7 @@ impl StarknetLegacyEthBridge { let upgrade_to_txn = invoke_contract( legacy_eth_bridge_proxy_address, "upgrade_to", - vec![contract_address, FieldElement::ZERO, FieldElement::ONE, account.address(), FieldElement::ZERO], + vec![contract_address, Felt::ZERO, Felt::ONE, account.address(), Felt::ZERO], account, ) .await; @@ -158,7 +158,7 @@ impl StarknetLegacyEthBridge { calldata.extend(empty_bytes); calldata.extend(padded_messaging_bytes); - log::debug!("🎡 add_implementation_eth_bridge : bytes : {:?}", Bytes::from(calldata.clone())); + log::info!("🎡 add_implementation_eth_bridge : bytes : {:?}", Bytes::from(calldata.clone())); self.eth_bridge .add_implementation(Bytes::from(calldata), self.implementation_address(), false) @@ -185,7 +185,7 @@ impl StarknetLegacyEthBridge { calldata.extend(empty_bytes); calldata.extend(padded_messaging_bytes); - log::debug!("🎡 upgrade_to_eth_bridge : bytes : {:?}", Bytes::from(calldata.clone())); + log::info!("🎡 upgrade_to_eth_bridge : bytes : {:?}", Bytes::from(calldata.clone())); self.eth_bridge .upgrade_to(Bytes::from(calldata), self.implementation_address(), false) @@ -198,7 +198,7 @@ impl StarknetLegacyEthBridge { &self, max_total_balance: &str, max_deposit: &str, - l2_bridge: FieldElement, + l2_bridge: Felt, l1_multisig_address: Address, is_dev: bool, ) { @@ -215,36 +215,36 @@ impl StarknetLegacyEthBridge { pub async fn setup_l2_bridge( &self, rpc_provider: &JsonRpcClient, - l2_bridge_address: FieldElement, - erc20_address: FieldElement, + l2_bridge_address: Felt, + erc20_address: Felt, l2_deployer_address: &str, account: &RpcAccount<'_>, ) { let tx = invoke_contract( l2_bridge_address, "initialize", - vec![FieldElement::from_dec_str("1").unwrap(), FieldElement::from_hex_be(l2_deployer_address).unwrap()], + vec![Felt::from_dec_str("1").unwrap(), Felt::from_hex(l2_deployer_address).unwrap()], account, ) .await; - log::debug!("🎡 setup_l2_bridge : l2 bridge initialized //"); + log::info!("🎡 setup_l2_bridge : l2 bridge initialized //"); wait_for_transaction(rpc_provider, tx.transaction_hash, "setup_l2_bridge : initialize").await.unwrap(); let tx = invoke_contract(l2_bridge_address, "set_l2_token", vec![erc20_address], account).await; - log::debug!("🎡 setup_l2_bridge : l2 token set //"); + log::info!("🎡 setup_l2_bridge : l2 token set //"); wait_for_transaction(rpc_provider, tx.transaction_hash, "setup_l2_bridge : set_l2_token").await.unwrap(); let tx = invoke_contract( l2_bridge_address, "set_l1_bridge", - vec![FieldElement::from_byte_slice_be(self.eth_bridge.address().as_bytes()).unwrap()], + vec![Felt::from_bytes_be_slice(self.eth_bridge.address().as_bytes())], account, ) .await; - log::debug!("🎡 setup_l2_bridge : l1 bridge set //"); + log::info!("🎡 setup_l2_bridge : l1 bridge set //"); wait_for_transaction(rpc_provider, tx.transaction_hash, "setup_l2_bridge : set_l1_bridge").await.unwrap(); } diff --git a/src/contract_clients/legacy_class.rs b/src/contract_clients/legacy_class.rs new file mode 100644 index 0000000..779595d --- /dev/null +++ b/src/contract_clients/legacy_class.rs @@ -0,0 +1,465 @@ +// Note: This code has been taken from the madara code-base. + +use starknet_types_core::felt::Felt; + +#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct EntryPointsByType { + pub constructor: Vec, + pub external: Vec, + pub l1_handler: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct SierraEntryPoint { + pub selector: Felt, + pub function_idx: u64, +} + +#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct CompressedLegacyContractClass { + pub program: Vec, + pub entry_points_by_type: LegacyEntryPointsByType, + pub abi: Option>, +} + +#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct LegacyEntryPointsByType { + #[serde(rename = "CONSTRUCTOR")] + pub constructor: Vec, + #[serde(rename = "EXTERNAL")] + pub external: Vec, + #[serde(rename = "L1_HANDLER")] + pub l1_handler: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct LegacyContractEntryPoint { + pub offset: u64, + pub selector: Felt, +} + +#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub enum LegacyContractAbiEntry { + Function(LegacyFunctionAbiEntry), + Event(LegacyEventAbiEntry), + Struct(LegacyStructAbiEntry), +} + +#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct LegacyFunctionAbiEntry { + pub r#type: LegacyFunctionAbiType, + pub name: String, + pub inputs: Vec, + pub outputs: Vec, + #[serde(rename = "stateMutability")] + pub state_mutability: Option, +} + +#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct LegacyEventAbiEntry { + pub r#type: LegacyEventAbiType, + pub name: String, + pub keys: Vec, + pub data: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct LegacyStructAbiEntry { + pub r#type: LegacyStructAbiType, + pub name: String, + pub size: u64, + pub members: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct LegacyStructMember { + pub name: String, + pub r#type: String, + pub offset: u64, +} + +#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct LegacyTypedParameter { + pub name: String, + pub r#type: String, +} + +#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub enum LegacyFunctionAbiType { + #[serde(rename = "function")] + Function, + #[serde(rename = "l1_handler")] + L1Handler, + #[serde(rename = "constructor")] + Constructor, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub enum LegacyEventAbiType { + #[serde(rename = "event")] + Event, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub enum LegacyStructAbiType { + #[serde(rename = "struct")] + Struct, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub enum FunctionStateMutability { + #[serde(rename = "view")] + View, +} + +impl From for EntryPointsByType { + fn from(entry_points_by_type: starknet_core::types::EntryPointsByType) -> Self { + EntryPointsByType { + constructor: entry_points_by_type + .constructor + .into_iter() + .map(|sierra_entry_point| sierra_entry_point.into()) + .collect(), + external: entry_points_by_type + .external + .into_iter() + .map(|sierra_entry_point| sierra_entry_point.into()) + .collect(), + l1_handler: entry_points_by_type + .l1_handler + .into_iter() + .map(|sierra_entry_point| sierra_entry_point.into()) + .collect(), + } + } +} + +impl From for starknet_core::types::EntryPointsByType { + fn from(entry_points_by_type: EntryPointsByType) -> Self { + starknet_core::types::EntryPointsByType { + constructor: entry_points_by_type + .constructor + .into_iter() + .map(|sierra_entry_point| sierra_entry_point.into()) + .collect(), + external: entry_points_by_type + .external + .into_iter() + .map(|sierra_entry_point| sierra_entry_point.into()) + .collect(), + l1_handler: entry_points_by_type + .l1_handler + .into_iter() + .map(|sierra_entry_point| sierra_entry_point.into()) + .collect(), + } + } +} + +impl From for SierraEntryPoint { + fn from(sierra_entry_point: starknet_core::types::SierraEntryPoint) -> Self { + SierraEntryPoint { selector: sierra_entry_point.selector, function_idx: sierra_entry_point.function_idx } + } +} + +impl From for starknet_core::types::SierraEntryPoint { + fn from(sierra_entry_point: SierraEntryPoint) -> Self { + starknet_core::types::SierraEntryPoint { + selector: sierra_entry_point.selector, + function_idx: sierra_entry_point.function_idx, + } + } +} + +impl From for CompressedLegacyContractClass { + fn from(compressed_legacy_contract_class: starknet_core::types::CompressedLegacyContractClass) -> Self { + CompressedLegacyContractClass { + program: compressed_legacy_contract_class.program, + entry_points_by_type: compressed_legacy_contract_class.entry_points_by_type.into(), + abi: compressed_legacy_contract_class + .abi + .map(|abi| abi.into_iter().map(|legacy_contract_abi_entry| legacy_contract_abi_entry.into()).collect()), + } + } +} + +impl From for starknet_core::types::CompressedLegacyContractClass { + fn from(compressed_legacy_contract_class: CompressedLegacyContractClass) -> Self { + starknet_core::types::CompressedLegacyContractClass { + program: compressed_legacy_contract_class.program, + entry_points_by_type: compressed_legacy_contract_class.entry_points_by_type.into(), + abi: compressed_legacy_contract_class + .abi + .map(|abi| abi.into_iter().map(|legacy_contract_abi_entry| legacy_contract_abi_entry.into()).collect()), + } + } +} + +impl From for LegacyEntryPointsByType { + fn from(legacy_entry_points_by_type: starknet_core::types::LegacyEntryPointsByType) -> Self { + LegacyEntryPointsByType { + constructor: legacy_entry_points_by_type + .constructor + .into_iter() + .map(|legacy_contract_entry_point| legacy_contract_entry_point.into()) + .collect(), + external: legacy_entry_points_by_type + .external + .into_iter() + .map(|legacy_contract_entry_point| legacy_contract_entry_point.into()) + .collect(), + l1_handler: legacy_entry_points_by_type + .l1_handler + .into_iter() + .map(|legacy_contract_entry_point| legacy_contract_entry_point.into()) + .collect(), + } + } +} + +impl From for starknet_core::types::LegacyEntryPointsByType { + fn from(legacy_entry_points_by_type: LegacyEntryPointsByType) -> Self { + starknet_core::types::LegacyEntryPointsByType { + constructor: legacy_entry_points_by_type + .constructor + .into_iter() + .map(|legacy_contract_entry_point| legacy_contract_entry_point.into()) + .collect(), + external: legacy_entry_points_by_type + .external + .into_iter() + .map(|legacy_contract_entry_point| legacy_contract_entry_point.into()) + .collect(), + l1_handler: legacy_entry_points_by_type + .l1_handler + .into_iter() + .map(|legacy_contract_entry_point| legacy_contract_entry_point.into()) + .collect(), + } + } +} + +impl From for LegacyContractEntryPoint { + fn from(legacy_contract_entry_point: starknet_core::types::LegacyContractEntryPoint) -> Self { + LegacyContractEntryPoint { + offset: legacy_contract_entry_point.offset, + selector: legacy_contract_entry_point.selector, + } + } +} + +impl From for starknet_core::types::LegacyContractEntryPoint { + fn from(legacy_contract_entry_point: LegacyContractEntryPoint) -> Self { + starknet_core::types::LegacyContractEntryPoint { + offset: legacy_contract_entry_point.offset, + selector: legacy_contract_entry_point.selector, + } + } +} + +impl From for LegacyContractAbiEntry { + fn from(legacy_contract_abi_entry: starknet_core::types::LegacyContractAbiEntry) -> Self { + match legacy_contract_abi_entry { + starknet_core::types::LegacyContractAbiEntry::Function(legacy_function_abi_entry) => { + LegacyContractAbiEntry::Function(legacy_function_abi_entry.into()) + } + starknet_core::types::LegacyContractAbiEntry::Event(legacy_event_abi_entry) => { + LegacyContractAbiEntry::Event(legacy_event_abi_entry.into()) + } + starknet_core::types::LegacyContractAbiEntry::Struct(legacy_struct_abi_entry) => { + LegacyContractAbiEntry::Struct(legacy_struct_abi_entry.into()) + } + } + } +} + +impl From for starknet_core::types::LegacyContractAbiEntry { + fn from(legacy_contract_abi_entry: LegacyContractAbiEntry) -> Self { + match legacy_contract_abi_entry { + LegacyContractAbiEntry::Function(legacy_function_abi_entry) => { + starknet_core::types::LegacyContractAbiEntry::Function(legacy_function_abi_entry.into()) + } + LegacyContractAbiEntry::Event(legacy_event_abi_entry) => { + starknet_core::types::LegacyContractAbiEntry::Event(legacy_event_abi_entry.into()) + } + LegacyContractAbiEntry::Struct(legacy_struct_abi_entry) => { + starknet_core::types::LegacyContractAbiEntry::Struct(legacy_struct_abi_entry.into()) + } + } + } +} + +impl From for LegacyFunctionAbiEntry { + fn from(legacy_function_abi_entry: starknet_core::types::LegacyFunctionAbiEntry) -> Self { + LegacyFunctionAbiEntry { + r#type: legacy_function_abi_entry.r#type.into(), + name: legacy_function_abi_entry.name, + inputs: legacy_function_abi_entry.inputs.into_iter().map(|abi_entry| abi_entry.into()).collect(), + outputs: legacy_function_abi_entry.outputs.into_iter().map(|abi_entry| abi_entry.into()).collect(), + state_mutability: legacy_function_abi_entry + .state_mutability + .map(|state_mutability| state_mutability.into()), + } + } +} + +impl From for starknet_core::types::LegacyFunctionAbiEntry { + fn from(legacy_function_abi_entry: LegacyFunctionAbiEntry) -> Self { + starknet_core::types::LegacyFunctionAbiEntry { + r#type: legacy_function_abi_entry.r#type.into(), + name: legacy_function_abi_entry.name, + inputs: legacy_function_abi_entry.inputs.into_iter().map(|abi_entry| abi_entry.into()).collect(), + outputs: legacy_function_abi_entry.outputs.into_iter().map(|abi_entry| abi_entry.into()).collect(), + state_mutability: legacy_function_abi_entry + .state_mutability + .map(|state_mutability| state_mutability.into()), + } + } +} + +impl From for LegacyEventAbiEntry { + fn from(legacy_event_abi_entry: starknet_core::types::LegacyEventAbiEntry) -> Self { + LegacyEventAbiEntry { + r#type: legacy_event_abi_entry.r#type.into(), + name: legacy_event_abi_entry.name, + keys: legacy_event_abi_entry.keys.into_iter().map(|abi_entry| abi_entry.into()).collect(), + data: legacy_event_abi_entry.data.into_iter().map(|abi_entry| abi_entry.into()).collect(), + } + } +} + +impl From for starknet_core::types::LegacyEventAbiEntry { + fn from(legacy_event_abi_entry: LegacyEventAbiEntry) -> Self { + starknet_core::types::LegacyEventAbiEntry { + r#type: legacy_event_abi_entry.r#type.into(), + name: legacy_event_abi_entry.name, + keys: legacy_event_abi_entry.keys.into_iter().map(|abi_entry| abi_entry.into()).collect(), + data: legacy_event_abi_entry.data.into_iter().map(|abi_entry| abi_entry.into()).collect(), + } + } +} + +impl From for LegacyStructAbiEntry { + fn from(legacy_struct_abi_entry: starknet_core::types::LegacyStructAbiEntry) -> Self { + LegacyStructAbiEntry { + r#type: legacy_struct_abi_entry.r#type.into(), + name: legacy_struct_abi_entry.name, + size: legacy_struct_abi_entry.size, + members: legacy_struct_abi_entry.members.into_iter().map(|member| member.into()).collect(), + } + } +} + +impl From for starknet_core::types::LegacyStructAbiEntry { + fn from(legacy_struct_abi_entry: LegacyStructAbiEntry) -> Self { + starknet_core::types::LegacyStructAbiEntry { + r#type: legacy_struct_abi_entry.r#type.into(), + name: legacy_struct_abi_entry.name, + size: legacy_struct_abi_entry.size, + members: legacy_struct_abi_entry.members.into_iter().map(|member| member.into()).collect(), + } + } +} + +impl From for LegacyStructMember { + fn from(legacy_struct_member: starknet_core::types::LegacyStructMember) -> Self { + LegacyStructMember { + name: legacy_struct_member.name, + r#type: legacy_struct_member.r#type, + offset: legacy_struct_member.offset, + } + } +} + +impl From for starknet_core::types::LegacyStructMember { + fn from(legacy_struct_member: LegacyStructMember) -> Self { + starknet_core::types::LegacyStructMember { + name: legacy_struct_member.name, + r#type: legacy_struct_member.r#type, + offset: legacy_struct_member.offset, + } + } +} + +impl From for LegacyTypedParameter { + fn from(legacy_typed_parameter: starknet_core::types::LegacyTypedParameter) -> Self { + LegacyTypedParameter { r#type: legacy_typed_parameter.r#type, name: legacy_typed_parameter.name } + } +} + +impl From for starknet_core::types::LegacyTypedParameter { + fn from(legacy_typed_parameter: LegacyTypedParameter) -> Self { + starknet_core::types::LegacyTypedParameter { + r#type: legacy_typed_parameter.r#type, + name: legacy_typed_parameter.name, + } + } +} + +impl From for LegacyFunctionAbiType { + fn from(legacy_function_abi_type: starknet_core::types::LegacyFunctionAbiType) -> Self { + match legacy_function_abi_type { + starknet_core::types::LegacyFunctionAbiType::Function => LegacyFunctionAbiType::Function, + starknet_core::types::LegacyFunctionAbiType::L1Handler => LegacyFunctionAbiType::L1Handler, + starknet_core::types::LegacyFunctionAbiType::Constructor => LegacyFunctionAbiType::Constructor, + } + } +} + +impl From for starknet_core::types::LegacyFunctionAbiType { + fn from(legacy_function_abi_type: LegacyFunctionAbiType) -> Self { + match legacy_function_abi_type { + LegacyFunctionAbiType::Function => starknet_core::types::LegacyFunctionAbiType::Function, + LegacyFunctionAbiType::L1Handler => starknet_core::types::LegacyFunctionAbiType::L1Handler, + LegacyFunctionAbiType::Constructor => starknet_core::types::LegacyFunctionAbiType::Constructor, + } + } +} + +impl From for LegacyEventAbiType { + fn from(legacy_event_abi_type: starknet_core::types::LegacyEventAbiType) -> Self { + match legacy_event_abi_type { + starknet_core::types::LegacyEventAbiType::Event => LegacyEventAbiType::Event, + } + } +} + +impl From for starknet_core::types::LegacyEventAbiType { + fn from(legacy_event_abi_type: LegacyEventAbiType) -> Self { + match legacy_event_abi_type { + LegacyEventAbiType::Event => starknet_core::types::LegacyEventAbiType::Event, + } + } +} + +impl From for LegacyStructAbiType { + fn from(legacy_struct_abi_type: starknet_core::types::LegacyStructAbiType) -> Self { + match legacy_struct_abi_type { + starknet_core::types::LegacyStructAbiType::Struct => LegacyStructAbiType::Struct, + } + } +} + +impl From for starknet_core::types::LegacyStructAbiType { + fn from(legacy_struct_abi_type: LegacyStructAbiType) -> Self { + match legacy_struct_abi_type { + LegacyStructAbiType::Struct => starknet_core::types::LegacyStructAbiType::Struct, + } + } +} + +impl From for FunctionStateMutability { + fn from(function_state_mutability: starknet_core::types::FunctionStateMutability) -> Self { + match function_state_mutability { + starknet_core::types::FunctionStateMutability::View => FunctionStateMutability::View, + } + } +} + +impl From for starknet_core::types::FunctionStateMutability { + fn from(function_state_mutability: FunctionStateMutability) -> Self { + match function_state_mutability { + FunctionStateMutability::View => starknet_core::types::FunctionStateMutability::View, + } + } +} diff --git a/src/contract_clients/mod.rs b/src/contract_clients/mod.rs index 3eea932..1265d2f 100644 --- a/src/contract_clients/mod.rs +++ b/src/contract_clients/mod.rs @@ -5,3 +5,5 @@ pub mod starknet_sovereign; pub mod starknet_validity; pub mod token_bridge; pub mod utils; + +pub mod legacy_class; diff --git a/src/contract_clients/starknet_sovereign.rs b/src/contract_clients/starknet_sovereign.rs index 247f567..2b1fcd3 100644 --- a/src/contract_clients/starknet_sovereign.rs +++ b/src/contract_clients/starknet_sovereign.rs @@ -2,15 +2,14 @@ use std::sync::Arc; use async_trait::async_trait; use ethers::types::Address; -use starknet_api::hash::{StarkFelt, StarkHash}; +use starknet::core::types::Felt; use starknet_core_contract_client::clients::StarknetSovereignContractClient; use starknet_core_contract_client::deploy_starknet_sovereign_behind_unsafe_proxy; use starknet_core_contract_client::interfaces::{OperatorTrait, StarknetGovernanceTrait}; -use starknet_ff::FieldElement; use starknet_proxy_client::interfaces::proxy::{CoreContractInitData, ProxyInitializeData, ProxySupport3_0_2Trait}; use zaun_utils::{LocalWalletSignerMiddleware, StarknetContractClient}; -use crate::contract_clients::config::Config; +use crate::contract_clients::config::Clients; use crate::contract_clients::core_contract::{ get_calldata_bytes, get_init_data_core_contract, CoreContract, CoreContractDeploy, }; @@ -21,8 +20,8 @@ pub struct StarknetSovereignContract { } impl CoreContractDeploy for StarknetSovereignContract { - async fn deploy(config: &Config) -> Self { - let client = deploy_starknet_sovereign_behind_unsafe_proxy(config.eth_client().signer().clone()) + async fn deploy(clients: &Clients) -> Self { + let client = deploy_starknet_sovereign_behind_unsafe_proxy(clients.eth_client().signer().clone()) .await .expect("Failed to deploy the starknet contact"); @@ -37,7 +36,7 @@ impl CoreContract for StarknetSovereignContract { } fn implementation_address(&self) -> Address { - log::debug!( + log::info!( "🎡 self.core_contract_client.implementation_address() : {:?}", self.core_contract_client.implementation_address() ); @@ -53,7 +52,7 @@ impl CoreContract for StarknetSovereignContract { async fn initialize_with(&self, init_data: CoreContractInitData) { let data = ProxyInitializeData::<0> { sub_contract_addresses: [], eic_address: Default::default(), init_data }; - log::debug!("ℹī¸ initialize_with : data : {:?}", data); + log::info!("ℹī¸ initialize_with : data : {:?}", data); self.core_contract_client.initialize_with(data).await.expect("Failed to initialize"); @@ -67,21 +66,26 @@ impl CoreContract for StarknetSovereignContract { #[allow(clippy::too_many_arguments)] async fn add_implementation_core_contract( &self, - block_number: StarkFelt, - state_root: StarkFelt, - program_hash: FieldElement, - config_hash: StarkHash, + block_number: Felt, + state_root: Felt, + block_hash: Felt, + program_hash: Felt, + config_hash: Felt, implementation_address: Address, verifier_address: Address, finalized: bool, ) { - let program_hash = StarkFelt(program_hash.to_bytes_be()); - - let init_data = - get_init_data_core_contract(block_number, state_root, program_hash, config_hash, verifier_address); + let init_data = get_init_data_core_contract( + block_number, + state_root, + block_hash, + program_hash, + config_hash, + verifier_address, + ); let final_bytes = get_calldata_bytes(init_data.clone()); - log::debug!("ℹī¸ add_implementation : data : {:?} : {:?}", init_data, final_bytes.clone()); + log::info!("ℹī¸ add_implementation : data : {:?} : {:?}", init_data, final_bytes.clone()); // https://sepolia.etherscan.io/tx/0x9ac02beb912e5c6226828110380d727a6fd7e4748cbded2198cdf62ea78dab62 // let bytes_etherscan = @@ -94,28 +98,33 @@ impl CoreContract for StarknetSovereignContract { .await .expect("Failed to call add implementation"); - log::debug!("ℹī¸ add_implementation : done"); + log::info!("ℹī¸ add_implementation : done"); } /// Add implementation Starknet core contract with the specified data. #[allow(clippy::too_many_arguments)] async fn upgrade_to_core_contract( &self, - block_number: StarkFelt, - state_root: StarkFelt, - program_hash: FieldElement, - config_hash: StarkHash, + block_number: Felt, + state_root: Felt, + block_hash: Felt, + program_hash: Felt, + config_hash: Felt, implementation_address: Address, verifier_address: Address, finalized: bool, ) { - let program_hash = StarkFelt(program_hash.to_bytes_be()); - - let init_data = - get_init_data_core_contract(block_number, state_root, program_hash, config_hash, verifier_address); + let init_data = get_init_data_core_contract( + block_number, + state_root, + block_hash, + program_hash, + config_hash, + verifier_address, + ); let final_bytes = get_calldata_bytes(init_data.clone()); - log::debug!("ℹī¸ upgrade_to : data : {:?} : {:?}", init_data, final_bytes.clone()); + log::info!("ℹī¸ upgrade_to : data : {:?} : {:?}", init_data, final_bytes.clone()); // https://sepolia.etherscan.io/tx/0x9ac02beb912e5c6226828110380d727a6fd7e4748cbded2198cdf62ea78dab62 // let bytes_etherscan = @@ -128,13 +137,13 @@ impl CoreContract for StarknetSovereignContract { .await .expect("Failed to call upgrade to"); - log::debug!("ℹī¸ upgrade_to : done"); + log::info!("ℹī¸ upgrade_to : done"); } /// For registering the operator for Starknet Core Contract async fn register_operator_core_contract(&self, operator_address: Address) { self.core_contract_client.register_operator(operator_address).await.expect("Failed to register operator"); - log::debug!("ℹī¸ register_operator : done"); + log::info!("ℹī¸ register_operator : done"); } /// For nominating the governor for Starknet Core Contract @@ -143,7 +152,7 @@ impl CoreContract for StarknetSovereignContract { .starknet_nominate_new_governor(l1_governor_address) .await .expect("Failed to nominate governor"); - log::debug!("ℹī¸ register_operator : done"); + log::info!("ℹī¸ register_operator : done"); } /// For nominating the governor for Starknet Core Contract Proxy @@ -152,13 +161,13 @@ impl CoreContract for StarknetSovereignContract { .proxy_nominate_new_governor(l1_governor_address) .await .expect("Failed to register operator"); - log::debug!("ℹī¸ proxy_nominate_new_governor : done"); + log::info!("ℹī¸ proxy_nominate_new_governor : done"); } /// Initialize Starknet core contract with the specified program and config hashes. The rest of /// parameters will be left default. /// IMP : only need to be called when using unsafe proxy - async fn initialize(&self, program_hash: StarkFelt, config_hash: StarkFelt) { + async fn initialize(&self, program_hash: Felt, config_hash: Felt) { self.initialize_with(CoreContractInitData { program_hash: convert_felt_to_u256(program_hash), config_hash: convert_felt_to_u256(config_hash), @@ -171,16 +180,21 @@ impl CoreContract for StarknetSovereignContract { /// IMP : only need to be called when using unsafe proxy async fn initialize_core_contract( &self, - block_number: StarkFelt, - state_root: StarkFelt, - program_hash: FieldElement, - config_hash: StarkHash, + block_number: Felt, + state_root: Felt, + block_hash: Felt, + program_hash: Felt, + config_hash: Felt, verifer_address: Address, ) { - let program_hash = StarkFelt(program_hash.to_bytes_be()); - - let init_data = - get_init_data_core_contract(block_number, state_root, program_hash, config_hash, verifer_address); + let init_data = get_init_data_core_contract( + block_number, + state_root, + block_hash, + program_hash, + config_hash, + verifer_address, + ); self.initialize_with(init_data).await; } diff --git a/src/contract_clients/starknet_validity.rs b/src/contract_clients/starknet_validity.rs index 270baa1..8dc6c83 100644 --- a/src/contract_clients/starknet_validity.rs +++ b/src/contract_clients/starknet_validity.rs @@ -2,27 +2,26 @@ use std::sync::Arc; use async_trait::async_trait; use ethers::types::Address; -use starknet_api::hash::{StarkFelt, StarkHash}; +use starknet::core::types::Felt; use starknet_core_contract_client::clients::StarknetValidityContractClient; use starknet_core_contract_client::deploy_starknet_validity_behind_safe_proxy; use starknet_core_contract_client::interfaces::{OperatorTrait, StarknetGovernanceTrait}; -use starknet_ff::FieldElement; use starknet_proxy_client::interfaces::proxy::{CoreContractInitData, ProxyInitializeData, ProxySupport3_0_2Trait}; use zaun_utils::{LocalWalletSignerMiddleware, StarknetContractClient}; -use crate::contract_clients::config::Config; +use crate::contract_clients::config::Clients; use crate::contract_clients::core_contract::{ get_calldata_bytes, get_init_data_core_contract, CoreContract, CoreContractDeploy, }; use crate::utils::convert_felt_to_u256; pub struct StarknetValidityContract { - core_contract_client: StarknetValidityContractClient, + pub core_contract_client: StarknetValidityContractClient, } impl CoreContractDeploy for StarknetValidityContract { - async fn deploy(config: &Config) -> Self { - let client = deploy_starknet_validity_behind_safe_proxy(config.eth_client().signer().clone()) + async fn deploy(clients: &Clients) -> Self { + let client = deploy_starknet_validity_behind_safe_proxy(clients.eth_client().signer().clone()) .await .expect("Failed to deploy the starknet contact"); @@ -37,7 +36,7 @@ impl CoreContract for StarknetValidityContract { } fn implementation_address(&self) -> Address { - log::debug!( + log::info!( "🎡 self.core_contract_client.implementation_address() : {:?}", self.core_contract_client.implementation_address() ); @@ -53,7 +52,7 @@ impl CoreContract for StarknetValidityContract { async fn initialize_with(&self, init_data: CoreContractInitData) { let data = ProxyInitializeData::<0> { sub_contract_addresses: [], eic_address: Default::default(), init_data }; - log::debug!("ℹī¸ initialize_with : data : {:?}", data); + log::info!("ℹī¸ initialize_with : data : {:?}", data); self.core_contract_client.initialize_with(data).await.expect("Failed to initialize"); @@ -67,21 +66,26 @@ impl CoreContract for StarknetValidityContract { #[allow(clippy::too_many_arguments)] async fn add_implementation_core_contract( &self, - block_number: StarkFelt, - state_root: StarkFelt, - program_hash: FieldElement, - config_hash: StarkHash, + block_number: Felt, + state_root: Felt, + block_hash: Felt, + program_hash: Felt, + config_hash: Felt, implementation_address: Address, verifier_address: Address, finalized: bool, ) { - let program_hash = StarkFelt(program_hash.to_bytes_be()); - - let init_data = - get_init_data_core_contract(block_number, state_root, program_hash, config_hash, verifier_address); + let init_data = get_init_data_core_contract( + block_number, + state_root, + block_hash, + program_hash, + config_hash, + verifier_address, + ); let final_bytes = get_calldata_bytes(init_data.clone()); - log::debug!("ℹī¸ add_implementation : data : {:?} : {:?}", init_data, final_bytes.clone()); + log::info!("ℹī¸ add_implementation : data : {:?} : {:?}", init_data, final_bytes.clone()); // https://sepolia.etherscan.io/tx/0x9ac02beb912e5c6226828110380d727a6fd7e4748cbded2198cdf62ea78dab62 // let bytes_etherscan = @@ -94,28 +98,33 @@ impl CoreContract for StarknetValidityContract { .await .expect("Failed to call add implementation"); - log::debug!("ℹī¸ add_implementation : done"); + log::info!("ℹī¸ add_implementation : done"); } /// Add implementation Starknet core contract with the specified data. #[allow(clippy::too_many_arguments)] async fn upgrade_to_core_contract( &self, - block_number: StarkFelt, - state_root: StarkFelt, - program_hash: FieldElement, - config_hash: StarkHash, + block_number: Felt, + state_root: Felt, + block_hash: Felt, + program_hash: Felt, + config_hash: Felt, implementation_address: Address, verifier_address: Address, finalized: bool, ) { - let program_hash = StarkFelt(program_hash.to_bytes_be()); - - let init_data = - get_init_data_core_contract(block_number, state_root, program_hash, config_hash, verifier_address); + let init_data = get_init_data_core_contract( + block_number, + state_root, + block_hash, + program_hash, + config_hash, + verifier_address, + ); let final_bytes = get_calldata_bytes(init_data.clone()); - log::debug!("ℹī¸ upgrade_to : data : {:?} : {:?}", init_data, final_bytes.clone()); + log::info!("ℹī¸ upgrade_to : data : {:?} : {:?}", init_data, final_bytes.clone()); // https://sepolia.etherscan.io/tx/0x9ac02beb912e5c6226828110380d727a6fd7e4748cbded2198cdf62ea78dab62 // let bytes_etherscan = @@ -128,13 +137,13 @@ impl CoreContract for StarknetValidityContract { .await .expect("Failed to call upgrade to"); - log::debug!("ℹī¸ upgrade_to : done"); + log::info!("ℹī¸ upgrade_to : done"); } /// For registering the operator for Starknet Core Contract async fn register_operator_core_contract(&self, operator_address: Address) { self.core_contract_client.register_operator(operator_address).await.expect("Failed to register operator"); - log::debug!("ℹī¸ register_operator : done"); + log::info!("ℹī¸ register_operator : done"); } /// For nominating the governor for Starknet Core Contract @@ -143,7 +152,7 @@ impl CoreContract for StarknetValidityContract { .starknet_nominate_new_governor(l1_governor_address) .await .expect("Failed to nominate governor"); - log::debug!("ℹī¸ register_operator : done"); + log::info!("ℹī¸ register_operator : done"); } /// For nominating the governor for Starknet Core Contract Proxy @@ -152,13 +161,13 @@ impl CoreContract for StarknetValidityContract { .proxy_nominate_new_governor(l1_governor_address) .await .expect("Failed to register operator"); - log::debug!("ℹī¸ proxy_nominate_new_governor : done"); + log::info!("ℹī¸ proxy_nominate_new_governor : done"); } /// Initialize Starknet core contract with the specified program and config hashes. The rest of /// parameters will be left default. /// IMP : only need to be called when using unsafe proxy - async fn initialize(&self, program_hash: StarkFelt, config_hash: StarkFelt) { + async fn initialize(&self, program_hash: Felt, config_hash: Felt) { self.initialize_with(CoreContractInitData { program_hash: convert_felt_to_u256(program_hash), config_hash: convert_felt_to_u256(config_hash), @@ -171,16 +180,21 @@ impl CoreContract for StarknetValidityContract { /// IMP : only need to be called when using unsafe proxy async fn initialize_core_contract( &self, - block_number: StarkFelt, - state_root: StarkFelt, - program_hash: FieldElement, - config_hash: StarkHash, + block_number: Felt, + state_root: Felt, + block_hash: Felt, + program_hash: Felt, + config_hash: Felt, verifer_address: Address, ) { - let program_hash = StarkFelt(program_hash.to_bytes_be()); - - let init_data = - get_init_data_core_contract(block_number, state_root, program_hash, config_hash, verifer_address); + let init_data = get_init_data_core_contract( + block_number, + state_root, + block_hash, + program_hash, + config_hash, + verifer_address, + ); self.initialize_with(init_data).await; } diff --git a/src/contract_clients/token_bridge.rs b/src/contract_clients/token_bridge.rs index a2577fd..86f0cda 100644 --- a/src/contract_clients/token_bridge.rs +++ b/src/contract_clients/token_bridge.rs @@ -14,11 +14,11 @@ use starkgate_registry_client::clients::starkgate_registry::StarkgateRegistryCon use starkgate_registry_client::{ deploy_starkgate_registry_behind_safe_proxy, deploy_starkgate_registry_behind_unsafe_proxy, }; -use starknet_accounts::{Account, ConnectedAccount}; +use starknet::accounts::{Account, ConnectedAccount}; +use starknet_core::types::Felt; use starknet_erc20_client::clients::erc20::ERC20ContractClient; use starknet_erc20_client::deploy_dai_erc20_behind_unsafe_proxy; use starknet_erc20_client::interfaces::erc20::ERC20TokenTrait; -use starknet_ff::FieldElement; use starknet_providers::jsonrpc::HttpTransport; use starknet_providers::JsonRpcClient; use starknet_proxy_client::interfaces::proxy::ProxySupport5_0_0Trait; @@ -111,7 +111,7 @@ impl StarknetTokenBridge { rpc_provider_l2: &JsonRpcClient, priv_key: &str, l2_deployer_address: &str, - ) -> FieldElement { + ) -> Felt { let account = build_single_owner_account(rpc_provider_l2, priv_key, l2_deployer_address, false).await; let token_bridge_class_hash = declare_contract(DeclarationInput::DeclarationInputs( @@ -124,19 +124,13 @@ impl StarknetTokenBridge { save_to_json("L2_token_bridge_class_hash", &JsonValueType::StringType(token_bridge_class_hash.to_string())) .unwrap(); - log::debug!("🌗 token_bridge_class_hash : {:?}", token_bridge_class_hash); + log::info!("🌗 token_bridge_class_hash : {:?}", token_bridge_class_hash); let deploy_contract_implementation_token_bridge = account .invoke_contract( account.address(), "deploy_contract", - vec![ - token_bridge_class_hash, - FieldElement::ZERO, - FieldElement::ZERO, - FieldElement::ONE, - FieldElement::ZERO, - ], + vec![token_bridge_class_hash, Felt::ZERO, Felt::ZERO, Felt::ONE, Felt::ZERO], None, ) .send() @@ -154,7 +148,7 @@ impl StarknetTokenBridge { get_contract_address_from_deploy_tx(account.provider(), &deploy_contract_implementation_token_bridge) .await .unwrap(); - log::debug!("🌗 contract address (token bridge) : {:?}", address_token_bridge_impl); + log::info!("🌗 contract address (token bridge) : {:?}", address_token_bridge_impl); address_token_bridge_impl } @@ -215,17 +209,17 @@ impl StarknetTokenBridge { .add_implementation(Bytes::from(manager_calldata.clone()), self.manager.implementation_address(), false) .await .expect("Failed to initialize starkgate manager"); - log::debug!("🎡 add_implementation_token_bridge : manager bytes : {:?}", Bytes::from(manager_calldata)); + log::info!("🎡 add_implementation_token_bridge : manager bytes : {:?}", Bytes::from(manager_calldata)); self.registry .add_implementation(Bytes::from(registry_calldata.clone()), self.registry.implementation_address(), false) .await .expect("Failed to initialize starkgate registry"); - log::debug!("🎡 add_implementation_token_bridge : registry bytes : {:?}", Bytes::from(registry_calldata)); + log::info!("🎡 add_implementation_token_bridge : registry bytes : {:?}", Bytes::from(registry_calldata)); self.token_bridge .add_implementation(Bytes::from(bridge_calldata.clone()), self.token_bridge.implementation_address(), false) .await .expect("Failed to initialize eth bridge"); - log::debug!("🎡 add_implementation_token_bridge : token_bridge bytes : {:?}", Bytes::from(bridge_calldata)); + log::info!("🎡 add_implementation_token_bridge : token_bridge bytes : {:?}", Bytes::from(bridge_calldata)); } /// Upgrade To Starknet Token Bridge @@ -250,17 +244,17 @@ impl StarknetTokenBridge { .upgrade_to(Bytes::from(manager_calldata.clone()), self.manager.implementation_address(), false) .await .expect("Failed to initialize starkgate manager"); - log::debug!("🎡 upgrade_to_token_bridge : manager bytes : {:?}", Bytes::from(manager_calldata)); + log::info!("🎡 upgrade_to_token_bridge : manager bytes : {:?}", Bytes::from(manager_calldata)); self.registry .upgrade_to(Bytes::from(registry_calldata.clone()), self.registry.implementation_address(), false) .await .expect("Failed to initialize starkgate registry"); - log::debug!("🎡 upgrade_to_token_bridge : registry bytes : {:?}", Bytes::from(registry_calldata)); + log::info!("🎡 upgrade_to_token_bridge : registry bytes : {:?}", Bytes::from(registry_calldata)); self.token_bridge .upgrade_to(Bytes::from(bridge_calldata.clone()), self.token_bridge.implementation_address(), false) .await .expect("Failed to initialize eth bridge"); - log::debug!("🎡 upgrade_to_token_bridge : token_bridge bytes : {:?}", Bytes::from(bridge_calldata)); + log::info!("🎡 upgrade_to_token_bridge : token_bridge bytes : {:?}", Bytes::from(bridge_calldata)); } /// Sets up the Token bridge with the specified data @@ -281,7 +275,7 @@ impl StarknetTokenBridge { } /// Deploys a test ERC20 token from L1 to L2 - pub async fn setup_l1_bridge(&self, fee: U256, l2_bridge: FieldElement) { + pub async fn setup_l1_bridge(&self, fee: U256, l2_bridge: Felt) { self.token_bridge.set_l2_token_bridge(field_element_to_u256(l2_bridge)).await.unwrap(); self.manager.enroll_token_bridge(self.address(), fee).await.unwrap(); } @@ -289,18 +283,14 @@ impl StarknetTokenBridge { pub async fn setup_l2_bridge( &self, rpc_provider_l2: &JsonRpcClient, - l2_bridge: FieldElement, + l2_bridge: Felt, l2_address: &str, account: &RpcAccount<'_>, - erc20_class_hash: FieldElement, + erc20_class_hash: Felt, ) { - let tx = invoke_contract( - l2_bridge, - "register_app_role_admin", - vec![FieldElement::from_hex_be(l2_address).unwrap()], - account, - ) - .await; + let tx = + invoke_contract(l2_bridge, "register_app_role_admin", vec![Felt::from_hex(l2_address).unwrap()], account) + .await; wait_for_transaction( rpc_provider_l2, @@ -309,15 +299,11 @@ impl StarknetTokenBridge { ) .await .unwrap(); - log::debug!("🌗 setup_l2_bridge : register_app_role_admin //"); + log::info!("🌗 setup_l2_bridge : register_app_role_admin //"); - let tx = invoke_contract( - l2_bridge, - "register_app_governor", - vec![FieldElement::from_hex_be(l2_address).unwrap()], - account, - ) - .await; + let tx = + invoke_contract(l2_bridge, "register_app_governor", vec![Felt::from_hex(l2_address).unwrap()], account) + .await; wait_for_transaction( rpc_provider_l2, @@ -326,15 +312,11 @@ impl StarknetTokenBridge { ) .await .unwrap(); - log::debug!("🌗 setup_l2_bridge : register_app_governor //"); + log::info!("🌗 setup_l2_bridge : register_app_governor //"); - let tx = invoke_contract( - l2_bridge, - "set_l2_token_governance", - vec![FieldElement::from_hex_be(l2_address).unwrap()], - account, - ) - .await; + let tx = + invoke_contract(l2_bridge, "set_l2_token_governance", vec![Felt::from_hex(l2_address).unwrap()], account) + .await; wait_for_transaction( rpc_provider_l2, @@ -343,7 +325,7 @@ impl StarknetTokenBridge { ) .await .unwrap(); - log::debug!("🌗 setup_l2_bridge : set_l2_token_governance //"); + log::info!("🌗 setup_l2_bridge : set_l2_token_governance //"); let tx = invoke_contract( l2_bridge, @@ -362,19 +344,19 @@ impl StarknetTokenBridge { ) .await .unwrap(); - log::debug!("🌗 setup_l2_bridge : set_erc20_class_hash //"); + log::info!("🌗 setup_l2_bridge : set_erc20_class_hash //"); let tx = invoke_contract( l2_bridge, "set_l1_bridge", - vec![FieldElement::from_byte_slice_be(self.token_bridge.address().as_bytes()).unwrap()], + vec![Felt::from_bytes_be_slice(self.token_bridge.address().as_bytes())], account, ) .await; wait_for_transaction(rpc_provider_l2, tx.transaction_hash, "setup_l2_bridge : token bridge : set_l1_bridge") .await .unwrap(); - log::debug!("🌗 setup_l2_bridge : set_l1_bridge //"); + log::info!("🌗 setup_l2_bridge : set_l1_bridge //"); } pub async fn register_app_role_admin(&self, address: Address) { diff --git a/src/contract_clients/utils.rs b/src/contract_clients/utils.rs index 187959b..490879f 100644 --- a/src/contract_clients/utils.rs +++ b/src/contract_clients/utils.rs @@ -4,20 +4,24 @@ use ethers::types::U256; use hex::encode; use serde::{Deserialize, Serialize}; use serde_json::json; -use starknet_accounts::{Account, AccountFactory, ConnectedAccount, OpenZeppelinAccountFactory, SingleOwnerAccount}; -use starknet_api::hash::{pedersen_hash_array, StarkFelt, StarkHash}; -use starknet_core::types::contract::legacy::LegacyContractClass; -use starknet_core::types::{BlockId, BlockTag, CompressedLegacyContractClass, DeclareTransactionResult, FunctionCall}; -use starknet_core::utils::get_selector_from_name; -use starknet_ff::FieldElement; -use starknet_providers::jsonrpc::HttpTransport; -use starknet_providers::{JsonRpcClient, Provider}; -use starknet_signers::{LocalWallet, SigningKey}; +use starknet::accounts::{ + Account, AccountFactory, ConnectedAccount, ExecutionEncoding, OpenZeppelinAccountFactory, SingleOwnerAccount, +}; +use starknet::core::types::contract::legacy::LegacyContractClass; +use starknet::core::types::{BlockId, BlockTag, DeclareTransactionResult, Felt, FunctionCall}; +use starknet::core::utils::get_selector_from_name; +use starknet::providers::jsonrpc::{HttpTransport, JsonRpcClient}; +use starknet::providers::Provider; +use starknet::signers::{LocalWallet, SigningKey}; +use starknet_core::types::contract::{CompiledClass, SierraClass}; +use starknet_core::types::BlockTag::Pending; +use starknet_types_core::hash::{Pedersen, StarkHash}; +use crate::contract_clients::legacy_class::CompressedLegacyContractClass; use crate::contract_clients::utils::DeclarationInput::{DeclarationInputs, LegacyDeclarationInputs}; use crate::helpers::account_actions::{get_contract_address_from_deploy_tx, AccountActions}; use crate::utils::{invoke_contract, save_to_json, wait_for_transaction, JsonValueType}; -use crate::CliArgs; +use crate::ConfigFile; pub type RpcAccount<'a> = SingleOwnerAccount<&'a JsonRpcClient, LocalWallet>; pub async fn build_single_owner_account<'a>( @@ -26,23 +30,26 @@ pub async fn build_single_owner_account<'a>( account_address: &str, is_legacy: bool, ) -> RpcAccount<'a> { - let signer = LocalWallet::from(SigningKey::from_secret_scalar(FieldElement::from_hex_be(private_key).unwrap())); - let account_address = FieldElement::from_hex_be(account_address).expect("Invalid Contract Address"); - let execution_encoding = if is_legacy { - starknet_accounts::ExecutionEncoding::Legacy - } else { - starknet_accounts::ExecutionEncoding::New - }; + let signer = LocalWallet::from(SigningKey::from_secret_scalar(Felt::from_hex(private_key).unwrap())); + let account_address = Felt::from_hex(account_address).expect("Invalid Contract Address"); + let execution_encoding = if is_legacy { ExecutionEncoding::Legacy } else { ExecutionEncoding::New }; let chain_id = rpc.chain_id().await.unwrap(); - SingleOwnerAccount::new(rpc, signer, account_address, chain_id, execution_encoding) + + // Note: it's a fix for the starknet rs issue, by default, starknet.rs asks for nonce at the latest + // block which causes the issues hence setting the block id to pending so that we get nonce in + // right order + let mut singer_with_pending_id = + SingleOwnerAccount::new(rpc, signer, account_address, chain_id, execution_encoding); + singer_with_pending_id.set_block_id(BlockId::Tag(Pending)); + singer_with_pending_id } pub async fn read_erc20_balance( rpc: &JsonRpcClient, - contract_address: FieldElement, - account_address: FieldElement, -) -> Vec { + contract_address: Felt, + account_address: Felt, +) -> Vec { rpc.call( FunctionCall { contract_address, @@ -55,42 +62,40 @@ pub async fn read_erc20_balance( .unwrap() } -pub fn field_element_to_u256(input: FieldElement) -> U256 { +pub fn field_element_to_u256(input: Felt) -> U256 { U256::from_big_endian(&input.to_bytes_be()) } pub fn generate_config_hash( - config_hash_version: FieldElement, - chain_id: FieldElement, - fee_token_address: FieldElement, -) -> StarkHash { - pedersen_hash_array(&[ - StarkFelt(config_hash_version.to_bytes_be()), - StarkFelt(chain_id.to_bytes_be()), - StarkFelt(fee_token_address.to_bytes_be()), - ]) + config_hash_version: Felt, + chain_id: Felt, + fee_token_address: Felt, + native_fee_token_address: Felt, +) -> Felt { + Pedersen::hash_array(&[config_hash_version, chain_id, fee_token_address, native_fee_token_address]) } -pub fn get_bridge_init_configs(config: &CliArgs) -> (FieldElement, StarkHash) { - let program_hash = FieldElement::from_hex_be(config.sn_os_program_hash.as_str()).unwrap(); +pub fn get_bridge_init_configs(config: &ConfigFile) -> (Felt, Felt) { + let program_hash = Felt::from_hex(config.sn_os_program_hash.as_str()).unwrap(); + let config_hash = generate_config_hash( - FieldElement::from_hex_be(&encode(config.config_hash_version.as_str())).expect("error in config_hash_version"), - FieldElement::from_hex_be(&encode(config.app_chain_id.as_str())).expect("error in app_chain_id"), - FieldElement::from_hex_be(config.fee_token_address.as_str()).expect("error in fee_token_address"), + Felt::from_hex(&encode(config.config_hash_version.as_str())).expect("error in config_hash_version"), + Felt::from_hex(&encode(config.app_chain_id.as_str())).expect("error in app_chain_id"), + Felt::from_hex(config.fee_token_address.as_str()).expect("error in fee_token_address"), + Felt::from_hex(config.native_fee_token_address.as_str()).expect("error in fee_token_address"), ); (program_hash, config_hash) } /// Broadcasted declare contract transaction v0. -#[derive(Debug, Eq, PartialEq, Serialize)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] pub struct BroadcastedDeclareTransactionV0 { /// The address of the account contract sending the declaration transaction - pub sender_address: FieldElement, + pub sender_address: Felt, /// The maximal fee that can be charged for including the transaction - pub max_fee: FieldElement, + pub max_fee: Felt, /// Signature - pub signature: Vec, + pub signature: Vec, /// The class to be declared pub contract_class: Arc, /// If set to `true`, uses a query-only transaction version that's invalid for execution @@ -110,63 +115,80 @@ pub(crate) enum DeclarationInput<'a> { // inputs : sierra_path, casm_path DeclarationInputs(String, String, RpcAccount<'a>), // input : artifact_path - LegacyDeclarationInputs(String, String), + LegacyDeclarationInputs(String, String, &'a JsonRpcClient), } #[allow(private_interfaces)] -pub async fn declare_contract(input: DeclarationInput<'_>) -> FieldElement { +pub async fn declare_contract(input: DeclarationInput<'_>) -> Felt { match input { DeclarationInputs(sierra_path, casm_path, account) => { - let (class_hash, sierra) = account.declare_contract_params_sierra(&sierra_path, &casm_path); + let contract_artifact: SierraClass = + serde_json::from_reader(std::fs::File::open(sierra_path).unwrap()).unwrap(); + + let contract_artifact_casm: CompiledClass = + serde_json::from_reader(std::fs::File::open(casm_path).unwrap()).unwrap(); + let class_hash = contract_artifact_casm.class_hash().unwrap(); + let sierra_class_hash = contract_artifact.class_hash().unwrap(); + + if account.provider().get_class(BlockId::Tag(Pending), sierra_class_hash).await.is_ok() { + return sierra_class_hash; + } + + let flattened_class = contract_artifact.flatten().unwrap(); account - .declare(Arc::new(sierra.clone()), class_hash) + .declare_v3(Arc::new(flattened_class), class_hash) + .gas(0) .send() .await .expect("Error in declaring the contract using Cairo 1 declaration using the provided account"); - sierra.class_hash() + sierra_class_hash } - LegacyDeclarationInputs(artifact_path, url) => { - let contract_abi_artifact_temp: LegacyContractClass = serde_json::from_reader( + LegacyDeclarationInputs(artifact_path, url, provider) => { + let contract_abi_artifact: LegacyContractClass = serde_json::from_reader( std::fs::File::open(env!("CARGO_MANIFEST_DIR").to_owned() + "/" + &artifact_path).unwrap(), ) .unwrap(); - let contract_abi_artifact = - contract_abi_artifact_temp.clone().compress().expect("Error : Failed to compress the contract class"); + let class_hash = contract_abi_artifact.class_hash().expect("Failed to get class hash"); + if provider.get_class(BlockId::Tag(Pending), class_hash).await.is_ok() { + return class_hash; + } + + let contract_abi_artifact: CompressedLegacyContractClass = + contract_abi_artifact.clone().compress().expect("Error : Failed to compress the contract class").into(); let params: BroadcastedDeclareTransactionV0 = BroadcastedDeclareTransactionV0 { - sender_address: FieldElement::from_hex_be("0x1").unwrap(), - max_fee: FieldElement::from(482250u128), + sender_address: Felt::from_hex("0x1").unwrap(), + max_fee: Felt::ZERO, signature: Vec::new(), contract_class: Arc::new(contract_abi_artifact), is_query: false, }; + // TODO: method can be updated based on the madara PR let json_body = &json!({ "jsonrpc": "2.0", - "method": "madara_addDeclareTransactionV0", + "method": "madara_addDeclareV0Transaction", "params": [params], "id": 4 }); let req_client = reqwest::Client::new(); let raw_txn_rpc = req_client.post(url).json(json_body).send().await; - match raw_txn_rpc { Ok(val) => { - log::debug!( + log::info!( "🚧 Txn Sent Successfully : {:?}", val.json::>().await.unwrap() ); } Err(err) => { - log::debug!("Error : Error sending the transaction using RPC"); - log::debug!("{:?}", err); + log::error!("Error : Error sending the transaction using RPC: {:?}", err); } } - contract_abi_artifact_temp.class_hash().unwrap() + class_hash } } } @@ -174,25 +196,30 @@ pub async fn declare_contract(input: DeclarationInput<'_>) -> FieldElement { pub(crate) async fn deploy_account_using_priv_key( priv_key: String, provider: &JsonRpcClient, - oz_account_class_hash: FieldElement, -) -> FieldElement { + oz_account_class_hash: Felt, +) -> Felt { let chain_id = provider.chain_id().await.unwrap(); - let signer = Arc::new(LocalWallet::from_signing_key(SigningKey::from_secret_scalar( - FieldElement::from_hex_be(&priv_key).unwrap(), - ))); - log::trace!("signer : {:?}", signer); + + let signer = LocalWallet::from(SigningKey::from_secret_scalar(Felt::from_hex(&priv_key).unwrap())); + log::debug!("signer : {:?}", signer); let mut oz_account_factory = OpenZeppelinAccountFactory::new(oz_account_class_hash, chain_id, signer, provider).await.unwrap(); oz_account_factory.set_block_id(BlockId::Tag(BlockTag::Pending)); - let deploy_txn = oz_account_factory.deploy(FieldElement::ZERO); + let deploy_txn = oz_account_factory.deploy_v1(Felt::ZERO).max_fee(Felt::ZERO); let account_address = deploy_txn.address(); - log::trace!("OZ Account Deployed : {:?}", account_address); + log::debug!("OZ Account Deploy Address: {:?}", account_address); save_to_json("account_address", &JsonValueType::StringType(account_address.to_string())).unwrap(); + if provider.get_class_at(BlockId::Tag(Pending), account_address).await.is_ok() { + log::info!("ℹī¸ Account is already deployed. Skipping...."); + return account_address; + } + let sent_txn = deploy_txn.send().await.expect("Error in deploying the OZ account"); - log::trace!("deploy account txn_hash : {:?}", sent_txn.transaction_hash); + log::debug!("deploy account txn_hash : {:?}", sent_txn.transaction_hash); + wait_for_transaction(provider, sent_txn.transaction_hash, "deploy_account_using_priv_key").await.unwrap(); account_address @@ -200,35 +227,37 @@ pub(crate) async fn deploy_account_using_priv_key( pub(crate) async fn deploy_proxy_contract( account: &RpcAccount<'_>, - account_address: FieldElement, - class_hash: FieldElement, - salt: FieldElement, - deploy_from_zero: FieldElement, -) -> FieldElement { + account_address: Felt, + class_hash: Felt, + salt: Felt, + deploy_from_zero: Felt, +) -> Felt { let txn = account .invoke_contract( account_address, "deploy_contract", - vec![class_hash, salt, deploy_from_zero, FieldElement::ONE, FieldElement::ZERO], + vec![class_hash, salt, deploy_from_zero, Felt::ONE, Felt::ZERO], None, ) .send() .await .expect("Error deploying the contract proxy."); + log::info!("txn in proxy contract is: {:?}", txn); + wait_for_transaction(account.provider(), txn.transaction_hash, "deploy_proxy_contract : deploy_contract") .await .unwrap(); - log::trace!("txn hash (proxy deployment) : {:?}", txn.transaction_hash); + log::debug!("txn hash (proxy deployment) : {:?}", txn.transaction_hash); let deployed_address = get_contract_address_from_deploy_tx(account.provider(), &txn).await.unwrap(); - log::trace!("[IMP] Event : {:?}", deployed_address); + log::debug!("[IMP] Event : {:?}", deployed_address); deployed_address } -pub(crate) async fn init_governance_proxy(account: &'_ RpcAccount<'_>, contract_address: FieldElement, tag: &str) { +pub(crate) async fn init_governance_proxy(account: &'_ RpcAccount<'_>, contract_address: Felt, tag: &str) { let txn = invoke_contract(contract_address, "init_governance", vec![], account).await; wait_for_transaction(account.provider(), txn.transaction_hash, tag).await.unwrap(); } diff --git a/src/helpers/account_actions.rs b/src/helpers/account_actions.rs index f1e7107..74d7d53 100644 --- a/src/helpers/account_actions.rs +++ b/src/helpers/account_actions.rs @@ -2,72 +2,55 @@ use std::future::Future; use assert_matches::assert_matches; use async_trait::async_trait; -use starknet_accounts::{Account, Call, Execution, SingleOwnerAccount}; -use starknet_api::core::{calculate_contract_address, ClassHash, ContractAddress}; -use starknet_api::transaction::{Calldata, ContractAddressSalt}; -use starknet_core::types::contract::legacy::LegacyContractClass; +use starknet::accounts::{Account, Call, ExecutionV1, SingleOwnerAccount}; +use starknet::core::types::contract::legacy::LegacyContractClass; +use starknet::core::types::{Felt, FlattenedSierraClass, TransactionReceipt}; +use starknet::core::utils::get_selector_from_name; +use starknet::providers::jsonrpc::{HttpTransport, JsonRpcClient}; +use starknet::providers::Provider; +use starknet::signers::LocalWallet; use starknet_core::types::contract::{CompiledClass, SierraClass}; -use starknet_core::types::{ - FlattenedSierraClass, InvokeTransactionResult, MaybePendingTransactionReceipt, TransactionReceipt, -}; -use starknet_core::utils::get_selector_from_name; -use starknet_ff::FieldElement; -use starknet_providers::jsonrpc::HttpTransport; -use starknet_providers::{JsonRpcClient, Provider, ProviderError}; -use starknet_signers::LocalWallet; +use starknet_core::types::{InvokeTransactionResult, TransactionReceiptWithBlockInfo}; +use starknet_providers::ProviderError; use crate::contract_clients::utils::RpcAccount; -use crate::utils::constants::MAX_FEE_OVERRIDE; use crate::utils::wait_for_transaction; -pub struct U256 { - pub high: FieldElement, - pub low: FieldElement, -} - -pub type TransactionExecution<'a> = Execution<'a, RpcAccount<'a>>; +pub type TransactionExecution<'a> = ExecutionV1<'a, RpcAccount<'a>>; #[async_trait] pub trait AccountActions { fn invoke_contract( &self, - address: FieldElement, + address: Felt, method: &str, - calldata: Vec, + calldata: Vec, nonce: Option, ) -> TransactionExecution; - fn declare_contract_params_sierra( - &self, - path_to_sierra: &str, - path_to_casm: &str, - ) -> (FieldElement, FlattenedSierraClass); + fn declare_contract_params_sierra(&self, path_to_sierra: &str, path_to_casm: &str) -> (Felt, FlattenedSierraClass); fn declare_contract_params_legacy(&self, path_to_compiled_contract: &str) -> LegacyContractClass; } impl AccountActions for SingleOwnerAccount<&JsonRpcClient, LocalWallet> { fn invoke_contract( &self, - address: FieldElement, + address: Felt, method: &str, - calldata: Vec, + calldata: Vec, nonce: Option, ) -> TransactionExecution { let calls = vec![Call { to: address, selector: get_selector_from_name(method).unwrap(), calldata }]; - let max_fee = FieldElement::from_hex_be(MAX_FEE_OVERRIDE).unwrap(); - + // TODO: if we have the madara with fee flag set as 0, it shouldn't matter + let max_fee = Felt::ZERO; match nonce { - Some(nonce) => self.execute(calls).max_fee(max_fee).nonce(nonce.into()), - None => self.execute(calls).max_fee(max_fee), + Some(nonce) => self.execute_v1(calls).max_fee(max_fee).nonce(nonce.into()), + None => self.execute_v1(calls).max_fee(max_fee), } } - fn declare_contract_params_sierra( - &self, - path_to_sierra: &str, - path_to_casm: &str, - ) -> (FieldElement, FlattenedSierraClass) { + fn declare_contract_params_sierra(&self, path_to_sierra: &str, path_to_casm: &str) -> (Felt, FlattenedSierraClass) { let sierra: SierraClass = serde_json::from_reader( std::fs::File::open(env!("CARGO_MANIFEST_DIR").to_owned() + "/" + path_to_sierra).unwrap(), ) @@ -109,15 +92,15 @@ where panic!("Max poll count exceeded."); } -type TransactionReceiptResult = Result; +type TransactionReceiptResult = Result; pub async fn get_transaction_receipt( rpc: &JsonRpcClient, - transaction_hash: FieldElement, + transaction_hash: Felt, ) -> TransactionReceiptResult { // there is a delay between the transaction being available at the client - // and the sealing of the block, hence sleeping for 100ms - assert_poll(|| async { rpc.get_transaction_receipt(transaction_hash).await.is_ok() }, 100, 20).await; + // and the sealing of the block, hence sleeping for 500ms + assert_poll(|| async { rpc.get_transaction_receipt(transaction_hash).await.is_ok() }, 500, 20).await; rpc.get_transaction_receipt(transaction_hash).await } @@ -125,7 +108,7 @@ pub async fn get_transaction_receipt( pub async fn get_contract_address_from_deploy_tx( rpc: &JsonRpcClient, tx: &InvokeTransactionResult, -) -> Result { +) -> Result { let deploy_tx_hash = tx.transaction_hash; wait_for_transaction(rpc, deploy_tx_hash, "get_contract_address_from_deploy_tx").await.unwrap(); @@ -134,20 +117,9 @@ pub async fn get_contract_address_from_deploy_tx( let contract_address = assert_matches!( deploy_tx_receipt, - MaybePendingTransactionReceipt::Receipt(TransactionReceipt::Invoke(receipt)) => { + TransactionReceiptWithBlockInfo { receipt: TransactionReceipt::Invoke(receipt), .. } => { receipt.events.iter().find(|e| e.keys[0] == get_selector_from_name("ContractDeployed").unwrap()).unwrap().data[0] } ); Ok(contract_address) } - -pub async fn calculate_deployed_address( - salt: ContractAddressSalt, - class_hash: ClassHash, - calldata: &Calldata, - deployer_address: ContractAddress, -) -> FieldElement { - let address = calculate_contract_address(salt, class_hash, calldata, deployer_address).unwrap(); - let bytes = address.0.0.0; - FieldElement::from_bytes_be(&bytes).unwrap() -} diff --git a/src/main.rs b/src/main.rs index 7ad97ae..7500cd5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,16 +5,27 @@ mod setup_scripts; pub mod tests; pub mod utils; -use clap::{ArgAction, Parser}; +use std::fs::File; +use std::path::PathBuf; +use std::str::FromStr; + +use clap::{Parser, ValueEnum}; +use contract_clients::utils::RpcAccount; use dotenv::dotenv; +use ethers::abi::Address; use inline_colorization::*; -use starknet_accounts::Account; -use starknet_ff::FieldElement; +use serde::{Deserialize, Serialize}; +use setup_scripts::argent::ArgentSetupOutput; +use setup_scripts::braavos::BraavosSetupOutput; +use setup_scripts::core_contract::CoreContractStarknetL1Output; +use setup_scripts::erc20_bridge::Erc20BridgeSetupOutput; +use setup_scripts::eth_bridge::EthBridgeSetupOutput; +use setup_scripts::udc::UdcSetupOutput; +use starknet::accounts::Account; +use starknet_core_contract_client::clients::StarknetValidityContractClient; -use crate::contract_clients::config::Config; -use crate::contract_clients::core_contract::CoreContract; -use crate::contract_clients::eth_bridge::StarknetLegacyEthBridge; -use crate::contract_clients::token_bridge::StarknetTokenBridge; +use crate::contract_clients::config::Clients; +use crate::contract_clients::starknet_validity::StarknetValidityContract; use crate::setup_scripts::account_setup::account_init; use crate::setup_scripts::argent::ArgentSetup; use crate::setup_scripts::braavos::BraavosSetup; @@ -25,49 +36,78 @@ use crate::setup_scripts::udc::UdcSetup; use crate::utils::banner::BANNER; use crate::utils::{save_to_json, JsonValueType}; +#[derive(Debug, Clone, Copy, ValueEnum)] +enum BootstrapMode { + Core, + SetupL1, + SetupL2, + EthBridge, + Erc20Bridge, + Udc, + Argent, + Braavos, +} + #[derive(Parser, Debug)] #[command(version, about, long_about = None)] pub struct CliArgs { - #[clap(long, env, default_value = "http://127.0.0.1:8545")] - eth_rpc: String, - #[clap(long, env, default_value = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80")] - eth_priv_key: String, - #[clap(long, env, default_value = "http://127.0.0.1:9944")] - rollup_seq_url: String, - #[clap(long, env, default_value = "0xabcd")] - rollup_priv_key: String, - #[clap(long, env, default_value_t = 31337)] - eth_chain_id: u64, - #[clap(long, env, default_value = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266")] - l1_deployer_address: String, - #[clap(long, env, default_value = "15")] - l1_wait_time: String, - #[clap(long, env, default_value = "0x41fc2a467ef8649580631912517edcab7674173f1dbfa2e9b64fbcd82bc4d79")] - sn_os_program_hash: String, - #[clap(long, env, default_value = "StarknetOsConfig1")] - config_hash_version: String, - #[clap(long, env, default_value = "MADARA")] - app_chain_id: String, - #[clap(long, env, default_value = "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7")] - fee_token_address: String, - #[clap(long, env, default_value_t = 80)] - cross_chain_wait_time: u64, - // Default test address value taken from anvil - // IMP : Not to be used in prod environment - #[clap(long, env, default_value = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8")] - l1_multisig_address: String, - // Default test address value taken from starknet-devnet - // IMP : Not to be used in prod environment - #[clap(long, env, default_value = "0x556455b8ac8bc00e0ad061d7df5458fa3c372304877663fa21d492a8d5e9435")] - l2_multisig_address: String, - // Given as 0xabcd by default - #[clap(long, env, default_value = "0x000000000000000000000000000000000000abcd")] - verifier_address: String, - // Given as 0xabcd by default - #[clap(long, env, default_value = "0x000000000000000000000000000000000000abcd")] - operator_address: String, - #[clap(long, env, action=ArgAction::SetTrue)] - dev: bool, + #[clap(long)] + config: Option, + #[clap(long, env, value_enum)] + mode: BootstrapMode, + #[clap(long, env)] + output_file: Option, +} + +#[derive(Serialize, Deserialize)] +pub struct ConfigFile { + pub eth_rpc: String, + pub eth_priv_key: String, + pub rollup_seq_url: String, + pub rollup_priv_key: String, + pub eth_chain_id: u64, + pub l1_deployer_address: String, + pub l1_wait_time: String, + pub sn_os_program_hash: String, + pub config_hash_version: String, + pub app_chain_id: String, + pub fee_token_address: String, + pub native_fee_token_address: String, + pub cross_chain_wait_time: u64, + pub l1_multisig_address: String, + pub l2_multisig_address: String, + pub verifier_address: String, + pub operator_address: String, + pub dev: bool, + pub core_contract_address: Option, + pub core_contract_implementation_address: Option, +} + +impl Default for ConfigFile { + fn default() -> Self { + Self { + eth_rpc: "http://127.0.0.1:8545".to_string(), + eth_priv_key: "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80".to_string(), + rollup_seq_url: "http://127.0.0.1:19944".to_string(), + rollup_priv_key: "0xabcd".to_string(), + eth_chain_id: 31337, + l1_deployer_address: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266".to_string(), + l1_wait_time: "15".to_string(), + sn_os_program_hash: "0x1e324682835e60c4779a683b32713504aed894fd73842f7d05b18e7bd29cd70".to_string(), + config_hash_version: "StarknetOsConfig2".to_string(), + app_chain_id: "MADARA_DEVNET".to_string(), + fee_token_address: "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7".to_string(), + native_fee_token_address: "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d".to_string(), + cross_chain_wait_time: 20, + l1_multisig_address: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8".to_string(), + l2_multisig_address: "0x556455b8ac8bc00e0ad061d7df5458fa3c372304877663fa21d492a8d5e9435".to_string(), + verifier_address: "0x000000000000000000000000000000000000abcd".to_string(), + operator_address: "0x000000000000000000000000000000000000abcd".to_string(), + dev: false, + core_contract_address: Some("0xe7f1725e7734ce288f8367e1bb143e90bb3f0512".to_string()), + core_contract_implementation_address: Some("0x5fbdb2315678afecb367f032d93f642f64180aa3".to_string()), + } + } } #[tokio::main] @@ -77,62 +117,194 @@ pub async fn main() { let args = CliArgs::parse(); - bootstrap(&args).await; + println!("{color_red}{}{color_reset}", BANNER); + + // Load config from file or use defaults + let config_file = match args.config { + Some(path) => { + let file = File::open(path).expect("Failed to open config file"); + serde_json::from_reader(file).expect("Failed to parse config file") + } + None => ConfigFile::default(), + }; + + let clients = Clients::init_from_config(&config_file).await; + + let output = match args.mode { + BootstrapMode::Core | BootstrapMode::SetupL1 => { + let output = setup_core_contract(&config_file, &clients).await; + + BootstrapperOutput { + starknet_contract_address: Some(output.core_contract_client.address()), + starknet_contract_implementation_address: Some(output.core_contract_client.implementation_address()), + ..Default::default() + } + } + BootstrapMode::SetupL2 => setup_l2(&config_file, &clients).await, + BootstrapMode::EthBridge => { + let core_contract_client = get_core_contract_client(&config_file, &clients); + let output = setup_eth_bridge(None, &core_contract_client, &config_file, &clients).await; + BootstrapperOutput { eth_bridge_setup_outputs: Some(output), ..Default::default() } + } + BootstrapMode::Erc20Bridge => { + let core_contract_client = get_core_contract_client(&config_file, &clients); + let output = setup_erc20_bridge(None, &core_contract_client, &config_file, &clients).await; + BootstrapperOutput { erc20_bridge_setup_outputs: Some(output), ..Default::default() } + } + BootstrapMode::Udc => { + let output = setup_udc(None, &config_file, &clients).await; + BootstrapperOutput { udc_setup_outputs: Some(output), ..Default::default() } + } + BootstrapMode::Argent => { + let output = setup_argent(None, &config_file, &clients).await; + BootstrapperOutput { argent_setup_outputs: Some(output), ..Default::default() } + } + BootstrapMode::Braavos => { + let output = setup_braavos(None, &config_file, &clients).await; + BootstrapperOutput { braavos_setup_outputs: Some(output), ..Default::default() } + } + }; + + let output_json = + serde_json::to_string_pretty(&output).unwrap_or_else(|e| format!("Error serializing output: {}", e)); + + // Print the output to the console + println!("Bootstrap Output:"); + println!("{}", output_json); + + if let Some(output_file) = args.output_file { + let file = File::create(&output_file).unwrap(); + serde_json::to_writer_pretty(file, &output).unwrap(); + println!("✅ Bootstrap output saved to {}", output_file); + } } -pub struct DeployBridgeOutput { - pub starknet_contract: Box, - pub starknet_token_bridge: StarknetTokenBridge, - pub erc20_class_hash: FieldElement, - pub legacy_eth_bridge_class_hash: FieldElement, - pub account_address: FieldElement, - pub eth_proxy_address: FieldElement, - pub eth_bridge_proxy_address: FieldElement, - pub legacy_proxy_class_hash: FieldElement, - pub starkgate_proxy_class_hash: FieldElement, - pub erc20_legacy_class_hash: FieldElement, - pub erc20_l2_bridge_address: FieldElement, - pub l2_erc20_token_address: FieldElement, - pub eth_bridge: StarknetLegacyEthBridge, +fn get_core_contract_client(config_file: &ConfigFile, clients: &Clients) -> CoreContractStarknetL1Output { + let Some(core_contract_address) = config_file.core_contract_address.clone() else { + panic!("Core contract address is required for ETH bridge setup"); + }; + let Some(core_contract_implementation_address) = config_file.core_contract_implementation_address.clone() else { + panic!("Core contract implementation address is required for ETH bridge setup"); + }; + let core_contract_client = StarknetValidityContractClient::new( + Address::from_str(&core_contract_address).unwrap(), + clients.eth_client().signer().clone(), + Address::from_str(&core_contract_implementation_address).unwrap(), + ); + CoreContractStarknetL1Output { core_contract_client: Box::new(StarknetValidityContract { core_contract_client }) } } -pub async fn bootstrap(config: &CliArgs) -> DeployBridgeOutput { - println!("{color_red}{}{color_reset}", BANNER); - let clients = Config::init(config).await; - let core_contract = CoreContractStarknetL1::new(config, &clients); +async fn get_account<'a>(clients: &'a Clients, config_file: &'a ConfigFile) -> RpcAccount<'a> { + log::info!("âŗ L2 State and Initialisation Started"); + let account = account_init(clients, config_file).await; + log::info!("🔐 Account with given private key deployed on L2. [Account Address : {:?}]", account.address()); + account +} + +#[derive(Serialize, Default)] +pub struct BootstrapperOutput { + #[serde(skip_serializing_if = "Option::is_none")] + pub starknet_contract_address: Option
, + #[serde(skip_serializing_if = "Option::is_none")] + pub starknet_contract_implementation_address: Option
, + #[serde(skip_serializing_if = "Option::is_none")] + pub eth_bridge_setup_outputs: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub erc20_bridge_setup_outputs: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub udc_setup_outputs: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub argent_setup_outputs: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub braavos_setup_outputs: Option, +} + +pub async fn bootstrap(config_file: &ConfigFile, clients: &Clients) -> BootstrapperOutput { + // setup core contract (L1) + let core_contract_client = setup_core_contract(config_file, clients).await; + + // setup L2 + let l2_output = setup_l2(config_file, clients).await; + + BootstrapperOutput { + starknet_contract_address: Some(core_contract_client.core_contract_client.address()), + starknet_contract_implementation_address: Some( + core_contract_client.core_contract_client.implementation_address(), + ), + ..l2_output + } +} + +async fn setup_core_contract(config_file: &ConfigFile, clients: &Clients) -> CoreContractStarknetL1Output { + let core_contract = CoreContractStarknetL1::new(config_file, clients); let core_contract_client = core_contract.setup().await; log::info!("đŸ“Ļ Core address : {:?}", core_contract_client.core_contract_client.address()); + log::info!( + "đŸ“Ļ Core implementation address : {:?}", + core_contract_client.core_contract_client.implementation_address() + ); save_to_json( "l1_core_contract_address", &JsonValueType::EthAddress(core_contract_client.core_contract_client.address()), ) .unwrap(); log::info!("✅ Core setup init for L1 successful."); - log::info!("âŗ L2 State and Initialisation Started"); - let account = account_init(&clients, config).await; - log::info!("🔐 Account with given private key deployed on L2. [Account Address : {:?}]", account.address()); + core_contract_client +} + +async fn setup_eth_bridge<'a>( + account: Option>, + core_contract_client: &CoreContractStarknetL1Output, + config_file: &ConfigFile, + clients: &Clients, +) -> EthBridgeSetupOutput { + let account = match account { + Some(account) => account, + None => get_account(clients, config_file).await, + }; log::info!("âŗ Starting ETH bridge deployment"); let eth_bridge = EthBridge::new( account.clone(), account.address(), - config, - &clients, + config_file, + clients, core_contract_client.core_contract_client.as_ref(), ); let eth_bridge_setup_outputs = eth_bridge.setup().await; log::info!("✅ ETH bridge deployment complete."); + eth_bridge_setup_outputs +} + +async fn setup_erc20_bridge<'a>( + account: Option>, + core_contract_client: &CoreContractStarknetL1Output, + config_file: &ConfigFile, + clients: &Clients, +) -> Erc20BridgeSetupOutput { + let account = match account { + Some(account) => account, + None => get_account(clients, config_file).await, + }; log::info!("âŗ Starting ERC20 token bridge deployment"); let erc20_bridge = Erc20Bridge::new( account.clone(), account.address(), - config, - &clients, + config_file, + clients, core_contract_client.core_contract_client.as_ref(), ); let erc20_bridge_setup_outputs = erc20_bridge.setup().await; log::info!("✅ ERC20 token bridge deployment complete."); + erc20_bridge_setup_outputs +} + +async fn setup_udc<'a>(account: Option>, config_file: &ConfigFile, clients: &Clients) -> UdcSetupOutput { + let account = match account { + Some(account) => account, + None => get_account(clients, config_file).await, + }; log::info!("âŗ Starting UDC (Universal Deployer Contract) deployment"); - let udc = UdcSetup::new(account.clone(), account.address(), config); + let udc = UdcSetup::new(account.clone(), account.address(), config_file, clients); let udc_setup_outputs = udc.setup().await; log::info!( "*ī¸âƒŖ UDC setup completed. [UDC Address : {:?}, UDC class hash : {:?}]", @@ -140,33 +312,74 @@ pub async fn bootstrap(config: &CliArgs) -> DeployBridgeOutput { udc_setup_outputs.udc_class_hash ); log::info!("✅ UDC (Universal Deployer Contract) deployment complete."); - log::info!("âŗ Starting Argent Account declaration"); + udc_setup_outputs +} + +async fn setup_argent<'a>( + account: Option>, + config_file: &ConfigFile, + clients: &Clients, +) -> ArgentSetupOutput { + let account = match account { + Some(account) => account, + None => get_account(clients, config_file).await, + }; + log::info!("âŗ Starting Argent Account deployment"); let argent = ArgentSetup::new(account.clone()); let argent_setup_outputs = argent.setup().await; log::info!("*ī¸âƒŖ Argent setup completed. [Argent account class hash : {:?}]", argent_setup_outputs.argent_class_hash); - log::info!("✅ Argent Account declaration complete."); - log::info!("âŗ Starting Braavos Account declaration"); - let braavos = BraavosSetup::new(account.clone(), config); + log::info!("✅ Argent Account deployment complete."); + argent_setup_outputs +} + +async fn setup_braavos<'a>( + account: Option>, + config_file: &ConfigFile, + clients: &Clients, +) -> BraavosSetupOutput { + let account = match account { + Some(account) => account, + None => get_account(clients, config_file).await, + }; + log::info!("âŗ Starting Braavos Account deployment"); + let braavos = BraavosSetup::new(account.clone(), config_file, clients); let braavos_setup_outputs = braavos.setup().await; log::info!( "*ī¸âƒŖ Braavos setup completed. [Braavos account class hash : {:?}]", braavos_setup_outputs.braavos_class_hash ); - log::info!("✅ Braavos Account declaration complete."); - - DeployBridgeOutput { - starknet_contract: core_contract_client.core_contract_client, - starknet_token_bridge: erc20_bridge_setup_outputs.starknet_token_bridge, - erc20_class_hash: erc20_bridge_setup_outputs.erc20_cairo_one_class_hash, - legacy_eth_bridge_class_hash: eth_bridge_setup_outputs.legacy_eth_bridge_class_hash, - account_address: account.address(), - eth_proxy_address: eth_bridge_setup_outputs.eth_proxy_address, - eth_bridge_proxy_address: eth_bridge_setup_outputs.eth_bridge_proxy_address, - legacy_proxy_class_hash: eth_bridge_setup_outputs.legacy_proxy_class_hash, - starkgate_proxy_class_hash: eth_bridge_setup_outputs.starkgate_proxy_class_hash, - erc20_legacy_class_hash: eth_bridge_setup_outputs.erc20_legacy_class_hash, - erc20_l2_bridge_address: erc20_bridge_setup_outputs.erc20_l2_bridge_address, - l2_erc20_token_address: erc20_bridge_setup_outputs.l2_erc20_token_address, - eth_bridge: eth_bridge_setup_outputs.eth_bridge, + log::info!("✅ Braavos Account deployment complete."); + braavos_setup_outputs +} + +pub async fn setup_l2(config_file: &ConfigFile, clients: &Clients) -> BootstrapperOutput { + let account = get_account(clients, config_file).await; + + let core_contract_client = get_core_contract_client(config_file, clients); + + // setup eth bridge + let eth_bridge_setup_outputs = + setup_eth_bridge(Some(account.clone()), &core_contract_client, config_file, clients).await; + + // setup erc20 bridge + let erc20_bridge_setup_outputs = + setup_erc20_bridge(Some(account.clone()), &core_contract_client, config_file, clients).await; + + // setup udc + let udc_setup_outputs = setup_udc(Some(account.clone()), config_file, clients).await; + + // setup argent account + let argent_setup_outputs = setup_argent(Some(account.clone()), config_file, clients).await; + + // setup braavos account + let braavos_setup_outputs = setup_braavos(Some(account.clone()), config_file, clients).await; + + BootstrapperOutput { + eth_bridge_setup_outputs: Some(eth_bridge_setup_outputs), + erc20_bridge_setup_outputs: Some(erc20_bridge_setup_outputs), + udc_setup_outputs: Some(udc_setup_outputs), + argent_setup_outputs: Some(argent_setup_outputs), + braavos_setup_outputs: Some(braavos_setup_outputs), + ..Default::default() } } diff --git a/src/setup_scripts/account_setup.rs b/src/setup_scripts/account_setup.rs index 1b70c09..9bb9bfd 100644 --- a/src/setup_scripts/account_setup.rs +++ b/src/setup_scripts/account_setup.rs @@ -2,28 +2,29 @@ use std::time::Duration; use tokio::time::sleep; -use crate::contract_clients::config::Config; +use crate::contract_clients::config::Clients; use crate::contract_clients::utils::{ build_single_owner_account, declare_contract, deploy_account_using_priv_key, DeclarationInput, RpcAccount, TEMP_ACCOUNT_PRIV_KEY, }; use crate::utils::constants::{OZ_ACCOUNT_CASM_PATH, OZ_ACCOUNT_PATH, OZ_ACCOUNT_SIERRA_PATH}; use crate::utils::{convert_to_hex, save_to_json, JsonValueType}; -use crate::CliArgs; +use crate::ConfigFile; -pub async fn account_init<'a>(clients: &'a Config, arg_config: &'a CliArgs) -> RpcAccount<'a> { +pub async fn account_init<'a>(clients: &'a Clients, arg_config: &'a ConfigFile) -> RpcAccount<'a> { // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> // Making temp account for declaration of OZ account Cairo 1 contract let oz_account_class_hash = declare_contract(DeclarationInput::LegacyDeclarationInputs( String::from(OZ_ACCOUNT_PATH), arg_config.rollup_seq_url.clone(), + clients.provider_l2(), )) .await; - log::debug!("OZ Account Class Hash Declared"); + log::info!("OZ Account Class Hash Declared"); save_to_json("oz_account_class_hash", &JsonValueType::StringType(oz_account_class_hash.to_string())).unwrap(); sleep(Duration::from_secs(10)).await; - log::debug!("Waiting for block to be mined [/]"); + log::info!("Waiting for block to be mined [/]"); sleep(Duration::from_secs(10)).await; let account_address_temp = diff --git a/src/setup_scripts/argent.rs b/src/setup_scripts/argent.rs index 09f01c0..f9f3780 100644 --- a/src/setup_scripts/argent.rs +++ b/src/setup_scripts/argent.rs @@ -1,6 +1,7 @@ use std::time::Duration; -use starknet_ff::FieldElement; +use serde::Serialize; +use starknet::core::types::Felt; use tokio::time::sleep; use crate::contract_clients::utils::{declare_contract, DeclarationInput, RpcAccount}; @@ -11,8 +12,9 @@ pub struct ArgentSetup<'a> { account: RpcAccount<'a>, } +#[derive(Debug, Clone, Serialize)] pub struct ArgentSetupOutput { - pub argent_class_hash: FieldElement, + pub argent_class_hash: Felt, } impl<'a> ArgentSetup<'a> { @@ -27,7 +29,7 @@ impl<'a> ArgentSetup<'a> { self.account.clone(), )) .await; - log::debug!("đŸ“Ŗ Argent Hash Declared"); + log::info!("đŸ“Ŗ Argent Hash Declared"); save_to_json("argent_class_hash", &JsonValueType::StringType(argent_class_hash.to_string())).unwrap(); sleep(Duration::from_secs(10)).await; diff --git a/src/setup_scripts/braavos.rs b/src/setup_scripts/braavos.rs index 750139a..d747792 100644 --- a/src/setup_scripts/braavos.rs +++ b/src/setup_scripts/braavos.rs @@ -1,9 +1,11 @@ use std::time::Duration; -use starknet_accounts::{Account, ConnectedAccount}; -use starknet_ff::FieldElement; +use serde::Serialize; +use starknet::accounts::{Account, ConnectedAccount}; +use starknet::core::types::Felt; use tokio::time::sleep; +use crate::contract_clients::config::Clients; use crate::contract_clients::utils::{declare_contract, DeclarationInput, RpcAccount}; use crate::helpers::account_actions::{get_contract_address_from_deploy_tx, AccountActions}; use crate::utils::constants::{ @@ -11,20 +13,22 @@ use crate::utils::constants::{ BRAAVOS_BASE_ACCOUNT_SIERRA_PATH, }; use crate::utils::{save_to_json, wait_for_transaction, JsonValueType}; -use crate::CliArgs; +use crate::ConfigFile; pub struct BraavosSetup<'a> { account: RpcAccount<'a>, - arg_config: &'a CliArgs, + arg_config: &'a ConfigFile, + clients: &'a Clients, } +#[derive(Debug, Clone, Serialize)] pub struct BraavosSetupOutput { - pub braavos_class_hash: FieldElement, + pub braavos_class_hash: Felt, } impl<'a> BraavosSetup<'a> { - pub fn new(account: RpcAccount<'a>, arg_config: &'a CliArgs) -> Self { - Self { account, arg_config } + pub fn new(account: RpcAccount<'a>, arg_config: &'a ConfigFile, clients: &'a Clients) -> Self { + Self { account, arg_config, clients } } pub async fn setup(&self) -> BraavosSetupOutput { @@ -34,7 +38,7 @@ impl<'a> BraavosSetup<'a> { self.account.clone(), )) .await; - log::debug!("đŸ“Ŗ Braavos Account class hash declared."); + log::info!("đŸ“Ŗ Braavos Account class hash declared."); save_to_json("braavos_class_hash", &JsonValueType::StringType(braavos_class_hash.to_string())).unwrap(); sleep(Duration::from_secs(10)).await; @@ -44,7 +48,7 @@ impl<'a> BraavosSetup<'a> { self.account.clone(), )) .await; - log::debug!("đŸ“Ŗ Braavos Base Account class hash declared."); + log::info!("đŸ“Ŗ Braavos Base Account class hash declared."); save_to_json( "braavos_base_account_class_hash", &JsonValueType::StringType(braavos_base_account_class_hash.to_string()), @@ -55,9 +59,10 @@ impl<'a> BraavosSetup<'a> { let braavos_aggregator_class_hash = declare_contract(DeclarationInput::LegacyDeclarationInputs( String::from(BRAAVOS_AGGREGATOR_PATH), self.arg_config.rollup_seq_url.clone(), + self.clients.provider_l2(), )) .await; - log::debug!("đŸ“Ŗ Braavos Aggregator class hash declared."); + log::info!("đŸ“Ŗ Braavos Aggregator class hash declared."); save_to_json( "braavos_aggregator_class_hash", &JsonValueType::StringType(braavos_aggregator_class_hash.to_string()), @@ -70,7 +75,7 @@ impl<'a> BraavosSetup<'a> { .invoke_contract( self.account.address(), "deploy_contract", - vec![braavos_aggregator_class_hash, FieldElement::ZERO, FieldElement::ZERO, FieldElement::ZERO], + vec![braavos_aggregator_class_hash, Felt::ZERO, Felt::ZERO, Felt::ZERO], None, ) .send() diff --git a/src/setup_scripts/core_contract.rs b/src/setup_scripts/core_contract.rs index ad70a35..62dc17d 100644 --- a/src/setup_scripts/core_contract.rs +++ b/src/setup_scripts/core_contract.rs @@ -1,19 +1,18 @@ use std::str::FromStr; use ethers::abi::Address; -use starknet_api::hash::StarkFelt; -use crate::contract_clients::config::Config; +use crate::contract_clients::config::Clients; use crate::contract_clients::core_contract::{CoreContract, CoreContractDeploy}; use crate::contract_clients::starknet_sovereign::StarknetSovereignContract; use crate::contract_clients::starknet_validity::StarknetValidityContract; use crate::contract_clients::utils::get_bridge_init_configs; use crate::utils::{save_to_json, JsonValueType}; -use crate::CliArgs; +use crate::ConfigFile; pub struct CoreContractStarknetL1<'a> { - arg_config: &'a CliArgs, - clients: &'a Config, + arg_config: &'a ConfigFile, + clients: &'a Clients, } pub struct CoreContractStarknetL1Output { @@ -21,7 +20,7 @@ pub struct CoreContractStarknetL1Output { } impl<'a> CoreContractStarknetL1<'a> { - pub fn new(arg_config: &'a CliArgs, clients: &'a Config) -> Self { + pub fn new(arg_config: &'a ConfigFile, clients: &'a Clients) -> Self { Self { arg_config, clients } } @@ -31,14 +30,16 @@ impl<'a> CoreContractStarknetL1<'a> { false => Box::new(StarknetValidityContract::deploy(self.clients).await), }; log::info!("đŸ“Ļ Core address : {:?}", core_contract_client.address()); + save_to_json("l1_core_contract_address", &JsonValueType::EthAddress(core_contract_client.address())).unwrap(); let (program_hash, config_hash) = get_bridge_init_configs(self.arg_config); if self.arg_config.dev { - core_contract_client.initialize(StarkFelt(program_hash.to_bytes_be()), config_hash).await; + core_contract_client.initialize(program_hash, config_hash).await; } else { core_contract_client .add_implementation_core_contract( + 0u64.into(), 0u64.into(), 0u64.into(), program_hash, @@ -50,6 +51,7 @@ impl<'a> CoreContractStarknetL1<'a> { .await; core_contract_client .upgrade_to_core_contract( + 0u64.into(), 0u64.into(), 0u64.into(), program_hash, diff --git a/src/setup_scripts/erc20_bridge.rs b/src/setup_scripts/erc20_bridge.rs index 4f5fdd7..db313ce 100644 --- a/src/setup_scripts/erc20_bridge.rs +++ b/src/setup_scripts/erc20_bridge.rs @@ -3,43 +3,49 @@ use std::time::Duration; use ethers::abi::Address; use ethers::prelude::{H160, U256}; +use serde::Serialize; +use starknet::core::types::Felt; use starknet_core::types::{BlockId, BlockTag, FunctionCall}; use starknet_core::utils::get_selector_from_name; -use starknet_ff::FieldElement; use starknet_providers::jsonrpc::HttpTransport; use starknet_providers::{JsonRpcClient, Provider}; use tokio::time::sleep; -use crate::contract_clients::config::Config; +use crate::contract_clients::config::Clients; use crate::contract_clients::core_contract::CoreContract; use crate::contract_clients::eth_bridge::BridgeDeployable; use crate::contract_clients::token_bridge::StarknetTokenBridge; use crate::contract_clients::utils::{build_single_owner_account, declare_contract, DeclarationInput, RpcAccount}; use crate::utils::constants::{ERC20_CASM_PATH, ERC20_SIERRA_PATH}; use crate::utils::{convert_to_hex, save_to_json, JsonValueType}; -use crate::CliArgs; +use crate::ConfigFile; pub struct Erc20Bridge<'a> { account: RpcAccount<'a>, - account_address: FieldElement, - arg_config: &'a CliArgs, - clients: &'a Config, + account_address: Felt, + arg_config: &'a ConfigFile, + clients: &'a Clients, core_contract: &'a dyn CoreContract, } +#[derive(Serialize)] pub struct Erc20BridgeSetupOutput { - pub erc20_cairo_one_class_hash: FieldElement, - pub starknet_token_bridge: StarknetTokenBridge, - pub erc20_l2_bridge_address: FieldElement, - pub l2_erc20_token_address: FieldElement, + pub erc20_cairo_one_class_hash: Felt, + pub l1_token_bridge_proxy: Address, + pub l1_manager_address: Address, + pub l1_registry_address: Address, + pub l2_token_bridge: Felt, + pub test_erc20_token_address: Felt, + #[serde(skip)] + pub token_bridge: StarknetTokenBridge, } impl<'a> Erc20Bridge<'a> { pub fn new( account: RpcAccount<'a>, - account_address: FieldElement, - arg_config: &'a CliArgs, - clients: &'a Config, + account_address: Felt, + arg_config: &'a ConfigFile, + clients: &'a Clients, core_contract: &'a dyn CoreContract, ) -> Self { Self { account, account_address, arg_config, clients, core_contract } @@ -52,7 +58,7 @@ impl<'a> Erc20Bridge<'a> { self.account.clone(), )) .await; - log::debug!("🌗 ERC20 Class Hash declared : {:?}", erc20_cairo_one_class_hash); + log::info!("🌗 ERC20 Class Hash declared : {:?}", erc20_cairo_one_class_hash); save_to_json("erc20_cairo_one_class_hash", &JsonValueType::StringType(erc20_cairo_one_class_hash.to_string())) .unwrap(); sleep(Duration::from_secs(10)).await; @@ -137,24 +143,27 @@ impl<'a> Erc20Bridge<'a> { Erc20BridgeSetupOutput { erc20_cairo_one_class_hash, - starknet_token_bridge: token_bridge, - erc20_l2_bridge_address: l2_bridge_address, - l2_erc20_token_address, + l1_manager_address: token_bridge.manager_address(), + l1_registry_address: token_bridge.registry_address(), + l1_token_bridge_proxy: token_bridge.bridge_address(), + l2_token_bridge: l2_bridge_address, + test_erc20_token_address: l2_erc20_token_address, + token_bridge, } } } async fn get_l2_token_address( rpc_provider_l2: &JsonRpcClient, - l2_bridge_address: &FieldElement, + l2_bridge_address: &Felt, l1_erc_20_address: &H160, -) -> FieldElement { +) -> Felt { rpc_provider_l2 .call( FunctionCall { contract_address: *l2_bridge_address, entry_point_selector: get_selector_from_name("get_l2_token").unwrap(), - calldata: vec![FieldElement::from_byte_slice_be(l1_erc_20_address.as_bytes()).unwrap()], + calldata: vec![Felt::from_bytes_be_slice(l1_erc_20_address.as_bytes())], }, BlockId::Tag(BlockTag::Pending), ) diff --git a/src/setup_scripts/eth_bridge.rs b/src/setup_scripts/eth_bridge.rs index 283cfb7..8c95762 100644 --- a/src/setup_scripts/eth_bridge.rs +++ b/src/setup_scripts/eth_bridge.rs @@ -2,13 +2,14 @@ use std::str::FromStr; use std::time::Duration; use ethers::abi::Address; -use starknet_accounts::{Account, ConnectedAccount}; -use starknet_ff::FieldElement; +use serde::Serialize; +use starknet::accounts::{Account, ConnectedAccount}; +use starknet::core::types::Felt; use starknet_providers::jsonrpc::HttpTransport; use starknet_providers::JsonRpcClient; use tokio::time::sleep; -use crate::contract_clients::config::Config; +use crate::contract_clients::config::Clients; use crate::contract_clients::core_contract::CoreContract; use crate::contract_clients::eth_bridge::{BridgeDeployable, StarknetLegacyEthBridge}; use crate::contract_clients::utils::{ @@ -18,32 +19,35 @@ use crate::contract_clients::utils::{ use crate::helpers::account_actions::{get_contract_address_from_deploy_tx, AccountActions}; use crate::utils::constants::{ERC20_LEGACY_PATH, LEGACY_BRIDGE_PATH, PROXY_LEGACY_PATH, STARKGATE_PROXY_PATH}; use crate::utils::{convert_to_hex, invoke_contract, save_to_json, wait_for_transaction, JsonValueType}; -use crate::CliArgs; +use crate::ConfigFile; pub struct EthBridge<'a> { account: RpcAccount<'a>, - account_address: FieldElement, - arg_config: &'a CliArgs, - clients: &'a Config, + account_address: Felt, + arg_config: &'a ConfigFile, + clients: &'a Clients, core_contract: &'a dyn CoreContract, } +#[derive(Serialize)] pub struct EthBridgeSetupOutput { - pub legacy_proxy_class_hash: FieldElement, - pub starkgate_proxy_class_hash: FieldElement, - pub erc20_legacy_class_hash: FieldElement, - pub legacy_eth_bridge_class_hash: FieldElement, - pub eth_proxy_address: FieldElement, - pub eth_bridge_proxy_address: FieldElement, - pub eth_bridge: StarknetLegacyEthBridge, + pub l2_legacy_proxy_class_hash: Felt, + pub l2_erc20_legacy_class_hash: Felt, + pub l2_eth_proxy_address: Felt, + pub l2_starkgate_proxy_class_hash: Felt, + pub l2_legacy_eth_bridge_class_hash: Felt, + pub l2_eth_bridge_proxy_address: Felt, + pub l1_bridge_address: Address, + #[serde(skip)] + pub l1_bridge: StarknetLegacyEthBridge, } impl<'a> EthBridge<'a> { pub fn new( account: RpcAccount<'a>, - account_address: FieldElement, - arg_config: &'a CliArgs, - clients: &'a Config, + account_address: Felt, + arg_config: &'a ConfigFile, + clients: &'a Clients, core_contract: &'a dyn CoreContract, ) -> Self { Self { account, account_address, arg_config, clients, core_contract } @@ -53,9 +57,10 @@ impl<'a> EthBridge<'a> { let legacy_proxy_class_hash = declare_contract(DeclarationInput::LegacyDeclarationInputs( String::from(PROXY_LEGACY_PATH), self.arg_config.rollup_seq_url.clone(), + self.clients.provider_l2(), )) .await; - log::debug!("🎡 Legacy proxy class hash declared."); + log::info!("🎡 Legacy proxy class hash declared."); save_to_json("legacy_proxy_class_hash", &JsonValueType::StringType(legacy_proxy_class_hash.to_string())) .unwrap(); sleep(Duration::from_secs(10)).await; @@ -63,9 +68,10 @@ impl<'a> EthBridge<'a> { let starkgate_proxy_class_hash = declare_contract(DeclarationInput::LegacyDeclarationInputs( String::from(STARKGATE_PROXY_PATH), self.arg_config.rollup_seq_url.clone(), + self.clients.provider_l2(), )) .await; - log::debug!("🎡 Starkgate proxy class hash declared."); + log::info!("🎡 Starkgate proxy class hash declared."); save_to_json("starkgate_proxy_class_hash", &JsonValueType::StringType(starkgate_proxy_class_hash.to_string())) .unwrap(); sleep(Duration::from_secs(10)).await; @@ -73,9 +79,10 @@ impl<'a> EthBridge<'a> { let erc20_legacy_class_hash = declare_contract(DeclarationInput::LegacyDeclarationInputs( String::from(ERC20_LEGACY_PATH), self.arg_config.rollup_seq_url.clone(), + self.clients.provider_l2(), )) .await; - log::debug!("🎡 ERC20 legacy class hash declared."); + log::info!("🎡 ERC20 legacy class hash declared."); save_to_json("erc20_legacy_class_hash", &JsonValueType::StringType(erc20_legacy_class_hash.to_string())) .unwrap(); sleep(Duration::from_secs(10)).await; @@ -83,9 +90,10 @@ impl<'a> EthBridge<'a> { let legacy_eth_bridge_class_hash = declare_contract(DeclarationInput::LegacyDeclarationInputs( String::from(LEGACY_BRIDGE_PATH), self.arg_config.rollup_seq_url.clone(), + self.clients.provider_l2(), )) .await; - log::debug!("🎡 Legacy ETH Bridge class hash declared"); + log::info!("🎡 Legacy ETH Bridge class hash declared"); save_to_json( "legacy_eth_bridge_class_hash", &JsonValueType::StringType(legacy_eth_bridge_class_hash.to_string()), @@ -98,8 +106,8 @@ impl<'a> EthBridge<'a> { self.account_address, legacy_proxy_class_hash, // salt taken from : https://sepolia.starkscan.co/tx/0x06a5a493cf33919e58aa4c75777bffdef97c0e39cac968896d7bee8cc67905a1 - FieldElement::from_str("0x322c2610264639f6b2cee681ac53fa65c37e187ea24292d1b21d859c55e1a78").unwrap(), - FieldElement::ONE, + Felt::from_str("0x322c2610264639f6b2cee681ac53fa65c37e187ea24292d1b21d859c55e1a78").unwrap(), + Felt::ONE, ) .await; log::info!("✴ī¸ ETH ERC20 proxy deployed [ETH : {:?}]", eth_proxy_address); @@ -110,8 +118,8 @@ impl<'a> EthBridge<'a> { &self.account, self.account_address, legacy_proxy_class_hash, - FieldElement::from_str("0xabcdabcdabcd").unwrap(), - FieldElement::ZERO, + Felt::from_str("0xabcdabcdabcd").unwrap(), + Felt::ZERO, ) .await; log::info!("✴ī¸ ETH Bridge proxy deployed [ETH Bridge : {:?}]", eth_bridge_proxy_address); @@ -121,6 +129,7 @@ impl<'a> EthBridge<'a> { init_governance_proxy(&self.account, eth_proxy_address, "eth_proxy_address : init_governance_proxy").await; sleep(Duration::from_secs(10)).await; + init_governance_proxy( &self.account, eth_bridge_proxy_address, @@ -198,29 +207,30 @@ impl<'a> EthBridge<'a> { log::info!("✴ī¸ ETH Bridge setup on L1 completed"); EthBridgeSetupOutput { - legacy_proxy_class_hash, - starkgate_proxy_class_hash, - erc20_legacy_class_hash, - legacy_eth_bridge_class_hash, - eth_proxy_address, - eth_bridge_proxy_address, - eth_bridge, + l2_legacy_proxy_class_hash: legacy_proxy_class_hash, + l2_starkgate_proxy_class_hash: starkgate_proxy_class_hash, + l2_erc20_legacy_class_hash: erc20_legacy_class_hash, + l2_legacy_eth_bridge_class_hash: legacy_eth_bridge_class_hash, + l2_eth_proxy_address: eth_proxy_address, + l2_eth_bridge_proxy_address: eth_bridge_proxy_address, + l1_bridge_address: eth_bridge.address(), + l1_bridge: eth_bridge, } } } pub async fn deploy_eth_token_on_l2( rpc_provider_l2: &JsonRpcClient, - eth_proxy_address: FieldElement, - eth_erc20_class_hash: FieldElement, + eth_proxy_address: Felt, + eth_erc20_class_hash: Felt, account: &RpcAccount<'_>, - eth_legacy_bridge_address: FieldElement, -) -> FieldElement { + eth_legacy_bridge_address: Felt, +) -> Felt { let deploy_tx = account .invoke_contract( account.address(), "deploy_contract", - vec![eth_erc20_class_hash, FieldElement::ZERO, FieldElement::ZERO, FieldElement::ZERO], + vec![eth_erc20_class_hash, Felt::ZERO, Felt::ZERO, Felt::ZERO], None, ) .send() @@ -229,20 +239,20 @@ pub async fn deploy_eth_token_on_l2( wait_for_transaction(rpc_provider_l2, deploy_tx.transaction_hash, "deploy_eth_token_on_l2 : deploy").await.unwrap(); let contract_address = get_contract_address_from_deploy_tx(account.provider(), &deploy_tx).await.unwrap(); - log::debug!("Contract address (eth erc20) : {:?}", contract_address); + log::info!("Contract address (eth erc20) : {:?}", contract_address); let add_implementation_txn = invoke_contract( eth_proxy_address, "add_implementation", vec![ contract_address, - FieldElement::ZERO, - FieldElement::from(4u64), - FieldElement::from_byte_slice_be("Ether".as_bytes()).unwrap(), - FieldElement::from_byte_slice_be("ETH".as_bytes()).unwrap(), - FieldElement::from_str("18").unwrap(), + Felt::ZERO, + Felt::from(4u64), + Felt::from_bytes_be_slice("Ether".as_bytes()), + Felt::from_bytes_be_slice("ETH".as_bytes()), + Felt::from_str("18").unwrap(), eth_legacy_bridge_address, - FieldElement::ZERO, + Felt::ZERO, ], account, ) @@ -261,13 +271,13 @@ pub async fn deploy_eth_token_on_l2( "upgrade_to", vec![ contract_address, - FieldElement::ZERO, - FieldElement::from(4u64), - FieldElement::from_byte_slice_be("Ether".as_bytes()).unwrap(), - FieldElement::from_byte_slice_be("ETH".as_bytes()).unwrap(), - FieldElement::from_str("18").unwrap(), + Felt::ZERO, + Felt::from(4u64), + Felt::from_bytes_be_slice("Ether".as_bytes()), + Felt::from_bytes_be_slice("ETH".as_bytes()), + Felt::from_str("18").unwrap(), eth_legacy_bridge_address, - FieldElement::ZERO, + Felt::ZERO, ], account, ) diff --git a/src/setup_scripts/udc.rs b/src/setup_scripts/udc.rs index fefa296..0773c9a 100644 --- a/src/setup_scripts/udc.rs +++ b/src/setup_scripts/udc.rs @@ -1,38 +1,48 @@ use std::time::Duration; -use starknet_accounts::ConnectedAccount; -use starknet_ff::FieldElement; +use serde::Serialize; +use starknet::accounts::ConnectedAccount; +use starknet::core::types::Felt; use tokio::time::sleep; +use crate::contract_clients::config::Clients; use crate::contract_clients::utils::{declare_contract, DeclarationInput, RpcAccount}; use crate::helpers::account_actions::{get_contract_address_from_deploy_tx, AccountActions}; use crate::utils::constants::UDC_PATH; use crate::utils::{save_to_json, wait_for_transaction, JsonValueType}; -use crate::CliArgs; +use crate::ConfigFile; pub struct UdcSetup<'a> { account: RpcAccount<'a>, - account_address: FieldElement, - arg_config: &'a CliArgs, + account_address: Felt, + arg_config: &'a ConfigFile, + clients: &'a Clients, } +#[derive(Debug, Clone, Serialize)] pub struct UdcSetupOutput { - pub udc_class_hash: FieldElement, - pub udc_address: FieldElement, + pub udc_class_hash: Felt, + pub udc_address: Felt, } impl<'a> UdcSetup<'a> { - pub fn new(account: RpcAccount<'a>, account_address: FieldElement, arg_config: &'a CliArgs) -> Self { - Self { account, account_address, arg_config } + pub fn new( + account: RpcAccount<'a>, + account_address: Felt, + arg_config: &'a ConfigFile, + clients: &'a Clients, + ) -> Self { + Self { account, account_address, arg_config, clients } } pub async fn setup(&self) -> UdcSetupOutput { let udc_class_hash = declare_contract(DeclarationInput::LegacyDeclarationInputs( String::from(UDC_PATH), self.arg_config.rollup_seq_url.clone(), + self.clients.provider_l2(), )) .await; - log::debug!("đŸ“Ŗ UDC Class Hash Declared."); + log::info!("đŸ“Ŗ UDC Class Hash Declared."); save_to_json("udc_class_hash", &JsonValueType::StringType(udc_class_hash.to_string())).unwrap(); sleep(Duration::from_secs(10)).await; @@ -41,7 +51,7 @@ impl<'a> UdcSetup<'a> { .invoke_contract( self.account_address, "deploy_contract", - Vec::from([udc_class_hash, FieldElement::ZERO, FieldElement::ONE, FieldElement::ZERO]), + Vec::from([udc_class_hash, Felt::ZERO, Felt::ONE, Felt::ZERO]), None, ) .send() @@ -56,7 +66,7 @@ impl<'a> UdcSetup<'a> { .unwrap(); let udc_address = get_contract_address_from_deploy_tx(self.account.provider(), &txn).await.unwrap(); save_to_json("udc_address", &JsonValueType::StringType(udc_address.to_string())).unwrap(); - log::debug!("đŸ“Ŗ udc_address : {:?}", udc_address); + log::info!("đŸ“Ŗ udc_address : {:?}", udc_address); UdcSetupOutput { udc_class_hash, udc_address } } diff --git a/src/tests/constants.rs b/src/tests/constants.rs index 08fe16d..f55b97a 100644 --- a/src/tests/constants.rs +++ b/src/tests/constants.rs @@ -1,16 +1,18 @@ pub const ETH_RPC: &str = "http://127.0.0.1:8545"; pub const ETH_PRIV_KEY: &str = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"; -pub const ROLLUP_SEQ_URL: &str = "http://127.0.0.1:9944"; +pub const ROLLUP_SEQ_URL: &str = "http://127.0.0.1:19944"; pub const ROLLUP_PRIV_KEY: &str = "0xabcd"; pub const ETH_CHAIN_ID: &str = "31337"; pub const L1_DEPLOYER_ADDRESS: &str = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"; pub const L1_WAIT_TIME: &str = "15"; pub const FEE_TOKEN_ADDRESS: &str = "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7"; -pub const SN_OS_PROGRAM_HASH: &str = "0x41fc2a467ef8649580631912517edcab7674173f1dbfa2e9b64fbcd82bc4d79"; -pub const SN_OS_CONFIG_HASH_VERSION: &str = "StarknetOsConfig1"; -pub const APP_CHAIN_ID: &str = "MADARA"; +pub const NATIVE_FEE_TOKEN_ADDRESS: &str = "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d"; +pub const SN_OS_PROGRAM_HASH: &str = "0x1e324682835e60c4779a683b32713504aed894fd73842f7d05b18e7bd29cd70"; +pub const SN_OS_CONFIG_HASH_VERSION: &str = "StarknetOsConfig2"; +pub const APP_CHAIN_ID: &str = "MADARA_DEVNET"; pub const L2_DEPLOYER_ADDRESS: &str = "0x4fe5eea46caa0a1f344fafce82b39d66b552f00d3cd12e89073ef4b4ab37860"; pub const L1_MULTISIG_ADDRESS: &str = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8"; pub const L2_MULTISIG_ADDRESS: &str = "0x556455b8ac8bc00e0ad061d7df5458fa3c372304877663fa21d492a8d5e9435"; pub const VERIFIER_ADDRESS: &str = "0x0000000000000000000000000000000000000000"; pub const OPERATOR_ADDRESS: &str = "0x000000000000000000000000000000000000abcd"; +pub const OUTPUT_PATH: &str = ""; diff --git a/src/tests/erc20_bridge.rs b/src/tests/erc20_bridge.rs index 3a30a4e..de00372 100644 --- a/src/tests/erc20_bridge.rs +++ b/src/tests/erc20_bridge.rs @@ -2,36 +2,32 @@ use std::str::FromStr; use std::time::Duration; use ethers::prelude::U256; -use starknet_ff::FieldElement; +use starknet::core::types::Felt; use tokio::time::sleep; -use crate::contract_clients::config::Config; +use crate::contract_clients::config::Clients; use crate::contract_clients::token_bridge::StarknetTokenBridge; use crate::contract_clients::utils::read_erc20_balance; use crate::tests::constants::L2_DEPLOYER_ADDRESS; -use crate::CliArgs; - +use crate::ConfigFile; // TODO : Uncomment L2 --> L1 part after this part is added in the madara-orchestrator. pub async fn erc20_bridge_test_helper( - clients: &Config, - arg_config: &CliArgs, - l2_erc20_token_address: FieldElement, + clients: &Clients, + arg_config: &ConfigFile, + l2_erc20_token_address: Felt, token_bridge: StarknetTokenBridge, - _l2_bridge_address: FieldElement, + _l2_bridge_address: Felt, ) -> Result<(), anyhow::Error> { token_bridge.approve(token_bridge.bridge_address(), 100000000.into()).await; sleep(Duration::from_secs(arg_config.l1_wait_time.parse().unwrap())).await; - log::debug!("Approval done [✅]"); - log::debug!("Waiting for message to be consumed on l2 [âŗ]"); + log::info!("Approval done [✅]"); + log::info!("Waiting for message to be consumed on l2 [âŗ]"); sleep(Duration::from_secs(arg_config.cross_chain_wait_time)).await; - let balance_before = read_erc20_balance( - clients.provider_l2(), - l2_erc20_token_address, - FieldElement::from_str(L2_DEPLOYER_ADDRESS).unwrap(), - ) - .await; + let balance_before = + read_erc20_balance(clients.provider_l2(), l2_erc20_token_address, Felt::from_str(L2_DEPLOYER_ADDRESS).unwrap()) + .await; token_bridge .deposit( @@ -42,37 +38,40 @@ pub async fn erc20_bridge_test_helper( ) .await; sleep(Duration::from_secs(arg_config.l1_wait_time.parse().unwrap())).await; - log::debug!("Deposit done [💰]"); - log::debug!("Waiting for message to be consumed on l2 [âŗ]"); + log::info!("Deposit done [💰]"); + log::info!("Waiting for message to be consumed on l2 [âŗ]"); sleep(Duration::from_secs(arg_config.cross_chain_wait_time)).await; - let balance_after = read_erc20_balance( - clients.provider_l2(), - l2_erc20_token_address, - FieldElement::from_str(L2_DEPLOYER_ADDRESS).unwrap(), - ) - .await; + let balance_after = + read_erc20_balance(clients.provider_l2(), l2_erc20_token_address, Felt::from_str(L2_DEPLOYER_ADDRESS).unwrap()) + .await; + + assert_eq!(balance_before[0] + Felt::from(10), balance_after[0]); - assert_eq!(balance_before[0] + FieldElement::from_dec_str("10").unwrap(), balance_after[0]); + // Note: we are ignoring the withdrawal tests here, it would be part of e2e where + // we have orch running as well - // let l1_recipient = FieldElement::from_hex_be(&arg_config.l1_deployer_address).unwrap(); + // let l1_recipient = Felt::from_hex(&arg_config.l1_deployer_address).unwrap(); + // let account = + // build_single_owner_account(clients.provider_l2(), &arg_config.rollup_priv_key, + // L2_DEPLOYER_ADDRESS, false) .await; // - // log::debug!("Initiated token withdraw on L2 [âŗ]"); + // log::info!("Initiated token withdraw on L2 [âŗ]"); // invoke_contract( // l2_bridge_address, // "initiate_token_withdraw", // vec![ - // FieldElement::from_byte_slice_be(token_bridge.address().as_bytes()).unwrap(), + // Felt::from_bytes_be_slice(token_bridge.address().as_bytes()), // l1_recipient, - // FieldElement::from_dec_str("5").unwrap(), - // FieldElement::ZERO, + // Felt::from_dec_str("5").unwrap(), + // Felt::ZERO, // ], // &account, // ) // .await; // // sleep(Duration::from_secs(arg_config.l1_wait_time.parse().unwrap())).await; - // log::debug!("Waiting for message to be consumed on l2 [âŗ]"); + // log::info!("Waiting for message to be consumed on l2 [âŗ]"); // sleep(Duration::from_secs(arg_config.cross_chain_wait_time)).await; // sleep(Duration::from_secs(arg_config.l1_wait_time.parse().unwrap())).await; // @@ -83,7 +82,7 @@ pub async fn erc20_bridge_test_helper( // // assert_eq!(balance_before + U256::from_dec_str("5").unwrap(), balance_after); // - // log::debug!("Token withdraw successful [✅]"); + // log::info!("Token withdraw successful [✅]"); anyhow::Ok(()) } diff --git a/src/tests/eth_bridge.rs b/src/tests/eth_bridge.rs index 8bf0c61..6f6ae1c 100644 --- a/src/tests/eth_bridge.rs +++ b/src/tests/eth_bridge.rs @@ -2,47 +2,42 @@ use std::str::FromStr; use std::time::Duration; use ethers::prelude::U256; -use starknet_ff::FieldElement; +use starknet::core::types::Felt; use tokio::time::sleep; -use crate::contract_clients::config::Config; +use crate::contract_clients::config::Clients; use crate::contract_clients::eth_bridge::StarknetLegacyEthBridge; use crate::contract_clients::utils::read_erc20_balance; use crate::tests::constants::L2_DEPLOYER_ADDRESS; -use crate::CliArgs; - +use crate::ConfigFile; // TODO : Uncomment L2 --> L1 part after this part is added in the madara-orchestrator. pub async fn eth_bridge_test_helper( - clients: &Config, - arg_config: &CliArgs, - l2_eth_address: FieldElement, - _l2_bridge_address: FieldElement, + clients: &Clients, + arg_config: &ConfigFile, + l2_eth_address: Felt, + _l2_bridge_address: Felt, eth_bridge: StarknetLegacyEthBridge, ) -> Result<(), anyhow::Error> { - let balance_before = read_erc20_balance( - clients.provider_l2(), - l2_eth_address, - FieldElement::from_hex_be(L2_DEPLOYER_ADDRESS).unwrap(), - ) - .await; + let balance_before = + read_erc20_balance(clients.provider_l2(), l2_eth_address, Felt::from_hex(L2_DEPLOYER_ADDRESS).unwrap()).await; eth_bridge.deposit(10.into(), U256::from_str(L2_DEPLOYER_ADDRESS).unwrap(), 1000.into()).await; - log::debug!("ETH deposited on l1 [💰]"); + + log::info!("ETH deposited on l1 [💰]"); sleep(Duration::from_secs(arg_config.cross_chain_wait_time)).await; sleep(Duration::from_secs((arg_config.l1_wait_time).parse()?)).await; - log::debug!("L1 message executed on L2 [🔁]"); + log::info!("L1 message executed on L2 [🔁]"); + + let balance_after = + read_erc20_balance(clients.provider_l2(), l2_eth_address, Felt::from_hex(L2_DEPLOYER_ADDRESS).unwrap()).await; - let balance_after = read_erc20_balance( - clients.provider_l2(), - l2_eth_address, - FieldElement::from_hex_be(L2_DEPLOYER_ADDRESS).unwrap(), - ) - .await; + assert_eq!(balance_before[0] + Felt::from_dec_str("10").unwrap(), balance_after[0]); - assert_eq!(balance_before[0] + FieldElement::from_dec_str("10").unwrap(), balance_after[0]); + // Note: we are ignoring the withdrawal tests here, it would be part of e2e where + // we have orch running as well - // let l1_receipient = FieldElement::from_hex_be(&arg_config.l1_deployer_address).unwrap(); + // let l1_receipient = Felt::from_hex(&arg_config.l1_deployer_address).unwrap(); // // sleep(Duration::from_secs((arg_config.l1_wait_time).parse()?)).await; // @@ -50,23 +45,18 @@ pub async fn eth_bridge_test_helper( // build_single_owner_account(clients.provider_l2(), &arg_config.rollup_priv_key, // L2_DEPLOYER_ADDRESS, false) .await; // - // invoke_contract( - // l2_bridge_address, - // "initiate_withdraw", - // vec![l1_receipient, FieldElement::from_dec_str("5").unwrap(), FieldElement::ZERO], - // &account, - // ) - // .await; - // log::debug!("ETH withdrawal initiated on l2 [💰]"); - // log::debug!("Waiting for message to be consumed on l2 [âŗ]"); + // invoke_contract(l2_bridge_address, "initiate_withdraw", vec![l1_receipient, Felt::from(5), + // Felt::ZERO], &account) .await; + // log::info!("ETH withdrawal initiated on l2 [💰]"); + // log::info!("Waiting for message to be consumed on l2 [âŗ]"); // sleep(Duration::from_secs(arg_config.cross_chain_wait_time)).await; // sleep(Duration::from_secs((arg_config.l1_wait_time).parse()?)).await; // // let balance_before = // eth_bridge.eth_balance(Address::from_str(&arg_config.l1_deployer_address).unwrap()).await; - // log::debug!("Withdraw initiated on ETH Bridge [âŗ]"); + // log::info!("Withdraw initiated on ETH Bridge [âŗ]"); // eth_bridge.withdraw(5.into(), Address::from_str(&arg_config.l1_deployer_address).unwrap()).await; - // log::debug!("Withdraw completed on ETH Bridge [✅]"); + // log::info!("Withdraw completed on ETH Bridge [✅]"); // let balance_after = // eth_bridge.eth_balance(Address::from_str(&arg_config.l1_deployer_address).unwrap()).await; // diff --git a/src/tests/madara.rs b/src/tests/madara.rs new file mode 100644 index 0000000..acf66de --- /dev/null +++ b/src/tests/madara.rs @@ -0,0 +1,172 @@ +use std::collections::HashMap; +use std::future::Future; +use std::ops::Range; +use std::path::PathBuf; +use std::process::{Child, Command, Stdio}; +use std::sync::Mutex; +use std::time::Duration; + +use tempfile::TempDir; +use url::Url; + +// This code has been take from [here](https://github.com/madara-alliance/madara/blob/main/crates/tests/src/lib.rs) +// and modified to fit the needs of this project. +pub struct MadaraCmd { + pub process: Option, + pub ready: bool, + pub rpc_url: Url, + pub _tempdir: TempDir, + pub _port: MadaraPortNum, +} + +pub async fn wait_for_cond>>( + mut cond: impl FnMut() -> F, + duration: Duration, +) -> color_eyre::Result { + let mut attempt = 0; + loop { + let err = match cond().await { + Ok(result) => return Ok(result), + Err(err) => { + // Empty block, no action needed + err + } + }; + + attempt += 1; + if attempt >= 10 { + panic!("No answer from the node after {attempt} attempts: {:#}", err) + } + + tokio::time::sleep(duration).await; + } +} + +impl MadaraCmd { + pub async fn wait_for_ready(&mut self) -> &mut Self { + // We are fine with `expect` here as this function is called in the intial phases of the + // program execution + let endpoint = self.rpc_url.join("/health").expect("Request to health endpoint failed"); + wait_for_cond( + || async { + let res = reqwest::get(endpoint.clone()).await?; + res.error_for_status()?; + Ok(true) + }, + Duration::from_millis(1000), + ) + .await + .expect("Could not get health of Madara"); + self.ready = true; + self + } +} + +impl Drop for MadaraCmd { + fn drop(&mut self) { + let Some(mut child) = self.process.take() else { return }; + let kill = || { + let mut kill = Command::new("kill").args(["-s", "TERM", &child.id().to_string()]).spawn()?; + kill.wait()?; + Ok::<_, color_eyre::Report>(()) + }; + if let Err(_err) = kill() { + match child.kill() { + Ok(kill) => kill, + Err(e) => { + log::error!("{}", format!("Failed to kill Madara {:?}", e)); + } + } + } + match child.wait() { + Ok(exit_status) => log::debug!("{}", exit_status), + Err(e) => log::error!("failed to exit madara {:?}", e), + } + } +} + +// this really should use unix sockets, sad + +const PORT_RANGE: Range = 19944..20000; + +struct AvailablePorts> { + to_reuse: Vec, + next: I, +} + +lazy_static::lazy_static! { + static ref AVAILABLE_PORTS: Mutex>> = Mutex::new(AvailablePorts { to_reuse: vec![], next: PORT_RANGE }); +} + +pub struct MadaraPortNum(pub u16); +impl Drop for MadaraPortNum { + fn drop(&mut self) { + let mut guard = AVAILABLE_PORTS.lock().expect("poisoned lock"); + guard.to_reuse.push(self.0); + } +} + +pub fn get_port() -> MadaraPortNum { + let mut guard = AVAILABLE_PORTS.lock().expect("poisoned lock"); + if let Some(el) = guard.to_reuse.pop() { + return MadaraPortNum(el); + } + MadaraPortNum(guard.next.next().expect("no more port to use")) +} + +pub struct MadaraCmdBuilder { + args: Vec, + env: HashMap, + tempdir: TempDir, + port: MadaraPortNum, +} + +impl Default for MadaraCmdBuilder { + fn default() -> Self { + Self::new() + } +} + +impl MadaraCmdBuilder { + pub fn new() -> Self { + Self { + args: Default::default(), + env: Default::default(), + tempdir: TempDir::with_prefix("madara-test").unwrap(), + port: get_port(), + } + } + + pub fn args(mut self, args: impl IntoIterator>) -> Self { + self.args = args.into_iter().map(Into::into).collect(); + self + } + + pub fn run(self) -> MadaraCmd { + let target_bin = PathBuf::from("./bin/madara"); + + if !target_bin.exists() { + panic!("No binary to run: {:?}", target_bin) + } + + let process = Command::new(target_bin) + .envs(self.env) + .args(self.args.into_iter().chain([ + "--base-path".into(), + format!("{}", self.tempdir.as_ref().display()), + "--rpc-port".into(), + format!("{}", self.port.0), + ])) + .stdout(Stdio::piped()) + .spawn() + .unwrap(); + + MadaraCmd { + process: Some(process), + ready: false, + rpc_url: Url::parse(&format!("http://127.0.0.1:{}/", self.port.0)).unwrap(), + _tempdir: self.tempdir, + _port: self.port, + } + } +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 15726a1..7cb71d1 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -1,44 +1,95 @@ pub mod constants; mod erc20_bridge; mod eth_bridge; +mod madara; -use constants::{ - APP_CHAIN_ID, ETH_CHAIN_ID, ETH_PRIV_KEY, ETH_RPC, FEE_TOKEN_ADDRESS, L1_DEPLOYER_ADDRESS, L1_WAIT_TIME, - ROLLUP_PRIV_KEY, ROLLUP_SEQ_URL, SN_OS_CONFIG_HASH_VERSION, SN_OS_PROGRAM_HASH, -}; use rstest::rstest; -use crate::contract_clients::config::Config; -use crate::tests::constants::{L1_MULTISIG_ADDRESS, L2_MULTISIG_ADDRESS, OPERATOR_ADDRESS, VERIFIER_ADDRESS}; +use crate::contract_clients::config::Clients; use crate::tests::erc20_bridge::erc20_bridge_test_helper; use crate::tests::eth_bridge::eth_bridge_test_helper; -use crate::{bootstrap, CliArgs}; +use crate::tests::madara::{MadaraCmd, MadaraCmdBuilder}; +use crate::{bootstrap, setup_core_contract, setup_l2, BootstrapperOutput, ConfigFile}; + +async fn test_setup(args: &ConfigFile, clients: &Clients) -> (BootstrapperOutput, MadaraCmd) { + // Setup L1 (core contract) + let core_contract_client = setup_core_contract(args, clients).await; + + let core_contract_address = core_contract_client.core_contract_client.address(); + let core_contract_implementation_address = core_contract_client.core_contract_client.implementation_address(); + + // Create a new config with the core contract addresses + let mut config = get_test_config_file(); + config.core_contract_address = Some(format!("{:?}", core_contract_address)); + config.core_contract_implementation_address = Some(format!("{:?}", core_contract_implementation_address)); + + let mut node = MadaraCmdBuilder::new() + .args([ + "--no-sync-polling", + "--l1-endpoint", + "http://localhost:8545", + "--chain-config-path=./bin/devnet.yaml", + "--rpc-cors", + "*", + "--rpc-external", + "--sequencer", + "--feeder-gateway-enable", + "--gateway-enable", + "--gateway-external", + "--rpc-methods", + "unsafe", + "--gas-price", + "0", + "--blob-gas-price", + "0", + "--strk-gas-price", + "0", + "--strk-blob-gas-price", + "0", + ]) + .run(); + node.wait_for_ready().await; + + // Setup L2 with the updated config + let l2_output = setup_l2(&config, clients).await; + + let output = BootstrapperOutput { + starknet_contract_address: Some(core_contract_address), + starknet_contract_implementation_address: Some(core_contract_implementation_address), + ..l2_output + }; + + (output, node) +} #[rstest] #[tokio::test] -#[ignore] +#[ignore = "ignored because we have a e2e test, and this is for a local test"] async fn deploy_bridge() -> Result<(), anyhow::Error> { env_logger::init(); - - bootstrap(&get_config()).await; + let config = get_test_config_file(); + let clients = Clients::init_from_config(&config).await; + bootstrap(&config, &clients).await; Ok(()) } #[rstest] #[tokio::test] -#[ignore] +#[ignore = "ignored because we have a e2e test, and this is for a local test"] async fn deposit_and_withdraw_eth_bridge() -> Result<(), anyhow::Error> { env_logger::init(); - let clients = Config::init(&get_config()).await; - let out = bootstrap(&get_config()).await; + let config = get_test_config_file(); + let clients = Clients::init_from_config(&config).await; + let out = bootstrap(&config, &clients).await; + let eth_bridge_setup = out.eth_bridge_setup_outputs.unwrap(); let _ = eth_bridge_test_helper( &clients, - &get_config(), - out.eth_proxy_address, - out.eth_bridge_proxy_address, - out.eth_bridge, + &config, + eth_bridge_setup.l2_eth_proxy_address, + eth_bridge_setup.l2_eth_bridge_proxy_address, + eth_bridge_setup.l1_bridge, ) .await; @@ -47,18 +98,20 @@ async fn deposit_and_withdraw_eth_bridge() -> Result<(), anyhow::Error> { #[rstest] #[tokio::test] -#[ignore] +#[ignore = "ignored because we have a e2e test, and this is for a local test"] async fn deposit_and_withdraw_erc20_bridge() -> Result<(), anyhow::Error> { env_logger::init(); - let clients = Config::init(&get_config()).await; - let out = bootstrap(&get_config()).await; + let config = get_test_config_file(); + let clients = Clients::init_from_config(&config).await; + let out = bootstrap(&config, &clients).await; + let eth_token_setup = out.erc20_bridge_setup_outputs.unwrap(); let _ = erc20_bridge_test_helper( &clients, - &get_config(), - out.l2_erc20_token_address, - out.starknet_token_bridge, - out.erc20_l2_bridge_address, + &config, + eth_token_setup.test_erc20_token_address, + eth_token_setup.token_bridge, + eth_token_setup.l2_token_bridge, ) .await; @@ -69,48 +122,34 @@ async fn deposit_and_withdraw_erc20_bridge() -> Result<(), anyhow::Error> { #[tokio::test] async fn deposit_tests_both_bridges() -> Result<(), anyhow::Error> { env_logger::init(); - let clients = Config::init(&get_config()).await; - let out = bootstrap(&get_config()).await; + let config = get_test_config_file(); + let clients = Clients::init_from_config(&config).await; + let (out, _madara) = test_setup(&config, &clients).await; + + let eth_bridge_setup = out.eth_bridge_setup_outputs.unwrap(); + let eth_token_setup = out.erc20_bridge_setup_outputs.unwrap(); let _ = eth_bridge_test_helper( &clients, - &get_config(), - out.eth_proxy_address, - out.eth_bridge_proxy_address, - out.eth_bridge, + &config, + eth_bridge_setup.l2_eth_proxy_address, + eth_bridge_setup.l2_eth_bridge_proxy_address, + eth_bridge_setup.l1_bridge, ) .await; let _ = erc20_bridge_test_helper( &clients, - &get_config(), - out.l2_erc20_token_address, - out.starknet_token_bridge, - out.erc20_l2_bridge_address, + &config, + eth_token_setup.test_erc20_token_address, + eth_token_setup.token_bridge, + eth_token_setup.l2_token_bridge, ) .await; Ok(()) } -fn get_config() -> CliArgs { - CliArgs { - eth_rpc: String::from(ETH_RPC), - eth_priv_key: String::from(ETH_PRIV_KEY), - rollup_seq_url: String::from(ROLLUP_SEQ_URL), - rollup_priv_key: String::from(ROLLUP_PRIV_KEY), - eth_chain_id: String::from(ETH_CHAIN_ID).parse().unwrap(), - l1_deployer_address: String::from(L1_DEPLOYER_ADDRESS), - l1_wait_time: String::from(L1_WAIT_TIME), - sn_os_program_hash: String::from(SN_OS_PROGRAM_HASH), - config_hash_version: String::from(SN_OS_CONFIG_HASH_VERSION), - app_chain_id: String::from(APP_CHAIN_ID), - fee_token_address: String::from(FEE_TOKEN_ADDRESS), - cross_chain_wait_time: 120, - l1_multisig_address: String::from(L1_MULTISIG_ADDRESS), - l2_multisig_address: String::from(L2_MULTISIG_ADDRESS), - verifier_address: String::from(VERIFIER_ADDRESS), - operator_address: String::from(OPERATOR_ADDRESS), - dev: true, - } +fn get_test_config_file() -> ConfigFile { + ConfigFile::default() } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index fad9ced..abe6d40 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,19 +1,15 @@ use std::path::Path; -use std::time::Duration; use std::{fs, io}; use ethers::addressbook::Address; use ethers::types::U256; use num_bigint::BigUint; use serde_json::{Map, Value}; -use starknet_accounts::ConnectedAccount; -use starknet_api::hash::StarkFelt; -use starknet_core::types::InvokeTransactionResult; -use starknet_core::types::MaybePendingTransactionReceipt::{PendingReceipt, Receipt}; -use starknet_ff::FieldElement; +use starknet::accounts::ConnectedAccount; +use starknet::core::types::{Felt, InvokeTransactionResult, TransactionReceipt}; +use starknet_core::types::TransactionReceiptWithBlockInfo; use starknet_providers::jsonrpc::HttpTransport; use starknet_providers::JsonRpcClient; -use tokio::time::sleep; use crate::contract_clients::utils::RpcAccount; use crate::helpers::account_actions::{get_transaction_receipt, AccountActions}; @@ -22,9 +18,9 @@ pub mod banner; pub mod constants; pub async fn invoke_contract<'a>( - contract: FieldElement, + contract: Felt, method: &str, - calldata: Vec, + calldata: Vec, account: &RpcAccount<'a>, ) -> InvokeTransactionResult { let txn_res = @@ -45,7 +41,7 @@ pub fn pad_bytes(address: Address) -> Vec { pub async fn wait_for_transaction( provider_l2: &JsonRpcClient, - transaction_hash: FieldElement, + transaction_hash: Felt, tag: &str, ) -> Result<(), anyhow::Error> { let transaction_receipt = get_transaction_receipt(provider_l2, transaction_hash).await; @@ -53,20 +49,24 @@ pub async fn wait_for_transaction( let transaction_status = transaction_receipt.ok().unwrap(); match transaction_status { - Receipt(transaction_receipt) => { - log::trace!("txn : {:?} : {:?}", tag, transaction_receipt); - Ok(()) + TransactionReceiptWithBlockInfo { receipt: TransactionReceipt::Invoke(receipt), .. } => { + log::trace!("txn : {:?} : {:?}", tag, receipt); } - PendingReceipt(..) => { - log::trace!("âŗ waiting for transaction : {:?}", transaction_hash); - sleep(Duration::from_secs(2)).await; - Box::pin(wait_for_transaction(provider_l2, transaction_hash, "")).await + TransactionReceiptWithBlockInfo { receipt: TransactionReceipt::DeployAccount(receipt), .. } => { + let contract_address = receipt.contract_address; + log::trace!("txn : {:?} : {:?}", tag, contract_address); } - } + _ => { + log::error!("Transaction status: {:?}", transaction_status); + panic!("Transaction failed"); + } + }; + + Ok(()) } -pub fn convert_felt_to_u256(felt: StarkFelt) -> U256 { - U256::from_big_endian(felt.bytes()) +pub fn convert_felt_to_u256(felt: Felt) -> U256 { + U256::from_big_endian(&felt.to_bytes_be()) } pub enum JsonValueType {