From 697eeace24c6d1cb2d56f38fa0f7ceafccf7edae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Delabrouille?= <34384633+tdelabro@users.noreply.github.com> Date: Thu, 28 Dec 2023 13:18:11 +0100 Subject: [PATCH] feat: l1-l2 messaging (#1312) Co-authored-by: Michael Zaikin Co-authored-by: Daniel Bigos Co-authored-by: Daniel Bigos Co-authored-by: apoorvsadana <95699312+apoorvsadana@users.noreply.github.com> --- .gitignore | 7 + CHANGELOG.md | 17 +- Cargo.lock | 541 +- Cargo.toml | 25 +- cairo-contracts/build/send_message.json | 1261 +++ cairo-contracts/build/test.json | 216 +- .../src/test_contracts/send_message.cairo | 10 + cairo-contracts/src/test_contracts/test.cairo | 6 + configs/genesis-assets/genesis.json | 4 +- configs/genesis-assets/test.json | 212 +- configs/index.json | 4 +- crates/client/data-availability/Cargo.toml | 6 +- .../data-availability/src/ethereum/config.rs | 7 +- crates/client/data-availability/src/lib.rs | 10 +- crates/client/db/Cargo.toml | 1 + crates/client/db/src/error.rs | 7 + crates/client/db/src/lib.rs | 18 +- crates/client/db/src/messaging_db.rs | 34 + crates/client/l1-messages/Cargo.toml | 45 + crates/client/l1-messages/src/config.rs | 62 + crates/client/l1-messages/src/contract.rs | 52 + crates/client/l1-messages/src/error.rs | 25 + crates/client/l1-messages/src/lib.rs | 5 + crates/client/l1-messages/src/worker.rs | 141 + crates/client/rpc/src/lib.rs | 45 +- crates/client/settlement/Cargo.toml | 61 + crates/client/settlement/src/errors.rs | 63 + .../client/settlement/src/ethereum/client.rs | 105 + .../client/settlement/src/ethereum/errors.rs | 26 + crates/client/settlement/src/ethereum/mod.rs | 52 + crates/client/settlement/src/lib.rs | 62 + crates/client/settlement/src/sync_state.rs | 283 + crates/node/Cargo.toml | 12 + crates/node/src/commands/run.rs | 100 +- crates/node/src/commands/setup.rs | 207 +- crates/node/src/service.rs | 49 +- crates/pallets/starknet/Cargo.toml | 7 +- .../pallets/starknet/runtime_api/Cargo.toml | 4 + .../pallets/starknet/runtime_api/src/lib.rs | 18 +- crates/pallets/starknet/src/lib.rs | 231 +- crates/pallets/starknet/src/message.rs | 84 - .../starknet/src/offchain_worker/mod.rs | 77 - .../starknet/src/offchain_worker/types.rs | 59 - .../pallets/starknet/src/tests/declare_tx.rs | 30 +- .../pallets/starknet/src/tests/invoke_tx.rs | 45 +- .../src/tests/l1_handler_validation.rs | 85 + .../pallets/starknet/src/tests/l1_message.rs | 155 +- crates/pallets/starknet/src/tests/message.rs | 26 - .../starknet/src/tests/mock/setup_mock.rs | 2 + crates/pallets/starknet/src/tests/mod.rs | 3 +- .../starknet/src/tests/send_message.rs | 99 + .../starknet/src/transaction_validation.rs | 108 + crates/primitives/messages/Cargo.toml | 40 + crates/primitives/messages/src/conversions.rs | 34 + crates/primitives/messages/src/lib.rs | 45 + crates/primitives/program-hash/Cargo.toml | 22 + crates/primitives/program-hash/src/lib.rs | 19 + crates/primitives/simulations/Cargo.toml | 10 +- crates/primitives/simulations/src/lib.rs | 29 +- crates/primitives/snos-output/Cargo.toml | 42 + crates/primitives/snos-output/src/codec.rs | 208 + .../primitives/snos-output/src/felt_reader.rs | 67 + crates/primitives/snos-output/src/lib.rs | 39 + crates/primitives/snos-output/src/tests.rs | 61 + .../primitives/transactions/src/execution.rs | 4 + crates/runtime/Cargo.toml | 2 + crates/runtime/src/lib.rs | 32 +- crates/runtime/src/pallets.rs | 5 +- docs/genesis.md | 4 +- examples/messaging/l1-messaging-config.json | 4 + madara-infra | 2 +- madara-test-runner/Cargo.toml | 31 + madara-test-runner/src/client.rs | 2 + madara-test-runner/src/lib.rs | 70 + madara-test-runner/src/node.rs | 119 + madara-zaun | 1 + starknet-e2e-test/Cargo.toml | 47 + starknet-e2e-test/README.md | 121 + starknet-e2e-test/contracts/Makefile | 8 + starknet-e2e-test/contracts/README.md | 30 + .../contracts/artifacts/Starknet.json | 8228 +++++++++++++++++ .../contracts/artifacts/UnsafeProxy.json | 702 ++ starknet-e2e-test/contracts/foundry.toml | 3 + .../contracts/src/UnsafeProxy.sol | 22 + starknet-e2e-test/ethereum_core_contract.rs | 137 + starknet-e2e-test/ethereum_e2e_settlement.rs | 172 + starknet-e2e-test/src/ethereum_sandbox.rs | 67 + starknet-e2e-test/src/lib.rs | 2 + starknet-e2e-test/src/starknet_contract.rs | 189 + starknet-rpc-test/Cargo.toml | 6 +- starknet-rpc-test/call.rs | 3 - starknet-rpc-test/get_class.rs | 13 +- starknet-rpc-test/get_class_at.rs | 1 - starknet-rpc-test/get_transaction_receipt.rs | 100 +- starknet-rpc-test/src/constants.rs | 3 +- starknet-rpc-test/src/fixtures.rs | 2 +- starknet-rpc-test/src/lib.rs | 8 +- starknet-rpc-test/src/utils.rs | 46 +- 98 files changed, 14711 insertions(+), 905 deletions(-) create mode 100644 cairo-contracts/build/send_message.json create mode 100644 cairo-contracts/src/test_contracts/send_message.cairo create mode 100644 crates/client/db/src/error.rs create mode 100644 crates/client/db/src/messaging_db.rs create mode 100644 crates/client/l1-messages/Cargo.toml create mode 100644 crates/client/l1-messages/src/config.rs create mode 100644 crates/client/l1-messages/src/contract.rs create mode 100644 crates/client/l1-messages/src/error.rs create mode 100644 crates/client/l1-messages/src/lib.rs create mode 100644 crates/client/l1-messages/src/worker.rs create mode 100644 crates/client/settlement/Cargo.toml create mode 100644 crates/client/settlement/src/errors.rs create mode 100644 crates/client/settlement/src/ethereum/client.rs create mode 100644 crates/client/settlement/src/ethereum/errors.rs create mode 100644 crates/client/settlement/src/ethereum/mod.rs create mode 100644 crates/client/settlement/src/lib.rs create mode 100644 crates/client/settlement/src/sync_state.rs delete mode 100644 crates/pallets/starknet/src/message.rs delete mode 100644 crates/pallets/starknet/src/offchain_worker/mod.rs delete mode 100644 crates/pallets/starknet/src/offchain_worker/types.rs create mode 100644 crates/pallets/starknet/src/tests/l1_handler_validation.rs delete mode 100644 crates/pallets/starknet/src/tests/message.rs create mode 100644 crates/pallets/starknet/src/tests/send_message.rs create mode 100644 crates/primitives/messages/Cargo.toml create mode 100644 crates/primitives/messages/src/conversions.rs create mode 100644 crates/primitives/messages/src/lib.rs create mode 100644 crates/primitives/program-hash/Cargo.toml create mode 100644 crates/primitives/program-hash/src/lib.rs create mode 100644 crates/primitives/snos-output/Cargo.toml create mode 100644 crates/primitives/snos-output/src/codec.rs create mode 100644 crates/primitives/snos-output/src/felt_reader.rs create mode 100644 crates/primitives/snos-output/src/lib.rs create mode 100644 crates/primitives/snos-output/src/tests.rs create mode 100644 examples/messaging/l1-messaging-config.json create mode 100644 madara-test-runner/Cargo.toml create mode 100644 madara-test-runner/src/client.rs create mode 100644 madara-test-runner/src/lib.rs create mode 100644 madara-test-runner/src/node.rs create mode 160000 madara-zaun create mode 100644 starknet-e2e-test/Cargo.toml create mode 100644 starknet-e2e-test/README.md create mode 100644 starknet-e2e-test/contracts/Makefile create mode 100644 starknet-e2e-test/contracts/README.md create mode 100644 starknet-e2e-test/contracts/artifacts/Starknet.json create mode 100644 starknet-e2e-test/contracts/artifacts/UnsafeProxy.json create mode 100644 starknet-e2e-test/contracts/foundry.toml create mode 100644 starknet-e2e-test/contracts/src/UnsafeProxy.sol create mode 100644 starknet-e2e-test/ethereum_core_contract.rs create mode 100644 starknet-e2e-test/ethereum_e2e_settlement.rs create mode 100644 starknet-e2e-test/src/ethereum_sandbox.rs create mode 100644 starknet-e2e-test/src/lib.rs create mode 100644 starknet-e2e-test/src/starknet_contract.rs diff --git a/.gitignore b/.gitignore index 59de33725e..b6e54e47fb 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,10 @@ cairo_venv # idea .idea + +# pyenv +.python-version + +# solidity cache +starknet-e2e-test/contracts/cache +starknet-e2e-test/contracts/build diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cb80fad26..18af1a823b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,20 @@ - chore: change SCARB config version for foundry CI - feat(da): update da calldata encoding to v0.11.0 spec, da conf examples, da conf flag, da-tests in CI +- refactor: use `map` in `estimate_fee` to stop computation on error +- fix(node/commands): md5 are also checked when running setup --from-local +- feat(data-availability): extend eth config with poll interval +- fix(snos-output): expose snos codec, remove unused `get_starknet_messages` + runtime method, and unnecessary mp-snos-output dependencies +- feat(program-hash): add new pallet constant for Starknet OS progam hash; + expose runtime getter method; add dedicated crate to manage versions +- feat(runtime): expose fee token address getter method +- feat(settlement): run client thread responsible for pushing state updates and + messaging on Ethereum +- feat(settlement): starknet core contract tests with anvil sandbox +- fix(rpc-test): incorrect node url +- feat(settlement): e2e test with Madara node settling on Ethereum contract +- refactor: use `map` in `estimate_fee` to stop computation on error ## v0.6.0 @@ -49,7 +63,6 @@ - chore(data-availability-avail): implement fire and forget, and add ws reconnection logic - chore: update `polkadot-sdk` to `release-polkadot-v1.3.0` -- refactor: use `map` in `estimate_fee` to stop computation on error ## v0.5.0 @@ -167,6 +180,8 @@ - fix: rpc tests and background node run - test: add tests for simulate tx offset - test: add tests for tx hashing +- fix: bring back messages in transaction receipts +- feat: starknet os program output primitive ## v0.2.0 diff --git a/Cargo.lock b/Cargo.lock index 9ee99728db..fa151a02de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -147,9 +147,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" dependencies = [ "anstyle", "anstyle-parse", @@ -167,30 +167,30 @@ checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.1" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" dependencies = [ "anstyle", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -593,7 +593,7 @@ dependencies = [ "futures-lite", "parking", "polling", - "rustix 0.38.26", + "rustix 0.38.28", "slab", "tracing", "windows-sys 0.52.0", @@ -627,7 +627,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -840,7 +840,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -1343,7 +1343,7 @@ source = "git+https://github.com/keep-starknet-strange/cairo.git?branch=no_std-s dependencies = [ "cairo-lang-debug", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -1885,9 +1885,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.10" +version = "4.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fffed7514f420abec6d183b1d3acfd9099c79c3a10a06ade4f8203f1411272" +checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" dependencies = [ "clap_builder", "clap_derive", @@ -1895,9 +1895,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.9" +version = "4.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63361bae7eef3771745f02d8d892bec2fee5f6e34af316ba556e7f97a7069ff1" +checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" dependencies = [ "anstream", "anstyle", @@ -1914,7 +1914,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -1993,11 +1993,10 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "colored" -version = "2.0.4" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" +checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" dependencies = [ - "is-terminal", "lazy_static", "windows-sys 0.48.0", ] @@ -2456,7 +2455,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -2496,7 +2495,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -2513,7 +2512,7 @@ checksum = "587663dd5fb3d10932c8aecfe7c844db1bcf0aee93eeab08fac13dc1212c2e7f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -2585,7 +2584,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -2607,7 +2606,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core 0.20.3", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -2816,7 +2815,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -2857,7 +2856,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.39", + "syn 2.0.40", "termcolor", "toml 0.8.8", "walkdir", @@ -3083,7 +3082,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -3194,8 +3193,7 @@ dependencies = [ [[package]] name = "ethers" version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5344eea9b20effb5efeaad29418215c4d27017639fd1f908260f59cbbd226e" +source = "git+https://github.com/gakonst/ethers-rs?rev=f0e5b194f09c533feb10d1a686ddb9e5946ec107#f0e5b194f09c533feb10d1a686ddb9e5946ec107" dependencies = [ "ethers-addressbook", "ethers-contract", @@ -3210,8 +3208,7 @@ dependencies = [ [[package]] name = "ethers-addressbook" version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c405f24ea3a517899ba7985385c43dc4a7eb1209af3b1e0a1a32d7dcc7f8d09" +source = "git+https://github.com/gakonst/ethers-rs?rev=f0e5b194f09c533feb10d1a686ddb9e5946ec107#f0e5b194f09c533feb10d1a686ddb9e5946ec107" dependencies = [ "ethers-core", "once_cell", @@ -3222,8 +3219,7 @@ dependencies = [ [[package]] name = "ethers-contract" version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0111ead599d17a7bff6985fd5756f39ca7033edc79a31b23026a8d5d64fa95cd" +source = "git+https://github.com/gakonst/ethers-rs?rev=f0e5b194f09c533feb10d1a686ddb9e5946ec107#f0e5b194f09c533feb10d1a686ddb9e5946ec107" dependencies = [ "const-hex", "ethers-contract-abigen", @@ -3241,8 +3237,7 @@ dependencies = [ [[package]] name = "ethers-contract-abigen" version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51258120c6b47ea9d9bec0d90f9e8af71c977fbefbef8213c91bfed385fe45eb" +source = "git+https://github.com/gakonst/ethers-rs?rev=f0e5b194f09c533feb10d1a686ddb9e5946ec107#f0e5b194f09c533feb10d1a686ddb9e5946ec107" dependencies = [ "Inflector", "const-hex", @@ -3257,7 +3252,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "syn 2.0.39", + "syn 2.0.40", "toml 0.8.8", "walkdir", ] @@ -3265,8 +3260,7 @@ dependencies = [ [[package]] name = "ethers-contract-derive" version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936e7a0f1197cee2b62dc89f63eff3201dbf87c283ff7e18d86d38f83b845483" +source = "git+https://github.com/gakonst/ethers-rs?rev=f0e5b194f09c533feb10d1a686ddb9e5946ec107#f0e5b194f09c533feb10d1a686ddb9e5946ec107" dependencies = [ "Inflector", "const-hex", @@ -3275,14 +3269,13 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] name = "ethers-core" version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f03e0bdc216eeb9e355b90cf610ef6c5bb8aca631f97b5ae9980ce34ea7878d" +source = "git+https://github.com/gakonst/ethers-rs?rev=f0e5b194f09c533feb10d1a686ddb9e5946ec107#f0e5b194f09c533feb10d1a686ddb9e5946ec107" dependencies = [ "arrayvec 0.7.4", "bytes", @@ -3301,7 +3294,7 @@ dependencies = [ "serde", "serde_json", "strum 0.25.0", - "syn 2.0.39", + "syn 2.0.40", "tempfile", "thiserror", "tiny-keccak", @@ -3311,8 +3304,7 @@ dependencies = [ [[package]] name = "ethers-etherscan" version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abbac2c890bdbe0f1b8e549a53b00e2c4c1de86bb077c1094d1f38cdf9381a56" +source = "git+https://github.com/gakonst/ethers-rs?rev=f0e5b194f09c533feb10d1a686ddb9e5946ec107#f0e5b194f09c533feb10d1a686ddb9e5946ec107" dependencies = [ "chrono", "ethers-core", @@ -3327,8 +3319,7 @@ dependencies = [ [[package]] name = "ethers-middleware" version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681ece6eb1d10f7cf4f873059a77c04ff1de4f35c63dd7bccde8f438374fcb93" +source = "git+https://github.com/gakonst/ethers-rs?rev=f0e5b194f09c533feb10d1a686ddb9e5946ec107#f0e5b194f09c533feb10d1a686ddb9e5946ec107" dependencies = [ "async-trait", "auto_impl", @@ -3354,8 +3345,7 @@ dependencies = [ [[package]] name = "ethers-providers" version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25d6c0c9455d93d4990c06e049abf9b30daf148cf461ee939c11d88907c60816" +source = "git+https://github.com/gakonst/ethers-rs?rev=f0e5b194f09c533feb10d1a686ddb9e5946ec107#f0e5b194f09c533feb10d1a686ddb9e5946ec107" dependencies = [ "async-trait", "auto_impl", @@ -3391,8 +3381,7 @@ dependencies = [ [[package]] name = "ethers-signers" version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cb1b714e227bbd2d8c53528adb580b203009728b17d0d0e4119353aa9bc5532" +source = "git+https://github.com/gakonst/ethers-rs?rev=f0e5b194f09c533feb10d1a686ddb9e5946ec107#f0e5b194f09c533feb10d1a686ddb9e5946ec107" dependencies = [ "async-trait", "coins-bip32", @@ -3410,8 +3399,7 @@ dependencies = [ [[package]] name = "ethers-solc" version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a64f710586d147864cff66540a6d64518b9ff37d73ef827fee430538265b595f" +source = "git+https://github.com/gakonst/ethers-rs?rev=f0e5b194f09c533feb10d1a686ddb9e5946ec107#f0e5b194f09c533feb10d1a686ddb9e5946ec107" dependencies = [ "cfg-if", "const-hex", @@ -3485,14 +3473,14 @@ dependencies = [ "fs-err", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] name = "eyre" -version = "0.6.9" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80f656be11ddf91bd709454d15d5bd896fbaf4cc3314e69349e4d1569f5b46cd" +checksum = "8bbb8258be8305fb0237d7b295f47bb24ff1b136a535f473baf40e70468515aa" dependencies = [ "indenter", "once_cell", @@ -3728,7 +3716,7 @@ dependencies = [ "Inflector", "array-bytes 6.2.2", "chrono", - "clap 4.4.10", + "clap 4.4.11", "comfy-table", "frame-benchmarking", "frame-support", @@ -3887,7 +3875,7 @@ dependencies = [ "proc-macro2", "quote", "sp-core-hashing 9.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.3.0)", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -3899,7 +3887,7 @@ dependencies = [ "proc-macro-crate 1.1.3", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -3909,7 +3897,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -3986,6 +3974,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + [[package]] name = "funty" version = "2.0.0" @@ -4069,7 +4063,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -4151,7 +4145,7 @@ checksum = "d4cf186fea4af17825116f72932fe52cce9a13bae39ff63b4dc0cfdb3fb4bde1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -4539,9 +4533,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -4606,7 +4600,7 @@ dependencies = [ "http", "hyper", "log", - "rustls 0.21.9", + "rustls 0.21.10", "rustls-native-certs", "tokio", "tokio-rustls", @@ -4898,7 +4892,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi 0.3.3", - "rustix 0.38.26", + "rustix 0.38.28", "windows-sys 0.48.0", ] @@ -4922,9 +4916,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "jobserver" @@ -5347,9 +5341,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "libloading" @@ -5998,7 +5992,7 @@ dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -6012,7 +6006,7 @@ dependencies = [ "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -6023,7 +6017,7 @@ checksum = "9ea73aa640dc01d62a590d48c0c3521ed739d53b27f919b25c3551e233481654" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -6034,7 +6028,7 @@ checksum = "ef9d79ae96aaba821963320eb2b6e34d17df1e5a83d8a1985c29cc5be59577b3" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -6043,7 +6037,8 @@ version = "0.6.0" dependencies = [ "async-trait", "blockifier", - "clap 4.4.10", + "clap 4.4.11", + "ethers", "frame-benchmarking", "frame-benchmarking-cli", "frame-system", @@ -6056,16 +6051,20 @@ dependencies = [ "mc-data-availability", "mc-db", "mc-genesis-data-provider", + "mc-l1-messages", "mc-mapping-sync", "mc-rpc", + "mc-settlement", "mc-storage", "md5", "mp-block", "mp-digest-log", "mp-felt", "mp-sequencer-address", + "mp-transactions", "pallet-starknet", "pallet-starknet-runtime-api", + "parity-scale-codec", "reqwest", "sc-basic-authorship", "sc-cli", @@ -6101,6 +6100,7 @@ dependencies = [ "sp-timestamp", "sp-trie 22.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.3.0)", "starknet-core", + "starknet_api", "substrate-build-script-utils", "substrate-frame-rpc-system", "substrate-prometheus-endpoint", @@ -6120,9 +6120,11 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", + "mp-block", "mp-chain-id", "mp-felt", "mp-hashers", + "mp-program-hash", "mp-simulations", "mp-transactions", "pallet-aura", @@ -6150,6 +6152,35 @@ dependencies = [ "substrate-wasm-builder", ] +[[package]] +name = "madara-test-runner" +version = "0.1.0" +dependencies = [ + "anyhow", + "assert_matches", + "async-lock 3.2.0", + "async-trait", + "derive_more", + "flate2", + "lazy_static", + "reqwest", + "rstest", + "serde", + "serde_json", + "starknet-accounts", + "starknet-contract", + "starknet-core", + "starknet-crypto", + "starknet-ff", + "starknet-providers", + "starknet-rpc-test", + "starknet-signers", + "starknet_api", + "thiserror", + "tokio", + "url", +] + [[package]] name = "maplit" version = "1.0.2" @@ -6233,7 +6264,7 @@ dependencies = [ "blockifier", "celestia-rpc", "celestia-types", - "clap 4.4.10", + "clap 4.4.11", "ethers", "futures", "indexmap 2.0.0-pre", @@ -6277,6 +6308,7 @@ dependencies = [ "sp-database", "sp-runtime 24.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.3.0)", "starknet_api", + "thiserror", "uuid 1.6.1", ] @@ -6294,6 +6326,29 @@ dependencies = [ "thiserror", ] +[[package]] +name = "mc-l1-messages" +version = "0.1.0" +dependencies = [ + "ethers", + "log", + "mc-db", + "mp-felt", + "mp-transactions", + "pallet-starknet-runtime-api", + "rustc-hex", + "sc-client-api", + "sc-transaction-pool-api", + "serde", + "serde_json", + "sp-api", + "sp-core 21.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.3.0)", + "sp-runtime 24.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.3.0)", + "starknet_api", + "thiserror", + "url", +] + [[package]] name = "mc-mapping-sync" version = "0.6.0" @@ -6393,6 +6448,40 @@ dependencies = [ "thiserror", ] +[[package]] +name = "mc-settlement" +version = "0.1.0" +dependencies = [ + "async-trait", + "clap 4.4.11", + "ethers", + "futures", + "futures-timer", + "log", + "mc-data-availability", + "mp-block", + "mp-digest-log", + "mp-hashers", + "mp-messages", + "mp-snos-output", + "mp-transactions", + "pallet-starknet-runtime-api", + "rustc-hex", + "sc-client-api", + "serde", + "serde_json", + "sp-api", + "sp-arithmetic 16.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.3.0)", + "sp-blockchain", + "sp-core 21.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.3.0)", + "sp-io 23.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.3.0)", + "sp-runtime 24.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.3.0)", + "starknet-crypto", + "starknet_api", + "thiserror", + "url", +] + [[package]] name = "mc-storage" version = "0.6.0" @@ -6444,7 +6533,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" dependencies = [ - "rustix 0.38.26", + "rustix 0.38.28", ] [[package]] @@ -6706,6 +6795,26 @@ dependencies = [ "starknet-crypto", ] +[[package]] +name = "mp-messages" +version = "0.6.0" +dependencies = [ + "mp-transactions", + "parity-scale-codec", + "scale-info", + "serde", + "serde_with", + "starknet_api", +] + +[[package]] +name = "mp-program-hash" +version = "0.6.0" +dependencies = [ + "mp-felt", + "starknet-ff", +] + [[package]] name = "mp-sequencer-address" version = "0.6.0" @@ -6723,6 +6832,7 @@ version = "0.6.0" dependencies = [ "blockifier", "mp-felt", + "mp-messages", "parity-scale-codec", "scale-info", "serde", @@ -6731,6 +6841,21 @@ dependencies = [ "starknet_api", ] +[[package]] +name = "mp-snos-output" +version = "0.6.0" +dependencies = [ + "assert_matches", + "hex", + "mp-messages", + "mp-transactions", + "parity-scale-codec", + "pretty_assertions", + "scale-info", + "sp-core 21.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.3.0)", + "starknet_api", +] + [[package]] name = "mp-state" version = "0.6.0" @@ -7256,7 +7381,7 @@ dependencies = [ "proc-macro-crate 2.0.0", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -7346,9 +7471,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.60" +version = "0.10.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79a4c6c3a2b158f7f8f2a2fc5a969fa3a068df6fc9dbb4a43845436e3af7c800" +checksum = "6b8419dc8cc6d866deb801274bba2e6f8f6108c1bb7fcc10ee5ab864931dbb45" dependencies = [ "bitflags 2.4.1", "cfg-if", @@ -7367,7 +7492,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -7378,9 +7503,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.96" +version = "0.9.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3812c071ba60da8b5677cc12bcb1d42989a65553772897a7e0355545a819838f" +checksum = "c3eaad34cdd97d81de97964fc7f29e2d104f483840d906ef56daa1912338460b" dependencies = [ "cc", "libc", @@ -7495,8 +7620,10 @@ dependencies = [ "mp-felt", "mp-genesis-config", "mp-hashers", + "mp-program-hash", "mp-sequencer-address", "mp-simulations", + "mp-snos-output", "mp-state", "mp-storage", "mp-transactions", @@ -7532,6 +7659,7 @@ dependencies = [ "hashbrown 0.14.3", "mp-felt", "mp-simulations", + "mp-snos-output", "mp-transactions", "parity-scale-codec", "scale-info", @@ -7793,7 +7921,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -7857,7 +7985,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -7901,7 +8029,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -7953,7 +8081,7 @@ dependencies = [ "cfg-if", "concurrent-queue", "pin-project-lite 0.2.13", - "rustix 0.38.26", + "rustix 0.38.28", "tracing", "windows-sys 0.52.0", ] @@ -8062,7 +8190,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" dependencies = [ "proc-macro2", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -8130,7 +8258,7 @@ checksum = "9b698b0b09d40e9b7c1a47b132d66a8b54bcd20583d9b6d06e4535e383b4405c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -8182,7 +8310,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -8260,7 +8388,7 @@ dependencies = [ "prost 0.12.3", "prost-types 0.12.3", "regex", - "syn 2.0.39", + "syn 2.0.40", "tempfile", "which", ] @@ -8288,7 +8416,7 @@ dependencies = [ "itertools 0.11.0", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -8390,6 +8518,19 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + [[package]] name = "rand" version = "0.7.3" @@ -8434,6 +8575,21 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + [[package]] name = "rand_core" version = "0.5.1" @@ -8527,6 +8683,15 @@ dependencies = [ "yasna", ] +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -8573,7 +8738,7 @@ checksum = "7f7473c2cfcf90008193dd0e3e16599455cb601a9fce322b5bb55de799664925" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -8644,6 +8809,15 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c707298afce11da2efef2f600116fa93ffa7a032b5d7b628aa17711ec81383ca" +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + [[package]] name = "reqwest" version = "0.11.22" @@ -8669,7 +8843,7 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite 0.2.13", - "rustls 0.21.9", + "rustls 0.21.10", "rustls-pemfile", "serde", "serde_json", @@ -8829,7 +9003,7 @@ dependencies = [ "regex", "relative-path", "rustc_version 0.4.0", - "syn 2.0.39", + "syn 2.0.40", "unicode-ident", ] @@ -8949,9 +9123,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.26" +version = "0.38.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9470c4bf8246c8daf25f9598dca807fb6510347b1e1cfa55749113850c79d88a" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" dependencies = [ "bitflags 2.4.1", "errno", @@ -8974,9 +9148,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.9" +version = "0.21.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", "ring 0.17.7", @@ -9034,9 +9208,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "safe_arch" @@ -9170,7 +9344,7 @@ dependencies = [ "proc-macro-crate 1.1.3", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -9180,7 +9354,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot dependencies = [ "array-bytes 6.2.2", "chrono", - "clap 4.4.10", + "clap 4.4.11", "fdlimit", "futures", "libp2p-identity 0.1.3", @@ -10035,7 +10209,7 @@ dependencies = [ "proc-macro-crate 1.1.3", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -10435,7 +10609,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -10468,7 +10642,7 @@ checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -10517,7 +10691,7 @@ dependencies = [ "darling 0.20.3", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -10702,9 +10876,9 @@ dependencies = [ [[package]] name = "snap" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e9f0ab6ef7eb7353d9119c170a436d1bf248eea575ac42d19d12f4e34130831" +checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" [[package]] name = "snow" @@ -10806,7 +10980,7 @@ dependencies = [ "proc-macro-crate 1.1.3", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -11102,7 +11276,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot dependencies = [ "quote", "sp-core-hashing 9.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.3.0)", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -11122,7 +11296,7 @@ checksum = "c7f531814d2f16995144c74428830ccf7d94ff4a7749632b83ad8199b181140c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -11132,7 +11306,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -11436,7 +11610,7 @@ dependencies = [ "proc-macro-crate 1.1.3", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -11448,7 +11622,7 @@ dependencies = [ "proc-macro-crate 1.1.3", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -11719,7 +11893,7 @@ dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -11915,7 +12089,7 @@ source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=a35ce22#a35ce2 dependencies = [ "starknet-curve", "starknet-ff", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -11926,6 +12100,41 @@ dependencies = [ "starknet-ff", ] +[[package]] +name = "starknet-e2e-test" +version = "0.1.0" +dependencies = [ + "anyhow", + "assert_matches", + "async-trait", + "ethers", + "ethers-solc", + "flate2", + "home", + "madara-runtime", + "madara-test-runner", + "mc-settlement", + "mp-messages", + "mp-snos-output", + "reqwest", + "rstest", + "serde", + "serde_json", + "starknet-accounts", + "starknet-contract", + "starknet-core", + "starknet-crypto", + "starknet-ff", + "starknet-providers", + "starknet-signers", + "starknet_api", + "tempdir", + "test-context", + "thiserror", + "tokio", + "url", +] + [[package]] name = "starknet-ff" version = "0.3.5" @@ -12142,7 +12351,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -12301,7 +12510,7 @@ dependencies = [ "quote", "scale-info", "subxt-metadata", - "syn 2.0.39", + "syn 2.0.40", "thiserror", "tokio", ] @@ -12315,7 +12524,7 @@ dependencies = [ "darling 0.20.3", "proc-macro-error", "subxt-codegen", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -12364,9 +12573,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.39" +version = "2.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "13fa70a4ee923979ffb522cacce59d34421ebdea5625e1073c4326ef9d2dd42e" dependencies = [ "proc-macro2", "quote", @@ -12418,6 +12627,16 @@ version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" +[[package]] +name = "tempdir" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +dependencies = [ + "rand 0.4.6", + "remove_dir_all", +] + [[package]] name = "tempfile" version = "3.8.1" @@ -12427,7 +12646,7 @@ dependencies = [ "cfg-if", "fastrand", "redox_syscall 0.4.1", - "rustix 0.38.26", + "rustix 0.38.28", "windows-sys 0.48.0", ] @@ -12520,7 +12739,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -12531,10 +12750,31 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", "test-case-core", ] +[[package]] +name = "test-context" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "055831a02a4f5aa28fede67f2902014273eb8c21b958ac5ebbd59b71ef30dbc3" +dependencies = [ + "async-trait", + "futures", + "test-context-macros", +] + +[[package]] +name = "test-context-macros" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8901a55b0a7a06ebc4a674dcca925170da8e613fa3b163a1df804ed10afb154d" +dependencies = [ + "quote", + "syn 1.0.109", +] + [[package]] name = "textwrap" version = "0.11.0" @@ -12561,7 +12801,7 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -12693,9 +12933,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.34.0" +version = "1.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +checksum = "841d45b238a16291a4e1584e61820b8ae57d696cc5015c459c229ccc6990cc1c" dependencies = [ "backtrace", "bytes", @@ -12718,7 +12958,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -12748,7 +12988,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.9", + "rustls 0.21.10", "tokio", ] @@ -12772,8 +13012,10 @@ checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" dependencies = [ "futures-util", "log", - "rustls 0.21.9", + "native-tls", + "rustls 0.21.10", "tokio", + "tokio-native-tls", "tokio-rustls", "tungstenite", "webpki-roots 0.25.3", @@ -12938,7 +13180,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -13088,9 +13330,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "try-runtime-cli" @@ -13098,7 +13340,7 @@ version = "0.10.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.3.0#401f8a3e9448db854f5605b679fa085b8f445039" dependencies = [ "async-trait", - "clap 4.4.10", + "clap 4.4.11", "frame-remote-externalities", "frame-try-runtime", "hex", @@ -13146,8 +13388,9 @@ dependencies = [ "http", "httparse", "log", + "native-tls", "rand 0.8.5", - "rustls 0.21.9", + "rustls 0.21.10", "sha1", "thiserror", "url", @@ -13427,7 +13670,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", "wasm-bindgen-shared", ] @@ -13461,7 +13704,7 @@ checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -13785,7 +14028,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.26", + "rustix 0.38.28", ] [[package]] @@ -14054,9 +14297,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.5.25" +version = "0.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e87b8dfbe3baffbe687eef2e164e32286eff31a5ee16463ce03d991643ec94" +checksum = "b67b5f0a4e7a27a64c651977932b9dc5667ca7fc31ac44b03ed37a0cf42fdfff" dependencies = [ "memchr", ] @@ -14192,22 +14435,22 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.29" +version = "0.7.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d075cf85bbb114e933343e087b92f2146bac0d55b534cbb8188becf0039948e" +checksum = "306dca4455518f1f31635ec308b6b3e4eb1b11758cefafc782827d0aa7acb5c7" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.29" +version = "0.7.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86cd5ca076997b97ef09d3ad65efe811fa68c9e874cb636ccb211223a813b0c2" +checksum = "be912bf68235a88fbefd1b73415cb218405958d1655b2ece9035a19920bdf6ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -14227,7 +14470,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 1462bed647..2ddb30e220 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ members = [ "crates/pallets/starknet", "crates/primitives/genesis-config/", "crates/primitives/digest-log", + "crates/primitives/snos-output", "crates/primitives/transactions", "crates/primitives/felt", "crates/primitives/hashers", @@ -17,6 +18,8 @@ members = [ "crates/primitives/storage", "crates/primitives/commitments", "crates/primitives/chain-id", + "crates/primitives/messages", + "crates/primitives/program-hash", "crates/client/genesis-data-provider", "crates/client/db", "crates/client/rpc-core", @@ -24,10 +27,13 @@ members = [ "crates/client/mapping-sync", "crates/client/storage", "crates/client/commitment-state-diff", + "crates/client/settlement", "starknet-rpc-test", "da-test", + "starknet-e2e-test", + "madara-test-runner", ] -# All previous except for `starknet-rpc-test` and `da-test` +# All previous except for `starknet-rpc-test` and `starknet-e2e-test` # We don't want `cargo test` to trigger its tests default-members = [ "crates/node", @@ -46,6 +52,8 @@ default-members = [ "crates/primitives/storage", "crates/primitives/commitments", "crates/primitives/chain-id", + "crates/primitives/messages", + "crates/primitives/program-hash", "crates/client/genesis-data-provider", "crates/client/db", "crates/client/rpc-core", @@ -53,6 +61,7 @@ default-members = [ "crates/client/mapping-sync", "crates/client/storage", "crates/client/commitment-state-diff", + "crates/client/settlement", ] [profile.release] @@ -163,12 +172,15 @@ mp-fee = { path = "crates/primitives/fee", default-features = false } mp-felt = { path = "crates/primitives/felt", default-features = false } mp-hashers = { path = "crates/primitives/hashers", default-features = false } mp-sequencer-address = { path = "crates/primitives/sequencer-address", default-features = false } +mp-snos-output = { path = "crates/primitives/snos-output", default-features = false } mp-state = { path = "crates/primitives/state", default-features = false } mp-storage = { path = "crates/primitives/storage", default-features = false } mp-transactions = { path = "crates/primitives/transactions", default-features = false } mp-commitments = { path = "crates/primitives/commitments", default-features = false } mp-chain-id = { path = "crates/primitives/chain-id", default-features = false } mp-simulations = { path = "crates/primitives/simulations", default-features = false } +mp-program-hash = { path = "crates/primitives/program-hash", default-features = false } +mp-messages = { path = "crates/primitives/messages", default-features = false } # Madara client mc-genesis-data-provider = { path = "crates/client/genesis-data-provider" } @@ -179,10 +191,15 @@ mc-rpc = { path = "crates/client/rpc" } mc-rpc-core = { path = "crates/client/rpc-core" } mc-data-availability = { path = "crates/client/data-availability" } mc-commitment-state-diff = { path = "crates/client/commitment-state-diff" } +mc-l1-messages = { path = "crates/client/l1-messages" } +mc-settlement = { path = "crates/client/settlement" } # Madara runtime madara-runtime = { path = "crates/runtime" } +# Madara test runner +madara-test-runner = { path = "madara-test-runner" } + # Starknet dependencies # Cairo Virtual Machine cairo-vm = { git = "https://github.com/keep-starknet-strange/cairo-rs", branch = "no_std-support-21eff70", default-features = false, features = [ @@ -211,6 +228,10 @@ cairo-lang-casm-contract-class = { git = "https://github.com/keep-starknet-stran cairo-lang-casm = { git = "https://github.com/keep-starknet-strange/cairo.git", branch = "no_std-support-8bbf530", default-features = false } cairo-lang-utils = { git = "https://github.com/keep-starknet-strange/cairo.git", branch = "no_std-support-8bbf530", default-features = false } +# Ethers: using the same versions as in Anvil +ethers = { git = "https://github.com/gakonst/ethers-rs", rev = "f0e5b194f09c533feb10d1a686ddb9e5946ec107" } +ethers-solc = { git = "https://github.com/gakonst/ethers-rs", rev = "f0e5b194f09c533feb10d1a686ddb9e5946ec107" } + # Other third party dependencies anyhow = "1.0.75" flate2 = "1.0.28" @@ -247,10 +268,10 @@ url = "2.4.1" hashbrown = "0.14.2" tokio = "1.34.0" openssl = { version = "0.10", features = ["vendored"] } -ethers = "2.0.7" subxt = "0.29" assert_matches = "1.5.0" async-lock = "3.1.0" +rustc-hex = { version = "2.0.0" } [patch."https://github.com/w3f/ring-vrf"] bandersnatch_vrfs = { git = "https://github.com/w3f/ring-vrf?rev=3ddc20", version = "0.0.4", rev = "3ddc20" } diff --git a/cairo-contracts/build/send_message.json b/cairo-contracts/build/send_message.json new file mode 100644 index 0000000000..9ac4374447 --- /dev/null +++ b/cairo-contracts/build/send_message.json @@ -0,0 +1,1261 @@ +{ + "abi": [ + { + "inputs": [ + { + "name": "to_address", + "type": "felt" + }, + { + "name": "payload_len", + "type": "felt" + }, + { + "name": "payload", + "type": "felt*" + } + ], + "name": "send_message_l2_to_l1", + "outputs": [], + "type": "function" + } + ], + "entry_points_by_type": { + "CONSTRUCTOR": [], + "EXTERNAL": [ + { + "offset": "0x13", + "selector": "0x9139dbd19ca9654d773cd88f31af4c8d583beecc3362fb986dccfef5cf134f" + } + ], + "L1_HANDLER": [] + }, + "program": { + "attributes": [], + "builtins": [ + "range_check" + ], + "compiler_version": "0.11.2", + "data": [ + "0x40780017fff7fff", + "0x1", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x53656e644d657373616765546f4c31", + "0x400280007ffa7fff", + "0x400380017ffa7ffb", + "0x400380027ffa7ffc", + "0x400380037ffa7ffd", + "0x482680017ffa8000", + "0x4", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff4", + "0x208b7fff7fff7ffe", + "0x480280017ffb8000", + "0x480280017ffd8000", + "0x400080007ffe7fff", + "0x482680017ffd8000", + "0x2", + "0x480280017ffd8000", + "0x48307fff7ffe8000", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x482680017ffd8000", + "0x2", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffed", + "0x40780017fff7fff", + "0x1", + "0x480280017ffb8000", + "0x48127ffd7fff8000", + "0x482480017ffe8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe" + ], + "debug_info": null, + "hints": { + "0": [ + { + "accessible_scopes": [ + "starkware.cairo.common.alloc", + "starkware.cairo.common.alloc.alloc" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 0, + "offset": 0 + }, + "reference_ids": {} + } + } + ], + "9": [ + { + "accessible_scopes": [ + "starkware.starknet.common.messages", + "starkware.starknet.common.messages.send_message_to_l1" + ], + "code": "syscall_handler.send_message_to_l1(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 1, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.messages.send_message_to_l1.syscall_ptr": 0 + } + } + } + ], + "34": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.send_message_l2_to_l1" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 3, + "offset": 19 + }, + "reference_ids": {} + } + } + ] + }, + "identifiers": { + "__main__.alloc": { + "destination": "starkware.cairo.common.alloc.alloc", + "type": "alias" + }, + "__main__.send_message_l2_to_l1": { + "decorators": [ + "external" + ], + "pc": 12, + "type": "function" + }, + "__main__.send_message_l2_to_l1.Args": { + "full_name": "__main__.send_message_l2_to_l1.Args", + "members": { + "payload": { + "cairo_type": "felt*", + "offset": 2 + }, + "payload_len": { + "cairo_type": "felt", + "offset": 1 + }, + "to_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.send_message_l2_to_l1.ImplicitArgs": { + "full_name": "__main__.send_message_l2_to_l1.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.send_message_l2_to_l1.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.send_message_l2_to_l1.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.send_message_to_l1": { + "destination": "starkware.starknet.common.messages.send_message_to_l1", + "type": "alias" + }, + "__wrappers__.send_message_l2_to_l1": { + "decorators": [ + "external" + ], + "pc": 19, + "type": "function" + }, + "__wrappers__.send_message_l2_to_l1.Args": { + "full_name": "__wrappers__.send_message_l2_to_l1.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.send_message_l2_to_l1.ImplicitArgs": { + "full_name": "__wrappers__.send_message_l2_to_l1.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.send_message_l2_to_l1.Return": { + "cairo_type": "(syscall_ptr: felt*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.send_message_l2_to_l1.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.send_message_l2_to_l1.__wrapped_func": { + "destination": "__main__.send_message_l2_to_l1", + "type": "alias" + }, + "__wrappers__.send_message_l2_to_l1_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "starkware.cairo.common.alloc.alloc": { + "decorators": [], + "pc": 0, + "type": "function" + }, + "starkware.cairo.common.alloc.alloc.Args": { + "full_name": "starkware.cairo.common.alloc.alloc.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.common.alloc.alloc.ImplicitArgs": { + "full_name": "starkware.cairo.common.alloc.alloc.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.cairo.common.alloc.alloc.Return": { + "cairo_type": "(ptr: felt*)", + "type": "type_definition" + }, + "starkware.cairo.common.alloc.alloc.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.bool.FALSE": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.bool.TRUE": { + "type": "const", + "value": 1 + }, + "starkware.cairo.common.cairo_builtins.BitwiseBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.BitwiseBuiltin", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "x_and_y": { + "cairo_type": "felt", + "offset": 2 + }, + "x_or_y": { + "cairo_type": "felt", + "offset": 4 + }, + "x_xor_y": { + "cairo_type": "felt", + "offset": 3 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.EcOpBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.EcOpBuiltin", + "members": { + "m": { + "cairo_type": "felt", + "offset": 4 + }, + "p": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 0 + }, + "q": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 2 + }, + "r": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.EcPoint": { + "destination": "starkware.cairo.common.ec_point.EcPoint", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.HashBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "members": { + "result": { + "cairo_type": "felt", + "offset": 2 + }, + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.KeccakBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.KeccakBuiltin", + "members": { + "input": { + "cairo_type": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "offset": 0 + }, + "output": { + "cairo_type": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "offset": 8 + } + }, + "size": 16, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.KeccakBuiltinState": { + "destination": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.PoseidonBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.PoseidonBuiltin", + "members": { + "input": { + "cairo_type": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "offset": 0 + }, + "output": { + "cairo_type": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "offset": 3 + } + }, + "size": 6, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.PoseidonBuiltinState": { + "destination": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.SignatureBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.SignatureBuiltin", + "members": { + "message": { + "cairo_type": "felt", + "offset": 1 + }, + "pub_key": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.dict_access.DictAccess": { + "full_name": "starkware.cairo.common.dict_access.DictAccess", + "members": { + "key": { + "cairo_type": "felt", + "offset": 0 + }, + "new_value": { + "cairo_type": "felt", + "offset": 2 + }, + "prev_value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.ec_point.EcPoint": { + "full_name": "starkware.cairo.common.ec_point.EcPoint", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "starkware.cairo.common.keccak_state.KeccakBuiltinState": { + "full_name": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "members": { + "s0": { + "cairo_type": "felt", + "offset": 0 + }, + "s1": { + "cairo_type": "felt", + "offset": 1 + }, + "s2": { + "cairo_type": "felt", + "offset": 2 + }, + "s3": { + "cairo_type": "felt", + "offset": 3 + }, + "s4": { + "cairo_type": "felt", + "offset": 4 + }, + "s5": { + "cairo_type": "felt", + "offset": 5 + }, + "s6": { + "cairo_type": "felt", + "offset": 6 + }, + "s7": { + "cairo_type": "felt", + "offset": 7 + } + }, + "size": 8, + "type": "struct" + }, + "starkware.cairo.common.math.FALSE": { + "destination": "starkware.cairo.common.bool.FALSE", + "type": "alias" + }, + "starkware.cairo.common.math.TRUE": { + "destination": "starkware.cairo.common.bool.TRUE", + "type": "alias" + }, + "starkware.cairo.common.poseidon_state.PoseidonBuiltinState": { + "full_name": "starkware.cairo.common.poseidon_state.PoseidonBuiltinState", + "members": { + "s0": { + "cairo_type": "felt", + "offset": 0 + }, + "s1": { + "cairo_type": "felt", + "offset": 1 + }, + "s2": { + "cairo_type": "felt", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.messages.SEND_MESSAGE_TO_L1_SELECTOR": { + "destination": "starkware.starknet.common.syscalls.SEND_MESSAGE_TO_L1_SELECTOR", + "type": "alias" + }, + "starkware.starknet.common.messages.SendMessageToL1SysCall": { + "destination": "starkware.starknet.common.syscalls.SendMessageToL1SysCall", + "type": "alias" + }, + "starkware.starknet.common.messages.send_message_to_l1": { + "decorators": [], + "pc": 3, + "type": "function" + }, + "starkware.starknet.common.messages.send_message_to_l1.Args": { + "full_name": "starkware.starknet.common.messages.send_message_to_l1.Args", + "members": { + "payload": { + "cairo_type": "felt*", + "offset": 2 + }, + "payload_size": { + "cairo_type": "felt", + "offset": 1 + }, + "to_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.messages.send_message_to_l1.ImplicitArgs": { + "full_name": "starkware.starknet.common.messages.send_message_to_l1.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.messages.send_message_to_l1.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.starknet.common.messages.send_message_to_l1.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.messages.send_message_to_l1.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.messages.send_message_to_l1.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 1, + "offset": 0 + }, + "pc": 3, + "value": "[cast(fp + (-6), felt**)]" + }, + { + "ap_tracking_data": { + "group": 1, + "offset": 1 + }, + "pc": 9, + "value": "cast([fp + (-6)] + 4, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.storage.ADDR_BOUND": { + "type": "const", + "value": -106710729501573572985208420194530329073740042555888586719489 + }, + "starkware.starknet.common.storage.MAX_STORAGE_ITEM_SIZE": { + "type": "const", + "value": 256 + }, + "starkware.starknet.common.storage.assert_250_bit": { + "destination": "starkware.cairo.common.math.assert_250_bit", + "type": "alias" + }, + "starkware.starknet.common.syscalls.CALL_CONTRACT_SELECTOR": { + "type": "const", + "value": 20853273475220472486191784820 + }, + "starkware.starknet.common.syscalls.CallContract": { + "full_name": "starkware.starknet.common.syscalls.CallContract", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractResponse", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.starknet.common.syscalls.CallContractRequest": { + "full_name": "starkware.starknet.common.syscalls.CallContractRequest", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 1 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.CallContractResponse": { + "full_name": "starkware.starknet.common.syscalls.CallContractResponse", + "members": { + "retdata": { + "cairo_type": "felt*", + "offset": 1 + }, + "retdata_size": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DELEGATE_CALL_SELECTOR": { + "type": "const", + "value": 21167594061783206823196716140 + }, + "starkware.starknet.common.syscalls.DELEGATE_L1_HANDLER_SELECTOR": { + "type": "const", + "value": 23274015802972845247556842986379118667122 + }, + "starkware.starknet.common.syscalls.DEPLOY_SELECTOR": { + "type": "const", + "value": 75202468540281 + }, + "starkware.starknet.common.syscalls.Deploy": { + "full_name": "starkware.starknet.common.syscalls.Deploy", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.DeployRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.DeployResponse", + "offset": 6 + } + }, + "size": 9, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DeployRequest": { + "full_name": "starkware.starknet.common.syscalls.DeployRequest", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "constructor_calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "contract_address_salt": { + "cairo_type": "felt", + "offset": 2 + }, + "deploy_from_zero": { + "cairo_type": "felt", + "offset": 5 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 6, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DeployResponse": { + "full_name": "starkware.starknet.common.syscalls.DeployResponse", + "members": { + "constructor_retdata": { + "cairo_type": "felt*", + "offset": 2 + }, + "constructor_retdata_size": { + "cairo_type": "felt", + "offset": 1 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DictAccess": { + "destination": "starkware.cairo.common.dict_access.DictAccess", + "type": "alias" + }, + "starkware.starknet.common.syscalls.EMIT_EVENT_SELECTOR": { + "type": "const", + "value": 1280709301550335749748 + }, + "starkware.starknet.common.syscalls.EmitEvent": { + "full_name": "starkware.starknet.common.syscalls.EmitEvent", + "members": { + "data": { + "cairo_type": "felt*", + "offset": 4 + }, + "data_len": { + "cairo_type": "felt", + "offset": 3 + }, + "keys": { + "cairo_type": "felt*", + "offset": 2 + }, + "keys_len": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GET_BLOCK_NUMBER_SELECTOR": { + "type": "const", + "value": 1448089106835523001438702345020786 + }, + "starkware.starknet.common.syscalls.GET_BLOCK_TIMESTAMP_SELECTOR": { + "type": "const", + "value": 24294903732626645868215235778792757751152 + }, + "starkware.starknet.common.syscalls.GET_CALLER_ADDRESS_SELECTOR": { + "type": "const", + "value": 94901967781393078444254803017658102643 + }, + "starkware.starknet.common.syscalls.GET_CONTRACT_ADDRESS_SELECTOR": { + "type": "const", + "value": 6219495360805491471215297013070624192820083 + }, + "starkware.starknet.common.syscalls.GET_SEQUENCER_ADDRESS_SELECTOR": { + "type": "const", + "value": 1592190833581991703053805829594610833820054387 + }, + "starkware.starknet.common.syscalls.GET_TX_INFO_SELECTOR": { + "type": "const", + "value": 1317029390204112103023 + }, + "starkware.starknet.common.syscalls.GET_TX_SIGNATURE_SELECTOR": { + "type": "const", + "value": 1448089128652340074717162277007973 + }, + "starkware.starknet.common.syscalls.GetBlockNumber": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumber", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockNumberRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockNumberResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockNumberRequest": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumberRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockNumberResponse": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumberResponse", + "members": { + "block_number": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestamp": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestamp", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockTimestampRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockTimestampResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestampRequest": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestampRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestampResponse": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestampResponse", + "members": { + "block_timestamp": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddress": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetCallerAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetCallerAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddressResponse", + "members": { + "caller_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddress": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetContractAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetContractAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddressResponse", + "members": { + "contract_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddress": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetSequencerAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetSequencerAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddressResponse", + "members": { + "sequencer_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfo": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfo", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxInfoRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxInfoResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfoRequest": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfoRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfoResponse": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfoResponse", + "members": { + "tx_info": { + "cairo_type": "starkware.starknet.common.syscalls.TxInfo*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignature": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignature", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxSignatureRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxSignatureResponse", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignatureRequest": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignatureRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignatureResponse": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignatureResponse", + "members": { + "signature": { + "cairo_type": "felt*", + "offset": 1 + }, + "signature_len": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.LIBRARY_CALL_L1_HANDLER_SELECTOR": { + "type": "const", + "value": 436233452754198157705746250789557519228244616562 + }, + "starkware.starknet.common.syscalls.LIBRARY_CALL_SELECTOR": { + "type": "const", + "value": 92376026794327011772951660 + }, + "starkware.starknet.common.syscalls.LibraryCall": { + "full_name": "starkware.starknet.common.syscalls.LibraryCall", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.LibraryCallRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractResponse", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.starknet.common.syscalls.LibraryCallRequest": { + "full_name": "starkware.starknet.common.syscalls.LibraryCallRequest", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.REPLACE_CLASS_SELECTOR": { + "type": "const", + "value": 25500403217443378527601783667 + }, + "starkware.starknet.common.syscalls.ReplaceClass": { + "full_name": "starkware.starknet.common.syscalls.ReplaceClass", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.SEND_MESSAGE_TO_L1_SELECTOR": { + "type": "const", + "value": 433017908768303439907196859243777073 + }, + "starkware.starknet.common.syscalls.STORAGE_READ_SELECTOR": { + "type": "const", + "value": 100890693370601760042082660 + }, + "starkware.starknet.common.syscalls.STORAGE_WRITE_SELECTOR": { + "type": "const", + "value": 25828017502874050592466629733 + }, + "starkware.starknet.common.syscalls.SendMessageToL1SysCall": { + "full_name": "starkware.starknet.common.syscalls.SendMessageToL1SysCall", + "members": { + "payload_ptr": { + "cairo_type": "felt*", + "offset": 3 + }, + "payload_size": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + }, + "to_address": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageRead": { + "full_name": "starkware.starknet.common.syscalls.StorageRead", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.StorageReadRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.StorageReadResponse", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageReadRequest": { + "full_name": "starkware.starknet.common.syscalls.StorageReadRequest", + "members": { + "address": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageReadResponse": { + "full_name": "starkware.starknet.common.syscalls.StorageReadResponse", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageWrite": { + "full_name": "starkware.starknet.common.syscalls.StorageWrite", + "members": { + "address": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.TxInfo": { + "full_name": "starkware.starknet.common.syscalls.TxInfo", + "members": { + "account_contract_address": { + "cairo_type": "felt", + "offset": 1 + }, + "chain_id": { + "cairo_type": "felt", + "offset": 6 + }, + "max_fee": { + "cairo_type": "felt", + "offset": 2 + }, + "nonce": { + "cairo_type": "felt", + "offset": 7 + }, + "signature": { + "cairo_type": "felt*", + "offset": 4 + }, + "signature_len": { + "cairo_type": "felt", + "offset": 3 + }, + "transaction_hash": { + "cairo_type": "felt", + "offset": 5 + }, + "version": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 8, + "type": "struct" + } + }, + "main_scope": "__main__", + "prime": "0x800000000000011000000000000000000000000000000000000000000000001", + "reference_manager": { + "references": [ + { + "ap_tracking_data": { + "group": 1, + "offset": 0 + }, + "pc": 3, + "value": "[cast(fp + (-6), felt**)]" + } + ] + } + } +} \ No newline at end of file diff --git a/cairo-contracts/build/test.json b/cairo-contracts/build/test.json index 71fb6e05bd..f35a733452 100644 --- a/cairo-contracts/build/test.json +++ b/cairo-contracts/build/test.json @@ -111,6 +111,21 @@ ], "type": "function" }, + { + "inputs": [ + { + "name": "from_address", + "type": "felt" + }, + { + "name": "value", + "type": "felt" + } + ], + "name": "test_l1_handler_store_under_caller_address", + "outputs": [], + "type": "l1_handler" + }, { "inputs": [ { @@ -303,23 +318,23 @@ "selector": "0x137a07fa9c479e27114b8ae1fbf252f2065cf91a0d8615272e060a7ccf37309" }, { - "offset": "0x2a1", + "offset": "0x2b9", "selector": "0x169f135eddda5ab51886052d777a57f2ea9c162d713691b5e04a6d4ed71d47f" }, { - "offset": "0x276", + "offset": "0x28e", "selector": "0x27c3334165536f239cfd400ed956eabff55fc60de4fb56728b6a4f6b87db01c" }, { - "offset": "0x208", + "offset": "0x220", "selector": "0x3604cea1cdb094a73a31144f14a3e5861613c008e1e879939ebc4827d10cd50" }, { - "offset": "0x2d4", + "offset": "0x2ec", "selector": "0x36fa6de2810d05c3e1a0ebe23f60b9c2f4629bbead09e5a9704e1c5632630d5" }, { - "offset": "0x2f7", + "offset": "0x30f", "selector": "0x38215592552d97419658d30db8f189b242ec2056641de3dff8a7217745ec205" }, { @@ -331,7 +346,7 @@ "selector": "0x39a1491f76903a16feed0a6433bec78de4c73194944e1118e226820ad479701" }, { - "offset": "0x250", + "offset": "0x268", "selector": "0x3a6a8bae4c51d5959683ae246347ffdd96aa5b2bfa68cc8c3a6a7c2ed0be331" }, { @@ -339,7 +354,12 @@ "selector": "0x3b097c62d3e4b85742aadd0dfb823f96134b886ec13bda57b68faf86f294d97" } ], - "L1_HANDLER": [] + "L1_HANDLER": [ + { + "offset": "0x206", + "selector": "0x14093c40d95d0a3641c087f7d48d55160e1a58bc7c07b0d2323efeeb3087269" + } + ] }, "program": { "attributes": [], @@ -862,13 +882,37 @@ "0x48127ffa7fff8000", "0x48127ffa7fff8000", "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe39", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x2", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff5", + "0x40780017fff7fff", + "0x1", + "0x48127ffe7fff8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280037ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", "0x480a7ff97fff8000", "0x480a7ffa7fff8000", "0x480a7ffb7fff8000", "0x480a7ffc7fff8000", "0x480a7ffd7fff8000", "0x1104800180018000", - "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe17", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdff", "0x208b7fff7fff7ffe", "0x480280027ffb8000", "0x480280027ffd8000", @@ -910,7 +954,7 @@ "0x482480017ffb8000", "0x1", "0x1104800180018000", - "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffddc", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdc4", "0x482480017fff8000", "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffc", "0x40137fff7fff8000", @@ -921,14 +965,14 @@ "0x5", "0x480a80007fff8000", "0x1104800180018000", - "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffde2", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdca", "0x48127ffd7fff8000", "0x480a7ff97fff8000", "0x480a7ffb7fff8000", "0x480a7ffc7fff8000", "0x480a7ffd7fff8000", "0x1104800180018000", - "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffddb", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdc3", "0x48127ffd7fff8000", "0x480680017fff8000", "0x0", @@ -978,7 +1022,7 @@ "0x480a7ffc7fff8000", "0x480a7ffd7fff8000", "0x1104800180018000", - "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd9d", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd85", "0x208b7fff7fff7ffe", "0x480280027ffb8000", "0x480280027ffd8000", @@ -1012,7 +1056,7 @@ "0x480a7ffc7fff8000", "0x480a7ffd7fff8000", "0x1104800180018000", - "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd93", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd7b", "0x208b7fff7fff7ffe", "0x40780017fff7fff", "0x1", @@ -1063,11 +1107,11 @@ "0x480680017fff8000", "0x27", "0x1104800180018000", - "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe6d", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe55", "0x480680017fff8000", "0x1", "0x1104800180018000", - "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe5b", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe43", "0x400680017fff7fff", "0x27", "0x48127ffc7fff8000", @@ -1098,7 +1142,7 @@ "0x480a7ffc7fff8000", "0x480a7ffd7fff8000", "0x1104800180018000", - "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdf7", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffddf", "0x208b7fff7fff7ffe", "0x40780017fff7fff", "0x1", @@ -1490,7 +1534,25 @@ } } ], - "583": [ + "526": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.test_l1_handler_store_under_caller_address" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 47, + "offset": 13 + }, + "reference_ids": {} + } + } + ], + "607": [ { "accessible_scopes": [ "__main__", @@ -1501,14 +1563,14 @@ "code": "memory[ap] = segments.add()", "flow_tracking_data": { "ap_tracking": { - "group": 49, + "group": 51, "offset": 0 }, "reference_ids": {} } } ], - "664": [ + "688": [ { "accessible_scopes": [ "__main__", @@ -1519,14 +1581,14 @@ "code": "memory[ap] = segments.add()", "flow_tracking_data": { "ap_tracking": { - "group": 54, + "group": 56, "offset": 0 }, "reference_ids": {} } } ], - "730": [ + "754": [ { "accessible_scopes": [ "__main__", @@ -1537,14 +1599,14 @@ "code": "memory[ap] = segments.add()", "flow_tracking_data": { "ap_tracking": { - "group": 57, + "group": 59, "offset": 126 }, "reference_ids": {} } } ], - "750": [ + "774": [ { "accessible_scopes": [ "__main__", @@ -1555,7 +1617,7 @@ "code": "memory[ap] = segments.add()", "flow_tracking_data": { "ap_tracking": { - "group": 60, + "group": 62, "offset": 0 }, "reference_ids": {} @@ -2072,7 +2134,7 @@ "external", "raw_output" ], - "pc": 622, + "pc": 646, "type": "function" }, "__main__.test_call_contract.Args": { @@ -2121,7 +2183,7 @@ "decorators": [ "external" ], - "pc": 740, + "pc": 764, "type": "function" }, "__main__.test_contract_address.Args": { @@ -2178,7 +2240,7 @@ "decorators": [ "external" ], - "pc": 655, + "pc": 679, "type": "function" }, "__main__.test_deploy.Args": { @@ -2227,12 +2289,53 @@ "type": "const", "value": 0 }, + "__main__.test_l1_handler_store_under_caller_address": { + "decorators": [ + "l1_handler" + ], + "pc": 512, + "type": "function" + }, + "__main__.test_l1_handler_store_under_caller_address.Args": { + "full_name": "__main__.test_l1_handler_store_under_caller_address.Args", + "members": { + "from_address": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.test_l1_handler_store_under_caller_address.ImplicitArgs": { + "full_name": "__main__.test_l1_handler_store_under_caller_address.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.test_l1_handler_store_under_caller_address.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.test_l1_handler_store_under_caller_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, "__main__.test_library_call": { "decorators": [ "external", "raw_output" ], - "pc": 512, + "pc": 536, "type": "function" }, "__main__.test_library_call.Args": { @@ -2281,7 +2384,7 @@ "decorators": [ "external" ], - "pc": 545, + "pc": 569, "type": "function" }, "__main__.test_nested_library_call.Args": { @@ -2375,7 +2478,7 @@ "decorators": [ "external" ], - "pc": 705, + "pc": 729, "type": "function" }, "__main__.test_storage_var.Args": { @@ -2684,7 +2787,7 @@ "external", "raw_output" ], - "pc": 630, + "pc": 654, "type": "function" }, "__wrappers__.test_call_contract.Args": { @@ -2719,7 +2822,7 @@ "decorators": [ "external" ], - "pc": 759, + "pc": 783, "type": "function" }, "__wrappers__.test_contract_address.Args": { @@ -2748,7 +2851,7 @@ }, "__wrappers__.test_contract_address_encode_return": { "decorators": [], - "pc": 750, + "pc": 774, "type": "function" }, "__wrappers__.test_contract_address_encode_return.Args": { @@ -2788,7 +2891,7 @@ "decorators": [ "external" ], - "pc": 673, + "pc": 697, "type": "function" }, "__wrappers__.test_deploy.Args": { @@ -2817,7 +2920,7 @@ }, "__wrappers__.test_deploy_encode_return": { "decorators": [], - "pc": 664, + "pc": 688, "type": "function" }, "__wrappers__.test_deploy_encode_return.Args": { @@ -2853,12 +2956,47 @@ "destination": "starkware.cairo.common.memcpy.memcpy", "type": "alias" }, + "__wrappers__.test_l1_handler_store_under_caller_address": { + "decorators": [ + "l1_handler" + ], + "pc": 518, + "type": "function" + }, + "__wrappers__.test_l1_handler_store_under_caller_address.Args": { + "full_name": "__wrappers__.test_l1_handler_store_under_caller_address.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_l1_handler_store_under_caller_address.ImplicitArgs": { + "full_name": "__wrappers__.test_l1_handler_store_under_caller_address.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_l1_handler_store_under_caller_address.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_l1_handler_store_under_caller_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_l1_handler_store_under_caller_address.__wrapped_func": { + "destination": "__main__.test_l1_handler_store_under_caller_address", + "type": "alias" + }, + "__wrappers__.test_l1_handler_store_under_caller_address_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, "__wrappers__.test_library_call": { "decorators": [ "external", "raw_output" ], - "pc": 520, + "pc": 544, "type": "function" }, "__wrappers__.test_library_call.Args": { @@ -2893,7 +3031,7 @@ "decorators": [ "external" ], - "pc": 592, + "pc": 616, "type": "function" }, "__wrappers__.test_nested_library_call.Args": { @@ -2922,7 +3060,7 @@ }, "__wrappers__.test_nested_library_call_encode_return": { "decorators": [], - "pc": 583, + "pc": 607, "type": "function" }, "__wrappers__.test_nested_library_call_encode_return.Args": { @@ -3031,7 +3169,7 @@ "decorators": [ "external" ], - "pc": 724, + "pc": 748, "type": "function" }, "__wrappers__.test_storage_var.Args": { diff --git a/cairo-contracts/src/test_contracts/send_message.cairo b/cairo-contracts/src/test_contracts/send_message.cairo new file mode 100644 index 0000000000..5540ad94e5 --- /dev/null +++ b/cairo-contracts/src/test_contracts/send_message.cairo @@ -0,0 +1,10 @@ +%lang starknet + +from starkware.starknet.common.messages import send_message_to_l1 +from starkware.cairo.common.alloc import alloc + +@external +func send_message_l2_to_l1{syscall_ptr : felt*}(to_address: felt, payload_len: felt, payload: felt*) { + send_message_to_l1(to_address, payload_len, payload); + return (); +} diff --git a/cairo-contracts/src/test_contracts/test.cairo b/cairo-contracts/src/test_contracts/test.cairo index 40f8998a75..ccdb69102f 100644 --- a/cairo-contracts/src/test_contracts/test.cairo +++ b/cairo-contracts/src/test_contracts/test.cairo @@ -83,6 +83,12 @@ func test_storage_read_write{syscall_ptr: felt*}(address: felt, value: felt) -> return (result=read_value); } +@l1_handler +func test_l1_handler_store_under_caller_address{syscall_ptr: felt*}(from_address: felt, value: felt) { + storage_write(address=from_address, value=value); + return (); +} + @external @raw_output func test_library_call{syscall_ptr: felt*}( diff --git a/configs/genesis-assets/genesis.json b/configs/genesis-assets/genesis.json index 06073a7657..b6579fcbf7 100644 --- a/configs/genesis-assets/genesis.json +++ b/configs/genesis-assets/genesis.json @@ -62,7 +62,7 @@ } ], [ - "0x05a2b92d9a36509a3d651e7df99144a4ad8301e2caf42465ee6ab0451ae91882", + "0x04c5efa8dc6f0554da51f125d04e379ac41153a8b837391083a8dc3771a33388", { "path": "genesis-assets/test.json", "version": 0 @@ -116,7 +116,7 @@ ], [ "0x1111", - "0x05a2b92d9a36509a3d651e7df99144a4ad8301e2caf42465ee6ab0451ae91882" + "0x04c5efa8dc6f0554da51f125d04e379ac41153a8b837391083a8dc3771a33388" ], [ "0x040e59c2c182a58fb0a74349bfa4769cbbcba32547591dd3fb1def8623997d00", diff --git a/configs/genesis-assets/test.json b/configs/genesis-assets/test.json index 725a498543..f8a279f192 100644 --- a/configs/genesis-assets/test.json +++ b/configs/genesis-assets/test.json @@ -111,6 +111,21 @@ ], "type": "function" }, + { + "inputs": [ + { + "name": "from_address", + "type": "felt" + }, + { + "name": "value", + "type": "felt" + } + ], + "name": "test_l1_handler_store_under_caller_address", + "outputs": [], + "type": "l1_handler" + }, { "inputs": [ { @@ -303,23 +318,23 @@ "selector": "0x137a07fa9c479e27114b8ae1fbf252f2065cf91a0d8615272e060a7ccf37309" }, { - "offset": "0x2a1", + "offset": "0x2b9", "selector": "0x169f135eddda5ab51886052d777a57f2ea9c162d713691b5e04a6d4ed71d47f" }, { - "offset": "0x276", + "offset": "0x28e", "selector": "0x27c3334165536f239cfd400ed956eabff55fc60de4fb56728b6a4f6b87db01c" }, { - "offset": "0x208", + "offset": "0x220", "selector": "0x3604cea1cdb094a73a31144f14a3e5861613c008e1e879939ebc4827d10cd50" }, { - "offset": "0x2d4", + "offset": "0x2ec", "selector": "0x36fa6de2810d05c3e1a0ebe23f60b9c2f4629bbead09e5a9704e1c5632630d5" }, { - "offset": "0x2f7", + "offset": "0x30f", "selector": "0x38215592552d97419658d30db8f189b242ec2056641de3dff8a7217745ec205" }, { @@ -331,7 +346,7 @@ "selector": "0x39a1491f76903a16feed0a6433bec78de4c73194944e1118e226820ad479701" }, { - "offset": "0x250", + "offset": "0x268", "selector": "0x3a6a8bae4c51d5959683ae246347ffdd96aa5b2bfa68cc8c3a6a7c2ed0be331" }, { @@ -339,7 +354,12 @@ "selector": "0x3b097c62d3e4b85742aadd0dfb823f96134b886ec13bda57b68faf86f294d97" } ], - "L1_HANDLER": [] + "L1_HANDLER": [ + { + "offset": "0x206", + "selector": "0x14093c40d95d0a3641c087f7d48d55160e1a58bc7c07b0d2323efeeb3087269" + } + ] }, "program": { "attributes": [], @@ -858,13 +878,37 @@ "0x48127ffa7fff8000", "0x48127ffa7fff8000", "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe39", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x2", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280007ffd8000", + "0x480280017ffd8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff5", + "0x40780017fff7fff", + "0x1", + "0x48127ffe7fff8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280037ffb8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", "0x480a7ff97fff8000", "0x480a7ffa7fff8000", "0x480a7ffb7fff8000", "0x480a7ffc7fff8000", "0x480a7ffd7fff8000", "0x1104800180018000", - "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe17", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdff", "0x208b7fff7fff7ffe", "0x480280027ffb8000", "0x480280027ffd8000", @@ -906,7 +950,7 @@ "0x482480017ffb8000", "0x1", "0x1104800180018000", - "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffddc", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdc4", "0x482480017fff8000", "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffc", "0x40137fff7fff8000", @@ -917,14 +961,14 @@ "0x5", "0x480a80007fff8000", "0x1104800180018000", - "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffde2", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdca", "0x48127ffd7fff8000", "0x480a7ff97fff8000", "0x480a7ffb7fff8000", "0x480a7ffc7fff8000", "0x480a7ffd7fff8000", "0x1104800180018000", - "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffddb", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdc3", "0x48127ffd7fff8000", "0x480680017fff8000", "0x0", @@ -974,7 +1018,7 @@ "0x480a7ffc7fff8000", "0x480a7ffd7fff8000", "0x1104800180018000", - "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd9d", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd85", "0x208b7fff7fff7ffe", "0x480280027ffb8000", "0x480280027ffd8000", @@ -1008,7 +1052,7 @@ "0x480a7ffc7fff8000", "0x480a7ffd7fff8000", "0x1104800180018000", - "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd93", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffd7b", "0x208b7fff7fff7ffe", "0x40780017fff7fff", "0x1", @@ -1059,11 +1103,11 @@ "0x480680017fff8000", "0x27", "0x1104800180018000", - "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe6d", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe55", "0x480680017fff8000", "0x1", "0x1104800180018000", - "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe5b", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe43", "0x400680017fff7fff", "0x27", "0x48127ffc7fff8000", @@ -1094,7 +1138,7 @@ "0x480a7ffc7fff8000", "0x480a7ffd7fff8000", "0x1104800180018000", - "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffdf7", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffddf", "0x208b7fff7fff7ffe", "0x40780017fff7fff", "0x1", @@ -1482,7 +1526,25 @@ } } ], - "583": [ + "526": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.test_l1_handler_store_under_caller_address" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 47, + "offset": 13 + }, + "reference_ids": {} + } + } + ], + "607": [ { "accessible_scopes": [ "__main__", @@ -1493,14 +1555,14 @@ "code": "memory[ap] = segments.add()", "flow_tracking_data": { "ap_tracking": { - "group": 49, + "group": 51, "offset": 0 }, "reference_ids": {} } } ], - "664": [ + "688": [ { "accessible_scopes": [ "__main__", @@ -1511,14 +1573,14 @@ "code": "memory[ap] = segments.add()", "flow_tracking_data": { "ap_tracking": { - "group": 54, + "group": 56, "offset": 0 }, "reference_ids": {} } } ], - "730": [ + "754": [ { "accessible_scopes": [ "__main__", @@ -1529,14 +1591,14 @@ "code": "memory[ap] = segments.add()", "flow_tracking_data": { "ap_tracking": { - "group": 57, + "group": 59, "offset": 126 }, "reference_ids": {} } } ], - "750": [ + "774": [ { "accessible_scopes": [ "__main__", @@ -1547,7 +1609,7 @@ "code": "memory[ap] = segments.add()", "flow_tracking_data": { "ap_tracking": { - "group": 60, + "group": 62, "offset": 0 }, "reference_ids": {} @@ -2051,7 +2113,7 @@ }, "__main__.test_call_contract": { "decorators": ["external", "raw_output"], - "pc": 622, + "pc": 646, "type": "function" }, "__main__.test_call_contract.Args": { @@ -2098,7 +2160,7 @@ }, "__main__.test_contract_address": { "decorators": ["external"], - "pc": 740, + "pc": 764, "type": "function" }, "__main__.test_contract_address.Args": { @@ -2153,7 +2215,7 @@ }, "__main__.test_deploy": { "decorators": ["external"], - "pc": 655, + "pc": 679, "type": "function" }, "__main__.test_deploy.Args": { @@ -2202,9 +2264,48 @@ "type": "const", "value": 0 }, + "__main__.test_l1_handler_store_under_caller_address": { + "decorators": ["l1_handler"], + "pc": 512, + "type": "function" + }, + "__main__.test_l1_handler_store_under_caller_address.Args": { + "full_name": "__main__.test_l1_handler_store_under_caller_address.Args", + "members": { + "from_address": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.test_l1_handler_store_under_caller_address.ImplicitArgs": { + "full_name": "__main__.test_l1_handler_store_under_caller_address.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.test_l1_handler_store_under_caller_address.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.test_l1_handler_store_under_caller_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, "__main__.test_library_call": { "decorators": ["external", "raw_output"], - "pc": 512, + "pc": 536, "type": "function" }, "__main__.test_library_call.Args": { @@ -2251,7 +2352,7 @@ }, "__main__.test_nested_library_call": { "decorators": ["external"], - "pc": 545, + "pc": 569, "type": "function" }, "__main__.test_nested_library_call.Args": { @@ -2341,7 +2442,7 @@ }, "__main__.test_storage_var": { "decorators": ["external"], - "pc": 705, + "pc": 729, "type": "function" }, "__main__.test_storage_var.Args": { @@ -2633,7 +2734,7 @@ }, "__wrappers__.test_call_contract": { "decorators": ["external", "raw_output"], - "pc": 630, + "pc": 654, "type": "function" }, "__wrappers__.test_call_contract.Args": { @@ -2666,7 +2767,7 @@ }, "__wrappers__.test_contract_address": { "decorators": ["external"], - "pc": 759, + "pc": 783, "type": "function" }, "__wrappers__.test_contract_address.Args": { @@ -2695,7 +2796,7 @@ }, "__wrappers__.test_contract_address_encode_return": { "decorators": [], - "pc": 750, + "pc": 774, "type": "function" }, "__wrappers__.test_contract_address_encode_return.Args": { @@ -2733,7 +2834,7 @@ }, "__wrappers__.test_deploy": { "decorators": ["external"], - "pc": 673, + "pc": 697, "type": "function" }, "__wrappers__.test_deploy.Args": { @@ -2762,7 +2863,7 @@ }, "__wrappers__.test_deploy_encode_return": { "decorators": [], - "pc": 664, + "pc": 688, "type": "function" }, "__wrappers__.test_deploy_encode_return.Args": { @@ -2798,9 +2899,42 @@ "destination": "starkware.cairo.common.memcpy.memcpy", "type": "alias" }, + "__wrappers__.test_l1_handler_store_under_caller_address": { + "decorators": ["l1_handler"], + "pc": 518, + "type": "function" + }, + "__wrappers__.test_l1_handler_store_under_caller_address.Args": { + "full_name": "__wrappers__.test_l1_handler_store_under_caller_address.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_l1_handler_store_under_caller_address.ImplicitArgs": { + "full_name": "__wrappers__.test_l1_handler_store_under_caller_address.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.test_l1_handler_store_under_caller_address.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: felt, range_check_ptr: felt, bitwise_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.test_l1_handler_store_under_caller_address.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.test_l1_handler_store_under_caller_address.__wrapped_func": { + "destination": "__main__.test_l1_handler_store_under_caller_address", + "type": "alias" + }, + "__wrappers__.test_l1_handler_store_under_caller_address_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, "__wrappers__.test_library_call": { "decorators": ["external", "raw_output"], - "pc": 520, + "pc": 544, "type": "function" }, "__wrappers__.test_library_call.Args": { @@ -2833,7 +2967,7 @@ }, "__wrappers__.test_nested_library_call": { "decorators": ["external"], - "pc": 592, + "pc": 616, "type": "function" }, "__wrappers__.test_nested_library_call.Args": { @@ -2862,7 +2996,7 @@ }, "__wrappers__.test_nested_library_call_encode_return": { "decorators": [], - "pc": 583, + "pc": 607, "type": "function" }, "__wrappers__.test_nested_library_call_encode_return.Args": { @@ -2967,7 +3101,7 @@ }, "__wrappers__.test_storage_var": { "decorators": ["external"], - "pc": 724, + "pc": 748, "type": "function" }, "__wrappers__.test_storage_var.Args": { diff --git a/configs/index.json b/configs/index.json index 64adcf8871..7ba91a6685 100644 --- a/configs/index.json +++ b/configs/index.json @@ -31,7 +31,7 @@ }, { "name": "genesis.json", - "md5": "62fca13757f5bbad9683a2d3ecd44e6d" + "md5": "19f69e5c1019a289af40873c251587e8" }, { "name": "NoValidateAccount.casm.json", @@ -51,7 +51,7 @@ }, { "name": "test.json", - "md5": "b022be5ad4dae9599d4fa44467abfbd9" + "md5": "3b96fc40d4fee4921c0ee44f3af5cec5" }, { "name": "UniversalDeployer.json", diff --git a/crates/client/data-availability/Cargo.toml b/crates/client/data-availability/Cargo.toml index 41e564318c..765a7c263e 100644 --- a/crates/client/data-availability/Cargo.toml +++ b/crates/client/data-availability/Cargo.toml @@ -14,7 +14,6 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] anyhow = { workspace = true } async-trait = { workspace = true } -clap = { workspace = true, features = ["derive"], optional = true } futures = "0.3.21" indexmap = { workspace = true } jsonrpsee = { version = "0.20.0", features = [ @@ -22,7 +21,7 @@ jsonrpsee = { version = "0.20.0", features = [ "ws-client", "macros", ] } -log = "0.4.19" +log = { workspace = true } reqwest = { version = "0.11.18", features = ["blocking", "json"] } serde = { workspace = true, default-features = true } serde_json = { workspace = true, default-features = true } @@ -63,6 +62,9 @@ mp-digest-log = { workspace = true, default-features = true } mp-hashers = { workspace = true, default-features = true } mp-storage = { workspace = true, default-features = true } +# Optional +clap = { workspace = true, features = ["derive"], optional = true } + [features] default = [] clap = ["dep:clap"] diff --git a/crates/client/data-availability/src/ethereum/config.rs b/crates/client/data-availability/src/ethereum/config.rs index 19ecf520a2..3ac3204fb7 100644 --- a/crates/client/data-availability/src/ethereum/config.rs +++ b/crates/client/data-availability/src/ethereum/config.rs @@ -1,7 +1,7 @@ use std::fs::File; use std::path::PathBuf; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use crate::DaMode; @@ -13,7 +13,7 @@ pub const DEFAULT_SEQUENCER_KEY: &str = "ac0974bec39a17e36ba4a6b4d238ff944bacb47 pub const DEFAULT_STARKNET_CORE_CONTRACTS: &str = "0x5FbDB2315678afecb367f032d93F642f64180aa3"; pub const DEFAULT_CHAIN_ID: u64 = 31337; -#[derive(Clone, PartialEq, Deserialize, Debug)] +#[derive(Clone, PartialEq, Serialize, Deserialize, Debug)] pub struct EthereumConfig { #[serde(default = "default_http")] pub http_provider: String, @@ -25,6 +25,8 @@ pub struct EthereumConfig { pub chain_id: u64, #[serde(default)] pub mode: DaMode, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub poll_interval_ms: Option, } impl TryFrom<&PathBuf> for EthereumConfig { @@ -60,6 +62,7 @@ impl Default for EthereumConfig { core_contracts: default_core_contracts(), sequencer_key: default_sequencer_key(), chain_id: default_chain_id(), + poll_interval_ms: None, } } } diff --git a/crates/client/data-availability/src/lib.rs b/crates/client/data-availability/src/lib.rs index ce77caf449..979c055f5d 100644 --- a/crates/client/data-availability/src/lib.rs +++ b/crates/client/data-availability/src/lib.rs @@ -16,7 +16,7 @@ use mc_commitment_state_diff::BlockDAData; use mp_hashers::HasherT; use pallet_starknet_runtime_api::StarknetRuntimeApi; use sc_client_api::client::BlockchainEvents; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use sp_api::ProvideRuntimeApi; use sp_blockchain::HeaderBackend; use sp_runtime::traits::{Block as BlockT, Header}; @@ -25,7 +25,7 @@ use utils::state_diff_to_calldata; pub struct DataAvailabilityWorker(PhantomData<(B, C, H)>); pub struct DataAvailabilityWorkerProving(PhantomData); -#[derive(Debug, Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "clap", derive(clap::ValueEnum))] pub enum DaLayer { Celestia, @@ -35,8 +35,8 @@ pub enum DaLayer { /// Data availability modes in which Madara can be initialized. /// -/// Default only mode currently implemented is Sovereign. -#[derive(Debug, Copy, Clone, PartialEq, Deserialize, Default)] +/// Default only mode currently implemented is Sovereing. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Default)] pub enum DaMode { /// Full Validity Rollup /// @@ -122,7 +122,7 @@ where C::Api: StarknetRuntimeApi, C: BlockchainEvents + 'static, C: HeaderBackend, - H: HasherT + Unpin, + H: HasherT, { pub async fn update_state( da_client: Box, diff --git a/crates/client/db/Cargo.toml b/crates/client/db/Cargo.toml index 55dd4d65d9..6277bedea6 100644 --- a/crates/client/db/Cargo.toml +++ b/crates/client/db/Cargo.toml @@ -28,6 +28,7 @@ sp-core = { workspace = true, default-features = true } sp-database = { workspace = true, default-features = true } sp-runtime = { workspace = true, default-features = true } starknet_api = { workspace = true, default-features = true } +thiserror = { workspace = true } uuid = "1.4.1" [features] diff --git a/crates/client/db/src/error.rs b/crates/client/db/src/error.rs new file mode 100644 index 0000000000..90753eb47f --- /dev/null +++ b/crates/client/db/src/error.rs @@ -0,0 +1,7 @@ +#[derive(thiserror::Error, Debug)] +pub enum DbError { + #[error("Failed to commit DB Update: `{0}`")] + CommitError(#[from] sp_database::error::DatabaseError), + #[error("Failed to deserialize DB Data: `{0}`")] + DeserializeError(#[from] scale_codec::Error), +} diff --git a/crates/client/db/src/lib.rs b/crates/client/db/src/lib.rs index 4ae94ad267..aa26d5d9ea 100644 --- a/crates/client/db/src/lib.rs +++ b/crates/client/db/src/lib.rs @@ -11,10 +11,14 @@ //! `paritydb` and `rocksdb` are both supported, behind the `kvdb-rocksd` and `parity-db` feature //! flags. Support for custom databases is possible but not supported yet. +mod error; +pub use error::DbError; + mod mapping_db; pub use mapping_db::MappingCommitment; mod da_db; mod db_opening_utils; +mod messaging_db; mod meta_db; use std::marker::PhantomData; @@ -23,6 +27,7 @@ use std::sync::Arc; use da_db::DaDb; use mapping_db::MappingDb; +use messaging_db::MessagingDb; use meta_db::MetaDb; use sc_client_db::DatabaseSource; use sp_database::Database; @@ -42,7 +47,7 @@ pub(crate) mod columns { // ===== /!\ =================================================================================== // MUST BE INCREMENTED WHEN A NEW COLUMN IN ADDED // ===== /!\ =================================================================================== - pub const NUM_COLUMNS: u32 = 6; + pub const NUM_COLUMNS: u32 = 7; pub const META: u32 = 0; pub const BLOCK_MAPPING: u32 = 1; @@ -54,11 +59,15 @@ pub(crate) mod columns { /// /// This column should only be accessed if the `--cache` flag is enabled. pub const STARKNET_TRANSACTION_HASHES_CACHE: u32 = 5; + + /// This column contains last synchronized L1 block. + pub const MESSAGING: u32 = 6; } pub mod static_keys { pub const CURRENT_SYNCING_TIPS: &[u8] = b"CURRENT_SYNCING_TIPS"; pub const LAST_PROVED_BLOCK: &[u8] = b"LAST_PROVED_BLOCK"; + pub const LAST_SYNCED_L1_BLOCK: &[u8] = b"LAST_SYNCED_L1_BLOCK"; } /// The Madara client database backend @@ -70,6 +79,7 @@ pub struct Backend { meta: Arc>, mapping: Arc>, da: Arc>, + messaging: Arc>, } /// Returns the Starknet database directory. @@ -110,6 +120,7 @@ impl Backend { mapping: Arc::new(MappingDb::new(db.clone(), cache_more_things)), meta: Arc::new(MetaDb { db: db.clone(), _marker: PhantomData }), da: Arc::new(DaDb { db: db.clone(), _marker: PhantomData }), + messaging: Arc::new(MessagingDb { db: db.clone(), _marker: PhantomData }), }) } @@ -127,4 +138,9 @@ impl Backend { pub fn da(&self) -> &Arc> { &self.da } + + /// Return the da database manager + pub fn messaging(&self) -> &Arc> { + &self.messaging + } } diff --git a/crates/client/db/src/messaging_db.rs b/crates/client/db/src/messaging_db.rs new file mode 100644 index 0000000000..c8bb450203 --- /dev/null +++ b/crates/client/db/src/messaging_db.rs @@ -0,0 +1,34 @@ +use std::marker::PhantomData; +use std::sync::Arc; + +// Substrate +use scale_codec::{Decode, Encode}; +use sp_database::Database; +use sp_runtime::traits::Block as BlockT; + +use crate::error::DbError; +use crate::DbHash; + +pub struct MessagingDb { + pub(crate) db: Arc>, + pub(crate) _marker: PhantomData, +} + +impl MessagingDb { + pub fn last_synced_l1_block(&self) -> Result { + match self.db.get(crate::columns::MESSAGING, crate::static_keys::LAST_SYNCED_L1_BLOCK) { + Some(raw) => Ok(u64::decode(&mut &raw[..])?), + None => Ok(0), + } + } + + pub fn update_last_synced_l1_block(&self, l1_block_number: &u64) -> Result<(), DbError> { + let mut transaction = sp_database::Transaction::new(); + + transaction.set(crate::columns::MESSAGING, crate::static_keys::LAST_SYNCED_L1_BLOCK, &l1_block_number.encode()); + + self.db.commit(transaction)?; + + Ok(()) + } +} diff --git a/crates/client/l1-messages/Cargo.toml b/crates/client/l1-messages/Cargo.toml new file mode 100644 index 0000000000..a491591caf --- /dev/null +++ b/crates/client/l1-messages/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "mc-l1-messages" +version = "0.1.0" +description = "L1 Messages processing library." +homepage = "https://github.com/keep-starknet-strange/madara" +edition = "2021" +license = "MIT" +publish = false +repository = "https://github.com/keep-starknet-strange/madara" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +log = { workspace = true } +rustc-hex = "2.1.0" +url = "2.5.0" + +# Madara RuntimeApi +pallet-starknet-runtime-api = { workspace = true, default-features = true } + +# Starknet dependencies +starknet_api = { workspace = true, default-features = true } + +# Starknet +mc-db = { workspace = true, default-features = true } + +# Madara Primitives +mp-felt = { workspace = true, default-features = true } +mp-transactions = { workspace = true, default-features = true } + +# Substrate Primitives +sp-api = { workspace = true, default-features = true } +sp-core = { workspace = true, default-features = true } +sp-runtime = { workspace = true, default-features = true } + +# Substrate client dependencies +sc-client-api = { workspace = true, default-features = true } +sc-transaction-pool-api = { workspace = true, default-features = true } + +# Other third party dependencies +ethers = { workspace = true } +serde = { workspace = true, default-features = true } +serde_json = { workspace = true, default-features = true } +thiserror = { workspace = true } diff --git a/crates/client/l1-messages/src/config.rs b/crates/client/l1-messages/src/config.rs new file mode 100644 index 0000000000..e2434a2a0e --- /dev/null +++ b/crates/client/l1-messages/src/config.rs @@ -0,0 +1,62 @@ +use std::fs::File; +use std::path::PathBuf; + +use ethers::types::Address; +use rustc_hex::FromHexError; +use serde::{Deserialize, Deserializer}; +use url::Url; + +#[derive(thiserror::Error, Debug)] +pub enum L1MessagesWorkerConfigError { + #[error("File with L1 Messages Worker config not found: {0}")] + FileNotFound(#[from] std::io::Error), + #[error("Failed to deserialize L1 Messages Worker Config from config file: {0}")] + InvalidFile(#[from] serde_json::Error), + #[error("Invalid Ethereum Provided Url: {0}")] + InvalidProviderUrl(#[from] url::ParseError), + #[error("Invalid L1 Contract Address: {0}")] + InvalidContractAddress(#[from] FromHexError), +} + +#[derive(Clone, PartialEq, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct L1MessagesWorkerConfig { + #[serde(deserialize_with = "deserialize_url")] + http_provider: Url, + contract_address: Address, +} + +fn deserialize_url<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let endpoint: String = String::deserialize(deserializer)?; + + Url::parse(&endpoint).map_err(serde::de::Error::custom) +} + +impl L1MessagesWorkerConfig { + pub fn new(http_provider: Url, contract_address: Address) -> Self { + Self { http_provider, contract_address } + } + + pub fn new_from_file(path: &PathBuf) -> Result { + let file = File::open(path)?; + let config = serde_json::from_reader(file)?; + Ok(config) + } + + pub fn new_from_params(provider_url: &str, contract_address: &str) -> Result { + let http_provider = Url::parse(provider_url)?; + let contract_address = contract_address.parse()?; + Ok(Self { http_provider, contract_address }) + } + + pub fn provider(&self) -> &Url { + &self.http_provider + } + + pub fn contract_address(&self) -> &Address { + &self.contract_address + } +} diff --git a/crates/client/l1-messages/src/contract.rs b/crates/client/l1-messages/src/contract.rs new file mode 100644 index 0000000000..f353ea5b6c --- /dev/null +++ b/crates/client/l1-messages/src/contract.rs @@ -0,0 +1,52 @@ +use ethers::contract::abigen; +use mp_felt::{Felt252Wrapper, Felt252WrapperError}; +use mp_transactions::HandleL1MessageTransaction; + +abigen!( + L1Contract, + r"[ + event LogMessageToL2(address indexed fromAddress, uint256 indexed toAddress, uint256 indexed selector, uint256[] payload, uint256 nonce, uint256 fee) +]" +); + +#[derive(thiserror::Error, Debug, PartialEq)] +#[allow(clippy::enum_variant_names)] +pub enum L1EventToTransactionError { + #[error("Failed to convert Calldata param from L1 Event: `{0}`")] + InvalidCalldata(Felt252WrapperError), + #[error("Failed to convert Contract Address from L1 Event: `{0}`")] + InvalidContractAddress(Felt252WrapperError), + #[error("Failed to convert Entrypoint Selector from L1 Event: `{0}`")] + InvalidEntryPointSelector(Felt252WrapperError), + #[error("Failed to convert Nonce param from L1 Event: `{0}`")] + InvalidNonce(Felt252WrapperError), +} + +impl TryFrom for HandleL1MessageTransaction { + type Error = L1EventToTransactionError; + + fn try_from(event: LogMessageToL2Filter) -> Result { + // L2 contract to call. + let contract_address = Felt252Wrapper::try_from(sp_core::U256(event.to_address.0)) + .map_err(L1EventToTransactionError::InvalidContractAddress)?; + + // Function of the contract to call. + let entry_point_selector = Felt252Wrapper::try_from(sp_core::U256(event.selector.0)) + .map_err(L1EventToTransactionError::InvalidEntryPointSelector)?; + + // L1 message nonce. + let nonce: u64 = Felt252Wrapper::try_from(sp_core::U256(event.nonce.0)) + .map_err(L1EventToTransactionError::InvalidNonce)? + .try_into() + .map_err(L1EventToTransactionError::InvalidNonce)?; + + let calldata: Vec = event + .payload + .iter() + .map(|param| Felt252Wrapper::try_from(sp_core::U256(param.0))) + .collect::, Felt252WrapperError>>() + .map_err(L1EventToTransactionError::InvalidCalldata)?; + + Ok(HandleL1MessageTransaction { nonce, contract_address, entry_point_selector, calldata }) + } +} diff --git a/crates/client/l1-messages/src/error.rs b/crates/client/l1-messages/src/error.rs new file mode 100644 index 0000000000..c77fadef55 --- /dev/null +++ b/crates/client/l1-messages/src/error.rs @@ -0,0 +1,25 @@ +use mc_db::DbError; +use sp_api::ApiError; +use url::ParseError; + +use crate::contract::L1EventToTransactionError; + +#[derive(thiserror::Error, Debug)] +pub enum L1MessagesWorkerError { + #[error("Failed to initialize L1 Messages Worker based on provided Config: `{0}`")] + ConfigError(#[from] ParseError), + #[error("Failed to convert transaction via Runtime API: `{0}`")] + ConvertTransactionRuntimeApiError(ApiError), + #[error("Madara Messaging DB Error: `{0}`")] + DatabaseError(#[from] DbError), + #[error("Message from L1 has been already processed, nonce: `{0}`")] + L1MessageAlreadyProcessed(u64), + #[error("Failed to use Runtime API: `{0}`")] + RuntimeApiError(ApiError), + #[error("Failed to submit transaction into Transaction Pool")] + SubmitTxError(#[source] PE), + #[error("Failed to convert L1 Message into Fee")] + ToFeeError, + #[error("Failed to convert L1 Message into L2 Transaction: `{0}`")] + ToTransactionError(#[from] L1EventToTransactionError), +} diff --git a/crates/client/l1-messages/src/lib.rs b/crates/client/l1-messages/src/lib.rs new file mode 100644 index 0000000000..fd0f1b4f9d --- /dev/null +++ b/crates/client/l1-messages/src/lib.rs @@ -0,0 +1,5 @@ +pub mod config; +pub mod error; +pub mod worker; + +mod contract; diff --git a/crates/client/l1-messages/src/worker.rs b/crates/client/l1-messages/src/worker.rs new file mode 100644 index 0000000000..f7e66c4e38 --- /dev/null +++ b/crates/client/l1-messages/src/worker.rs @@ -0,0 +1,141 @@ +use std::sync::Arc; + +use ethers::providers::{Http, Provider, StreamExt}; +use ethers::types::U256; +use mp_transactions::HandleL1MessageTransaction; +use pallet_starknet_runtime_api::{ConvertTransactionRuntimeApi, StarknetRuntimeApi}; +use sc_client_api::HeaderBackend; +use sc_transaction_pool_api::{TransactionPool, TransactionSource}; +use sp_api::ProvideRuntimeApi; +use sp_runtime::traits::Block as BlockT; +use starknet_api::api_core::Nonce; +use starknet_api::hash::StarkFelt; +use starknet_api::transaction::Fee; + +use crate::config::L1MessagesWorkerConfig; +use crate::contract::{L1Contract, LogMessageToL2Filter}; +use crate::error::L1MessagesWorkerError; + +const TX_SOURCE: TransactionSource = TransactionSource::External; + +pub async fn run_worker( + config: L1MessagesWorkerConfig, + client: Arc, + pool: Arc

, + backend: Arc>, +) where + B: BlockT, + C: ProvideRuntimeApi + HeaderBackend, + C::Api: StarknetRuntimeApi + ConvertTransactionRuntimeApi, + P: TransactionPool + 'static, +{ + log::info!("⟠ Starting L1 Messages Worker with settings: {:?}", config); + + let l1_contract = + L1Contract::new(*config.contract_address(), Arc::new(Provider::new(Http::new(config.provider().clone())))); + + let last_synced_l1_block = match backend.messaging().last_synced_l1_block() { + Ok(blknum) => blknum, + Err(e) => { + log::error!("⟠ Madara Messaging DB unavailable: {:?}", e); + return; + } + }; + + let events = l1_contract.events().from_block(last_synced_l1_block); + let mut event_stream = match events.stream_with_meta().await { + Ok(stream) => stream, + Err(e) => { + log::error!("⟠ Unexpected error with L1 event stream: {:?}", e); + return; + } + }; + + while let Some(Ok((event, meta))) = event_stream.next().await { + log::info!( + "⟠ Processing L1 Message from block: {:?}, transaction_hash: {:?}, log_index: {:?}", + meta.block_number, + meta.transaction_hash, + meta.log_index + ); + + match process_l1_message(event, &client, &pool, &backend, &meta.block_number.as_u64()).await { + Ok(Some(tx_hash)) => { + log::info!( + "⟠ L1 Message from block: {:?}, transaction_hash: {:?}, log_index: {:?} submitted, transaction \ + hash on L2: {:?}", + meta.block_number, + meta.transaction_hash, + meta.log_index, + tx_hash + ); + } + Ok(None) => {} + Err(e) => { + log::error!( + "⟠ Unexpected error while processing L1 Message from block: {:?}, transaction_hash: {:?}, \ + log_index: {:?}, error: {:?}", + meta.block_number, + meta.transaction_hash, + meta.log_index, + e + ) + } + } + } +} + +async fn process_l1_message( + event: LogMessageToL2Filter, + client: &Arc, + pool: &Arc

, + backend: &Arc>, + l1_block_number: &u64, +) -> Result, L1MessagesWorkerError> +where + B: BlockT, + C: ProvideRuntimeApi + HeaderBackend, + C::Api: StarknetRuntimeApi + ConvertTransactionRuntimeApi, + P: TransactionPool + 'static, + PE: std::error::Error, +{ + // Check against panic + // https://docs.rs/ethers/latest/ethers/types/struct.U256.html#method.as_u128 + let fee: Fee = if event.fee > U256::from_big_endian(&(u128::MAX.to_be_bytes())) { + return Err(L1MessagesWorkerError::ToFeeError); + } else { + Fee(event.fee.as_u128()) + }; + let transaction: HandleL1MessageTransaction = event.try_into()?; + + let best_block_hash = client.info().best_hash; + + match client.runtime_api().l1_nonce_unused(best_block_hash, Nonce(StarkFelt::from(transaction.nonce))) { + Ok(true) => Ok(()), + Ok(false) => { + log::debug!("⟠ Event already processed: {:?}", transaction); + return Ok(None); + } + Err(e) => { + log::error!("⟠ Unexpected Runtime Api error: {:?}", e); + Err(L1MessagesWorkerError::RuntimeApiError(e)) + } + }?; + + let extrinsic = client.runtime_api().convert_l1_transaction(best_block_hash, transaction, fee).map_err(|e| { + log::error!("⟠ Failed to convert L1 Transaction via Runtime Api: {:?}", e); + L1MessagesWorkerError::ConvertTransactionRuntimeApiError(e) + })?; + + let tx_hash = pool.submit_one(best_block_hash, TX_SOURCE, extrinsic).await.map_err(|e| { + log::error!("⟠ Failed to submit transaction with L1 Message: {:?}", e); + L1MessagesWorkerError::SubmitTxError(e) + })?; + + backend.messaging().update_last_synced_l1_block(l1_block_number).map_err(|e| { + log::error!("⟠ Failed to save last L1 synced block: {:?}", e); + L1MessagesWorkerError::DatabaseError(e) + })?; + + Ok(Some(tx_hash)) +} diff --git a/crates/client/rpc/src/lib.rs b/crates/client/rpc/src/lib.rs index d985212143..5bcb8a1236 100644 --- a/crates/client/rpc/src/lib.rs +++ b/crates/client/rpc/src/lib.rs @@ -291,7 +291,7 @@ where return Err(StarknetRpcApiError::ClassAlreadyDeclared.into()); } - let extrinsic = convert_transaction(self.client.clone(), best_block_hash, transaction.clone()).await?; + let extrinsic = convert_tx_to_extrinsic(self.client.clone(), best_block_hash, transaction.clone()).await?; submit_extrinsic(self.pool.clone(), best_block_hash, extrinsic).await?; @@ -323,7 +323,7 @@ where StarknetRpcApiError::InternalServerError })?; - let extrinsic = convert_transaction(self.client.clone(), best_block_hash, transaction.clone()).await?; + let extrinsic = convert_tx_to_extrinsic(self.client.clone(), best_block_hash, transaction.clone()).await?; submit_extrinsic(self.pool.clone(), best_block_hash, extrinsic).await?; @@ -353,7 +353,7 @@ where StarknetRpcApiError::InternalServerError })?; - let extrinsic = convert_transaction(self.client.clone(), best_block_hash, transaction.clone()).await?; + let extrinsic = convert_tx_to_extrinsic(self.client.clone(), best_block_hash, transaction.clone()).await?; submit_extrinsic(self.pool.clone(), best_block_hash, extrinsic).await?; @@ -1472,6 +1472,25 @@ where events_converted.last().unwrap().data[2] }; + let messages = self + .client + .runtime_api() + .get_tx_messages_to_l1(substrate_block_hash, Felt252Wrapper(transaction_hash).into()) + .map_err(|e| { + error!("'{e}'"); + StarknetRpcApiError::InternalServerError + })?; + + fn message_conversion(message: starknet_api::transaction::MessageToL1) -> starknet_core::types::MsgToL1 { + let mut to_address = [0u8; 32]; + to_address[12..32].copy_from_slice(message.to_address.0.as_bytes()); + starknet_core::types::MsgToL1 { + from_address: Felt252Wrapper::from(message.from_address).0, + to_address: FieldElement::from_bytes_be(&to_address).unwrap(), + payload: message.payload.0.into_iter().map(|felt| Felt252Wrapper::from(felt).0).collect(), + } + } + let receipt = match transaction { mp_transactions::Transaction::Declare(_) => TransactionReceipt::Declare(DeclareTransactionReceipt { transaction_hash, @@ -1479,7 +1498,7 @@ where finality_status: TransactionFinalityStatus::AcceptedOnL2, block_hash, block_number, - messages_sent: Default::default(), + messages_sent: messages.into_iter().map(message_conversion).collect(), events: events_converted, execution_result, }), @@ -1490,7 +1509,7 @@ where finality_status: TransactionFinalityStatus::AcceptedOnL2, block_hash, block_number, - messages_sent: Default::default(), + messages_sent: messages.into_iter().map(message_conversion).collect(), events: events_converted, contract_address: tx.get_account_address(), execution_result, @@ -1502,7 +1521,7 @@ where finality_status: TransactionFinalityStatus::AcceptedOnL2, block_hash, block_number, - messages_sent: Default::default(), + messages_sent: messages.into_iter().map(message_conversion).collect(), events: events_converted, execution_result, }), @@ -1512,7 +1531,7 @@ where finality_status: TransactionFinalityStatus::AcceptedOnL2, block_hash, block_number, - messages_sent: Default::default(), + messages_sent: messages.into_iter().map(message_conversion).collect(), events: events_converted, execution_result, }), @@ -1596,7 +1615,7 @@ where }) } -async fn convert_transaction( +async fn convert_tx_to_extrinsic( client: Arc, best_block_hash: ::Hash, transaction: UserTransaction, @@ -1606,18 +1625,12 @@ where C: ProvideRuntimeApi, C::Api: StarknetRuntimeApi + ConvertTransactionRuntimeApi, { - let result = client.runtime_api().convert_transaction(best_block_hash, transaction).map_err(|e| { + let extrinsic = client.runtime_api().convert_transaction(best_block_hash, transaction).map_err(|e| { error!("Failed to convert transaction: {:?}", e); StarknetRpcApiError::InternalServerError })?; - match result { - Ok(extrinsic) => Ok(extrinsic), - Err(dispatch_error) => { - error!("Failed to convert transaction: {:?}", dispatch_error); - Err(StarknetRpcApiError::InternalServerError) - } - } + Ok(extrinsic) } fn convert_error( diff --git a/crates/client/settlement/Cargo.toml b/crates/client/settlement/Cargo.toml new file mode 100644 index 0000000000..af6ccec146 --- /dev/null +++ b/crates/client/settlement/Cargo.toml @@ -0,0 +1,61 @@ +[package] +name = "mc-settlement" +version = "0.1.0" +description = "Starknet chain settlement." +homepage = "https://github.com/keep-starknet-strange/madara" +edition = "2021" +license = "MIT" +publish = false +repository = "https://github.com/keep-starknet-strange/madara" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +# Async +async-trait = { workspace = true } +futures = { workspace = true } +futures-timer = { workspace = true } + +# Serde +serde = { workspace = true } +serde_json = { workspace = true } + +# Substrate +sc-client-api = { workspace = true, default-features = true } +sp-api = { workspace = true, default-features = true } +sp-arithmetic = { workspace = true, default-features = true } +sp-blockchain = { workspace = true, default-features = true } +sp-core = { workspace = true, default-features = true } +sp-io = { workspace = true, default-features = true } +sp-runtime = { workspace = true, default-features = true } + +# Starknet +mc-data-availability = { workspace = true, default-features = true } +mp-block = { workspace = true, default-features = true } +mp-digest-log = { workspace = true, features = ["std"] } +mp-hashers = { workspace = true, default-features = true } +mp-messages = { workspace = true, default-features = true } +mp-snos-output = { workspace = true, default-features = true } +mp-transactions = { workspace = true, default-features = true } +starknet-crypto = { workspace = true, default-features = true } +starknet_api = { workspace = true, default-features = true } + +# Madara +pallet-starknet-runtime-api = { workspace = true, default-features = true } + +# Ethereum +ethers = { workspace = true } + +# Others +log = { workspace = true } +rustc-hex = { workspace = true } +thiserror = { workspace = true } +url = { workspace = true } + +# Optional +clap = { workspace = true, optional = true, features = ["std", "derive"] } + +[features] +default = [] +clap = ["dep:clap"] diff --git a/crates/client/settlement/src/errors.rs b/crates/client/settlement/src/errors.rs new file mode 100644 index 0000000000..fab59e6409 --- /dev/null +++ b/crates/client/settlement/src/errors.rs @@ -0,0 +1,63 @@ +use std::time::Duration; + +use sp_runtime::traits::Block; +use starknet_api::hash::StarkHash; + +use crate::{ethereum, RetryStrategy}; + +/// Settlement error type. +#[derive(thiserror::Error, Debug)] +#[allow(missing_docs)] +pub enum Error { + #[error("Blockchain error: {0}")] + Blockchain(#[from] sp_blockchain::Error), + + #[error("Starknet API error: {0}")] + StarknetApi(#[from] starknet_api::StarknetApiError), + + #[error("Failed to find Madara log: {0}")] + DigestLog(#[from] mp_digest_log::FindLogError), + + #[error("Runtime API error: {0}")] + RuntimeApi(#[from] sp_api::ApiError), + + #[error("Ethereum client error: {0}")] + EthereumClient(#[from] ethereum::errors::Error), + + #[error("Failed to find Substrate block hash for Starknet block #{0}")] + UnknownStarknetBlock(u64), + + #[error("Failed to find Substrate block header for hash: {0}")] + UnknownSubstrateBlock(B::Hash), + + #[error("Unexpected global state root for block #{height}: expected {expected}, got {actual}")] + StateRootMismatch { height: u64, expected: StarkHash, actual: StarkHash }, + + #[error("Unexpected Starknet OS program hash: expected {expected}, got {actual}")] + ProgramHashMismatch { expected: StarkHash, actual: StarkHash }, + + #[error("Unexpected Starknet OS config hash: expected {expected}, got {actual}")] + ConfigHashMismatch { expected: StarkHash, actual: StarkHash }, + + #[error("Starknet state is not initialized yet")] + StateNotInitialized, +} + +pub type Result = std::result::Result>; + +pub struct RetryOnRecoverableErrors { + pub delay: Duration, +} + +impl RetryStrategy for RetryOnRecoverableErrors { + fn can_retry(&self, error: &Error) -> Option { + match error { + // List of non-recoverable errors + Error::StateRootMismatch { .. } => None, + Error::ConfigHashMismatch { .. } => None, + Error::ProgramHashMismatch { .. } => None, + // Otherwise we can continue after some delay + _ => Some(self.delay), + } + } +} diff --git a/crates/client/settlement/src/ethereum/client.rs b/crates/client/settlement/src/ethereum/client.rs new file mode 100644 index 0000000000..3d920ac87b --- /dev/null +++ b/crates/client/settlement/src/ethereum/client.rs @@ -0,0 +1,105 @@ +use std::sync::Arc; +use std::time::Duration; + +use ethers::prelude::{abigen, SignerMiddleware}; +use ethers::providers::{Http, Provider}; +use ethers::signers::{LocalWallet, Signer}; +use ethers::types::{Address, TransactionReceipt, I256, U256}; +pub use mc_data_availability::ethereum::config::EthereumConfig; + +use crate::ethereum::errors::{Error, Result}; + +// Starknet core contract is responsible for advancing the rollup state and l1<>l2 messaging. +// Check out https://l2beat.com/scaling/projects/starknet#contracts to get a big picture. +// +// In this scope we work with a subset of methods responsible for querying and updating chain state. +// Starknet state is basically block number + state root hash. +// In order to update the state we need to provide the output of the Starknet OS program, consisting +// of: +// 1. Main part: previous/next state root, block number/hash, config hash, list of l1<>l2 +// messages +// 2. Data availability part: hash and size of the DA blob (the actual data is submitted +// onchain separately) +// +// NOTE that currently we are using a "validium" version of the core contract which does not +// require the DA part. +// +// Starknet OS program is a Cairo program run by the SHARP to prove Starknet state transition. +// SNOS program hash is registered on the Starknet core contract to lock the version: +// * SNOS program sources: https://github.com/starkware-libs/cairo-lang/tree/27a157d761ae49b242026bcbe5fca6e60c1e98bd/src/starkware/starknet/core/os +// * You can calculate program hash by running: cairo-hash-program --program +// build/os_latest.json +// +// SNOS config consists of: +// 1. Config version +// 2. Starknet chain ID +// 3. Fee token address +// +// Read this great overview to learn more about SNOS: +// https://hackmd.io/@pragma/ByP-iux1T +abigen!( + StarknetContract, + r#"[ + function programHash() public view returns (uint256) + function stateBlockNumber() external view returns (int256) + function stateRoot() external view returns (uint256) + function configHash() public view returns (uint256) + function updateState(uint256[] calldata programOutput) external + ]"#, +); + +pub type LocalMiddleware = SignerMiddleware, LocalWallet>; + +pub struct StarknetContractClient { + contract: StarknetContract, +} + +impl StarknetContractClient { + pub fn new(address: Address, client: Arc) -> Self { + Self { contract: StarknetContract::new(address, client) } + } + + pub async fn state_block_number(&self) -> Result { + self.contract.state_block_number().call().await.map_err(Into::into) + } + + pub async fn state_root(&self) -> Result { + self.contract.state_root().call().await.map_err(Into::into) + } + + pub async fn config_hash(&self) -> Result { + self.contract.config_hash().call().await.map_err(Into::into) + } + + pub async fn program_hash(&self) -> Result { + self.contract.program_hash().call().await.map_err(Into::into) + } + + pub async fn update_state(&self, program_output: Vec) -> Result { + self.contract + .update_state(program_output) + .send() + .await? + .inspect(|s| log::debug!("[ethereum client] pending update_state transaction: {:?}", **s)) + .await? + .ok_or_else(|| Error::MissingTransactionRecepit) + } +} + +impl TryFrom for StarknetContractClient { + type Error = Error; + + fn try_from(config: EthereumConfig) -> Result { + let mut provider = Provider::::try_from(config.http_provider)?; + + if let Some(poll_interval_ms) = config.poll_interval_ms { + provider = provider.interval(Duration::from_millis(poll_interval_ms)); + } + + let wallet: LocalWallet = config.sequencer_key.parse::()?.with_chain_id(config.chain_id); + let signer = Arc::new(SignerMiddleware::new(provider, wallet)); + let address: Address = config.core_contracts.parse()?; + + Ok(Self::new(address, signer)) + } +} diff --git a/crates/client/settlement/src/ethereum/errors.rs b/crates/client/settlement/src/ethereum/errors.rs new file mode 100644 index 0000000000..021dd33c55 --- /dev/null +++ b/crates/client/settlement/src/ethereum/errors.rs @@ -0,0 +1,26 @@ +use super::client::LocalMiddleware; + +/// Ethereum client error type. +#[derive(thiserror::Error, Debug)] +#[allow(missing_docs)] +pub enum Error { + #[error("Failed to parse HTTP provider URL: {0}")] + UrlParser(#[from] url::ParseError), + + #[error("Failed to initialize local wallet from private key: {0}")] + LocalWallet(#[from] ethers::signers::WalletError), + + #[error("Failed to parse contract address: {0}")] + HexParser(#[from] rustc_hex::FromHexError), + + #[error("Error while interacting with contract: {0}")] + Contract(#[from] ethers::contract::ContractError), + + #[error("HTTP provider error: {0}")] + Provider(#[from] ethers::providers::ProviderError), + + #[error("Failed to get transaction receipt")] + MissingTransactionRecepit, +} + +pub type Result = std::result::Result; diff --git a/crates/client/settlement/src/ethereum/mod.rs b/crates/client/settlement/src/ethereum/mod.rs new file mode 100644 index 0000000000..7734095c4b --- /dev/null +++ b/crates/client/settlement/src/ethereum/mod.rs @@ -0,0 +1,52 @@ +pub mod client; +pub mod errors; + +use async_trait::async_trait; +pub use client::StarknetContractClient; +use ethers::types::U256; +use mp_snos_output::{SnosCodec, StarknetOsOutput}; +use sp_runtime::traits::Block; +use starknet_api::hash::StarkFelt; + +use crate::{Result, SettlementProvider, StarknetSpec, StarknetState}; + +pub fn convert_u256_to_felt(word: U256) -> Result { + let mut bytes = [0u8; 32]; + word.to_big_endian(bytes.as_mut_slice()); + Ok(StarkFelt::new(bytes)?) +} + +pub fn convert_felt_to_u256(felt: StarkFelt) -> U256 { + U256::from_big_endian(felt.bytes()) +} + +#[async_trait] +impl SettlementProvider for StarknetContractClient { + async fn is_initialized(&self) -> Result { + Ok(U256::zero() != self.program_hash().await?) + } + + async fn get_chain_spec(&self) -> Result { + Ok(StarknetSpec { + program_hash: convert_u256_to_felt(self.program_hash().await?)?, + config_hash: convert_u256_to_felt(self.config_hash().await?)?, + }) + } + + async fn get_state(&self) -> Result { + Ok(StarknetState { + block_number: convert_u256_to_felt(self.state_block_number().await?.into_raw())?, + state_root: convert_u256_to_felt(self.state_root().await?)?, + }) + } + + async fn update_state(&self, program_output: StarknetOsOutput) -> Result<(), B> { + let program_output: Vec = + program_output.into_encoded_vec().into_iter().map(convert_felt_to_u256).collect(); + + let tx_receipt = self.update_state(program_output).await?; + log::trace!("[settlement] State was successfully updated: {:#?}", tx_receipt); + + Ok(()) + } +} diff --git a/crates/client/settlement/src/lib.rs b/crates/client/settlement/src/lib.rs new file mode 100644 index 0000000000..70315e4adc --- /dev/null +++ b/crates/client/settlement/src/lib.rs @@ -0,0 +1,62 @@ +pub mod errors; +pub mod ethereum; +mod sync_state; + +use std::marker::PhantomData; +use std::time::Duration; + +use async_trait::async_trait; +use mp_snos_output::StarknetOsOutput; +use serde::{Deserialize, Serialize}; +use sp_runtime::traits::Block; +use starknet_api::hash::{StarkFelt, StarkHash}; + +use crate::errors::{Error, Result}; + +pub struct SettlementWorker(PhantomData<(B, H, SC)>); + +#[derive(Debug, Copy, Clone, PartialEq)] +#[cfg_attr(feature = "clap", derive(clap::ValueEnum))] +pub enum SettlementLayer { + /// Use Ethereum core contract + Ethereum, +} + +#[async_trait] +pub trait SettlementProvider: Send + Sync { + async fn is_initialized(&self) -> Result; + async fn get_chain_spec(&self) -> Result; + async fn get_state(&self) -> Result; + async fn update_state(&self, program_output: StarknetOsOutput) -> Result<(), B>; +} + +/// Starknet chain identity, contains OS config & program hashes +/// +/// How to calculate program hash: +/// 1. Install Cairo https://docs.cairo-lang.org/quickstart.html +/// 2. Get latest Starknet OS sources (e.g. https://github.com/keep-starknet-strange/snos) +/// 3. Run `cairo-hash-program --program .json` +/// +/// How to calculate config hash: +/// 1. Get Starknet chain ID, which is a string reinterpreted as big number +/// 2. Get Starknet fee token address +/// 3. Calculate Pedersen hash of [CONFIG_HASH_VERSION; chain_id; fee_token_address] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +pub struct StarknetSpec { + /// Starknet OS config hash + pub config_hash: StarkHash, + /// Starknet OS program hash + pub program_hash: StarkHash, +} + +#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)] +pub struct StarknetState { + /// The state commitment after last settled block. + pub state_root: StarkHash, + /// The number (height) of last settled block. + pub block_number: StarkFelt, +} + +pub trait RetryStrategy: Send + Sync { + fn can_retry(&self, error: &Error) -> Option; +} diff --git a/crates/client/settlement/src/sync_state.rs b/crates/client/settlement/src/sync_state.rs new file mode 100644 index 0000000000..ec4273d668 --- /dev/null +++ b/crates/client/settlement/src/sync_state.rs @@ -0,0 +1,283 @@ +use std::sync::Arc; + +use futures::StreamExt; +use futures_timer::Delay; +use mp_block::Block as StarknetBlock; +use mp_hashers::HasherT; +use mp_messages::{MessageL1ToL2, MessageL2ToL1}; +use mp_snos_output::StarknetOsOutput; +use mp_transactions::compute_hash::ComputeTransactionHash; +use mp_transactions::Transaction; +use pallet_starknet_runtime_api::StarknetRuntimeApi; +use sc_client_api::BlockchainEvents; +use sp_api::{HeaderT, ProvideRuntimeApi}; +use sp_arithmetic::traits::UniqueSaturatedInto; +use sp_blockchain::HeaderBackend; +use sp_runtime::traits::Block as BlockT; +use starknet_api::hash::{pedersen_hash_array, StarkFelt, StarkHash}; +use starknet_api::transaction::TransactionHash; +use starknet_crypto::FieldElement; + +use crate::errors::Error; +use crate::{Result, RetryStrategy, SettlementProvider, SettlementWorker, StarknetSpec, StarknetState}; + +pub const SN_OS_CONFIG_HASH_VERSION: &str = "StarknetOsConfig1"; + +impl SettlementWorker +where + B: BlockT, + H: HasherT, + SC: ProvideRuntimeApi + HeaderBackend + BlockchainEvents, + SC::Api: StarknetRuntimeApi, +{ + /// A thread responsible for updating (progressing) Starknet state on the settlement layer. + /// For now we use a simplified setup without validity proofs & DA, but in the future + /// Starknet state contract will also validate state transition against the fact registry. + /// That means we will need to publish state diffs and STARK proof before state update. + /// + /// This is an external loop that is responsible for handling temporary (recoverable) errors. + pub async fn sync_state( + substrate_client: Arc, + settlement_provider: Box>, + retry_strategy: Box>, + ) { + loop { + match Self::sync_state_loop(&substrate_client, settlement_provider.as_ref()).await { + Ok(()) => { + return; + } + Err(err) => { + log::error!("[settlement] {err}"); + match retry_strategy.can_retry(&err) { + Some(dur) => { + log::info!("[settlement] Retrying after {} ms", dur.as_millis()); + Delay::new(dur).await; + continue; + } + None => panic!("Unrecoverable error in settlement thread: {}", err), + } + } + } + } + } + + /// This is an internal loop that listens to the new finalized blocks + /// and attempts to settle the state. + /// + /// It works as follows: + /// + /// 1. First of all it retrieves the latest settled state + /// 2. Then it starts to listen for new finality notifications + /// 3. For all incoming blocks with height lower than the settled one it checks the state root + /// validity. + /// Inconsistent state root means we have a fatal error, which cannot be resolved automatically. + /// + /// 4. Once it gets up to the tip of the chain it starts to apply new state updates. + /// It is possible that there is a need to apply multiple state updates. + /// + /// Sync state loop operates as long as there are new blocks being finalized. + /// In case chain is stuck it won't update the state, even if there are pending blocks. + /// It is ok, since it's not a normal condition, and generally we expect that the chain will + /// advance indefinitely. + async fn sync_state_loop(substrate_client: &SC, settlement_provider: &SP) -> Result<(), B> + where + SP: ?Sized + SettlementProvider, + { + if !settlement_provider.is_initialized().await? { + return Err(Error::StateNotInitialized); + } + + let starknet_spec = settlement_provider.get_chain_spec().await?; + log::debug!("[settlement] Starknet chain spec {:?}", starknet_spec); + + // We need to make sure that we are on the same page with the settlement contract. + Self::verify_starknet_spec(substrate_client, &starknet_spec)?; + + let mut last_settled_state = settlement_provider.get_state().await?; + log::debug!("[settlement] Last settled state {:?}", last_settled_state); + + // If we haven't reached the settled level yet (e.g. syncing from scratch) this check will pass. + // But we need to run it again once we are up to speed. + Self::verify_starknet_state(substrate_client, &last_settled_state)?; + + let mut finality_notifications = substrate_client.finality_notification_stream(); + let mut sync_from: u64 = last_settled_state.block_number.try_into()?; + + while let Some(notification) = finality_notifications.next().await { + let block = mp_digest_log::find_starknet_block(notification.header.digest())?; + let sync_to = block.header().block_number; + + if sync_from > sync_to { + log::info!("[settlement] Skipping block {} (already settled)", sync_to); + continue; + } + + if sync_from == sync_to { + log::info!("[settlement] Verifying state root for block {}", sync_to); + Self::verify_starknet_state(substrate_client, &last_settled_state)?; + continue; + } + + log::info!("[settlement] Syncing state for blocks {} -> {}", sync_from, sync_to); + while sync_from < sync_to { + let (next_block, substrate_block_hash) = if sync_from + 1 == sync_to { + // This is a typical scenario when we are up to speed with the chain + (block.clone(), notification.hash) + } else { + Self::get_starknet_block(substrate_client, sync_from + 1)? + }; + + let new_state = Self::update_starknet_state( + substrate_client, + settlement_provider, + &last_settled_state, + &next_block, + substrate_block_hash, + starknet_spec.config_hash, + ) + .await?; + + log::debug!("[settlement] State transitioned to {:?}", new_state); + last_settled_state = new_state; + sync_from += 1; + } + } + + Ok(()) + } + + /// Returns Starknet block given it's height (level, number). + /// The trick here is that Starknet blocks are embedded into Substrate blocks. + /// + /// Firstly, we need to get Substrate block hash by the Starknet block height. + /// This mapping is kept in a separate storage and there is a dedicated thread which maintains + /// it. There might be situations when we cannot resolve the query (e.g. our node is out of + /// sync), but eventually it will be ok. + /// + /// Secondly, we try to find a corresponding Substrate block (header) by its hash. + /// Lastly, we extract Starknet block from the Substrate block digest. + fn get_starknet_block(substrate_client: &SC, block_number: u64) -> Result<(StarknetBlock, B::Hash), B> { + let substrate_block_hash = substrate_client + .hash(UniqueSaturatedInto::unique_saturated_into(block_number))? + .ok_or_else(|| Error::UnknownStarknetBlock(block_number))?; + + let substrate_block_header = substrate_client + .header(substrate_block_hash)? + .ok_or_else(|| Error::UnknownSubstrateBlock(substrate_block_hash))?; + + let starknet_block = mp_digest_log::find_starknet_block(substrate_block_header.digest())?; + + Ok((starknet_block, substrate_block_hash)) + } + + /// Checks that settlement contract is initialized with the same program & config hash as + /// Madara. + fn verify_starknet_spec(substrate_client: &SC, starknet_spec: &StarknetSpec) -> Result<(), B> { + let substrate_hash = substrate_client.info().best_hash; + let program_hash: StarkHash = substrate_client.runtime_api().program_hash(substrate_hash)?.into(); + + if starknet_spec.program_hash != program_hash { + return Err(Error::ProgramHashMismatch { expected: program_hash, actual: starknet_spec.program_hash }); + } + + let chain_id = substrate_client.runtime_api().chain_id(substrate_hash)?; + let fee_token_address = substrate_client.runtime_api().fee_token_address(substrate_hash)?; + + let config_hash = pedersen_hash_array(&[ + StarkFelt::from(FieldElement::from_byte_slice_be(SN_OS_CONFIG_HASH_VERSION.as_bytes()).unwrap()), + chain_id.into(), + fee_token_address.0.0, + ]); + + if starknet_spec.config_hash != config_hash { + return Err(Error::ConfigHashMismatch { expected: config_hash, actual: starknet_spec.config_hash }); + } + + Ok(()) + } + + /// Tries to verify that the state root for the specified block in Madara storage + /// is the same as in the given state. + /// + /// If Madara chain haven't reached the given block level yet, it returns OK, assuming that as + /// soon as it catches up - this check will be done again. + fn verify_starknet_state(substrate_client: &SC, state: &StarknetState) -> Result<(), B> { + let height: u64 = state.block_number.try_into()?; + + match Self::get_starknet_block(substrate_client, height) { + Ok((block, _)) => { + let state_root = block.header().global_state_root; + // Verify that current onchain state is consistent with corresponding Madara block + if state.state_root != state_root { + return Err(Error::StateRootMismatch { height, expected: state_root, actual: state.state_root }); + } + Ok(()) + } + Err(Error::UnknownStarknetBlock(_)) => Ok(()), + Err(err) => Err(err), + } + } + + /// Aggregates Starknet OS output from a given Starknet block and tries to settle it using a + /// particular provider. + /// + /// "Main part" of Starknet OS program output consists of: + /// - previous state root (at the beginning of the block) + /// - next state root (at the end of the block) + /// - block number + /// - config hash + /// - list of messages transferred between L1 and L2 + /// + /// We construct it using fast execution results, without producing the execution trace which is + /// used for STARK proof. Still it must match the output got from the respective circuit, + /// otherwise the settlement will fail. + async fn update_starknet_state( + substrate_client: &SC, + settlement_provider: &SP, + prev_state: &StarknetState, + next_block: &StarknetBlock, + substrate_block_hash: B::Hash, + config_hash: StarkHash, + ) -> Result + where + SP: ?Sized + SettlementProvider, + { + let next_state = StarknetState { + block_number: next_block.header().block_number.into(), + state_root: next_block.header().global_state_root, + }; + + let mut messages_to_l1: Vec = Vec::new(); + let mut messages_to_l2: Vec = Vec::new(); + + let chain_id = substrate_client.runtime_api().chain_id(substrate_block_hash)?; + + for tx in next_block.transactions() { + if let Transaction::L1Handler(l1_handler) = tx { + messages_to_l2.push(l1_handler.clone().into()); + } + let tx_hash = TransactionHash(tx.compute_hash::(chain_id, false).into()); + substrate_client + .runtime_api() + .get_tx_messages_to_l1(substrate_block_hash, tx_hash)? + .into_iter() + .for_each(|msg| messages_to_l1.push(msg.into())); + } + + // See https://github.com/starkware-libs/cairo-lang/blob/27a157d761ae49b242026bcbe5fca6e60c1e98bd/src/starkware/starknet/core/os/output.cairo + let program_output = StarknetOsOutput { + prev_state_root: prev_state.state_root, + new_state_root: next_state.state_root, + block_number: next_state.block_number, + block_hash: next_block.header().hash::().into(), + config_hash, + messages_to_l1, + messages_to_l2, + }; + log::trace!("{:#?}", program_output); + + settlement_provider.update_state(program_output).await?; + + Ok(next_state) + } +} diff --git a/crates/node/Cargo.toml b/crates/node/Cargo.toml index 5cd43cf9d0..bc25f230c5 100644 --- a/crates/node/Cargo.toml +++ b/crates/node/Cargo.toml @@ -20,6 +20,9 @@ targets = ["x86_64-unknown-linux-gnu"] name = "madara" [dependencies] +# Ethereum +ethers = { workspace = true, features = ["openssl"] } + async-trait = "0.1" clap = { workspace = true, features = ["derive"] } futures = { workspace = true, features = ["thread-pool"] } @@ -82,12 +85,18 @@ madara-runtime = { workspace = true } mc-commitment-state-diff = { workspace = true } mc-data-availability = { workspace = true, features = ["clap"] } mc-db = { workspace = true } +mc-l1-messages = { workspace = true } mc-mapping-sync = { workspace = true } mc-rpc = { workspace = true } +mc-settlement = { workspace = true, features = ["clap"] } mc-storage = { workspace = true } pallet-starknet = { workspace = true } pallet-starknet-runtime-api = { workspace = true } starknet-core = { workspace = true } +starknet_api = { workspace = true, features = [ + "scale-info", + "parity-scale-codec", +] } # Madara utils mc-genesis-data-provider = { workspace = true } @@ -97,10 +106,13 @@ mp-block = { workspace = true } mp-digest-log = { workspace = true } mp-felt = { workspace = true } mp-sequencer-address = { workspace = true, features = ["client"] } +mp-transactions = { workspace = true, features = ["scale-info"] } + # CLI-specific dependencies try-runtime-cli = { optional = true, git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.3.0" } +parity-scale-codec = { workspace = true, features = ["derive"] } reqwest = { workspace = true } serde_json = { workspace = true } url = { workspace = true } diff --git a/crates/node/src/commands/run.rs b/crates/node/src/commands/run.rs index 4074912d9d..61ea9bc0be 100644 --- a/crates/node/src/commands/run.rs +++ b/crates/node/src/commands/run.rs @@ -1,7 +1,10 @@ use std::path::PathBuf; +use clap::ValueHint::FilePath; use madara_runtime::SealingMode; use mc_data_availability::DaLayer; +use mc_l1_messages::config::{L1MessagesWorkerConfig, L1MessagesWorkerConfigError}; +use mc_settlement::SettlementLayer; use sc_cli::{Result, RpcMethods, RunCmd, SubstrateCli}; use sc_service::BasePath; use serde::{Deserialize, Serialize}; @@ -9,6 +12,42 @@ use serde::{Deserialize, Serialize}; use crate::cli::Cli; use crate::service; +#[derive(Debug, Clone, clap::Args)] +#[group(multiple = true)] +pub struct L1MessagesParams { + /// Ethereum Provider (Node) Url + #[clap( + long, + value_hint=clap::ValueHint::Url, + conflicts_with="l1_messages_config", + requires="l1_contract_address", + )] + pub provider_url: Option, + + /// L1 Contract Address + #[clap( + long, + value_hint=clap::ValueHint::Other, + conflicts_with="l1_messages_config", + requires="provider_url", + )] + pub l1_contract_address: Option, +} + +#[derive(Debug, Clone, clap::Args)] +pub struct L1Messages { + /// Path to configuration file for Ethereum Core Contract Events Listener + #[clap( + long, + conflicts_with_all=["provider_url", "l1_contract_address"], + value_hint=clap::ValueHint::FilePath, + )] + pub l1_messages_config: Option, + + #[clap(flatten)] + pub config_params: L1MessagesParams, +} + /// Available Sealing methods. #[derive(Debug, Copy, Clone, clap::ValueEnum, Default, Serialize, Deserialize)] pub enum Sealing { @@ -42,11 +81,20 @@ pub struct ExtendedRunCmd { pub sealing: Option, /// Choose a supported DA Layer - #[clap(long, requires = "da_conf")] + #[clap(long, ignore_case = true, requires = "da_conf")] pub da_layer: Option, - #[clap(long, requires = "da_layer")] - pub da_conf: Option, + /// Path to a file containing the DA configuration + #[clap(long, value_hint = FilePath, requires = "da_layer")] + pub da_conf: Option, + + /// Choose a supported settlement layer + #[clap(long, ignore_case = true, requires = "settlement_conf")] + pub settlement: Option, + + /// Path to a file containing the settlement configuration + #[clap(long, value_hint = FilePath, requires = "settlement")] + pub settlement_conf: Option, /// When enabled, more information about the blocks and their transaction is cached and stored /// in the database. @@ -55,6 +103,10 @@ pub struct ExtendedRunCmd { /// increases the memory footprint of the node. #[clap(long)] pub cache: bool, + + /// Configuration for L1 Messages (Syncing) Worker + #[clap(flatten)] + pub l1_messages_worker: L1Messages, } impl ExtendedRunCmd { @@ -75,7 +127,7 @@ pub fn run_node(mut cli: Cli) -> Result<()> { let da_config: Option<(DaLayer, PathBuf)> = match cli.run.da_layer { Some(da_layer) => { - let da_conf = PathBuf::from(cli.run.da_conf.expect("clap requires da_conf when da_layer is present")); + let da_conf = cli.run.da_conf.expect("clap requires da_conf when da_layer is present"); if !da_conf.exists() { log::info!("{} does not contain DA config", da_conf.display()); return Err("DA config not available".into()); @@ -88,13 +140,51 @@ pub fn run_node(mut cli: Cli) -> Result<()> { None } }; + + let l1_messages_worker_config = extract_l1_messages_worker_config(&cli.run.l1_messages_worker) + .map_err(|e| sc_cli::Error::Input(e.to_string()))?; + + let settlement_config: Option<(SettlementLayer, PathBuf)> = match cli.run.settlement { + Some(SettlementLayer::Ethereum) => { + let settlement_conf = cli.run.settlement_conf.expect("clap requires da_conf when settlement is present"); + if !settlement_conf.exists() { + return Err(sc_cli::Error::Input(format!( + "Ethereum config not found at {}", + settlement_conf.display() + ))); + } + Some((SettlementLayer::Ethereum, settlement_conf)) + } + None => { + log::info!("Madara initialized w/o settlement layer"); + None + } + }; + runner.run_node_until_exit(|config| async move { let sealing = cli.run.sealing.map(Into::into).unwrap_or_default(); let cache = cli.run.cache; - service::new_full(config, sealing, da_config, cache).map_err(sc_cli::Error::Service) + service::new_full(config, sealing, da_config, cache, l1_messages_worker_config, settlement_config) + .map_err(sc_cli::Error::Service) }) } +fn extract_l1_messages_worker_config( + run_cmd: &L1Messages, +) -> std::result::Result, L1MessagesWorkerConfigError> { + if let Some(ref config_path) = run_cmd.l1_messages_config { + let config = L1MessagesWorkerConfig::new_from_file(config_path)?; + return Ok(Some(config)); + } + + if let L1MessagesParams { provider_url: Some(url), l1_contract_address: Some(address) } = &run_cmd.config_params { + let config = L1MessagesWorkerConfig::new_from_params(url, address)?; + return Ok(Some(config)); + } + + Ok(None) +} + fn override_dev_environment(cmd: &mut ExtendedRunCmd) { // create a reproducible dev environment // by disabling the default substrate `dev` behaviour diff --git a/crates/node/src/commands/setup.rs b/crates/node/src/commands/setup.rs index ff9b25e461..479b1a8bb2 100644 --- a/crates/node/src/commands/setup.rs +++ b/crates/node/src/commands/setup.rs @@ -60,6 +60,85 @@ impl SetupCmd { } } +enum ConfigSource { + Local(PathBuf), + Remote(Url), +} + +impl ConfigSource { + fn display(&self, child_path: Option>) -> Result { + let string = match self { + ConfigSource::Local(path_buf) => { + let mut full = path_buf.clone(); + + if let Some(childs) = child_path { + for child in childs { + full = full.join(child); + } + } + + full.display().to_string() + } + ConfigSource::Remote(url) => { + let mut full = url.clone(); + + if let Some(childs) = child_path { + for child in childs { + full = full.join(child).map_err(|e| Error::Application(Box::new(e)))?; + } + } + + full.to_string() + } + }; + + Ok(string) + } + + fn load_config(&self) -> Result> { + let configs: Vec = match self { + ConfigSource::Local(source_configs_path) => { + let index_file_path = source_configs_path.join("index.json"); + std::fs::read(index_file_path).map_err(|e| Error::Application(Box::new(e)))? + } + ConfigSource::Remote(source_configs_url) => { + println!("Fetching chain config from '{}'", &source_configs_url); + + // Query, deserialize and copy it + let response = + reqwest::blocking::get(source_configs_url.clone()).map_err(|e| Error::Application(Box::new(e)))?; + response.bytes().map_err(|e| Error::Application(Box::new(e)))?.into() + } + }; + + Ok(configs) + } + + fn load_asset(&self, asset: &FileInfos) -> Result> { + let file_as_bytes = match self { + ConfigSource::Local(source_config_dir_path) => { + let asset_path = &source_config_dir_path.join(GENESIS_ASSETS_DIR).join(&asset.name); + if !asset_path.exists() { + return Err(format!("Source file '{}' does not exist", asset_path.display()).into()); + } + std::fs::read(asset_path)? + } + ConfigSource::Remote(source_configs_dir_url) => { + let full_url = source_configs_dir_url + .join(GENESIS_ASSETS_DIR) + .map_err(|e| Error::Application(Box::new(e)))? + .join(&asset.name) + .map_err(|e| Error::Application(Box::new(e)))?; + + let response = reqwest::blocking::get(full_url.clone()).map_err(|e| Error::Application(Box::new(e)))?; + response.bytes().map_err(|e| Error::Application(Box::new(e)))?.into() + } + }; + + Ok(file_as_bytes) + } +} + impl SetupCmd { pub fn run(&self) -> Result<()> { log::info!("setup cmd: {:?}", self); @@ -70,60 +149,49 @@ impl SetupCmd { }; log::info!("Setting up madara config at '{}'", dest_config_dir_path.display()); - // Load config from disk - if let Some(src_configs_dir_path) = &self.source.from_local { - // Build the source file path - let src_configs_dir_path = PathBuf::from(src_configs_dir_path); - let index_file_path = src_configs_dir_path.join("index.json"); - - // Read, deserialize and copy it - let madara_configs = { - let src_file_content = - std::fs::read_to_string(index_file_path).map_err(|e| Error::Application(Box::new(e)))?; - // Make sure content is valid before writing it to disk - let configs_content: configs::Configs = serde_json::from_str(&src_file_content) - .map_err(|e| Error::Input(format!("invalid `index.json` content: {}", e)))?; - write_content_to_disk(src_file_content, dest_config_dir_path.join("index.json").as_path())?; - - configs_content - }; - - // Copy each asset - for asset in madara_configs.genesis_assets { - copy_file( - &src_configs_dir_path.join(GENESIS_ASSETS_DIR).join(asset.name), - &dest_config_dir_path.join(GENESIS_ASSETS_DIR), - )?; - } - // Load config form a remote server - } else if let Some(configs_url) = &self.source.from_remote { - // Build the source url - let configs_url = Url::parse(configs_url) + let config_source = if let Some(src_cfg_dir_path) = &self.source.from_local { + let path = PathBuf::from(src_cfg_dir_path); + ConfigSource::Local(path) + } else if let Some(src_cfg_dir_url) = &self.source.from_remote { + let url = Url::parse(src_cfg_dir_url) .map_err(|e| Error::Input(format!("invalid input for 'fetch_madara_configs': {}", e)))?; - println!("Fetching chain config from '{}'", &configs_url); - - // Query, deserialize and copy it - let madara_configs = { - let response = reqwest::blocking::get(configs_url).map_err(|e| Error::Application(Box::new(e)))?; - let bytes = response.bytes().map_err(|e| Error::Application(Box::new(e)))?; - // Make sure content is valid before writing it to disk - let configs_content: configs::Configs = - serde_json::from_slice(&bytes[..]).map_err(|e| Error::Application(Box::new(e)))?; - write_content_to_disk(bytes, dest_config_dir_path.join("index.json").as_path())?; - - configs_content - }; - - // Query and copy each asset - let base_url = Url::parse(&madara_configs.remote_base_path).map_err(|e| Error::Application(Box::new(e)))?; - for asset in madara_configs.genesis_assets { - fetch_and_validate_genesis_assets(&base_url, asset, &dest_config_dir_path)?; - } + ConfigSource::Remote(url) } else { unreachable!( "clap::Args is derived upon `SetupSource` in a way that guarantee that either `from_remote` or \ `from_local` is present" ); + }; + + let configs_file_content = config_source.load_config()?; + // Make sure it is valid data before writing it to disk + let configs: configs::Configs = + serde_json::from_slice(&configs_file_content).map_err(|e| Error::Application(Box::new(e)))?; + write_content_to_disk(configs_file_content, dest_config_dir_path.join("index.json").as_path())?; + + let assets_dir_dest_path = &dest_config_dir_path.join(GENESIS_ASSETS_DIR); + for asset in &configs.genesis_assets { + let asset_file_content = config_source.load_asset(asset)?; + + // Verify it's md5 + if let Some(file_hash) = &asset.md5 { + let digest = md5::compute(&asset_file_content); + let hash = format!("{:x}", digest); + if hash != *file_hash { + return Err(Error::Input(format!( + "Hash mismatch for file '{}': {} != {}", + asset.name, hash, file_hash + ))); + } + } + + let asset_dest_path = assets_dir_dest_path.join(&asset.name); + println!( + "Copying '{}' to '{}'", + config_source.display(Some(vec![&GENESIS_ASSETS_DIR, &asset.name]))?, + asset_dest_path.display() + ); + write_content_to_disk(&asset_file_content, &asset_dest_path)?; } Ok(()) @@ -132,7 +200,7 @@ impl SetupCmd { fn write_content_to_disk>(config_content: T, dest_config_file_path: &Path) -> Result<()> { std::fs::create_dir_all( - dest_config_file_path.parent().expect("dest_config_file_path should be the path to a file, not a dict"), + dest_config_file_path.parent().expect("dest_config_file_path should be the path to a file, not a directory"), )?; let mut dest_file = std::fs::File::create(dest_config_file_path)?; let mut reader = std::io::Cursor::new(config_content); @@ -140,44 +208,3 @@ fn write_content_to_disk>(config_content: T, dest_config_file_pat Ok(()) } - -fn copy_file(src_path: &Path, dest_dir_path: &PathBuf) -> Result<()> { - if !src_path.exists() { - return Err(format!("Source file '{}' does not exist", src_path.display()).into()); - } - - std::fs::create_dir_all(dest_dir_path)?; - let dest_file_path = dest_dir_path.join(src_path.file_name().ok_or("File name not found")?); - println!("Copying '{}' to '{}'", src_path.display(), dest_file_path.display()); - std::fs::copy(src_path, dest_file_path)?; - - Ok(()) -} - -fn fetch_and_validate_genesis_assets(base_remote_url: &Url, file: FileInfos, base_path: &Path) -> Result<()> { - let full_url = base_remote_url - .join(GENESIS_ASSETS_DIR) - .map_err(|e| Error::Application(Box::new(e)))? - .join(&file.name) - .map_err(|e| Error::Application(Box::new(e)))?; - println!("Fetching '{}'", &full_url); - let dest_path = base_path.join(GENESIS_ASSETS_DIR); - - // Copy - let file_as_bytes = { - let response = reqwest::blocking::get(full_url.clone()).map_err(|e| Error::Application(Box::new(e)))?; - let bytes = response.bytes().map_err(|e| Error::Application(Box::new(e)))?; - write_content_to_disk(&bytes, &dest_path.join(file.name))?; - bytes - }; - - if let Some(file_hash) = file.md5 { - let digest = md5::compute(file_as_bytes); - let hash = format!("{:x}", digest); - if hash != file_hash { - return Err(Error::Input(format!("Hash mismatch for file '{}': {} != {}", full_url, hash, file_hash))); - } - } - - Ok(()) -} diff --git a/crates/node/src/service.rs b/crates/node/src/service.rs index 0b045145a1..9c7bddb89a 100644 --- a/crates/node/src/service.rs +++ b/crates/node/src/service.rs @@ -20,7 +20,11 @@ use mc_data_availability::ethereum::config::EthereumConfig; use mc_data_availability::ethereum::EthereumClient; use mc_data_availability::{DaClient, DaLayer, DataAvailabilityWorker, DataAvailabilityWorkerProving}; use mc_genesis_data_provider::OnDiskGenesisConfig; +use mc_l1_messages::config::L1MessagesWorkerConfig; use mc_mapping_sync::MappingSyncWorker; +use mc_settlement::errors::RetryOnRecoverableErrors; +use mc_settlement::ethereum::StarknetContractClient; +use mc_settlement::{SettlementLayer, SettlementProvider, SettlementWorker}; use mc_storage::overrides_handle; use mp_sequencer_address::{ InherentDataProvider as SeqAddrInherentDataProvider, DEFAULT_SEQUENCER_ADDRESS, SEQ_ADDR_STORAGE_KEY, @@ -48,6 +52,9 @@ use crate::starknet::{db_config_dir, MadaraBackend}; // Our native executor instance. pub struct ExecutorDispatch; +const MADARA_TASK_GROUP: &str = "madara"; +const DEFAULT_SETTLEMENT_RETRY_INTERVAL: Duration = Duration::from_millis(100); + impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { /// Only enable the benchmarking host functions when we actually want to benchmark. #[cfg(feature = "runtime-benchmarks")] @@ -267,6 +274,8 @@ pub fn new_full( sealing: SealingMode, da_layer: Option<(DaLayer, PathBuf)>, cache_more_things: bool, + l1_messages_worker_config: Option, + settlement_config: Option<(SettlementLayer, PathBuf)>, ) -> Result { let build_import_queue = if sealing.is_default() { build_aura_grandpa_import_queue } else { build_manual_seal_import_queue }; @@ -398,7 +407,7 @@ pub fn new_full( task_manager.spawn_essential_handle().spawn( "mc-mapping-sync-worker", - Some("madara"), + Some(MADARA_TASK_GROUP), MappingSyncWorker::<_, _, _, StarknetHasher>::new( client.import_notification_stream(), Duration::new(6, 0), @@ -439,7 +448,7 @@ pub fn new_full( task_manager.spawn_essential_handle().spawn( "da-worker-prove", - Some("madara"), + Some(MADARA_TASK_GROUP), DataAvailabilityWorkerProving::prove_current_block( da_client.get_mode(), commitment_state_diff_rx, @@ -449,11 +458,34 @@ pub fn new_full( task_manager.spawn_essential_handle().spawn( "da-worker-update", - Some("madara"), - DataAvailabilityWorker::<_, _, StarknetHasher>::update_state(da_client, client.clone(), madara_backend), + Some(MADARA_TASK_GROUP), + DataAvailabilityWorker::<_, _, StarknetHasher>::update_state( + da_client, + client.clone(), + madara_backend.clone(), + ), ); }; + // initialize settlement worker + if let Some((layer_kind, config_path)) = settlement_config { + let settlement_provider: Box> = match layer_kind { + SettlementLayer::Ethereum => { + let ethereum_conf = EthereumConfig::try_from(&config_path)?; + Box::new( + StarknetContractClient::try_from(ethereum_conf).map_err(|e| ServiceError::Other(e.to_string()))?, + ) + } + }; + let retry_strategy = Box::new(RetryOnRecoverableErrors { delay: DEFAULT_SETTLEMENT_RETRY_INTERVAL }); + + task_manager.spawn_essential_handle().spawn( + "settlement-worker-sync-state", + Some("madara"), + SettlementWorker::<_, StarknetHasher, _>::sync_state(client.clone(), settlement_provider, retry_strategy), + ); + } + if role.is_authority() { // manual-seal authorship if !sealing.is_default() { @@ -488,7 +520,7 @@ pub fn new_full( let aura = sc_consensus_aura::start_aura::(StartAuraParams { slot_duration, - client, + client: client.clone(), select_chain, block_import, proposer_factory, @@ -578,6 +610,13 @@ pub fn new_full( ); } + if let Some(l1_messages_worker_config) = l1_messages_worker_config { + task_manager.spawn_handle().spawn( + "ethereum-core-contract-events-listener", + Some(MADARA_TASK_GROUP), + mc_l1_messages::worker::run_worker(l1_messages_worker_config, client, transaction_pool, madara_backend), + ); + } network_starter.start_network(); Ok(task_manager) } diff --git a/crates/pallets/starknet/Cargo.toml b/crates/pallets/starknet/Cargo.toml index 0e46599833..5efa5e734e 100644 --- a/crates/pallets/starknet/Cargo.toml +++ b/crates/pallets/starknet/Cargo.toml @@ -23,11 +23,16 @@ mp-fee = { workspace = true } mp-felt = { workspace = true, features = ["parity-scale-codec", "serde"] } mp-genesis-config = { workspace = true } mp-hashers = { workspace = true } +mp-program-hash = { workspace = true } mp-sequencer-address = { workspace = true, features = ["parity-scale-codec"] } mp-simulations = { workspace = true, features = [ "parity-scale-codec", "serde", ] } +mp-snos-output = { workspace = true, features = [ + "parity-scale-codec", + "scale-info", +] } mp-state = { workspace = true } mp-storage = { workspace = true, features = ["parity-scale-codec"] } mp-transactions = { workspace = true, features = ["scale-info"] } @@ -105,8 +110,8 @@ std = [ # Starknet "starknet-crypto/std", "blockifier/std", - "mp-sequencer-address/std", "mp-felt/std", + "mp-sequencer-address/std", # Other third party dependencies "dep:reqwest", "dep:cairo-lang-casm-contract-class", diff --git a/crates/pallets/starknet/runtime_api/Cargo.toml b/crates/pallets/starknet/runtime_api/Cargo.toml index 0950fa133b..5762c6dcca 100644 --- a/crates/pallets/starknet/runtime_api/Cargo.toml +++ b/crates/pallets/starknet/runtime_api/Cargo.toml @@ -12,6 +12,10 @@ mp-simulations = { workspace = true, features = [ "parity-scale-codec", "scale-info", ] } +mp-snos-output = { workspace = true, features = [ + "parity-scale-codec", + "scale-info", +] } mp-transactions = { workspace = true, features = [ "parity-scale-codec", "scale-info", diff --git a/crates/pallets/starknet/runtime_api/src/lib.rs b/crates/pallets/starknet/runtime_api/src/lib.rs index bdb9524dfa..73a39fab1d 100644 --- a/crates/pallets/starknet/runtime_api/src/lib.rs +++ b/crates/pallets/starknet/runtime_api/src/lib.rs @@ -10,7 +10,7 @@ use alloc::sync::Arc; use blockifier::execution::contract_class::ContractClass; use mp_felt::Felt252Wrapper; -use mp_transactions::{Transaction, UserTransaction}; +use mp_transactions::{HandleL1MessageTransaction, Transaction, UserTransaction}; use sp_api::BlockT; pub extern crate alloc; use alloc::string::String; @@ -22,7 +22,7 @@ use starknet_api::api_core::{ChainId, ClassHash, ContractAddress, EntryPointSele use starknet_api::block::{BlockNumber, BlockTimestamp}; use starknet_api::hash::StarkFelt; use starknet_api::state::StorageKey; -use starknet_api::transaction::{Calldata, Event as StarknetEvent, TransactionHash}; +use starknet_api::transaction::{Calldata, Event as StarknetEvent, Fee, MessageToL1, TransactionHash}; #[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, scale_info::TypeInfo)] pub enum StarknetTransactionExecutionError { @@ -47,6 +47,10 @@ sp_api::decl_runtime_apis! { fn contract_class_by_class_hash(class_hash: ClassHash) -> Option; /// Returns the chain id. fn chain_id() -> Felt252Wrapper; + /// Returns the Starknet OS Cairo program hash. + fn program_hash() -> Felt252Wrapper; + /// Returns the fee token address. + fn fee_token_address() -> ContractAddress; /// Returns fee estimate fn estimate_fee(transactions: Vec) -> Result, DispatchError>; /// Simulates transactions and returns their trace @@ -74,11 +78,19 @@ sp_api::decl_runtime_apis! { fn get_block_context() -> BlockContext; /// Return is fee disabled in state fn is_transaction_fee_disabled() -> bool; + /// Return messages sent to L1 during tx execution + fn get_tx_messages_to_l1(tx_hash: TransactionHash) -> Vec; + /// Check if L1 Message Nonce has not been used + fn l1_nonce_unused(nonce: Nonce) -> bool; } pub trait ConvertTransactionRuntimeApi { /// Converts the transaction to an UncheckedExtrinsic for submission to the pool. - fn convert_transaction(transaction: UserTransaction) -> Result<::Extrinsic, DispatchError>; + fn convert_transaction(transaction: UserTransaction) -> ::Extrinsic; + + /// Converts the L1 Message transaction to an UncheckedExtrinsic for submission to the pool. + fn convert_l1_transaction(transaction: HandleL1MessageTransaction, fee: Fee) -> ::Extrinsic; + /// Converts the DispatchError to an understandable error for the client fn convert_error(error: DispatchError) -> StarknetTransactionExecutionError; } diff --git a/crates/pallets/starknet/src/lib.rs b/crates/pallets/starknet/src/lib.rs index 8ccd173a30..c50815c257 100644 --- a/crates/pallets/starknet/src/lib.rs +++ b/crates/pallets/starknet/src/lib.rs @@ -46,16 +46,11 @@ pub mod blockifier_state_adapter; pub mod execution_config; #[cfg(feature = "std")] pub mod genesis_loader; -/// The implementation of the message type. -pub mod message; /// Transaction validation logic. pub mod transaction_validation; /// The Starknet pallet's runtime custom types. pub mod types; -/// Everything needed to run the pallet offchain workers -mod offchain_worker; - use blockifier::execution::entry_point::{CallEntryPoint, CallType, EntryPointExecutionContext}; use blockifier::state::cached_state::ContractStorageKey; use starknet_api::state::StorageKey; @@ -67,8 +62,8 @@ mod utils; #[macro_use] pub extern crate alloc; -extern crate core; +use alloc::collections::BTreeSet; use alloc::str::from_utf8_unchecked; use alloc::string::String; use alloc::vec; @@ -93,7 +88,7 @@ use mp_simulations::{ SimulatedTransaction, SimulationFlags, TransactionTrace, }; use mp_storage::{StarknetStorageSchemaVersion, PALLET_STARKNET_SCHEMA}; -use mp_transactions::execution::{Execute, Validate}; +use mp_transactions::execution::Execute; use mp_transactions::{ DeclareTransaction, DeployAccountTransaction, HandleL1MessageTransaction, InvokeTransaction, Transaction, UserAndL1HandlerTransaction, UserTransaction, @@ -104,8 +99,9 @@ use starknet_api::api_core::{ChainId, ClassHash, CompiledClassHash, ContractAddr use starknet_api::block::{BlockNumber, BlockTimestamp}; use starknet_api::deprecated_contract_class::EntryPointType; use starknet_api::hash::StarkFelt; -use starknet_api::transaction::TransactionHash; +use starknet_api::transaction::{MessageToL1, TransactionHash}; use starknet_crypto::FieldElement; +use transaction_validation::TxPriorityInfo; use crate::alloc::string::ToString; use crate::execution_config::RuntimeExecutionConfigBuilder; @@ -116,7 +112,6 @@ pub(crate) const LOG_TARGET: &str = "runtime::starknet"; pub const ETHEREUM_EXECUTION_RPC: &[u8] = b"starknet::ETHEREUM_EXECUTION_RPC"; pub const ETHEREUM_CONSENSUS_RPC: &[u8] = b"starknet::ETHEREUM_CONSENSUS_RPC"; -pub(crate) const NONCE_DECODE_FAILURE: u8 = 1; // syntactic sugar for logging. #[macro_export] @@ -131,8 +126,6 @@ macro_rules! log { #[frame_support::pallet] pub mod pallet { - use blockifier::transaction::errors::TransactionExecutionError; - use super::*; #[pallet::pallet] @@ -176,6 +169,8 @@ pub mod pallet { type ChainId: Get; #[pallet::constant] type MaxRecursionDepth: Get; + #[pallet::constant] + type ProgramHash: Get; } /// The Starknet pallet hooks. @@ -203,24 +198,6 @@ pub mod pallet { fn on_runtime_upgrade() -> Weight { Weight::zero() } - - /// Run offchain tasks. - /// See: `` - /// # Arguments - /// * `n` - The block number. - fn offchain_worker(n: BlockNumberFor) { - log!(info, "Running offchain worker at block {:?}.", n); - - match Self::process_l1_messages() { - Ok(_) => log!(info, "Successfully executed L1 messages"), - Err(err) => match err { - offchain_worker::OffchainWorkerError::NoLastKnownEthBlock => { - log!(info, "No last known Ethereum block number found. Skipping execution of L1 messages.") - } - _ => log!(error, "Failed to execute L1 messages: {:?}", err), - }, - } - } } /// The Starknet pallet storage items. @@ -243,6 +220,11 @@ pub mod pallet { #[pallet::getter(fn tx_events)] pub(super) type TxEvents = StorageMap<_, Identity, TransactionHash, Vec, ValueQuery>; + #[pallet::storage] + #[pallet::unbounded] + #[pallet::getter(fn tx_messages)] + pub(super) type TxMessages = StorageMap<_, Identity, TransactionHash, Vec, ValueQuery>; + #[pallet::storage] #[pallet::unbounded] #[pallet::getter(fn tx_revert_error)] @@ -335,6 +317,13 @@ pub mod pallet { #[pallet::getter(fn seq_addr_update)] pub type SeqAddrUpdate = StorageValue<_, bool, ValueQuery>; + /// Information about processed L1 Messages + /// Based on Nonce value. + #[pallet::storage] + #[pallet::unbounded] + #[pallet::getter(fn l1_messages)] + pub(super) type L1Messages = StorageValue<_, BTreeSet, ValueQuery>; + /// Starknet genesis configuration. #[pallet::genesis_config] pub struct GenesisConfig { @@ -443,6 +432,7 @@ pub mod pallet { MissingRevertReason, MissingCallInfo, TransactionalExecutionFailed, + L1MessageAlreadyExecuted, } /// The Starknet pallet external functions. @@ -520,10 +510,9 @@ pub mod pallet { let tx_hash = transaction.tx_hash; Self::emit_and_store_tx_and_fees_events( tx_hash, - tx_execution_infos.execute_call_info, - tx_execution_infos.fee_transfer_call_info, + &tx_execution_infos.execute_call_info, + &tx_execution_infos.fee_transfer_call_info, ); - Self::store_transaction(tx_hash, Transaction::Invoke(input_transaction), tx_execution_infos.revert_error); Ok(()) @@ -579,10 +568,9 @@ pub mod pallet { let tx_hash = transaction.tx_hash(); Self::emit_and_store_tx_and_fees_events( tx_hash, - tx_execution_infos.execute_call_info, - tx_execution_infos.fee_transfer_call_info, + &tx_execution_infos.execute_call_info, + &tx_execution_infos.fee_transfer_call_info, ); - Self::store_transaction(tx_hash, Transaction::Declare(input_transaction), tx_execution_infos.revert_error); Ok(()) @@ -624,17 +612,16 @@ pub mod pallet { &RuntimeExecutionConfigBuilder::new::().build(), ) .map_err(|e| { - log::error!("failed to deploy accout: {:?}", e); + log::error!("failed to deploy account: {:?}", e); Error::::TransactionExecutionFailed })?; let tx_hash = transaction.tx_hash; Self::emit_and_store_tx_and_fees_events( tx_hash, - tx_execution_infos.execute_call_info, - tx_execution_infos.fee_transfer_call_info, + &tx_execution_infos.execute_call_info, + &tx_execution_infos.fee_transfer_call_info, ); - Self::store_transaction( tx_hash, Transaction::DeployAccount(input_transaction), @@ -671,6 +658,16 @@ pub mod pallet { let chain_id = Self::chain_id(); let transaction = input_transaction.into_executable::(chain_id, paid_fee_on_l1, false); + let nonce: Nonce = transaction.tx.nonce; + + // Ensure that L1 Message has not been executed + Self::ensure_l1_message_not_executed(&nonce).map_err(|_| Error::::L1MessageAlreadyExecuted)?; + + // Store infornamtion about message being processed + // The next instruction executes the message + // Either successfully or not + L1Messages::::mutate(|nonces| nonces.insert(nonce)); + // Execute let tx_execution_infos = transaction .execute( @@ -686,10 +683,9 @@ pub mod pallet { let tx_hash = transaction.tx_hash; Self::emit_and_store_tx_and_fees_events( tx_hash, - tx_execution_infos.execute_call_info, - tx_execution_infos.fee_transfer_call_info, + &tx_execution_infos.execute_call_info, + &tx_execution_infos.fee_transfer_call_info, ); - Self::store_transaction( tx_hash, Transaction::L1Handler(input_transaction), @@ -734,95 +730,21 @@ pub mod pallet { // otherwise we have a nonce error and everything fails. // Once we have a real fee market this is where we'll chose the most profitable transaction. - let chain_id = Self::chain_id(); - let block_context = Self::get_block_context(); - let mut state: BlockifierStateAdapter = BlockifierStateAdapter::::default(); - let mut execution_resources = ExecutionResources::default(); - let mut initial_gas = blockifier::abi::constants::INITIAL_GAS_COST; - let transaction = Self::get_call_transaction(call.clone()).map_err(|_| InvalidTransaction::Call)?; - // Check the nonce is correct - let (sender_address, sender_nonce, transaction_nonce) = - if let UserAndL1HandlerTransaction::User(ref transaction) = transaction { - let sender_address: ContractAddress = transaction.sender_address().into(); - let sender_nonce: Felt252Wrapper = Pallet::::nonce(sender_address).into(); - let transaction_nonce = transaction.nonce(); - - // InvokeV0 does not have a nonce - if let Some(transaction_nonce) = transaction_nonce { - // Reject transaction with an already used Nonce - if sender_nonce > *transaction_nonce { - Err(InvalidTransaction::Stale)?; - } - - // A transaction with a nonce higher than the expected nonce is placed in - // the future queue of the transaction pool. - if sender_nonce < *transaction_nonce { - log!( - debug, - "Nonce is too high. Expected: {:?}, got: {:?}. This transaction will be placed in the \ - transaction pool and executed in the future when the nonce is reached.", - sender_nonce, - transaction_nonce - ); - } - }; - - (transaction.sender_address(), sender_nonce, transaction_nonce.cloned()) - } else { - // TODO: create and check L1 messages Nonce - unimplemented!() - }; - - // Validate the user transactions - if let UserAndL1HandlerTransaction::User(transaction) = transaction { - let validate_result = - match transaction { - UserTransaction::Declare(tx, contract_class) => tx - .try_into_executable::(chain_id, contract_class, false) - .map_err(|_| InvalidTransaction::BadProof)? - .validate_tx(&mut state, &block_context, &mut execution_resources, &mut initial_gas, false), - // There is no way to validate it before the account is actually deployed - UserTransaction::DeployAccount(_) => Ok(None), - UserTransaction::Invoke(tx) => tx - .into_executable::(chain_id, false) - .validate_tx(&mut state, &block_context, &mut execution_resources, &mut initial_gas, false), - }; - match validate_result { - Ok(_) => {} - Err(TransactionExecutionError::ValidateTransactionError( - EntryPointExecutionError::PreExecutionError(PreExecutionError::UninitializedStorageAddress( - contract_address, - )), - )) => { - // If the the txn is failing because the account isn't deployed yet - // then don't throw an error and add a `require` tag for transaction - // of nonce 0 to be executed first. - if contract_address.0.0 != sender_address.into() - || transaction_nonce != Some(Felt252Wrapper::ONE) - { - Err(InvalidTransaction::BadProof)? - } - } - Err(_) => Err(InvalidTransaction::BadProof)?, - }; - } + let tx_priority_info = Self::validate_unsigned_tx_nonce(&transaction)?; - let nonce_for_priority: u64 = transaction_nonce - .unwrap_or(Felt252Wrapper::ZERO) - .try_into() - .map_err(|_| InvalidTransaction::Custom(NONCE_DECODE_FAILURE))?; + Self::validate_unsigned_tx(&transaction)?; let mut valid_transaction_builder = ValidTransaction::with_tag_prefix("starknet") - .priority(u64::MAX - nonce_for_priority) + .priority(u64::MAX) .longevity(T::TransactionLongevity::get()) .propagate(true); - if let Some(transaction_nonce) = transaction_nonce { - valid_transaction_builder = valid_transaction_builder.and_provides((sender_address, transaction_nonce)); - // Enforce waiting for the tx with the previous nonce, - // to be either executed or ordered before in the block + // Make sure txs from same account are executed in correct order (nonce based ordering) + if let TxPriorityInfo::RegularTxs { sender_address, transaction_nonce, sender_nonce } = tx_priority_info { + valid_transaction_builder = + valid_transaction_builder.and_provides((sender_address, Felt252Wrapper(transaction_nonce.0))); if transaction_nonce > sender_nonce { valid_transaction_builder = valid_transaction_builder .and_requires((sender_address, Felt252Wrapper(transaction_nonce.0 - FieldElement::ONE))); @@ -1057,6 +979,54 @@ impl Pallet { frame_system::Pallet::::deposit_log(digest); } + /// Aggregate L2 > L1 messages from the call info. + /// + /// # Arguments + /// + /// * `tx_hash` - The hash of the transaction being processed + /// * `call_info` — A ref to the call info structure. + /// * `next_order` — Next expected message order, has to be 0 for a top level invocation + /// + /// # Returns + /// + /// Next expected message order + fn aggregate_messages_in_call_info(tx_hash: TransactionHash, call_info: &CallInfo, next_order: usize) -> usize { + let mut message_idx = 0; + let mut inner_call_idx = 0; + let mut next_order = next_order; + + loop { + // Store current call's messages as long as they have sequential orders + if message_idx < call_info.execution.l2_to_l1_messages.len() { + let ordered_message = &call_info.execution.l2_to_l1_messages[message_idx]; + if ordered_message.order == next_order { + let message = MessageToL1 { + from_address: call_info.call.storage_address, + to_address: ordered_message.message.to_address, + payload: ordered_message.message.payload.clone(), + }; + TxMessages::::append(tx_hash, message); + next_order += 1; + message_idx += 1; + continue; + } + } + + // Go deeper to find the continuation of the sequence + if inner_call_idx < call_info.inner_calls.len() { + next_order = + Self::aggregate_messages_in_call_info(tx_hash, &call_info.inner_calls[inner_call_idx], next_order); + inner_call_idx += 1; + continue; + } + + // At this point we have iterated over all sequential messages and visited all internal calls + break; + } + + next_order + } + /// Emit events from the call info. /// /// # Arguments @@ -1222,14 +1192,16 @@ impl Pallet { pub fn emit_and_store_tx_and_fees_events( tx_hash: TransactionHash, - execute_call_info: Option, - fee_transfer_call_info: Option, + execute_call_info: &Option, + fee_transfer_call_info: &Option, ) { if let Some(call_info) = execute_call_info { - let _ = Self::emit_events_in_call_info(tx_hash, &call_info, 0); + Self::emit_events_in_call_info(tx_hash, call_info, 0); + Self::aggregate_messages_in_call_info(tx_hash, call_info, 0); } if let Some(call_info) = fee_transfer_call_info { - let _ = Self::emit_events_in_call_info(tx_hash, &call_info, 0); + Self::emit_events_in_call_info(tx_hash, call_info, 0); + Self::aggregate_messages_in_call_info(tx_hash, call_info, 0); } } @@ -1242,6 +1214,11 @@ impl Pallet { pub fn chain_id() -> Felt252Wrapper { T::ChainId::get() } + + pub fn program_hash() -> Felt252Wrapper { + T::ProgramHash::get() + } + pub fn is_transaction_fee_disabled() -> bool { T::DisableTransactionFee::get() } diff --git a/crates/pallets/starknet/src/message.rs b/crates/pallets/starknet/src/message.rs deleted file mode 100644 index 0e1ec357dc..0000000000 --- a/crates/pallets/starknet/src/message.rs +++ /dev/null @@ -1,84 +0,0 @@ -use mp_felt::Felt252Wrapper; -use mp_transactions::HandleL1MessageTransaction; -use parity_scale_codec::{Decode, Encode}; -use serde::Deserialize; - -use crate::alloc::format; -use crate::alloc::string::String; -use crate::alloc::vec::Vec; -use crate::offchain_worker::OffchainWorkerError; - -#[derive(Deserialize, Encode, Decode, Default, Debug)] -pub struct Message { - /// Topics of the event. - pub topics: Vec, - /// Data of the event. - pub data: String, -} - -#[inline(always)] -pub fn get_messages_events(from_block: u64, to_block: u64) -> String { - format!( - "{{ - \"jsonrpc\": \"2.0\", - \"method\": \"eth_getLogs\", - \"params\": [ - {{ - \"fromBlock\": \"0x{:x}\", - \"toBlock\": \"0x{:x}\", - \"address\": \"0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4\", - \"topics\": [ - \"0xdb80dd488acf86d17c747445b0eabb5d57c541d3bd7b6b87af987858e5066b2b\" - ] - }} - ], - \"id\": 0 - }}", - from_block, to_block - ) -} - -impl Message { - /// Converts a `Message` into a transaction object. - pub fn try_into_transaction(&self) -> Result { - // Data at least contains a nonce and at some point the fees. - if self.data.is_empty() { - return Err(OffchainWorkerError::EmptyData); - } - // L2 contract to call. - let contract_address = match Felt252Wrapper::from_hex_be(self.topics[2].as_str()) { - Ok(f) => f, - Err(_) => return Err(OffchainWorkerError::ToTransactionError), - }; - - // Function of the contract to call. - let entry_point_selector = match Felt252Wrapper::from_hex_be(self.topics[3].as_str()) { - Ok(f) => f, - Err(_) => return Err(OffchainWorkerError::ToTransactionError), - }; - - // Add the from address here so it's directly in the calldata. - let char_vec = format!("{:}{:}", self.topics[1].trim_start_matches("0x"), self.data.trim_start_matches("0x")) - .chars() - .collect::>(); - // Split the data String into values. (The event Log(a: uin256, b: uin256, c: uin256) logs a single - // string which is the concatenation of those fields). - let data_map = char_vec.chunks(64).map(|chunk| chunk.iter().collect::()); - // L1 message nonce. - let nonce = u64::from_str_radix( - data_map.clone().last().ok_or(OffchainWorkerError::ToTransactionError)?.trim_start_matches("0x"), - 16, - ) - .map_err(|_| OffchainWorkerError::ToTransactionError)?; - let mut calldata: Vec = Vec::new(); - for val in data_map.take(self.data.len() - 2) { - calldata.push(match Felt252Wrapper::from_hex_be(val.as_str()) { - Ok(f) => f, - Err(_) => return Err(OffchainWorkerError::ToTransactionError), - }) - } - let tx = HandleL1MessageTransaction { nonce, contract_address, entry_point_selector, calldata }; - - Ok(tx) - } -} diff --git a/crates/pallets/starknet/src/offchain_worker/mod.rs b/crates/pallets/starknet/src/offchain_worker/mod.rs deleted file mode 100644 index 2afae4a213..0000000000 --- a/crates/pallets/starknet/src/offchain_worker/mod.rs +++ /dev/null @@ -1,77 +0,0 @@ -mod types; -use alloc::string::{String, ToString}; -use alloc::vec; -use alloc::vec::Vec; - -use frame_support::traits::OriginTrait; -use frame_system::pallet_prelude::OriginFor; -use serde_json::from_slice; -use sp_runtime::offchain::http; -use sp_runtime::offchain::storage::StorageValueRef; -use starknet_api::transaction::Fee; -pub use types::*; - -use crate::message::get_messages_events; -use crate::{Config, Pallet, ETHEREUM_EXECUTION_RPC}; - -pub const LAST_FINALIZED_BLOCK_QUERY: &str = - r#"{"jsonrpc": "2.0", "method": "eth_getBlockByNumber", "params": ["finalized", true], "id": 0}"#; - -impl Pallet { - /// Fetches L1 messages and execute them. - /// This function is called by the offchain worker. - /// It is executed in a separate thread. - /// # Returns - /// The result of the offchain worker execution. - pub(crate) fn process_l1_messages() -> Result<(), OffchainWorkerError> { - // Get the last known block from storage. - let last_known_eth_block = Self::last_known_eth_block().ok_or(OffchainWorkerError::NoLastKnownEthBlock)?; - // Query L1 for the last finalized block. - let raw_body = query_eth(LAST_FINALIZED_BLOCK_QUERY)?; - let last_finalized_block: u64 = from_slice::(&raw_body) - .map_err(|_| OffchainWorkerError::SerdeError)? - .try_into()?; - // Check if there are new messages to be processed. - if last_finalized_block > last_known_eth_block { - // Read the new messages from L1. - let raw_body = query_eth(&get_messages_events(last_known_eth_block, last_finalized_block))?; - let res: EthLogs = from_slice(&raw_body).map_err(|_| OffchainWorkerError::SerdeError)?; - // Iterate over the messages and execute them. - res.result.iter().try_for_each(|message| { - // Execute the message. - // Fee is required but the blockifier just check it's not zero - Self::consume_l1_message(OriginFor::::none(), message.try_into_transaction()?, Fee(1)) - .map_err(OffchainWorkerError::ConsumeMessageError) - })?; - } - Ok(()) - } -} - -/// Returns Ethereum RPC URL from Storage -fn get_eth_rpc_url() -> Result { - let eth_execution_rpc_url = StorageValueRef::persistent(ETHEREUM_EXECUTION_RPC) - .get::>() - .map_err(|_| OffchainWorkerError::GetStorageFailed)? - .ok_or(OffchainWorkerError::EthRpcNotSet)?; - - let endpoint: &str = - core::str::from_utf8(ð_execution_rpc_url).map_err(|_| OffchainWorkerError::FormatBytesFailed)?; - - if endpoint.is_empty() { - return Err(OffchainWorkerError::EthRpcNotSet); - } - - Ok(endpoint.to_string()) -} - -/// Queries an Eth json rpc node -fn query_eth(request: &str) -> Result, OffchainWorkerError> { - let res = http::Request::post(&get_eth_rpc_url()?, vec![request]) - .add_header("content-type", "application/json") - .send() - .map_err(OffchainWorkerError::HttpError)? - .wait() - .map_err(OffchainWorkerError::RequestError)?; - Ok(res.body().collect::>()) -} diff --git a/crates/pallets/starknet/src/offchain_worker/types.rs b/crates/pallets/starknet/src/offchain_worker/types.rs deleted file mode 100644 index 90790f8826..0000000000 --- a/crates/pallets/starknet/src/offchain_worker/types.rs +++ /dev/null @@ -1,59 +0,0 @@ -use alloc::string::String; -use alloc::vec::Vec; -use core::str::Utf8Error; - -use parity_scale_codec::{Decode, Encode}; -use serde::Deserialize; -use sp_runtime::offchain::http::Error; -use sp_runtime::offchain::HttpError; -use sp_runtime::DispatchError; - -use crate::message::Message; - -/// Error enum wrapper for offchain worker tasks. -#[derive(Debug, Eq, PartialEq)] -pub enum OffchainWorkerError { - HttpError(HttpError), - RequestError(Error), - SerdeError, - ToBytesError(Utf8Error), - ConsumeMessageError(DispatchError), - ToTransactionError, - U256ConversionError, - HexDecodeError, - EmptyData, - NoLastKnownEthBlock, - GetStorageFailed, - EthRpcNotSet, - FormatBytesFailed, -} - -/// Struct that represents the response fields that we need of the eth node for -/// `eth_getBlockByNumber`. -#[derive(Deserialize, Encode, Decode, Default, Debug)] -pub struct EthGetBlockByNumberResponse { - /// Object that contains the block number. - pub result: NumberRes, -} - -impl TryFrom for u64 { - type Error = OffchainWorkerError; - - fn try_from(value: EthGetBlockByNumberResponse) -> Result { - u64::from_str_radix(&value.result.number[2..], 16).map_err(|_| OffchainWorkerError::HexDecodeError) - } -} - -/// Inner struct for block number. -#[derive(Deserialize, Encode, Decode, Default, Debug)] -pub struct NumberRes { - /// Block number. - pub number: String, -} - -/// Struct that represents an Ethereum event for a message sent to starknet. -#[derive(Deserialize, Encode, Decode, Default, Debug)] -pub struct EthLogs { - /// Array that contains the events. - pub result: Vec, -} diff --git a/crates/pallets/starknet/src/tests/declare_tx.rs b/crates/pallets/starknet/src/tests/declare_tx.rs index 28838687f6..d79ac1a7de 100644 --- a/crates/pallets/starknet/src/tests/declare_tx.rs +++ b/crates/pallets/starknet/src/tests/declare_tx.rs @@ -311,34 +311,6 @@ fn test_verify_tx_longevity() { }); } -#[test] -fn test_verify_no_require_tag() { - new_test_ext::().execute_with(|| { - basic_test_setup(2); - - let chain_id = Starknet::chain_id(); - let transaction = - get_declare_dummy(chain_id, Felt252Wrapper::ZERO, AccountType::V0(AccountTypeV0Inner::NoValidate)); - let erc20_class = get_contract_class("ERC20.json", 0); - - let validate_result = Starknet::validate_unsigned( - TransactionSource::InBlock, - &crate::Call::declare { transaction: transaction.clone(), contract_class: erc20_class }, - ) - .unwrap(); - - let valid_transaction_expected = ValidTransaction::with_tag_prefix("starknet") - .priority(u64::MAX - (TryInto::::try_into(*transaction.nonce())).unwrap()) - .and_provides((*transaction.sender_address(), *transaction.nonce())) - .longevity(TransactionLongevity::get()) - .propagate(true) - .build() - .unwrap(); - - assert_eq!(validate_result, valid_transaction_expected) - }); -} - #[test] fn test_verify_require_tag() { new_test_ext::().execute_with(|| { @@ -356,7 +328,7 @@ fn test_verify_require_tag() { .unwrap(); let valid_transaction_expected = ValidTransaction::with_tag_prefix("starknet") - .priority(u64::MAX - (TryInto::::try_into(*transaction.nonce())).unwrap()) + .priority(u64::MAX) .and_provides((*transaction.sender_address(), *transaction.nonce())) .longevity(TransactionLongevity::get()) .propagate(true) diff --git a/crates/pallets/starknet/src/tests/invoke_tx.rs b/crates/pallets/starknet/src/tests/invoke_tx.rs index b6f68325be..ef89c9a17a 100644 --- a/crates/pallets/starknet/src/tests/invoke_tx.rs +++ b/crates/pallets/starknet/src/tests/invoke_tx.rs @@ -11,7 +11,7 @@ use sp_runtime::transaction_validity::{ use starknet_api::api_core::{ContractAddress, Nonce, PatriciaKey}; use starknet_api::hash::StarkFelt; use starknet_api::state::StorageKey; -use starknet_api::transaction::{Event as StarknetEvent, EventContent, EventData, EventKey, Fee, TransactionHash}; +use starknet_api::transaction::{Event as StarknetEvent, EventContent, EventData, EventKey, TransactionHash}; use starknet_core::utils::get_selector_from_name; use starknet_crypto::FieldElement; @@ -19,7 +19,6 @@ use super::constants::{BLOCKIFIER_ACCOUNT_ADDRESS, MULTIPLE_EVENT_EMITTING_CONTR use super::mock::default_mock::*; use super::mock::*; use super::utils::sign_message_hash; -use crate::message::Message; use crate::tests::{ get_invoke_argent_dummy, get_invoke_braavos_dummy, get_invoke_dummy, get_invoke_emit_event_dummy, get_invoke_nonce_dummy, get_invoke_openzeppelin_dummy, get_storage_read_write_dummy, set_nonce, @@ -58,25 +57,12 @@ fn given_hardcoded_contract_run_invoke_tx_then_it_works() { let transaction: InvokeTransaction = get_invoke_dummy(Felt252Wrapper::ZERO).into(); - let tx = Message { - topics: vec![ - "0xdb80dd488acf86d17c747445b0eabb5d57c541d3bd7b6b87af987858e5066b2b".to_owned(), - "0x0000000000000000000000000000000000000000000000000000000000000001".to_owned(), - "0x0000000000000000000000000000000000000000000000000000000000000001".to_owned(), - "0x01310e2c127c3b511c5ac0fd7949d544bb4d75b8bc83aaeb357e712ecf582771".to_owned(), - ], - data: "0x0000000000000000000000000000000000000000000000000000000000000001".to_owned(), - } - .try_into_transaction() - .unwrap(); - assert_ok!(Starknet::invoke(none_origin.clone(), transaction)); - assert_ok!(Starknet::consume_l1_message(none_origin, tx, Fee(100))); let pending_txs = Starknet::pending(); - pretty_assertions::assert_eq!(pending_txs.len(), 2); + pretty_assertions::assert_eq!(pending_txs.len(), 1); let pending_hashes = Starknet::pending_hashes(); - pretty_assertions::assert_eq!(pending_hashes.len(), 2); + pretty_assertions::assert_eq!(pending_hashes.len(), 1); assert_eq!( pending_hashes[0], @@ -490,29 +476,6 @@ fn test_verify_tx_longevity() { }); } -#[test] -fn test_verify_no_require_tag() { - new_test_ext::().execute_with(|| { - basic_test_setup(2); - - let transaction = get_invoke_dummy(Felt252Wrapper::ZERO); - - let validate_result = Starknet::validate_unsigned( - TransactionSource::InBlock, - &crate::Call::invoke { transaction: transaction.clone().into() }, - ); - - let valid_transaction_expected = ValidTransaction::with_tag_prefix("starknet") - .priority(u64::MAX - (TryInto::::try_into(transaction.nonce)).unwrap()) - .and_provides((transaction.sender_address, transaction.nonce)) - .longevity(TransactionLongevity::get()) - .propagate(true) - .build(); - - assert_eq!(validate_result.unwrap(), valid_transaction_expected.unwrap()) - }); -} - #[test] fn test_verify_require_tag() { new_test_ext::().execute_with(|| { @@ -526,7 +489,7 @@ fn test_verify_require_tag() { ); let valid_transaction_expected = ValidTransaction::with_tag_prefix("starknet") - .priority(u64::MAX - (TryInto::::try_into(transaction.nonce)).unwrap()) + .priority(u64::MAX) .and_provides((transaction.sender_address, transaction.nonce)) .longevity(TransactionLongevity::get()) .propagate(true) diff --git a/crates/pallets/starknet/src/tests/l1_handler_validation.rs b/crates/pallets/starknet/src/tests/l1_handler_validation.rs new file mode 100644 index 0000000000..4ba2e10fc3 --- /dev/null +++ b/crates/pallets/starknet/src/tests/l1_handler_validation.rs @@ -0,0 +1,85 @@ +use assert_matches::assert_matches; +use mp_transactions::{HandleL1MessageTransaction, UserAndL1HandlerTransaction}; +use sp_runtime::transaction_validity::InvalidTransaction; +use starknet_api::api_core::Nonce; +use starknet_api::hash::StarkFelt; +use starknet_api::transaction::Fee; + +use super::mock::default_mock::*; +use super::mock::*; +use crate::transaction_validation::TxPriorityInfo; +use crate::L1Messages; + +#[test] +fn should_ensure_l1_message_not_executed_work_properly() { + new_test_ext::().execute_with(|| { + basic_test_setup(2); + + let nonce = Nonce(StarkFelt::from(1u64)); + + assert!(Starknet::ensure_l1_message_not_executed(&nonce).is_ok()); + + L1Messages::::mutate(|nonces| nonces.insert(nonce)); + + assert_eq!(Starknet::ensure_l1_message_not_executed(&nonce), Err(InvalidTransaction::Stale)); + }); +} + +#[test] +fn should_accept_unused_nonce() { + new_test_ext::().execute_with(|| { + basic_test_setup(2); + + let nonce: u64 = 1; + let transaction = HandleL1MessageTransaction { + nonce, + contract_address: Default::default(), + entry_point_selector: Default::default(), + calldata: Default::default(), + }; + + let tx = UserAndL1HandlerTransaction::L1Handler(transaction, Fee(100)); + + assert_matches!(Starknet::validate_unsigned_tx_nonce(&tx), Ok(TxPriorityInfo::L1Handler)); + }); +} + +#[test] +fn should_reject_used_nonce() { + new_test_ext::().execute_with(|| { + basic_test_setup(2); + + let nonce: u64 = 1; + let transaction = HandleL1MessageTransaction { + nonce, + contract_address: Default::default(), + entry_point_selector: Default::default(), + calldata: Default::default(), + }; + + let tx = UserAndL1HandlerTransaction::L1Handler(transaction, Fee(100)); + + L1Messages::::mutate(|nonces| nonces.insert(Nonce(nonce.into()))); + + assert_matches!(Starknet::validate_unsigned_tx_nonce(&tx), Err(InvalidTransaction::Stale)); + }); +} + +#[test] +fn should_accept_valid_unsigned_l1_message_tx() { + new_test_ext::().execute_with(|| { + basic_test_setup(2); + + let nonce: u64 = 1; + let transaction = HandleL1MessageTransaction { + nonce, + contract_address: Default::default(), + entry_point_selector: Default::default(), + calldata: Default::default(), + }; + + let tx = UserAndL1HandlerTransaction::L1Handler(transaction, Fee(100)); + + assert!(Starknet::validate_unsigned_tx(&tx).is_ok()); + }); +} diff --git a/crates/pallets/starknet/src/tests/l1_message.rs b/crates/pallets/starknet/src/tests/l1_message.rs index a048f48995..d44ef90a18 100644 --- a/crates/pallets/starknet/src/tests/l1_message.rs +++ b/crates/pallets/starknet/src/tests/l1_message.rs @@ -1,61 +1,160 @@ -use frame_support::assert_err; +use frame_support::{assert_err, assert_ok}; use mp_felt::Felt252Wrapper; -use mp_transactions::{DeclareTransactionV1, HandleL1MessageTransaction}; +use mp_transactions::HandleL1MessageTransaction; use sp_runtime::traits::ValidateUnsigned; -use sp_runtime::transaction_validity::TransactionSource; +use sp_runtime::transaction_validity::{TransactionSource, TransactionValidityError}; +use starknet_api::api_core::{ContractAddress, Nonce, PatriciaKey}; +use starknet_api::hash::StarkFelt; +use starknet_api::state::StorageKey; use starknet_api::transaction::Fee; use super::mock::default_mock::*; use super::mock::*; -use super::utils::get_contract_class; -use crate::Error; +use crate::{Call, Error, InvalidTransaction, L1Messages}; #[test] -fn given_contract_l1_message_fails_sender_not_deployed() { +fn verify_tx_validity() { new_test_ext::().execute_with(|| { basic_test_setup(2); - let none_origin = RuntimeOrigin::none(); + let transaction = HandleL1MessageTransaction { + nonce: Default::default(), + contract_address: Default::default(), + entry_point_selector: Default::default(), + calldata: Default::default(), + }; - // Wrong address (not deployed) - let contract_address = - Felt252Wrapper::from_hex_be("0x03e437FB56Bb213f5708Fcd6966502070e276c093ec271aA33433b89E21fd31f").unwrap(); + let expected_priority = u64::MAX; + let expected_longetivity = TransactionLongevity::get(); + let expected_propagate = true; - let erc20_class = get_contract_class("ERC20.json", 0); + let validate_result = Starknet::validate_unsigned( + TransactionSource::InBlock, + &Call::consume_l1_message { transaction, paid_fee_on_l1: Fee(100) }, + ); - let transaction = DeclareTransactionV1 { - sender_address: contract_address, - nonce: Default::default(), - signature: Default::default(), - max_fee: Default::default(), - class_hash: Default::default(), + assert!(validate_result.is_ok()); + let validate_result = validate_result.unwrap(); + + assert_eq!(validate_result.priority, expected_priority); + assert_eq!(validate_result.longevity, expected_longetivity); + assert_eq!(validate_result.propagate, expected_propagate); + }); +} + +#[test] +fn should_reject_used_nonce() { + new_test_ext::().execute_with(|| { + basic_test_setup(2); + + let nonce: u64 = 1; + + let transaction = HandleL1MessageTransaction { + nonce, + contract_address: Default::default(), + entry_point_selector: Default::default(), + calldata: Default::default(), }; - assert_err!( - Starknet::declare(none_origin, transaction.into(), erc20_class), - Error::::AccountNotDeployed + let tx_source = TransactionSource::InBlock; + let call = Call::consume_l1_message { transaction, paid_fee_on_l1: Fee(100) }; + + assert!(Starknet::validate_unsigned(tx_source, &call).is_ok()); + + L1Messages::::mutate(|nonces| nonces.insert(Nonce(StarkFelt::from(nonce)))); + + assert_eq!( + Starknet::validate_unsigned(tx_source, &call), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)) ); - }) + }); } #[test] -#[ignore = "l1 handler validation not implemented yet"] -fn verify_tx_longevity() { +fn should_reject_zero_fee() { new_test_ext::().execute_with(|| { basic_test_setup(2); + let nonce: u64 = 1; + let transaction = HandleL1MessageTransaction { - nonce: Default::default(), + nonce, contract_address: Default::default(), entry_point_selector: Default::default(), calldata: Default::default(), }; - let validate_result = Starknet::validate_unsigned( - TransactionSource::InBlock, - &crate::Call::consume_l1_message { transaction, paid_fee_on_l1: Fee(100) }, + let tx_source = TransactionSource::InBlock; + let call = Call::consume_l1_message { transaction, paid_fee_on_l1: Fee(0) }; + + assert_eq!( + Starknet::validate_unsigned(tx_source, &call), + Err(TransactionValidityError::Invalid(InvalidTransaction::Payment)) ); + }); +} - assert!(validate_result.unwrap().longevity == TransactionLongevity::get()); +#[test] +fn work() { + // Execute `test_l1_handler_store_under_caller_address()` + new_test_ext::().execute_with(|| { + basic_test_setup(2); + let contract_address = + Felt252Wrapper::from_hex_be("0x024d1e355f6b9d27a5a420c8f4b50cea9154a8e34ad30fc39d7c98d3c177d0d7").unwrap(); + let from_address = Felt252Wrapper::from_hex_be("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045").unwrap(); + + let transaction = HandleL1MessageTransaction { + nonce: 1, + contract_address, + entry_point_selector: Felt252Wrapper::from_hex_be( + "0x014093c40d95d0a3641c087f7d48d55160e1a58bc7c07b0d2323efeeb3087269", // test_l1_handler_store_under_caller_address + ) + .unwrap(), + calldata: vec![ + from_address, + Felt252Wrapper::from_hex_be("0x1").unwrap(), // value + ], + }; + assert_ok!(Starknet::consume_l1_message(RuntimeOrigin::none(), transaction, Fee(1))); + + let storage_key = ( + ContractAddress(PatriciaKey(StarkFelt::from(contract_address))), + StorageKey(PatriciaKey(StarkFelt::from(from_address))), + ); + assert_eq!(Starknet::storage(storage_key), StarkFelt::from(1u128)); + }); +} + +#[test] +fn fail_if_no_fee() { + // Execute `test_l1_handler_store_under_caller_address()` + new_test_ext::().execute_with(|| { + basic_test_setup(2); + let contract_address = + Felt252Wrapper::from_hex_be("0x024d1e355f6b9d27a5a420c8f4b50cea9154a8e34ad30fc39d7c98d3c177d0d7").unwrap(); + let from_address = Felt252Wrapper::from_hex_be("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045").unwrap(); + + let transaction = HandleL1MessageTransaction { + nonce: 1, + contract_address, + entry_point_selector: Felt252Wrapper::from_hex_be( + "0x014093c40d95d0a3641c087f7d48d55160e1a58bc7c07b0d2323efeeb3087269", + ) + .unwrap(), + calldata: vec![ + from_address, + Felt252Wrapper::from_hex_be("0x1").unwrap(), // value + ], + }; + assert_err!( + Starknet::consume_l1_message(RuntimeOrigin::none(), transaction, Fee(0)), + Error::::TransactionExecutionFailed + ); + + let storage_key = ( + ContractAddress(PatriciaKey(StarkFelt::from(contract_address))), + StorageKey(PatriciaKey(StarkFelt::from(from_address))), + ); + assert_eq!(Starknet::storage(storage_key), StarkFelt::from(0u128)); }); } diff --git a/crates/pallets/starknet/src/tests/message.rs b/crates/pallets/starknet/src/tests/message.rs deleted file mode 100644 index d37dc93c09..0000000000 --- a/crates/pallets/starknet/src/tests/message.rs +++ /dev/null @@ -1,26 +0,0 @@ -use crate::message::Message; -use crate::offchain_worker::OffchainWorkerError; - -#[test] -fn test_try_into_transaction_incorrect_topic_should_fail() { - let hex = "0x1".to_owned(); - let test_message: Message = - Message { topics: vec![hex.clone(), hex.clone(), "foo".to_owned(), hex.clone()], data: hex }; - assert_eq!(test_message.try_into_transaction().unwrap_err(), OffchainWorkerError::ToTransactionError); -} - -#[test] -fn test_try_into_transaction_incorrect_selector_in_topic_should_fail() { - let hex = "0x1".to_owned(); - let test_message: Message = - Message { topics: vec![hex.clone(), hex.clone(), hex.clone(), "foo".to_owned()], data: hex }; - assert_eq!(test_message.try_into_transaction().unwrap_err(), OffchainWorkerError::ToTransactionError); -} - -#[test] -fn test_try_into_transaction_empty_data_should_fail() { - let hex = "0x1".to_owned(); - let test_message: Message = - Message { topics: vec![hex.clone(), hex.clone(), hex.clone(), hex], data: "".to_owned() }; - assert_eq!(test_message.try_into_transaction().unwrap_err(), OffchainWorkerError::EmptyData); -} diff --git a/crates/pallets/starknet/src/tests/mock/setup_mock.rs b/crates/pallets/starknet/src/tests/mock/setup_mock.rs index e2c43005c6..fb64c7ac92 100644 --- a/crates/pallets/starknet/src/tests/mock/setup_mock.rs +++ b/crates/pallets/starknet/src/tests/mock/setup_mock.rs @@ -73,6 +73,7 @@ macro_rules! mock_runtime { pub const ProtocolVersion: u8 = 0; pub const ChainId: Felt252Wrapper = mp_chain_id::SN_GOERLI_CHAIN_ID; pub const MaxRecursionDepth: u32 = 50; + pub const ProgramHash: Felt252Wrapper = mp_program_hash::SN_OS_PROGRAM_HASH; } impl pallet_starknet::Config for MockRuntime { @@ -88,6 +89,7 @@ macro_rules! mock_runtime { type ProtocolVersion = ProtocolVersion; type ChainId = ChainId; type MaxRecursionDepth = MaxRecursionDepth; + type ProgramHash = ProgramHash; } /// Run to block n. diff --git a/crates/pallets/starknet/src/tests/mod.rs b/crates/pallets/starknet/src/tests/mod.rs index 6bbd7a87f6..f5cd7364ec 100644 --- a/crates/pallets/starknet/src/tests/mod.rs +++ b/crates/pallets/starknet/src/tests/mod.rs @@ -21,14 +21,15 @@ mod erc20; mod events; mod fees_disabled; mod invoke_tx; +mod l1_handler_validation; mod l1_message; mod no_nonce_validation; mod query_tx; +mod send_message; mod sequencer_address; mod block; mod constants; -mod message; mod mock; mod utils; diff --git a/crates/pallets/starknet/src/tests/send_message.rs b/crates/pallets/starknet/src/tests/send_message.rs new file mode 100644 index 0000000000..54c69064b4 --- /dev/null +++ b/crates/pallets/starknet/src/tests/send_message.rs @@ -0,0 +1,99 @@ +use frame_support::assert_ok; +use mp_felt::Felt252Wrapper; +use mp_transactions::compute_hash::ComputeTransactionHash; +use mp_transactions::{DeclareTransactionV1, DeployAccountTransaction, InvokeTransactionV1}; +use starknet_api::api_core::EthAddress; +use starknet_api::transaction::{L2ToL1Payload, MessageToL1, TransactionHash}; + +use super::mock::default_mock::*; +use super::mock::*; +use super::utils::get_contract_class; +use crate::Config; + +// NoValidateAccount (Cairo 0) +const DEPLOY_CONTRACT_SELECTOR: &str = "0x02730079d734ee55315f4f141eaed376bddd8c2133523d223a344c5604e0f7f8"; + +// Generate: starkli class-hash ./cairo-contracts/build/send_message.json +const SEND_MESSAGE_CLASS_HASH: &str = "0x024e12108da2b3d3c80c7bc99aacdec97e445199c5a8ded7435bf77ce4507631"; +// const SEND_MESSAGE_TO_L2_SELECTOR: &str = +// "0x38fb0bf48fe489ae23d0a1d7f2b7195ec0b94bfeb2f408b13bfd943d8410d72"; +const SEND_MESSAGE_TO_L1_SELECTOR: &str = "0x9139dbd19ca9654d773cd88f31af4c8d583beecc3362fb986dccfef5cf134f"; + +// Troubleshooting notes: +// Add println! to the necessary runtime method (e.g. print CallInfo structs or extended blockifier +// message), then run: +// cargo test --package pallet-starknet send_message -- --nocapture + +#[test] +fn messages_to_l1_are_stored() { + new_test_ext::().execute_with(|| { + basic_test_setup(2); + + let sender_address: Felt252Wrapper = + get_account_address(None, AccountType::V0(AccountTypeV0Inner::NoValidate)).into(); + let contract_class = get_contract_class("send_message.json", 0); + let class_hash = Felt252Wrapper::from_hex_be(SEND_MESSAGE_CLASS_HASH).unwrap(); + + let declare_tx = DeclareTransactionV1 { + sender_address, + class_hash, + nonce: Felt252Wrapper::ZERO, + max_fee: u128::MAX, + signature: vec![], + }; + + assert_ok!(Starknet::declare(RuntimeOrigin::none(), declare_tx.into(), contract_class)); + + let salt = Felt252Wrapper::ZERO; + let contract_address: Felt252Wrapper = + DeployAccountTransaction::calculate_contract_address(salt.into(), class_hash.into(), &[]).into(); + + let deploy_tx = InvokeTransactionV1 { + sender_address, + calldata: vec![ + sender_address, + Felt252Wrapper::from_hex_be(DEPLOY_CONTRACT_SELECTOR).unwrap(), + Felt252Wrapper::from(3u128), // Calldata len + class_hash, + salt, + Felt252Wrapper::ZERO, // Constructor calldata len (no explicit constructor declared) + ], + nonce: Felt252Wrapper::ONE, + max_fee: u128::MAX, + signature: vec![], + }; + + assert_ok!(Starknet::invoke(RuntimeOrigin::none(), deploy_tx.into())); + + let invoke_tx = InvokeTransactionV1 { + sender_address, + calldata: vec![ + contract_address, + Felt252Wrapper::from_hex_be(SEND_MESSAGE_TO_L1_SELECTOR).unwrap(), + Felt252Wrapper::from(3u128), // Calldata len + Felt252Wrapper::ZERO, // to_address + Felt252Wrapper::ONE, // payload_len + Felt252Wrapper::TWO, // payload + ], + nonce: Felt252Wrapper::TWO, + max_fee: u128::MAX, + signature: vec![], + }; + + assert_ok!(Starknet::invoke(RuntimeOrigin::none(), invoke_tx.clone().into())); + + let chain_id = Starknet::chain_id(); + let tx_hash = invoke_tx.compute_hash::<::SystemHash>(chain_id, false); + let messages = Starknet::tx_messages(TransactionHash::from(tx_hash)); + + assert_eq!(1, messages.len()); + pretty_assertions::assert_eq!( + messages[0], + MessageToL1 { + from_address: contract_address.into(), + to_address: EthAddress([0u8; 20].into()), + payload: L2ToL1Payload(vec![Felt252Wrapper::TWO.into()]) + } + ); + }); +} diff --git a/crates/pallets/starknet/src/transaction_validation.rs b/crates/pallets/starknet/src/transaction_validation.rs index 4c5b212f1e..0da8bd6955 100644 --- a/crates/pallets/starknet/src/transaction_validation.rs +++ b/crates/pallets/starknet/src/transaction_validation.rs @@ -1,5 +1,9 @@ //! Transaction validation logic. +use blockifier::transaction::errors::TransactionExecutionError; use frame_support::traits::EnsureOrigin; +use mp_transactions::execution::Validate; + +use super::*; /// Representation of the origin of a Starknet transaction. /// For now, we still don't know how to represent the origin of a Starknet transaction, @@ -50,3 +54,107 @@ impl> + From> Ensure Ok(OuterOrigin::from(RawOrigin::StarknetTransaction)) } } + +#[derive(Debug)] +pub enum TxPriorityInfo { + InvokeV0, + L1Handler, + RegularTxs { sender_address: Felt252Wrapper, transaction_nonce: Felt252Wrapper, sender_nonce: Felt252Wrapper }, +} + +impl Pallet { + pub fn validate_unsigned_tx_nonce( + transaction: &UserAndL1HandlerTransaction, + ) -> Result { + match transaction { + UserAndL1HandlerTransaction::User(tx) => { + let sender_address: ContractAddress = tx.sender_address().into(); + let sender_nonce: Felt252Wrapper = Pallet::::nonce(sender_address).into(); + let transaction_nonce = match tx.nonce() { + Some(n) => *n, + None => return Ok(TxPriorityInfo::InvokeV0), + }; + + // Reject transaction with an already used Nonce + if sender_nonce > transaction_nonce { + Err(InvalidTransaction::Stale)?; + } + + // A transaction with a nonce higher than the expected nonce is placed in + // the future queue of the transaction pool. + if sender_nonce < transaction_nonce { + log::debug!( + "Nonce is too high. Expected: {:?}, got: {:?}. This transaction will be placed in the \ + transaction pool and executed in the future when the nonce is reached.", + sender_nonce, + transaction_nonce + ); + } + + Ok(TxPriorityInfo::RegularTxs { sender_address: tx.sender_address(), transaction_nonce, sender_nonce }) + } + UserAndL1HandlerTransaction::L1Handler(tx, _fee) => { + Self::ensure_l1_message_not_executed(&Nonce(StarkFelt::from(tx.nonce)))?; + Ok(TxPriorityInfo::L1Handler) + } + } + } + + pub fn validate_unsigned_tx(transaction: &UserAndL1HandlerTransaction) -> Result<(), InvalidTransaction> { + let chain_id = Self::chain_id(); + let block_context = Self::get_block_context(); + let mut state: BlockifierStateAdapter = BlockifierStateAdapter::::default(); + let mut execution_resources = ExecutionResources::default(); + let mut initial_gas = blockifier::abi::constants::INITIAL_GAS_COST; + + match transaction { + UserAndL1HandlerTransaction::User(transaction) => { + let validation_result = + match transaction { + // There is no way to validate it before the account is actuallly deployed + UserTransaction::DeployAccount(_) => Ok(None), + UserTransaction::Declare(tx, contract_class) => tx + .try_into_executable::(chain_id, contract_class.clone(), false) + .map_err(|_| InvalidTransaction::BadProof)? + .validate_tx(&mut state, &block_context, &mut execution_resources, &mut initial_gas, false), + UserTransaction::Invoke(tx) => tx + .into_executable::(chain_id, false) + .validate_tx(&mut state, &block_context, &mut execution_resources, &mut initial_gas, false), + }; + + if let Err(TransactionExecutionError::ValidateTransactionError( + EntryPointExecutionError::PreExecutionError(PreExecutionError::UninitializedStorageAddress( + contract_address, + )), + )) = validation_result + { + let transaction_nonce = transaction.nonce(); + let sender_address = transaction.sender_address(); + if contract_address.0.0 == sender_address.into() && transaction_nonce == Some(&Felt252Wrapper::ONE) + { + Ok(None) + } else { + validation_result + } + } else { + validation_result + } + } + UserAndL1HandlerTransaction::L1Handler(_, fee) => { + // The tx will fail if no fee have been paid + if fee.0 == 0 { + return Err(InvalidTransaction::Payment); + } + + Ok(None) + } + } + .map_err(|_| InvalidTransaction::BadProof)?; + + Ok(()) + } + + pub fn ensure_l1_message_not_executed(nonce: &Nonce) -> Result<(), InvalidTransaction> { + if L1Messages::::get().contains(nonce) { Err(InvalidTransaction::Stale) } else { Ok(()) } + } +} diff --git a/crates/primitives/messages/Cargo.toml b/crates/primitives/messages/Cargo.toml new file mode 100644 index 0000000000..32fe945d93 --- /dev/null +++ b/crates/primitives/messages/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "mp-messages" +version.workspace = true +edition.workspace = true +license = "MIT" +description = "Starknet l1-l2 messages" +authors = { workspace = true } +repository = { workspace = true } + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +mp-transactions = { workspace = true } +starknet_api = { workspace = true } + +# Optional +parity-scale-codec = { workspace = true, features = [ + "derive", +], optional = true } +scale-info = { workspace = true, features = ["derive"], optional = true } +serde = { workspace = true, optional = true } +serde_with = { workspace = true, optional = true } + +[features] +default = ["std"] +std = [ + "starknet_api/std", + "mp-transactions/std", + "parity-scale-codec?/std", + "scale-info?/std", + "serde_with?/std", + "serde?/std", +] +parity-scale-codec = [ + "dep:parity-scale-codec", + "starknet_api/parity-scale-codec", +] +scale-info = ["dep:scale-info", "starknet_api/scale-info"] +serde = ["dep:serde", "dep:serde_with"] diff --git a/crates/primitives/messages/src/conversions.rs b/crates/primitives/messages/src/conversions.rs new file mode 100644 index 0000000000..e8046b9edb --- /dev/null +++ b/crates/primitives/messages/src/conversions.rs @@ -0,0 +1,34 @@ +use mp_transactions::HandleL1MessageTransaction; +use starknet_api::api_core::{ContractAddress, EthAddress, Nonce, PatriciaKey}; +use starknet_api::hash::StarkFelt; +use starknet_api::transaction::MessageToL1; + +use crate::{MessageL1ToL2, MessageL2ToL1}; + +pub fn eth_address_to_felt(eth_address: &EthAddress) -> StarkFelt { + let mut bytes = [0u8; 32]; + // Padding H160 with zeros to 32 bytes (big endian) + bytes[12..32].copy_from_slice(eth_address.0.as_bytes()); + StarkFelt(bytes) +} + +impl From for MessageL2ToL1 { + fn from(message: MessageToL1) -> Self { + Self { from_address: message.from_address, to_address: message.to_address, payload: message.payload.0 } + } +} + +impl From for MessageL1ToL2 { + fn from(tx: HandleL1MessageTransaction) -> Self { + let mut calldata = tx.calldata; + // Source Eth address is always passed as the first calldata arg + let from_address = ContractAddress(PatriciaKey(StarkFelt::from(calldata.remove(0)))); + Self { + from_address, + to_address: tx.contract_address.into(), + nonce: Nonce(tx.nonce.into()), + selector: tx.entry_point_selector.into(), + payload: calldata.into_iter().map(|felt| felt.into()).collect(), + } + } +} diff --git a/crates/primitives/messages/src/lib.rs b/crates/primitives/messages/src/lib.rs new file mode 100644 index 0000000000..38cfe80b21 --- /dev/null +++ b/crates/primitives/messages/src/lib.rs @@ -0,0 +1,45 @@ +//! L1-L2 messages types definition +#![cfg_attr(not(feature = "std"), no_std)] + +#[doc(hidden)] +pub extern crate alloc; + +use alloc::vec::Vec; + +use starknet_api::api_core::{ContractAddress, EthAddress, Nonce}; +use starknet_api::hash::{StarkFelt, StarkHash}; + +pub mod conversions; + +#[derive(Debug, Clone, Eq, PartialEq)] +#[cfg_attr(feature = "serde", serde_with::serde_as, derive(serde::Serialize))] +#[cfg_attr(feature = "scale-info", derive(scale_info::TypeInfo))] +#[cfg_attr(feature = "parity-scale-codec", derive(parity_scale_codec::Encode, parity_scale_codec::Decode))] +pub struct MessageL2ToL1 { + /// The address of the L2 contract sending the message + #[cfg_attr(feature = "serde", serde_as(as = "UfeHex"))] + pub from_address: ContractAddress, + /// The target L1 address the message is sent to + pub to_address: EthAddress, + /// The payload of the message + #[cfg_attr(feature = "serde", serde_as(as = "Vec"))] + pub payload: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq, Default)] +#[cfg_attr(feature = "serde", serde_with::serde_as, derive(serde::Serialize))] +#[cfg_attr(feature = "scale-info", derive(scale_info::TypeInfo))] +#[cfg_attr(feature = "parity-scale-codec", derive(parity_scale_codec::Encode, parity_scale_codec::Decode))] +/// Message sent to L2 by calling Starknet smart contract on Ethereum +pub struct MessageL1ToL2 { + #[cfg_attr(feature = "serde", serde_as(as = "UfeHex"))] + pub from_address: ContractAddress, + #[cfg_attr(feature = "serde", serde_as(as = "UfeHex"))] + pub to_address: ContractAddress, + #[cfg_attr(feature = "serde", serde_as(as = "UfeHex"))] + pub nonce: Nonce, + #[cfg_attr(feature = "serde", serde_as(as = "UfeHex"))] + pub selector: StarkHash, + #[cfg_attr(feature = "serde", serde_as(as = "Vec"))] + pub payload: Vec, +} diff --git a/crates/primitives/program-hash/Cargo.toml b/crates/primitives/program-hash/Cargo.toml new file mode 100644 index 0000000000..1873eafaaa --- /dev/null +++ b/crates/primitives/program-hash/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "mp-program-hash" +version.workspace = true +edition.workspace = true +license = "MIT" +description = "Starknet program hashes" +authors = { workspace = true } +repository = { workspace = true } + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] + +# Madara Primitives +mp-felt = { workspace = true } +# Starknet dependencies +starknet-ff = { workspace = true } + +[features] +default = ["std"] +std = ["mp-felt/std"] diff --git a/crates/primitives/program-hash/src/lib.rs b/crates/primitives/program-hash/src/lib.rs new file mode 100644 index 0000000000..5ddaaf4ba1 --- /dev/null +++ b/crates/primitives/program-hash/src/lib.rs @@ -0,0 +1,19 @@ +//! Traits for Starknet OS program hash. +#![cfg_attr(not(feature = "std"), no_std)] + +use mp_felt::Felt252Wrapper; + +/// ProgramHash for Starknet OS Cairo program +/// +/// How to calculate: +/// 1. Get Starknet OS program sources (e.g. check keep-starknet-strange/snos) +/// 2. Install Cairo-lang and run `cairo-hash-program --program .json` +/// 3. Install Starkli and run `starkli mont ` +/// +/// Hex value: 0x41fc2a467ef8649580631912517edcab7674173f1dbfa2e9b64fbcd82bc4d79 +pub const SN_OS_PROGRAM_HASH: Felt252Wrapper = Felt252Wrapper(starknet_ff::FieldElement::from_mont([ + 6431315658044554931, + 6518314672963632076, + 7993178465604693533, + 95212460539797968, +])); diff --git a/crates/primitives/simulations/Cargo.toml b/crates/primitives/simulations/Cargo.toml index 8d32f10437..670f096b1e 100644 --- a/crates/primitives/simulations/Cargo.toml +++ b/crates/primitives/simulations/Cargo.toml @@ -16,6 +16,7 @@ serde_with = { workspace = true, optional = true } # Madara primitives mp-felt = { workspace = true } +mp-messages = { workspace = true } # Substrate dependencies parity-scale-codec = { workspace = true, optional = true } @@ -32,9 +33,14 @@ parity-scale-codec = [ "dep:parity-scale-codec", "starknet_api/parity-scale-codec", "mp-felt/parity-scale-codec", + "mp-messages/parity-scale-codec", +] +serde = ["dep:serde", "dep:serde_with", "mp-felt/serde", "mp-messages/serde"] +scale-info = [ + "dep:scale-info", + "starknet_api/scale-info", + "mp-messages/scale-info", ] -serde = ["dep:serde", "dep:serde_with", "mp-felt/serde"] -scale-info = ["dep:scale-info", "starknet_api/scale-info"] std = [ "mp-felt/std", "starknet_api/std", diff --git a/crates/primitives/simulations/src/lib.rs b/crates/primitives/simulations/src/lib.rs index fd12d2da2d..4b0f40519c 100644 --- a/crates/primitives/simulations/src/lib.rs +++ b/crates/primitives/simulations/src/lib.rs @@ -11,7 +11,8 @@ use blockifier::execution::entry_point::{CallInfo, OrderedL2ToL1Message}; use blockifier::transaction::errors::TransactionExecutionError; use blockifier::transaction::objects::TransactionExecutionResult; use mp_felt::{Felt252Wrapper, UfeHex}; -use starknet_api::api_core::EthAddress; +use mp_messages::MessageL2ToL1; +use starknet_api::api_core::{ContractAddress, PatriciaKey}; use starknet_api::deprecated_contract_class::EntryPointType; use starknet_api::transaction::EventContent; @@ -138,22 +139,6 @@ pub struct L1HandlerTransactionTrace { pub function_invocation: FunctionInvocation, } -#[serde_with::serde_as] -#[derive(Debug, Clone)] -#[cfg_attr(feature = "parity-scale-codec", derive(parity_scale_codec::Encode, parity_scale_codec::Decode))] -#[cfg_attr(feature = "scale-info", derive(scale_info::TypeInfo))] -#[cfg_attr(feature = "serde", derive(serde::Serialize))] -pub struct MessageToL1 { - /// The address of the L2 contract sending the message - #[serde_as(as = "UfeHex")] - pub from_address: Felt252Wrapper, - /// The target L1 address the message is sent to - pub to_address: EthAddress, - /// The payload of the message - #[serde_as(as = "Vec")] - pub payload: Vec, -} - #[serde_with::serde_as] #[derive(Debug, Clone)] #[cfg_attr(feature = "parity-scale-codec", derive(parity_scale_codec::Encode, parity_scale_codec::Decode))] @@ -185,7 +170,7 @@ pub struct FunctionInvocation { /// The events emitted in this invocation pub events: Vec, /// The messages sent by this invocation to L1 - pub messages: Vec, + pub messages: Vec, } impl TryFrom<&CallInfo> for FunctionInvocation { @@ -218,17 +203,17 @@ impl TryFrom<&CallInfo> for FunctionInvocation { } } -fn ordered_l2_to_l1_messages(call_info: &CallInfo) -> Vec { +fn ordered_l2_to_l1_messages(call_info: &CallInfo) -> Vec { let mut messages = BTreeMap::new(); for call in call_info.into_iter() { for OrderedL2ToL1Message { order, message } in &call.execution.l2_to_l1_messages { messages.insert( order, - MessageToL1 { - payload: message.payload.0.iter().map(|x| (*x).into()).collect(), + MessageL2ToL1 { + payload: message.payload.0.to_vec(), to_address: message.to_address, - from_address: call.call.storage_address.0.0.into(), + from_address: ContractAddress(PatriciaKey(call.call.storage_address.0.0)), }, ); } diff --git a/crates/primitives/snos-output/Cargo.toml b/crates/primitives/snos-output/Cargo.toml new file mode 100644 index 0000000000..e9799da44a --- /dev/null +++ b/crates/primitives/snos-output/Cargo.toml @@ -0,0 +1,42 @@ +[package] +name = "mp-snos-output" +version.workspace = true +edition.workspace = true +license = "MIT" +description = "Primitives for Starknet OS output" +authors = { workspace = true } +repository = { workspace = true } + +[dependencies] +mp-messages = { workspace = true } +mp-transactions = { workspace = true } +parity-scale-codec = { workspace = true, features = [ + "derive", +], optional = true } +scale-info = { workspace = true, features = ["derive"], optional = true } +sp-core = { workspace = true } +starknet_api = { workspace = true } + +[dev-dependencies] +pretty_assertions = { workspace = true } +assert_matches = "1.5.0" +hex = "*" + +[features] +default = ["std"] +std = [ + "parity-scale-codec/std", + "mp-transactions/std", + "mp-messages/std", + "starknet_api/std", +] +parity-scale-codec = [ + "dep:parity-scale-codec", + "starknet_api/parity-scale-codec", + "mp-messages/parity-scale-codec", +] +scale-info = [ + "dep:scale-info", + "starknet_api/scale-info", + "mp-messages/scale-info", +] diff --git a/crates/primitives/snos-output/src/codec.rs b/crates/primitives/snos-output/src/codec.rs new file mode 100644 index 0000000000..adc0b923ed --- /dev/null +++ b/crates/primitives/snos-output/src/codec.rs @@ -0,0 +1,208 @@ +use alloc::vec::Vec; + +use mp_messages::conversions::eth_address_to_felt; +use mp_messages::{MessageL1ToL2, MessageL2ToL1}; +use starknet_api::api_core::{ContractAddress, EthAddress, Nonce, PatriciaKey}; +use starknet_api::hash::StarkFelt; + +use crate::felt_reader::{FeltReader, FeltReaderError}; +use crate::StarknetOsOutput; + +/// This codec allows to convert structured OS program output into array of felts +/// +/// In order to prepare parameters for the Starknet contract `updateState` method: +/// 1. Cast the output to dynamic uint256[] array +/// 2. Get onchain data hash & size +/// 3. ABI encode parameters +/// +/// NOTE: Field element (252 bit) is encoded as an EVM word (256 bit) and vice versa +/// EVM developer should be aware of that and prevent data loss by not using the higest 4 bits +pub trait SnosCodec: Sized { + /// Return an estimation of the number of field elements required to encode `self` + /// + /// This is to be used for allocating the correct amount of memory before encoding. + /// It's for optimization purpose (avoiding reallocation) so it's implementation should be + /// efficient (no iteration, no IO, no other allocation, no expensive + fn size_in_felts(&self) -> usize; + /// Encodes current snos output field as felt array and appends to the result + fn encode_to(self, output: &mut Vec); + /// Tries to decode snos output field given a felt reader instance + fn decode(input: &mut FeltReader) -> Result; + /// Converts structured snos program output into array of field elements + fn into_encoded_vec(self) -> Vec { + let mut output: Vec = Vec::with_capacity(self.size_in_felts()); + self.encode_to(&mut output); + output + } +} + +impl SnosCodec for StarkFelt { + fn size_in_felts(&self) -> usize { + 1 + } + + fn encode_to(self, output: &mut Vec) { + output.push(self); + } + + fn decode(input: &mut FeltReader) -> Result { + input.read() + } +} + +impl SnosCodec for ContractAddress { + fn size_in_felts(&self) -> usize { + 1 + } + + fn encode_to(self, output: &mut Vec) { + output.push(self.0.0); + } + + fn decode(input: &mut FeltReader) -> Result { + Ok(ContractAddress(PatriciaKey(StarkFelt::decode(input)?))) + } +} + +impl SnosCodec for EthAddress { + fn size_in_felts(&self) -> usize { + 1 + } + + fn encode_to(self, output: &mut Vec) { + output.push(eth_address_to_felt(&self)); + } + + fn decode(input: &mut FeltReader) -> Result { + StarkFelt::decode(input)?.try_into().map_err(|_| FeltReaderError::InvalidCast) + } +} + +impl SnosCodec for Nonce { + fn size_in_felts(&self) -> usize { + 1 + } + + fn encode_to(self, output: &mut Vec) { + output.push(self.0); + } + + fn decode(input: &mut FeltReader) -> Result { + Ok(Nonce(StarkFelt::decode(input)?)) + } +} + +impl SnosCodec for Vec { + fn size_in_felts(&self) -> usize { + // Works well for Vec + // Works less well for Vec, but it just means there will be some realocation + // Nothing terrible, and still better than iterating + 1 + self.len() + } + + fn encode_to(self, output: &mut Vec) { + // Temporary placeholder value + output.push(StarkFelt::from(0u8)); + + let output_len_before = output.len(); + + for elt in self.into_iter() { + elt.encode_to(output); + } + + let added_data = output.len() - output_len_before; + // Replace the zero placeholder + output[output_len_before - 1] = StarkFelt::from(added_data as u64); + } + + fn decode(input: &mut FeltReader) -> Result { + let mut segment_reader = FeltReader::new(input.read_segment()?); + let mut elements: Vec = Vec::new(); + while segment_reader.remaining_len() > 0 { + elements.push(T::decode(&mut segment_reader)?); + } + Ok(elements) + } +} + +impl SnosCodec for MessageL2ToL1 { + fn size_in_felts(&self) -> usize { + self.from_address.size_in_felts() + self.to_address.size_in_felts() + self.payload.size_in_felts() + } + + fn encode_to(self, output: &mut Vec) { + self.from_address.encode_to(output); + self.to_address.encode_to(output); + self.payload.encode_to(output); + } + + fn decode(input: &mut FeltReader) -> Result { + Ok(Self { + from_address: ContractAddress::decode(input)?, + to_address: EthAddress::decode(input)?, + payload: Vec::::decode(input)?, + }) + } +} + +impl SnosCodec for MessageL1ToL2 { + fn size_in_felts(&self) -> usize { + self.from_address.size_in_felts() + + self.to_address.size_in_felts() + + self.nonce.size_in_felts() + + self.selector.size_in_felts() + + self.payload.size_in_felts() + } + + fn encode_to(self, output: &mut Vec) { + self.from_address.encode_to(output); + self.to_address.encode_to(output); + self.nonce.encode_to(output); + self.selector.encode_to(output); + self.payload.encode_to(output); + } + + fn decode(input: &mut FeltReader) -> Result { + Ok(Self { + from_address: ContractAddress::decode(input)?, + to_address: ContractAddress::decode(input)?, + nonce: Nonce::decode(input)?, + selector: StarkFelt::decode(input)?, + payload: Vec::::decode(input)?, + }) + } +} + +impl SnosCodec for StarknetOsOutput { + fn size_in_felts(&self) -> usize { + self.prev_state_root.size_in_felts() + + self.new_state_root.size_in_felts() + + self.block_number.size_in_felts() + + self.block_hash.size_in_felts() + + self.config_hash.size_in_felts() + + self.messages_to_l1.size_in_felts() + + self.messages_to_l2.size_in_felts() + } + + fn encode_to(self, output: &mut Vec) { + self.prev_state_root.encode_to(output); + self.new_state_root.encode_to(output); + self.block_number.encode_to(output); + self.block_hash.encode_to(output); + self.config_hash.encode_to(output); + self.messages_to_l1.encode_to(output); + self.messages_to_l2.encode_to(output); + } + + fn decode(input: &mut FeltReader) -> Result { + Ok(Self { + prev_state_root: StarkFelt::decode(input)?, + new_state_root: StarkFelt::decode(input)?, + block_number: StarkFelt::decode(input)?, + block_hash: StarkFelt::decode(input)?, + config_hash: StarkFelt::decode(input)?, + messages_to_l1: Vec::::decode(input)?, + messages_to_l2: Vec::::decode(input)?, + }) + } +} diff --git a/crates/primitives/snos-output/src/felt_reader.rs b/crates/primitives/snos-output/src/felt_reader.rs new file mode 100644 index 0000000000..67160e4960 --- /dev/null +++ b/crates/primitives/snos-output/src/felt_reader.rs @@ -0,0 +1,67 @@ +use starknet_api::hash::StarkFelt; + +/// Error that may occur while reading felt array +#[derive(Clone, Debug)] +pub enum FeltReaderError { + /// Reader reached the end of felt array + OutOfBounds, + /// Reader failed to cast felt to the target type + InvalidCast, +} + +#[cfg(feature = "std")] +impl std::error::Error for FeltReaderError {} + +impl core::fmt::Display for FeltReaderError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + FeltReaderError::OutOfBounds => write!(f, "Reader reached the end of felt array"), + FeltReaderError::InvalidCast => write!(f, "Reader failed to cast felt to the target type"), + } + } +} + +/// Analogue of std::io::Cursor but for field elements. +/// Allows to sequentially read felts and felt segments given a reference to a felt array. +/// +/// Felt segment is sub sequence of field elements within the original felt array. +/// Felt segments can be recursively embedded. +/// Felt segment is preceded by its size also encoded as felt, not included in segment size. +pub struct FeltReader<'a> { + data: &'a [StarkFelt], + offset: usize, +} + +impl<'a> FeltReader<'a> { + pub fn new(data: &'a [StarkFelt]) -> Self { + Self { data, offset: 0 } + } + + pub fn remaining_len(&self) -> usize { + self.data.len() - self.offset + } + + pub fn read(&mut self) -> Result { + if self.offset >= self.data.len() { + return Err(FeltReaderError::OutOfBounds); + } + + let res = self.data[self.offset]; + self.offset += 1; + + Ok(res) + } + + pub fn read_segment(&mut self) -> Result<&'a [StarkFelt], FeltReaderError> { + let segment_size = TryInto::::try_into(self.read()?).map_err(|_| FeltReaderError::InvalidCast)? as usize; + let start = self.offset; + + if start + segment_size > self.data.len() { + return Err(FeltReaderError::OutOfBounds); + } + + self.offset += segment_size; + + Ok(&self.data[start..start + segment_size]) + } +} diff --git a/crates/primitives/snos-output/src/lib.rs b/crates/primitives/snos-output/src/lib.rs new file mode 100644 index 0000000000..c53e4e8a5b --- /dev/null +++ b/crates/primitives/snos-output/src/lib.rs @@ -0,0 +1,39 @@ +//! StarkNet OS program output primitives. +#![cfg_attr(not(feature = "std"), no_std)] + +#[doc(hidden)] +pub extern crate alloc; + +mod codec; +mod felt_reader; + +#[cfg(test)] +mod tests; + +use alloc::vec::Vec; + +use mp_messages::{MessageL1ToL2, MessageL2ToL1}; +use starknet_api::hash::StarkFelt; + +pub use crate::codec::SnosCodec; + +#[derive(Clone, Debug, PartialEq, Eq, Default)] +#[cfg_attr(feature = "scale-info", derive(scale_info::TypeInfo))] +#[cfg_attr(feature = "parity-scale-codec", derive(parity_scale_codec::Encode, parity_scale_codec::Decode))] +/// Main part of Starknet OS program output +pub struct StarknetOsOutput { + /// The state commitment before this block. + pub prev_state_root: StarkFelt, + /// The state commitment after this block. + pub new_state_root: StarkFelt, + /// The number (height) of this block. + pub block_number: StarkFelt, + /// The hash of this block. + pub block_hash: StarkFelt, + /// The Starknet chain config hash + pub config_hash: StarkFelt, + /// List of messages sent to L1 in this block + pub messages_to_l1: Vec, + /// List of messages from L1 handled in this block + pub messages_to_l2: Vec, +} diff --git a/crates/primitives/snos-output/src/tests.rs b/crates/primitives/snos-output/src/tests.rs new file mode 100644 index 0000000000..cf0e4ed05d --- /dev/null +++ b/crates/primitives/snos-output/src/tests.rs @@ -0,0 +1,61 @@ +use mp_messages::conversions::eth_address_to_felt; +use starknet_api::api_core::EthAddress; +use starknet_api::hash::StarkFelt; + +use crate::codec::SnosCodec; +use crate::felt_reader::FeltReader; +use crate::StarknetOsOutput; + +// Starknet::update_state sample invocation from mainnet +// https://etherscan.io/tx/0x9a6f9ee53f0b558f466d4340613740b9483e10c230313aa9c31fd0ba80f1a40f +// +// Calldata: +// "0x0000000000000000000000000000000000000000000000000000000000000060", programOutput offset (96 +// bytes) "0x64f464be0437d366556e4fe7cfc0fc8d2eec0ed531050137ca44052de9c97219", onchainDataHash +// "0x0000000000000000000000000000000000000000000000000000000000000816", onchainDataSize +// "0x0000000000000000000000000000000000000000000000000000000000000016", programOutput length +const SNOS_PROGRAM_OUTPUT_HEX: &str = "\ + 00bf8721ac2af6f7f40155c973c2bf5c15b7e0ed790b0865af20bf25ab57e9ff\ + 03d46b43f31ccfed7ce09a0e318f1f98f59b28f4527ea01de34382ab8c7f2a26\ + 00000000000000000000000000000000000000000000000000000000000441ee\ + 0770ab05ba02edc49516cebde84bbffb76da74cdc98fd142c9c703ab871c4c7a\ + 017c0bc29d31e9a7d14671610a7626264ce9ce8e3ed066a4775adf9b123de9dd\ + 0000000000000000000000000000000000000000000000000000000000000007\ + 073314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82\ + 000000000000000000000000ae0ee0a63a2ce6baeeffe56e7714fb4efe48d419\ + 0000000000000000000000000000000000000000000000000000000000000004\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000def47ac573dd080526c2e6dd3bc8b4d66e9c6a77\ + 00000000000000000000000000000000000000000000000000009184e72a0000\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000008\ + 000000000000000000000000ae0ee0a63a2ce6baeeffe56e7714fb4efe48d419\ + 073314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82\ + 000000000000000000000000000000000000000000000000000000000014de2c\ + 02d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5\ + 0000000000000000000000000000000000000000000000000000000000000003\ + 015342c9b50c5eed063ef19efb9a57ad10c30d1d39f1f1977f48bcc7199e91e0\ + 0000000000000000000000000000000000000000000000000429d069189e0000\ + 0000000000000000000000000000000000000000000000000000000000000000"; + +#[test] +fn test_snos_output_codec() { + let output_bytes = hex::decode(SNOS_PROGRAM_OUTPUT_HEX).unwrap(); + let output: Vec = output_bytes.chunks(32).map(|chunk| StarkFelt(chunk.try_into().unwrap())).collect(); + let mut reader = FeltReader::new(&output); + + let snos_output = StarknetOsOutput::decode(&mut reader).unwrap(); + + let mut actual: Vec = Vec::new(); + snos_output.into_encoded_vec().into_iter().for_each(|felt| actual.extend_from_slice(felt.0.as_slice())); + + pretty_assertions::assert_eq!(output_bytes, actual); +} + +#[test] +fn test_eth_address_cast() { + let felt = StarkFelt::try_from("0x000000000000000000000000ae0ee0a63a2ce6baeeffe56e7714fb4efe48d419").unwrap(); + let eth_address = EthAddress::try_from(felt).unwrap(); + let actual = eth_address_to_felt(ð_address); + assert_eq!(felt, actual); +} diff --git a/crates/primitives/transactions/src/execution.rs b/crates/primitives/transactions/src/execution.rs index e2f81fb200..05998addda 100644 --- a/crates/primitives/transactions/src/execution.rs +++ b/crates/primitives/transactions/src/execution.rs @@ -571,6 +571,10 @@ impl Execute for DeployAccountTransaction { } } +impl Validate for L1HandlerTransaction { + const VALIDATE_TX_ENTRY_POINT_NAME: &'static str = VALIDATE_ENTRY_POINT_NAME; +} + impl Execute for L1HandlerTransaction { fn execute_inner( &self, diff --git a/crates/runtime/Cargo.toml b/crates/runtime/Cargo.toml index 033419578c..2428aa2a56 100644 --- a/crates/runtime/Cargo.toml +++ b/crates/runtime/Cargo.toml @@ -53,9 +53,11 @@ pallet-starknet = { workspace = true } pallet-starknet-runtime-api = { workspace = true } # Madara Primitives +mp-block = { workspace = true } mp-chain-id = { workspace = true } mp-felt = { workspace = true } mp-hashers = { workspace = true } +mp-program-hash = { workspace = true } mp-simulations = { workspace = true } mp-transactions = { workspace = true } # Starknet dependencies diff --git a/crates/runtime/src/lib.rs b/crates/runtime/src/lib.rs index ad532dff92..cd7d883315 100644 --- a/crates/runtime/src/lib.rs +++ b/crates/runtime/src/lib.rs @@ -30,7 +30,7 @@ use frame_system::{EventRecord, Phase}; use mp_felt::Felt252Wrapper; use mp_simulations::{SimulatedTransaction, SimulationFlags}; use mp_transactions::compute_hash::ComputeTransactionHash; -use mp_transactions::{Transaction, UserTransaction}; +use mp_transactions::{HandleL1MessageTransaction, Transaction, UserTransaction}; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; /// Import the Starknet pallet. pub use pallet_starknet; @@ -54,7 +54,7 @@ use sp_version::RuntimeVersion; use starknet_api::api_core::{ClassHash, ContractAddress, EntryPointSelector, Nonce}; use starknet_api::hash::StarkFelt; use starknet_api::state::StorageKey; -use starknet_api::transaction::{Calldata, Event as StarknetEvent, TransactionHash}; +use starknet_api::transaction::{Calldata, Event as StarknetEvent, Fee, MessageToL1, TransactionHash}; /// Import the types. pub use types::*; @@ -259,6 +259,14 @@ impl_runtime_apis! { Starknet::chain_id() } + fn program_hash() -> Felt252Wrapper { + Starknet::program_hash() + } + + fn fee_token_address() -> ContractAddress { + Starknet::fee_token_address() + } + fn is_transaction_fee_disabled() -> bool { Starknet::is_transaction_fee_disabled() } @@ -363,17 +371,25 @@ impl_runtime_apis! { Some(events) } + fn get_tx_messages_to_l1(tx_hash: TransactionHash) -> Vec { + Starknet::tx_messages(tx_hash) + } + fn get_tx_execution_outcome(tx_hash: TransactionHash) -> Option> { - Starknet::tx_revert_error(tx_hash).map(|s| s.into_bytes()) + Starknet::tx_revert_error(tx_hash).map(|s| s.into_bytes()) } fn get_block_context() -> pallet_starknet_runtime_api::BlockContext { Starknet::get_block_context().into() } + + fn l1_nonce_unused(nonce: Nonce) -> bool { + Starknet::ensure_l1_message_not_executed(&nonce).is_ok() + } } impl pallet_starknet_runtime_api::ConvertTransactionRuntimeApi for Runtime { - fn convert_transaction(transaction: UserTransaction) -> Result { + fn convert_transaction(transaction: UserTransaction) -> UncheckedExtrinsic { let call = match transaction { UserTransaction::Declare(tx, contract_class) => { pallet_starknet::Call::declare { transaction: tx, contract_class } @@ -386,7 +402,13 @@ impl_runtime_apis! { } }; - Ok(UncheckedExtrinsic::new_unsigned(call.into())) + UncheckedExtrinsic::new_unsigned(call.into()) + } + + fn convert_l1_transaction(transaction: HandleL1MessageTransaction, fee: Fee) -> UncheckedExtrinsic { + let call = pallet_starknet::Call::::consume_l1_message { transaction, paid_fee_on_l1: fee }; + + UncheckedExtrinsic::new_unsigned(call.into()) } fn convert_error(error: DispatchError) -> StarknetTransactionExecutionError { diff --git a/crates/runtime/src/pallets.rs b/crates/runtime/src/pallets.rs index ecb4c1dcc2..12a57d6ace 100644 --- a/crates/runtime/src/pallets.rs +++ b/crates/runtime/src/pallets.rs @@ -11,7 +11,8 @@ pub use frame_support::weights::{IdentityFee, Weight}; pub use frame_support::{construct_runtime, parameter_types, StorageValue}; pub use frame_system::Call as SystemCall; pub use mp_chain_id::SN_GOERLI_CHAIN_ID; -/// Import the Starknet pallet. +pub use mp_program_hash::SN_OS_PROGRAM_HASH; +/// Import the StarkNet pallet. pub use pallet_starknet; pub use pallet_timestamp::Call as TimestampCall; use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -46,6 +47,7 @@ impl pallet_starknet::Config for Runtime { type ProtocolVersion = ProtocolVersion; type ChainId = ChainId; type MaxRecursionDepth = MaxRecursionDepth; + type ProgramHash = ProgramHash; } /// -------------------------------------- @@ -159,6 +161,7 @@ parameter_types! { pub const ProtocolVersion: u8 = 0; pub const ChainId: Felt252Wrapper = SN_GOERLI_CHAIN_ID; pub const MaxRecursionDepth: u32 = 50; + pub const ProgramHash: Felt252Wrapper = SN_OS_PROGRAM_HASH; } /// Implement the OnTimestampSet trait to override the default Aura. diff --git a/docs/genesis.md b/docs/genesis.md index 41a6f967d7..0e402097a6 100644 --- a/docs/genesis.md +++ b/docs/genesis.md @@ -39,7 +39,7 @@ The below defines all hardcoded values set in the geneses: | 0x07db5c2c2676c2a5bfc892ee4f596b49514e3056a0eee8ad125870b4fb1dd909 | Braavos account call aggregator class hash | | 0x3131fa018d520a037686ce3efddeab8f28895662f019ca3ca18a626650f7d1e | Proxy class hash | | 0x006280083f8c2a2db9f737320d5e3029b380e0e820fe24b8d312a6a34fdba0cd | Openzeppelin account class hash | -| 0x05a2b92d9a36509a3d651e7df99144a4ad8301e2caf42465ee6ab0451ae91882 | Test contract class hash | +| 0x04c5efa8dc6f0554da51f125d04e379ac41153a8b837391083a8dc3771a33388 | Test contract class hash | | 0x0372ee6669dc86563007245ed7343d5180b96221ce28f44408cff2898038dbd4 | ERC20 class hash | | 0x077cc28ed3c661419fda16bf120fb81f1f8f28617f5543b05a86d63b0926bbf4 | ERC721 class hash | | 0x04569ffd48c2a3d455437c16dc843801fb896b1af845bc8bc7ba83ebc4358b7f | Universal deployer class hash | @@ -76,7 +76,7 @@ where `pk` is the following vector of `u8`: | 0x2 | 0x06f0d6f6ae72e1a507ff4b65181291642889742dbf8f1a53e9ec1c595d01ba7d | | 0x3 | 0x006280083f8c2a2db9f737320d5e3029b380e0e820fe24b8d312a6a34fdba0cd | | 0x4 | 0x35ccefcf9d5656da623468e27e682271cd327af196785df99e7fee1436b6276 | -| 0x1111 | 0x05a2b92d9a36509a3d651e7df99144a4ad8301e2caf42465ee6ab0451ae91882 | +| 0x1111 | 0x04c5efa8dc6f0554da51f125d04e379ac41153a8b837391083a8dc3771a33388 | | 0x040e59c2c182a58fb0a74349bfa4769cbbcba32547591dd3fb1def8623997d00 | 0x0372ee6669dc86563007245ed7343d5180b96221ce28f44408cff2898038dbd4 | | 0x040e59c2c182a58fb0a74349bfa4769cbbcba32547591dd3fb1def8623997d02 | 0x077cc28ed3c661419fda16bf120fb81f1f8f28617f5543b05a86d63b0926bbf4 | | 0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7 | 0x0372ee6669dc86563007245ed7343d5180b96221ce28f44408cff2898038dbd4 | diff --git a/examples/messaging/l1-messaging-config.json b/examples/messaging/l1-messaging-config.json new file mode 100644 index 0000000000..fa84e504dc --- /dev/null +++ b/examples/messaging/l1-messaging-config.json @@ -0,0 +1,4 @@ +{ + "httpProvider": "http://127.0.0.1:8545", + "contractAddress": "0x5fbdb2315678afecb367f032d93f642f64180aa3" +} diff --git a/madara-infra b/madara-infra index d14adc999f..f95ec194ac 160000 --- a/madara-infra +++ b/madara-infra @@ -1 +1 @@ -Subproject commit d14adc999fe37ae0495459edba7e226f8841815f +Subproject commit f95ec194acc51a8592798f4e6c781ee1c11580b0 diff --git a/madara-test-runner/Cargo.toml b/madara-test-runner/Cargo.toml new file mode 100644 index 0000000000..e01e0332fc --- /dev/null +++ b/madara-test-runner/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "madara-test-runner" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "1.0.72" +assert_matches = "1.5.0" +async-lock = "3.1.0" +async-trait = "0.1" +derive_more = "0.99.17" +flate2 = { workspace = true } +lazy_static = "1.4.0" +reqwest = "0.11.18" +rstest = "0.18.1" +serde = { version = "1.0.179", features = ["derive"] } +serde_json = "1.0.107" +starknet-accounts = { workspace = true } +starknet-contract = { workspace = true } +starknet-core = { workspace = true } +starknet-crypto = { workspace = true } +starknet-ff = { workspace = true } +starknet-providers = { workspace = true } +starknet-signers = { workspace = true } +starknet_api = { workspace = true, default-features = true } +thiserror = { workspace = true } +tokio = { version = "1.29.1", features = ["rt", "macros", "parking_lot"] } +url = "2.4.1" + +# Temporary dependency +starknet-rpc-test = { path = "../starknet-rpc-test" } diff --git a/madara-test-runner/src/client.rs b/madara-test-runner/src/client.rs new file mode 100644 index 0000000000..3acc3374a3 --- /dev/null +++ b/madara-test-runner/src/client.rs @@ -0,0 +1,2 @@ +// TODO: refactor starknet-rpc-test +pub use starknet_rpc_test::MadaraClient; diff --git a/madara-test-runner/src/lib.rs b/madara-test-runner/src/lib.rs new file mode 100644 index 0000000000..b4f2b74522 --- /dev/null +++ b/madara-test-runner/src/lib.rs @@ -0,0 +1,70 @@ +pub mod client; +pub mod node; + +use std::ops::{Deref, DerefMut}; +use std::path::PathBuf; + +use derive_more::Display; +use lazy_static::lazy_static; +use tokio::sync::Mutex; + +use crate::client::MadaraClient; +use crate::node::MadaraNode; + +lazy_static! { + /// This is to prevent TOCTOU errors; i.e. one background madara node might find one + /// port to be free, and while it's trying to start listening to it, another instance + /// finds that it's free and tries occupying it + /// Using the mutex in `get_free_port_listener` might be safer than using no mutex at all, + /// but not sufficiently safe + static ref FREE_PORT_ATTRIBUTION_MUTEX: Mutex<()> = Mutex::new(()); +} + +#[derive(Display, Clone)] +pub enum Settlement { + Ethereum, +} + +pub struct MadaraRunner { + _node: MadaraNode, + client: MadaraClient, +} + +impl MadaraRunner { + pub async fn new(settlement: Option, base_path: Option) -> Self { + // we keep the reference, otherwise the mutex unlocks immediately + let _mutex_guard = FREE_PORT_ATTRIBUTION_MUTEX.lock().await; + + let mut node = MadaraNode::run(settlement, base_path); + let client = MadaraClient::new(node.url()); + + // Wait until node is ready + loop { + // Check if there are no build / launch issues + if let Some(status) = node.has_exited() { + panic!("Madara node exited early with {}", status) + } + + match client.health().await { + Ok(is_ready) if is_ready => break, + _ => {} + } + } + + Self { _node: node, client } + } +} + +impl Deref for MadaraRunner { + type Target = MadaraClient; + + fn deref(&self) -> &Self::Target { + &self.client + } +} + +impl DerefMut for MadaraRunner { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.client + } +} diff --git a/madara-test-runner/src/node.rs b/madara-test-runner/src/node.rs new file mode 100644 index 0000000000..344a4d779d --- /dev/null +++ b/madara-test-runner/src/node.rs @@ -0,0 +1,119 @@ +use std::env; +use std::fmt::Debug; +use std::fs::{create_dir_all, File}; +use std::net::TcpListener; +use std::path::{Path, PathBuf}; +use std::process::{Child, Command, ExitStatus, Stdio}; +use std::str::FromStr; + +use url::Url; + +use crate::Settlement; + +const MIN_PORT: u16 = 49_152; +const MAX_PORT: u16 = 65_535; + +#[derive(Debug)] +/// A wrapper over the Madara process handle, reqwest client and request counter +/// +/// When this struct goes out of scope, it's `Drop` impl +/// will take care of killing the Madara process. +pub struct MadaraNode { + process: Child, + port: u16, +} + +impl Drop for MadaraNode { + fn drop(&mut self) { + if let Err(e) = self.process.kill() { + eprintln!("Could not kill Madara process: {}", e) + } + } +} + +fn get_free_port() -> u16 { + for port in MIN_PORT..=MAX_PORT { + if let Ok(listener) = TcpListener::bind(("127.0.0.1", port)) { + return listener.local_addr().expect("No local addr").port(); + } + // otherwise port is occupied + } + panic!("No free ports available"); +} + +fn get_repository_root() -> PathBuf { + let manifest_path = Path::new(&env!("CARGO_MANIFEST_DIR")); + let repository_root = manifest_path.parent().expect("Failed to get parent directory of CARGO_MANIFEST_DIR"); + repository_root.to_path_buf() +} + +impl MadaraNode { + /// Run the Madara node + /// + /// The node is run in `release` mode. + /// Parameters to the node can be passed with the `params` argument. + fn cargo_run(root_dir: &Path, params: Vec<&str>) -> Child { + let arguments = [vec!["run".into(), "--release", "--"], params].concat(); + + let (stdout, stderr) = if env::var("MADARA_LOG").is_ok() { + let logs_dir = Path::join(root_dir, Path::new("target/madara-log")); + create_dir_all(logs_dir.clone()).expect("Failed to create logs dir"); + ( + Stdio::from(File::create(Path::join(&logs_dir, Path::new("madara-stdout-log.txt"))).unwrap()), + Stdio::from(File::create(Path::join(&logs_dir, Path::new("madara-stderr-log.txt"))).unwrap()), + ) + } else { + (Stdio::null(), Stdio::null()) + }; + + Command::new("cargo").stdout(stdout).stderr(stderr).args(arguments).spawn().expect("Could not run Madara node") + } + + pub fn run(settlement: Option, base_path: Option) -> Self { + let port = get_free_port(); + let repository_root = &get_repository_root(); + + std::env::set_current_dir(repository_root).expect("Failed to change working directory"); + + let base_path_arg = base_path.map(|arg| format!("--base-path={}", arg.display())); + let settlement_arg = settlement.map(|arg| format!("--settlement={arg}")); + let rpc_port_arg = format!("--rpc-port={port}"); + let chain_arg = format!("--chain=dev"); + let from_local_arg = format!("--from-local={}", repository_root.join("configs").display()); + + // Codeblock to drop `setup_args` and be able to borrow again for `run_args` + { + let mut setup_args = vec!["setup", &chain_arg, &from_local_arg]; + if let Some(bp) = &base_path_arg { + setup_args.push(bp); + }; + + let setup_res = + Self::cargo_run(repository_root.as_path(), setup_args).wait().expect("Failed to setup Madara node"); + + if !setup_res.success() { + panic!("Madara setup failed with {} (check out stderr logs)", setup_res.to_string()); + } + } + + let mut run_args = vec!["--alice", "--sealing=manual", &chain_arg, &rpc_port_arg]; + if let Some(bp) = &base_path_arg { + run_args.push(bp); + }; + if let Some(s) = &settlement_arg { + run_args.push(s); + }; + + let process = Self::cargo_run(repository_root.as_path(), run_args); + + Self { process, port } + } + + pub fn url(&self) -> Url { + Url::from_str(&format!("http://127.0.0.1:{}", self.port)).unwrap() + } + + pub fn has_exited(&mut self) -> Option { + self.process.try_wait().expect("Failed to get Madara node exit status") + } +} diff --git a/madara-zaun b/madara-zaun new file mode 160000 index 0000000000..2b431a94c1 --- /dev/null +++ b/madara-zaun @@ -0,0 +1 @@ +Subproject commit 2b431a94c194ad2efe62051811224c15e9196556 diff --git a/starknet-e2e-test/Cargo.toml b/starknet-e2e-test/Cargo.toml new file mode 100644 index 0000000000..3dc840e259 --- /dev/null +++ b/starknet-e2e-test/Cargo.toml @@ -0,0 +1,47 @@ +[package] +name = "starknet-e2e-test" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "1.0.72" +assert_matches = "1.5.0" +async-trait = "0.1" +ethers = { workspace = true } +ethers-solc = { workspace = true } +flate2 = { workspace = true } +home = "0.5.5" +reqwest = "0.11.18" +rstest = "0.18.1" +serde = { version = "1.0.179", features = ["derive"] } +serde_json = "1.0.107" +tempdir = "0.3.7" +test-context = "0.1.3" +thiserror = { workspace = true } +tokio = { version = "1.29.1", features = ["rt", "macros", "parking_lot"] } +url = "2.4.1" + +# Starknet +starknet-accounts = { workspace = true } +starknet-contract = { workspace = true } +starknet-core = { workspace = true } +starknet-crypto = { workspace = true } +starknet-ff = { workspace = true } +starknet-providers = { workspace = true } +starknet-signers = { workspace = true } +starknet_api = { workspace = true, default-features = true } + +# Madara +madara-runtime = { workspace = true } +madara-test-runner = { workspace = true } +mc-settlement = { workspace = true } +mp-messages = { workspace = true } +mp-snos-output = { workspace = true } + +[[test]] +name = "ethereum_core_contract" +path = "ethereum_core_contract.rs" + +[[test]] +name = "ethereum_e2e_settlement" +path = "ethereum_e2e_settlement.rs" diff --git a/starknet-e2e-test/README.md b/starknet-e2e-test/README.md new file mode 100644 index 0000000000..40b44f73e3 --- /dev/null +++ b/starknet-e2e-test/README.md @@ -0,0 +1,121 @@ +# Integration tests + +This crate contains integration tests run against a fully-fledged Madara node. + +In order to run all tests: + +```shell +cargo test --package starknet-e2e-test -- --nocapture +``` + +In order to run a specific test case: + +```shell +cargo test --package starknet-e2e-test -- --nocapture +``` + +## Madara runner + +Sometimes you might want more control over the launched node. Here is how you +can instantiate Madara runner which will run a node and provide you with a +client: + +```rust +use madara_test_runner::{MadaraRunner, Settlement}; + +let madara_client = MadaraRunner::new( + Some(Settlement::Ethereum), + Some(format!("/tmp/madara").into()), +) +.await; +``` + +Available arguments: + +- `settlement` [Optional] - which settlement layer to use (can be + `Settlement::Ethereum` for now) +- `base_path` [Optional] - override Madara base path which is used for storing + configs and other assets + +Note that DA & settlement configs are expected to be stored in "data path" which +is `base_path/chains/` (for tests it's `dev`). + +## Logging + +When you run integration tests for the first time, cargo needs to build the +Madara binary first - it takes some time (depending on your h/w) and you might +see " has been running for over 60 seconds" in your console +which is fine and it will eventually terminate. + +However, if there are some building or launch errors, the process will stuck +(under the hood it will try to reconnect to the node, but the node fails to +start). In order to troubleshoot such issues you can enable Madara logs. Simply +run tests with `MADARA_LOG` environment variable set: + +```shell +MADARA_LOG=1 cargo test --package starknet-rpc-test -- --nocapture +``` + +The logs will be available at: + +- `/target/madara-log/madara-stderr-log.txt` +- `/target/madara-log/madara-stdout-log.txt` + +It can also be helpful if you want to troubleshoot some issue with debug/trace +logs. + +## Parallel instances + +Note that cargo might run tests in parallel meaning that there can be multiple +running Madara instance at a single point of time. In order to avoid concurrent +access to e.g. config files you can override Madara base path and use unique +temporary directories for each instance. + +Here is how you can do that using `test_context` and `tempdir` crate: + +```rust +use tempdir::TempDir; +use test_context::{test_context, AsyncTestContext}; +use async_trait::async_trait; +use madara_node_runner::MadaraRunner; + +struct Context { + pub madara_path: TempDir, +} + +#[async_trait] +impl AsyncTestContext for Context { + async fn setup() -> Self { + let madara_path = TempDir::new("madara").expect("Failed to create Madara path"); + Self { madara_path } + } + + async fn teardown(self) { + self.madara_path.close().expect("Failed to clean up"); + } +} + +#[test_context(Context)] +#[rstest] +#[tokio::test] +async fn my_test_case(ctx: &mut Context) -> Result<(), anyhow::Error> { + let madara = MadaraRunner::new( + None, + Some(ctx.madara_path.path().into()), + ) + .await; + + todo!() +} +``` + +## Anvil + +By default, integration tests involving Ethereum contracts will try to find +Anvil at `~/.foundry/bin/anvil`. +Alternatively you can specify the Anvil binary location by setting `ANVIL_PATH` +environment variable. + +IMPORTANT: make sure your Anvil version uses a compatiuble `ethers-rs` library +version. +In case of an issue, try to update both dependencies first. diff --git a/starknet-e2e-test/contracts/Makefile b/starknet-e2e-test/contracts/Makefile new file mode 100644 index 0000000000..d281ddd542 --- /dev/null +++ b/starknet-e2e-test/contracts/Makefile @@ -0,0 +1,8 @@ +.PHONY: artifacts + +artifacts: + mkdir artifacts || true + forge build + forge build --root ../../madara-zaun + cp build/UnsafeProxy.sol/UnsafeProxy.json artifacts/ + cp ../../madara-zaun/out/StarknetValidium.sol/Starknet.json artifacts/ \ No newline at end of file diff --git a/starknet-e2e-test/contracts/README.md b/starknet-e2e-test/contracts/README.md new file mode 100644 index 0000000000..aece112c2d --- /dev/null +++ b/starknet-e2e-test/contracts/README.md @@ -0,0 +1,30 @@ +# Solidity contracts + +This folder contains compiled contracts that are used for integration / e2e +tests of Madara L1 <> L2 messaging. + +## Compilation + +First make sure you have +[Foundry](https://book.getfoundry.sh/getting-started/installation) installed. + +Starknet contract sources live in [madara-zaun](../madara-zaun/) folder which is +git submodule pointing at +[zaun repo](https://github.com/keep-starknet-strange/zaun). If you haven't +cloned the submodules together with the Madara repository, run: + +```bash +git submodule update --init +``` + +If `zaun` submodule is out of sync, do: + +```bash +git submodule sync --recursive +``` + +In this folder run: + +```bash +make artifacts +``` diff --git a/starknet-e2e-test/contracts/artifacts/Starknet.json b/starknet-e2e-test/contracts/artifacts/Starknet.json new file mode 100644 index 0000000000..3bcbb0ec80 --- /dev/null +++ b/starknet-e2e-test/contracts/artifacts/Starknet.json @@ -0,0 +1,8228 @@ +{ + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "changedBy", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldConfigHash", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newConfigHash", + "type": "uint256" + } + ], + "name": "ConfigHashChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fromAddress", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "toAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "payload", + "type": "uint256[]" + } + ], + "name": "ConsumedMessageToL1", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "fromAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "toAddress", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "selector", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "payload", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + } + ], + "name": "ConsumedMessageToL2", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "Finalized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fromAddress", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "toAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "payload", + "type": "uint256[]" + } + ], + "name": "LogMessageToL1", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "fromAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "toAddress", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "selector", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "payload", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "name": "LogMessageToL2", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "acceptedGovernor", + "type": "address" + } + ], + "name": "LogNewGovernorAccepted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "nominatedGovernor", + "type": "address" + } + ], + "name": "LogNominatedGovernor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "LogNominationCancelled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "LogOperatorAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "LogOperatorRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "removedGovernor", + "type": "address" + } + ], + "name": "LogRemovedGovernor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "stateTransitionFact", + "type": "bytes32" + } + ], + "name": "LogStateTransitionFact", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "globalRoot", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "blockNumber", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "blockHash", + "type": "uint256" + } + ], + "name": "LogStateUpdate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "fromAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "toAddress", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "selector", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "payload", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + } + ], + "name": "MessageToL2Canceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "fromAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "toAddress", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "selector", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "payload", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + } + ], + "name": "MessageToL2CancellationStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "changedBy", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldProgramHash", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newProgramHash", + "type": "uint256" + } + ], + "name": "ProgramHashChanged", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "toAddress", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "selector", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "payload", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + } + ], + "name": "cancelL1ToL2Message", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "configHash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fromAddress", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "payload", + "type": "uint256[]" + } + ], + "name": "consumeMessageFromL2", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "finalize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxL1MsgFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "identify", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isFinalized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isFrozen", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "isOperator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "msgHash", + "type": "bytes32" + } + ], + "name": "l1ToL2MessageCancellations", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1ToL2MessageNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "msgHash", + "type": "bytes32" + } + ], + "name": "l1ToL2Messages", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "msgHash", + "type": "bytes32" + } + ], + "name": "l2ToL1Messages", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "messageCancellationDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "programHash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOperator", + "type": "address" + } + ], + "name": "registerOperator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "toAddress", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "selector", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "payload", + "type": "uint256[]" + } + ], + "name": "sendMessageToL2", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newConfigHash", + "type": "uint256" + } + ], + "name": "setConfigHash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "delayInSeconds", + "type": "uint256" + } + ], + "name": "setMessageCancellationDelay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newProgramHash", + "type": "uint256" + } + ], + "name": "setProgramHash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "starknetAcceptGovernance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "starknetCancelNomination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "starknetIsGovernor", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newGovernor", + "type": "address" + } + ], + "name": "starknetNominateNewGovernor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "governorForRemoval", + "type": "address" + } + ], + "name": "starknetRemoveGovernor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "toAddress", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "selector", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "payload", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + } + ], + "name": "startL1ToL2MessageCancellation", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stateBlockHash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "stateBlockNumber", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "stateRoot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "removedOperator", + "type": "address" + } + ], + "name": "unregisterOperator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "programOutput", + "type": "uint256[]" + } + ], + "name": "updateState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": { + "object": "0x60a060405234801561001057600080fd5b5030606081901b608052612cee610031600039806109365250612cee6000f3fe6080604052600436106101e35760003560e01c80638303bd8a1161010257806396115bc211610095578063e1f1176d11610064578063e1f1176d14610515578063e37fec251461052a578063e87e73321461053f578063eeb728661461055f576101e3565b806396115bc2146104955780639be446bf146104b5578063a46efaf3146104d5578063c99d397f146104f5576101e3565b80638d4e4083116100d15780638d4e40831461043657806391a66a261461044b578063946be3ed1461046b5780639588eca214610480576101e3565b80638303bd8a146103cc57806384f921cd146103e1578063853e2461146104015780638a9bf09014610421576101e3565b80633e3aa6c51161017a5780636170ff1b116101495780636170ff1b1461034c5780636d70f7ae1461036c57806377c7d7a91461038c5780637a98660b146103ac576101e3565b80633e3aa6c5146102e1578063439fab91146103025780634bb278f31461032257806354eccba414610337576101e3565b806335befa5d116101b657806335befa5d146102755780633682a4501461028a578063382d83e3146102ac5780633d07b336146102c1576101e3565b8063018cccdf146101e857806301a01590146102135780632c9dd5c01461024057806333eeb14714610260575b600080fd5b3480156101f457600080fd5b506101fd610581565b60405161020a919061235d565b60405180910390f35b34801561021f57600080fd5b5061023361022e366004611f37565b6105c6565b60405161020a9190612352565b34801561024c57600080fd5b506101fd61025b3660046120ae565b6105d7565b34801561026c57600080fd5b506102336106ba565b34801561028157600080fd5b506101fd6106bf565b34801561029657600080fd5b506102aa6102a5366004611f37565b6106d2565b005b3480156102b857600080fd5b506101fd610773565b3480156102cd57600080fd5b506102aa6102dc366004611f9a565b610786565b6102f46102ef3660046120f8565b61081a565b60405161020a929190612366565b34801561030e57600080fd5b506102aa61031d366004611fb2565b610934565b34801561032e57600080fd5b506102aa610a7c565b34801561034357600080fd5b506101fd610b14565b34801561035857600080fd5b506101fd610367366004612149565b610b20565b34801561037857600080fd5b50610233610387366004611f37565b610c62565b34801561039857600080fd5b506101fd6103a7366004611f9a565b610c8f565b3480156103b857600080fd5b506101fd6103c7366004612149565b610caa565b3480156103d857600080fd5b506101fd610d61565b3480156103ed57600080fd5b506102aa6103fc366004611f37565b610d84565b34801561040d57600080fd5b506102aa61041c366004611f5a565b610d8d565b34801561042d57600080fd5b506101fd610ef3565b34801561044257600080fd5b50610233610f16565b34801561045757600080fd5b506102aa610466366004611f37565b610f39565b34801561047757600080fd5b506102aa610f42565b34801561048c57600080fd5b506101fd610f4c565b3480156104a157600080fd5b506102aa6104b0366004611f37565b610f5c565b3480156104c157600080fd5b506101fd6104d0366004611f9a565b610ff2565b3480156104e157600080fd5b506101fd6104f0366004611f9a565b610ffc565b34801561050157600080fd5b506102aa610510366004611f9a565b611006565b34801561052157600080fd5b506101fd611059565b34801561053657600080fd5b506102aa61107c565b34801561054b57600080fd5b506102aa61055a366004611f9a565b611084565b34801561056b57600080fd5b50610574611118565b60405161020a91906123a3565b60006105c16040518060400160405280602081526020017f535441524b4e45545f312e305f4d5347494e475f4c31544f4c325f4e4f4e434581525061114f565b905090565b60006105d182611183565b92915050565b60405160009081906105f59086903390869088908290602001612235565b60405160208183030381529060405280519060200120905060006106176111b2565b600083815260209190915260409020541161064d5760405162461bcd60e51b8152600401610644906128ee565b60405180910390fd5b336001600160a01b0316857f7a06c571aa77f34d9706c51e5d8122b5595aebeaa34233bfe866f22befb973b186866040516106899291906122ab565b60405180910390a3600161069b6111b2565b6000838152602091909152604090208054919091039055949350505050565b600090565b60006106c96111d5565b60010154905090565b6106db33611183565b6106f75760405162461bcd60e51b81526004016106449061283c565b61070081610c62565b61077057600161070e61121f565b6001600160a01b0383166000908152602091909152604090819020805460ff191692151592909217909155517f50a18c352ee1c02ffe058e15c2eb6e58be387c81e73cc1e17035286e54c19a5790610767908390612297565b60405180910390a15b50565b600061077d6111d5565b60020154905090565b61078e610f16565b156107ab5760405162461bcd60e51b815260040161064490612819565b6107b433611183565b6107d05760405162461bcd60e51b81526004016106449061283c565b337f393c6beb5756a944b2967f15f31ff671e312e945d7a84fd3bdcfd6b408b2dc796107fa611059565b83604051610809929190612366565b60405180910390a261077081611242565b6000806000341161083d5760405162461bcd60e51b815260040161064490612a3d565b610845610b14565b3411156108645760405162461bcd60e51b8152600401610644906125b0565b600061086e610581565b90506108b26040518060400160405280602081526020017f535441524b4e45545f312e305f4d5347494e475f4c31544f4c325f4e4f4e434581525082600101611260565b8587336001600160a01b03167fdb80dd488acf86d17c747445b0eabb5d57c541d3bd7b6b87af987858e5066b2b888886346040516108f394939291906122e3565b60405180910390a4600061090a8888888886611293565b9050346001016109186112d4565b6000838152602091909152604090205597909650945050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031630141561097d5760405162461bcd60e51b81526004016106449061267c565b60006109876106ba565b602090810291508101808310156109b05760405162461bcd60e51b81526004016106449061288a565b60006109be82848688612abf565b8101906109cb9190611f37565b90503660006109dc8582888a612abf565b915091506109ea8282610a78565b3660006109f98887818c612abf565b90925090506001600160a01b03851615610a2457610a188583836112f7565b50505050505050610a78565b610a2c61141c565b15610a54578015610a4f5760405162461bcd60e51b81526004016106449061261e565b610a70565b610a5e828261142d565b610a68828261148d565b610a706114e7565b505050505050505b5050565b610a8533611183565b610aa15760405162461bcd60e51b81526004016106449061283c565b610aa9610f16565b15610ac65760405162461bcd60e51b815260040161064490612819565b610ae9604051806060016040528060318152602001612c88603191396001611260565b6040517f6823b073d48d6e3a7d385eeb601452d680e74bb46afe3255a7d778f3a9b1768190600090a1565b670de0b6b3a764000090565b60008486336001600160a01b03167f8abd2ec2e0a10c82f5b60ea00455fa96c41fd144f225fcc52b8d83d94f803ed8878787604051610b61939291906122bf565b60405180910390a46000610b788787878787611293565b90506000610b846112d4565b60008381526020919091526040902054905080610bb35760405162461bcd60e51b81526004016106449061277d565b6000610bbd61153e565b60008481526020919091526040902054905080610bec5760405162461bcd60e51b8152600401610644906129fb565b6000610bf6610d61565b8201905081811015610c1a5760405162461bcd60e51b815260040161064490612510565b80421015610c3a5760405162461bcd60e51b815260040161064490612547565b6000610c446112d4565b60008681526020919091526040902055509198975050505050505050565b6000610c6c61121f565b6001600160a01b0392909216600090815260209290925250604090205460ff1690565b6000610c996112d4565b600092835260205250604090205490565b60008486336001600160a01b03167f2e00dccd686fd6823ec7dc3e125582aa82881b6ff5f6b5a73856e1ea8338a3be878787604051610ceb939291906122bf565b60405180910390a46000610d028787878787611293565b90506000610d0e6112d4565b60008381526020919091526040902054905080610d3d5760405162461bcd60e51b81526004016106449061277d565b42610d4661153e565b60008481526020919091526040902055509695505050505050565b60006105c16040518060600160405280602d8152602001612bf1602d913961114f565b61077081611561565b610d9633610c62565b610db25760405162461bcd60e51b815260040161064490612952565b6000610dbc6111d5565b600101549050610dcc838361163c565b82826004818110610dd957fe5b90506020020135610de8611059565b14610e055760405162461bcd60e51b8152600401610644906124b6565b610e198383610e126111d5565b919061165c565b6005610e396001610e2c85848189612a94565b610e346111b2565b611706565b01610e536000610e4b85848189612a94565b610e346112d4565b01828114610e735760405162461bcd60e51b815260040161064490612746565b6000610e7d6111d5565b90507fd342ddf7a308dec111745b00315c14b7efb2bdae570a6856e088ed0c65a3576c816000015482600101548360020154604051610ebe93929190612a7e565b60405180910390a182600101816001015414610eec5760405162461bcd60e51b8152600401610644906125e7565b5050505050565b60006105c1604051806060016040528060238152602001612bce6023913961114f565b60006105c1604051806060016040528060318152602001612c886031913961114f565b61077081611afb565b610f4a611bf0565b565b6000610f566111d5565b54905090565b610f6533611183565b610f815760405162461bcd60e51b81526004016106449061283c565b610f8a81610c62565b15610770576000610f9961121f565b6001600160a01b0383166000908152602091909152604090819020805460ff191692151592909217909155517fec5f6c3a91a1efb1f9a308bb33c6e9e66bf9090fad0732f127dfdbf516d0625d90610767908390612297565b6000610c9961153e565b6000610c996111b2565b61100e610f16565b1561102b5760405162461bcd60e51b815260040161064490612819565b61103433611183565b6110505760405162461bcd60e51b81526004016106449061283c565b61077081611c45565b60006105c1604051806060016040528060218152602001612c1e6021913961114f565b610f4a611c67565b61108c610f16565b156110a95760405162461bcd60e51b815260040161064490612819565b6110b233611183565b6110ce5760405162461bcd60e51b81526004016106449061283c565b337f600a61c1b32ac42fb2fe76e8fc7582a98106668fc16dcd85567cd3937363e49b6110f8610ef3565b83604051611107929190612366565b60405180910390a261077081611cea565b60408051808201909152601981527f537461726b576172655f537461726b6e65745f323032335f3600000000000000602082015290565b600080826040516020016111639190612216565b60408051601f198184030181529190528051602090910120549392505050565b60008061118e611d0c565b6001600160a01b039390931660009081526020939093525050604090205460ff1690565b60006105c1604051806060016040528060238152602001612c3f60239139611d55565b600080604051806060016040528060278152602001612ba7602791396040516020016112019190612216565b60408051601f19818403018152919052805160209091012092915050565b60006105c1604051806060016040528060288152602001612b4f60289139611d55565b610770604051806060016040528060218152602001612c1e60219139825b6000826040516020016112739190612216565b604051602081830303815290604052805190602001209050818155505050565b6040516000906112b390339088908590899088908a90829060200161225f565b60405160208183030381529060405280519060200120905095945050505050565b60006105c1604051806060016040528060268152602001612c6260269139611d55565b611309836001600160a01b0316611d88565b6113255760405162461bcd60e51b8152600401610644906123d6565b60006060846001600160a01b031663439fab9160e01b858560405160240161134e929190612374565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161138c9190612216565b600060405180830381855af49150503d80600081146113c7576040519150601f19603f3d011682016040523d82523d6000602084013e6113cc565b606091505b50915091508181906113f15760405162461bcd60e51b815260040161064491906123a3565b5080518190156114145760405162461bcd60e51b815260040161064491906123a3565b505050505050565b6000611426610ef3565b1515905090565b60c0811461144d5760405162461bcd60e51b81526004016106449061242d565b600061145c6020828486612abf565b8101906114699190611f9a565b9050806114885760405162461bcd60e51b8152600401610644906126e3565b505050565b600080600061149a611ed4565b6114a68587018761201f565b93509350935093506114b784611cea565b6114c083611d8e565b6114d2816114cc6111d5565b90611db0565b6114db82611242565b61141462069780611c45565b60006114f1611d0c565b6001810154909150600160a01b900460ff16156115205760405162461bcd60e51b8152600401610644906124e3565b60018101805460ff60a01b1916600160a01b17905561077033611dca565b60006105c1604051806060016040528060308152602001612b7760309139611d55565b61156a33611183565b6115865760405162461bcd60e51b81526004016106449061283c565b336001600160a01b03821614156115af5760405162461bcd60e51b8152600401610644906129a7565b60006115b9611d0c565b90506115c482611183565b6115e05760405162461bcd60e51b8152600401610644906129d5565b6001600160a01b03821660009081526020829052604090819020805460ff19169055517fd75f94825e770b8b512be8e74759e252ad00e102e38f50cce2f7c6f868a2959990611630908490612297565b60405180910390a15050565b60058111610a785760405162461bcd60e51b8152600401610644906127ab565b6001838101805490910190558181600281811061167557fe5b9050602002013583600101541461169e5760405162461bcd60e51b815260040161064490612979565b818160038181106116ab57fe5b60200291909101356002850155503660006116c68484611e50565b915091506116d48282611e6c565b8554146116f35760405162461bcd60e51b815260040161064490612487565b6116fd8282611e8a565b90945550505050565b6000808484600081811061171657fe5b905060200201359050634000000081106117425760405162461bcd60e51b81526004016106449061270f565b6001818101600088611755576004611758565b60025b905060005b82841015611a4a578382018881106117875760405162461bcd60e51b815260040161064490612402565b60008a8a8381811061179557fe5b905060200201359050634000000081106117c15760405162461bcd60e51b81526004016106449061264c565b8181016001018a8111156117e75760405162461bcd60e51b8152600401610644906127e2565b8c156118c55760008c8c8990849261180193929190612a94565b604051602001611812929190612201565b6040516020818303038152906040528051906020012090508c8c60018a0181811061183957fe5b905060200201356001600160a01b03168d8d60008b0181811061185857fe5b905060200201357f4264ac208b5fde633ccdd42e0f12c3d6d443a4f3779bbf886925b94665b63a228f8f60038d0190879261189593929190612a94565b6040516118a39291906122ab565b60405180910390a3600090815260208b90526040902080546001019055611a40565b60008c8c899084926118d993929190612a94565b6040516020016118ea929190612201565b60408051601f1981840301815291815281516020928301206000818152928e90529120549091508061192e5760405162461bcd60e51b8152600401610644906128ee565b600091825260208c9052604082208290559490940160001901938c8c60028a0181811061195757fe5b90506020020135905060608d8d60058b0190859261197793929190612a94565b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505090508d8d60038b018181106119c857fe5b905060200201358e8e60018c018181106119de57fe5b905060200201358f8f60008d018181106119f457fe5b905060200201356001600160a01b03167f9592d37825c744e33fa80c469683bbd04d336241bb600b574758efd182abe26a8486604051611a3592919061230a565b60405180910390a450505b955061175d915050565b828414611a695760405162461bcd60e51b81526004016106449061270f565b8015611aed576000336001600160a01b031682604051611a8890612232565b60006040518083038185875af1925050503d8060008114611ac5576040519150601f19603f3d011682016040523d82523d6000602084013e611aca565b606091505b5050905080611aeb5760405162461bcd60e51b815260040161064490612925565b505b509198975050505050505050565b611b0433611183565b611b205760405162461bcd60e51b81526004016106449061283c565b6000611b2a611d0c565b90506001600160a01b038216611b525760405162461bcd60e51b815260040161064490612865565b611b5b82611183565b15611b785760405162461bcd60e51b81526004016106449061245d565b60018101546001600160a01b031615611ba35760405162461bcd60e51b8152600401610644906128b7565b6001810180546001600160a01b0319166001600160a01b0384161790556040517f6166272c8d3f5f579082f2827532732f97195007983bb5b83ac12c56700b01a690611630908490612297565b6000611bfa611d0c565b60018101549091506001600160a01b03163314611c295760405162461bcd60e51b8152600401610644906126ac565b611c3233611dca565b60010180546001600160a01b0319169055565b6107706040518060600160405280602d8152602001612bf1602d913982611260565b611c7033611183565b611c8c5760405162461bcd60e51b81526004016106449061283c565b6000611c96611d0c565b60018101549091506001600160a01b031615610770576001810180546001600160a01b03191690556040517f7a8dc7dd7fffb43c4807438fa62729225156941e641fd877938f4edade3429f590600090a150565b610770604051806060016040528060238152602001612bce6023913982611260565b6000806040518060400160405280601c81526020017f535441524b4e45545f312e305f474f5645524e414e43455f494e464f000000008152506040516020016112019190612216565b60008082604051602001611d699190612216565b60408051601f1981840301815291905280516020909101209392505050565b3b151590565b610770604051806060016040528060228152602001612b2d6022913982611e99565b805182556020810151600183015560400151600290910155565b611dd381611183565b15611df05760405162461bcd60e51b81526004016106449061245d565b6000611dfa611d0c565b6001600160a01b03831660009081526020829052604090819020805460ff19166001179055519091507fcfb473e6c03f9a29ddaf990e736fa3de5188a0bd85d684f5b6e164ebfbfff5d290611630908490612297565b366000611e606002828587612a94565b915091505b9250929050565b600082826000818110611e7b57fe5b90506020020135905092915050565b600082826001818110611e7b57fe5b6000611ea48361114f565b6001600160a01b031614611eca5760405162461bcd60e51b81526004016106449061258b565b610a788282611260565b60405180606001604052806000815260200160008152602001600081525090565b60008083601f840112611f06578182fd5b50813567ffffffffffffffff811115611f1d578182fd5b6020830191508360208083028501011115611e6557600080fd5b600060208284031215611f48578081fd5b8135611f5381612b17565b9392505050565b60008060208385031215611f6c578081fd5b823567ffffffffffffffff811115611f82578182fd5b611f8e85828601611ef5565b90969095509350505050565b600060208284031215611fab578081fd5b5035919050565b60008060208385031215611fc4578182fd5b823567ffffffffffffffff80821115611fdb578384fd5b818501915085601f830112611fee578384fd5b813581811115611ffc578485fd5b86602082850101111561200d578485fd5b60209290920196919550909350505050565b60008060008084860360c0811215612035578283fd5b85359450602086013561204781612b17565b9350604086013592506060605f1982011215612061578182fd5b506040516060810181811067ffffffffffffffff82111715612081578283fd5b8060405250606086013581526080860135602082015260a086013560408201528091505092959194509250565b6000806000604084860312156120c2578283fd5b83359250602084013567ffffffffffffffff8111156120df578283fd5b6120eb86828701611ef5565b9497909650939450505050565b6000806000806060858703121561210d578384fd5b8435935060208501359250604085013567ffffffffffffffff811115612131578283fd5b61213d87828801611ef5565b95989497509550505050565b600080600080600060808688031215612160578081fd5b8535945060208601359350604086013567ffffffffffffffff811115612184578182fd5b61219088828901611ef5565b96999598509660600135949350505050565b81835260006001600160fb1b038311156121ba578081fd5b6020830280836020870137939093016020019283525090919050565b60006001600160fb1b038311156121eb578081fd5b6020830280838637939093019283525090919050565b600061220e8284866121d6565b949350505050565b60008251612228818460208701612ae7565b9190910192915050565b90565b60008682528560208301528460408301526122546060830184866121d6565b979650505050505050565b600088825287602083015286604083015285606083015284608083015261228a60a0830184866121d6565b9998505050505050505050565b6001600160a01b0391909116815260200190565b60006020825261220e6020830184866121a2565b6000604082526122d36040830185876121a2565b9050826020830152949350505050565b6000606082526122f76060830186886121a2565b6020830194909452506040015292915050565b604080825283519082018190526000906020906060840190828701845b8281101561234357815184529284019290840190600101612327565b50505092019290925292915050565b901515815260200190565b90815260200190565b918252602082015260400190565b60006020825282602083015282846040840137818301604090810191909152601f909201601f19160101919050565b60006020825282518060208401526123c2816040850160208701612ae7565b601f01601f19169190910160400192915050565b602080825260129082015271115250d7d393d517d057d0d3d395149050d560721b604082015260600190565b602080825260119082015270135154d4d051d157d513d3d7d4d213d495607a1b604082015260600190565b602080825260169082015275494c4c4547414c5f494e49545f444154415f53495a4560501b604082015260600190565b60208082526010908201526f20a62922a0a22cafa3a7ab22a92727a960811b604082015260600190565b6020808252601590820152741253959053125117d41491559253d554d7d493d3d5605a1b604082015260600190565b6020808252601390820152720929cac82989288be869e9c8c928ebe9082a69606b1b604082015260600190565b6020808252601390820152721053149150511657d253925512505312569151606a1b604082015260600190565b6020808252601c908201527f43414e43454c5f414c4c4f5745445f54494d455f4f564552464c4f5700000000604082015260600190565b60208082526024908201527f4d4553534147455f43414e43454c4c4154494f4e5f4e4f545f414c4c4f57454460408201526317d6515560e21b606082015260800190565b6020808252600b908201526a1053149150511657d4d15560aa1b604082015260600190565b60208082526017908201527f4d41585f4c315f4d53475f4645455f4558434545444544000000000000000000604082015260600190565b6020808252601a908201527f494e56414c49445f46494e414c5f424c4f434b5f4e554d424552000000000000604082015260600190565b602080825260149082015273554e45585045435445445f494e49545f4441544160601b604082015260600190565b6020808252601690820152750929cac82989288bea082b2989e8288be988a9c8ea8960531b604082015260600190565b6020808252601690820152751112549150d517d0d0531317d11254d0531313d5d15160521b604082015260600190565b60208082526017908201527f4f4e4c595f43414e4449444154455f474f5645524e4f52000000000000000000604082015260600190565b6020808252601290820152712120a22fa4a724aa24a0a624ad20aa24a7a760711b604082015260600190565b6020808252601c908201527f494e56414c49445f4d4553534147455f5345474d454e545f53495a4500000000604082015260600190565b60208082526018908201527f535441524b4e45545f4f55545055545f544f4f5f4c4f4e470000000000000000604082015260600190565b6020808252601490820152731393d7d35154d4d051d157d513d7d0d05390d15360621b604082015260600190565b60208082526019908201527f535441524b4e45545f4f55545055545f544f4f5f53484f525400000000000000604082015260600190565b60208082526019908201527f5452554e43415445445f4d4553534147455f5041594c4f414400000000000000604082015260600190565b60208082526009908201526811925390531256915160ba1b604082015260600190565b6020808252600f908201526e4f4e4c595f474f5645524e414e434560881b604082015260600190565b6020808252600b908201526a4241445f4144445245535360a81b604082015260600190565b6020808252601390820152721253925517d110551057d513d3d7d4d3505313606a1b604082015260600190565b60208082526017908201527f4f544845525f43414e4449444154455f50454e44494e47000000000000000000604082015260600190565b6020808252601a908201527f494e56414c49445f4d4553534147455f544f5f434f4e53554d45000000000000604082015260600190565b60208082526013908201527211551217d514905394d1915497d19052531151606a1b604082015260600190565b6020808252600d908201526c27a7262cafa7a822a920aa27a960991b604082015260600190565b60208082526014908201527324a72b20a624a22fa12627a1a5afa72aa6a122a960611b604082015260600190565b602080825260149082015273474f5645524e4f525f53454c465f52454d4f564560601b604082015260600190565b6020808252600c908201526b2727aa2fa3a7ab22a92727a960a11b604082015260600190565b60208082526022908201527f4d4553534147455f43414e43454c4c4154494f4e5f4e4f545f52455155455354604082015261115160f21b606082015260800190565b60208082526021908201527f4c315f4d53475f4645455f4d5553545f42455f475245415445525f5448414e5f6040820152600360fc1b606082015260800190565b9283526020830191909152604082015260600190565b60008085851115612aa3578182fd5b83861115612aaf578182fd5b5050602083020193919092039150565b60008085851115612ace578081fd5b83861115612ada578081fd5b5050820193919092039150565b60005b83811015612b02578181015183820152602001612aea565b83811115612b11576000848401525b50505050565b6001600160a01b038116811461077057600080fdfe535441524b4e45545f312e305f494e49545f56455249464945525f41444452455353535441524b4e45545f312e305f524f4c45535f4f50455241544f52535f4d415050494e475f544147535441524b4e45545f312e305f4d5347494e475f4c31544f4c325f43414e43454c4c4154494f4e5f4d41505050494e47535441524b4e45545f312e305f494e49545f535441524b4e45545f53544154455f535452554354535441524b4e45545f312e305f494e49545f50524f4752414d5f484153485f55494e54535441524b4e45545f312e305f4d5347494e475f4c31544f4c325f43414e43454c4c4154494f4e5f44454c4159535441524b4e45545f312e305f535441524b4e45545f434f4e4649475f48415348535441524b4e45545f312e305f4d5347494e475f4c32544f4c315f4d41505050494e47535441524b4e45545f312e305f4d5347494e475f4c31544f4c325f4d41505050494e475f5632535441524b574152455f434f4e5452414354535f474f564552454e45445f46494e414c495a41424c455f312e305f544147a2646970667358221220749105af4323f28521c03a1b6b128ff7ceb5750ce7bcf9475b742af277f1611264736f6c634300060c0033", + "sourceMap": "729:7138:37:-:0;;;;;;;;;;;;-1:-1:-1;489:4:4;473:21;;;;;;729:7138:37;;;;;;;", + "linkReferences": {} + }, + "deployedBytecode": { + "object": "0x6080604052600436106101e35760003560e01c80638303bd8a1161010257806396115bc211610095578063e1f1176d11610064578063e1f1176d14610515578063e37fec251461052a578063e87e73321461053f578063eeb728661461055f576101e3565b806396115bc2146104955780639be446bf146104b5578063a46efaf3146104d5578063c99d397f146104f5576101e3565b80638d4e4083116100d15780638d4e40831461043657806391a66a261461044b578063946be3ed1461046b5780639588eca214610480576101e3565b80638303bd8a146103cc57806384f921cd146103e1578063853e2461146104015780638a9bf09014610421576101e3565b80633e3aa6c51161017a5780636170ff1b116101495780636170ff1b1461034c5780636d70f7ae1461036c57806377c7d7a91461038c5780637a98660b146103ac576101e3565b80633e3aa6c5146102e1578063439fab91146103025780634bb278f31461032257806354eccba414610337576101e3565b806335befa5d116101b657806335befa5d146102755780633682a4501461028a578063382d83e3146102ac5780633d07b336146102c1576101e3565b8063018cccdf146101e857806301a01590146102135780632c9dd5c01461024057806333eeb14714610260575b600080fd5b3480156101f457600080fd5b506101fd610581565b60405161020a919061235d565b60405180910390f35b34801561021f57600080fd5b5061023361022e366004611f37565b6105c6565b60405161020a9190612352565b34801561024c57600080fd5b506101fd61025b3660046120ae565b6105d7565b34801561026c57600080fd5b506102336106ba565b34801561028157600080fd5b506101fd6106bf565b34801561029657600080fd5b506102aa6102a5366004611f37565b6106d2565b005b3480156102b857600080fd5b506101fd610773565b3480156102cd57600080fd5b506102aa6102dc366004611f9a565b610786565b6102f46102ef3660046120f8565b61081a565b60405161020a929190612366565b34801561030e57600080fd5b506102aa61031d366004611fb2565b610934565b34801561032e57600080fd5b506102aa610a7c565b34801561034357600080fd5b506101fd610b14565b34801561035857600080fd5b506101fd610367366004612149565b610b20565b34801561037857600080fd5b50610233610387366004611f37565b610c62565b34801561039857600080fd5b506101fd6103a7366004611f9a565b610c8f565b3480156103b857600080fd5b506101fd6103c7366004612149565b610caa565b3480156103d857600080fd5b506101fd610d61565b3480156103ed57600080fd5b506102aa6103fc366004611f37565b610d84565b34801561040d57600080fd5b506102aa61041c366004611f5a565b610d8d565b34801561042d57600080fd5b506101fd610ef3565b34801561044257600080fd5b50610233610f16565b34801561045757600080fd5b506102aa610466366004611f37565b610f39565b34801561047757600080fd5b506102aa610f42565b34801561048c57600080fd5b506101fd610f4c565b3480156104a157600080fd5b506102aa6104b0366004611f37565b610f5c565b3480156104c157600080fd5b506101fd6104d0366004611f9a565b610ff2565b3480156104e157600080fd5b506101fd6104f0366004611f9a565b610ffc565b34801561050157600080fd5b506102aa610510366004611f9a565b611006565b34801561052157600080fd5b506101fd611059565b34801561053657600080fd5b506102aa61107c565b34801561054b57600080fd5b506102aa61055a366004611f9a565b611084565b34801561056b57600080fd5b50610574611118565b60405161020a91906123a3565b60006105c16040518060400160405280602081526020017f535441524b4e45545f312e305f4d5347494e475f4c31544f4c325f4e4f4e434581525061114f565b905090565b60006105d182611183565b92915050565b60405160009081906105f59086903390869088908290602001612235565b60405160208183030381529060405280519060200120905060006106176111b2565b600083815260209190915260409020541161064d5760405162461bcd60e51b8152600401610644906128ee565b60405180910390fd5b336001600160a01b0316857f7a06c571aa77f34d9706c51e5d8122b5595aebeaa34233bfe866f22befb973b186866040516106899291906122ab565b60405180910390a3600161069b6111b2565b6000838152602091909152604090208054919091039055949350505050565b600090565b60006106c96111d5565b60010154905090565b6106db33611183565b6106f75760405162461bcd60e51b81526004016106449061283c565b61070081610c62565b61077057600161070e61121f565b6001600160a01b0383166000908152602091909152604090819020805460ff191692151592909217909155517f50a18c352ee1c02ffe058e15c2eb6e58be387c81e73cc1e17035286e54c19a5790610767908390612297565b60405180910390a15b50565b600061077d6111d5565b60020154905090565b61078e610f16565b156107ab5760405162461bcd60e51b815260040161064490612819565b6107b433611183565b6107d05760405162461bcd60e51b81526004016106449061283c565b337f393c6beb5756a944b2967f15f31ff671e312e945d7a84fd3bdcfd6b408b2dc796107fa611059565b83604051610809929190612366565b60405180910390a261077081611242565b6000806000341161083d5760405162461bcd60e51b815260040161064490612a3d565b610845610b14565b3411156108645760405162461bcd60e51b8152600401610644906125b0565b600061086e610581565b90506108b26040518060400160405280602081526020017f535441524b4e45545f312e305f4d5347494e475f4c31544f4c325f4e4f4e434581525082600101611260565b8587336001600160a01b03167fdb80dd488acf86d17c747445b0eabb5d57c541d3bd7b6b87af987858e5066b2b888886346040516108f394939291906122e3565b60405180910390a4600061090a8888888886611293565b9050346001016109186112d4565b6000838152602091909152604090205597909650945050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031630141561097d5760405162461bcd60e51b81526004016106449061267c565b60006109876106ba565b602090810291508101808310156109b05760405162461bcd60e51b81526004016106449061288a565b60006109be82848688612abf565b8101906109cb9190611f37565b90503660006109dc8582888a612abf565b915091506109ea8282610a78565b3660006109f98887818c612abf565b90925090506001600160a01b03851615610a2457610a188583836112f7565b50505050505050610a78565b610a2c61141c565b15610a54578015610a4f5760405162461bcd60e51b81526004016106449061261e565b610a70565b610a5e828261142d565b610a68828261148d565b610a706114e7565b505050505050505b5050565b610a8533611183565b610aa15760405162461bcd60e51b81526004016106449061283c565b610aa9610f16565b15610ac65760405162461bcd60e51b815260040161064490612819565b610ae9604051806060016040528060318152602001612c88603191396001611260565b6040517f6823b073d48d6e3a7d385eeb601452d680e74bb46afe3255a7d778f3a9b1768190600090a1565b670de0b6b3a764000090565b60008486336001600160a01b03167f8abd2ec2e0a10c82f5b60ea00455fa96c41fd144f225fcc52b8d83d94f803ed8878787604051610b61939291906122bf565b60405180910390a46000610b788787878787611293565b90506000610b846112d4565b60008381526020919091526040902054905080610bb35760405162461bcd60e51b81526004016106449061277d565b6000610bbd61153e565b60008481526020919091526040902054905080610bec5760405162461bcd60e51b8152600401610644906129fb565b6000610bf6610d61565b8201905081811015610c1a5760405162461bcd60e51b815260040161064490612510565b80421015610c3a5760405162461bcd60e51b815260040161064490612547565b6000610c446112d4565b60008681526020919091526040902055509198975050505050505050565b6000610c6c61121f565b6001600160a01b0392909216600090815260209290925250604090205460ff1690565b6000610c996112d4565b600092835260205250604090205490565b60008486336001600160a01b03167f2e00dccd686fd6823ec7dc3e125582aa82881b6ff5f6b5a73856e1ea8338a3be878787604051610ceb939291906122bf565b60405180910390a46000610d028787878787611293565b90506000610d0e6112d4565b60008381526020919091526040902054905080610d3d5760405162461bcd60e51b81526004016106449061277d565b42610d4661153e565b60008481526020919091526040902055509695505050505050565b60006105c16040518060600160405280602d8152602001612bf1602d913961114f565b61077081611561565b610d9633610c62565b610db25760405162461bcd60e51b815260040161064490612952565b6000610dbc6111d5565b600101549050610dcc838361163c565b82826004818110610dd957fe5b90506020020135610de8611059565b14610e055760405162461bcd60e51b8152600401610644906124b6565b610e198383610e126111d5565b919061165c565b6005610e396001610e2c85848189612a94565b610e346111b2565b611706565b01610e536000610e4b85848189612a94565b610e346112d4565b01828114610e735760405162461bcd60e51b815260040161064490612746565b6000610e7d6111d5565b90507fd342ddf7a308dec111745b00315c14b7efb2bdae570a6856e088ed0c65a3576c816000015482600101548360020154604051610ebe93929190612a7e565b60405180910390a182600101816001015414610eec5760405162461bcd60e51b8152600401610644906125e7565b5050505050565b60006105c1604051806060016040528060238152602001612bce6023913961114f565b60006105c1604051806060016040528060318152602001612c886031913961114f565b61077081611afb565b610f4a611bf0565b565b6000610f566111d5565b54905090565b610f6533611183565b610f815760405162461bcd60e51b81526004016106449061283c565b610f8a81610c62565b15610770576000610f9961121f565b6001600160a01b0383166000908152602091909152604090819020805460ff191692151592909217909155517fec5f6c3a91a1efb1f9a308bb33c6e9e66bf9090fad0732f127dfdbf516d0625d90610767908390612297565b6000610c9961153e565b6000610c996111b2565b61100e610f16565b1561102b5760405162461bcd60e51b815260040161064490612819565b61103433611183565b6110505760405162461bcd60e51b81526004016106449061283c565b61077081611c45565b60006105c1604051806060016040528060218152602001612c1e6021913961114f565b610f4a611c67565b61108c610f16565b156110a95760405162461bcd60e51b815260040161064490612819565b6110b233611183565b6110ce5760405162461bcd60e51b81526004016106449061283c565b337f600a61c1b32ac42fb2fe76e8fc7582a98106668fc16dcd85567cd3937363e49b6110f8610ef3565b83604051611107929190612366565b60405180910390a261077081611cea565b60408051808201909152601981527f537461726b576172655f537461726b6e65745f323032335f3600000000000000602082015290565b600080826040516020016111639190612216565b60408051601f198184030181529190528051602090910120549392505050565b60008061118e611d0c565b6001600160a01b039390931660009081526020939093525050604090205460ff1690565b60006105c1604051806060016040528060238152602001612c3f60239139611d55565b600080604051806060016040528060278152602001612ba7602791396040516020016112019190612216565b60408051601f19818403018152919052805160209091012092915050565b60006105c1604051806060016040528060288152602001612b4f60289139611d55565b610770604051806060016040528060218152602001612c1e60219139825b6000826040516020016112739190612216565b604051602081830303815290604052805190602001209050818155505050565b6040516000906112b390339088908590899088908a90829060200161225f565b60405160208183030381529060405280519060200120905095945050505050565b60006105c1604051806060016040528060268152602001612c6260269139611d55565b611309836001600160a01b0316611d88565b6113255760405162461bcd60e51b8152600401610644906123d6565b60006060846001600160a01b031663439fab9160e01b858560405160240161134e929190612374565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161138c9190612216565b600060405180830381855af49150503d80600081146113c7576040519150601f19603f3d011682016040523d82523d6000602084013e6113cc565b606091505b50915091508181906113f15760405162461bcd60e51b815260040161064491906123a3565b5080518190156114145760405162461bcd60e51b815260040161064491906123a3565b505050505050565b6000611426610ef3565b1515905090565b60c0811461144d5760405162461bcd60e51b81526004016106449061242d565b600061145c6020828486612abf565b8101906114699190611f9a565b9050806114885760405162461bcd60e51b8152600401610644906126e3565b505050565b600080600061149a611ed4565b6114a68587018761201f565b93509350935093506114b784611cea565b6114c083611d8e565b6114d2816114cc6111d5565b90611db0565b6114db82611242565b61141462069780611c45565b60006114f1611d0c565b6001810154909150600160a01b900460ff16156115205760405162461bcd60e51b8152600401610644906124e3565b60018101805460ff60a01b1916600160a01b17905561077033611dca565b60006105c1604051806060016040528060308152602001612b7760309139611d55565b61156a33611183565b6115865760405162461bcd60e51b81526004016106449061283c565b336001600160a01b03821614156115af5760405162461bcd60e51b8152600401610644906129a7565b60006115b9611d0c565b90506115c482611183565b6115e05760405162461bcd60e51b8152600401610644906129d5565b6001600160a01b03821660009081526020829052604090819020805460ff19169055517fd75f94825e770b8b512be8e74759e252ad00e102e38f50cce2f7c6f868a2959990611630908490612297565b60405180910390a15050565b60058111610a785760405162461bcd60e51b8152600401610644906127ab565b6001838101805490910190558181600281811061167557fe5b9050602002013583600101541461169e5760405162461bcd60e51b815260040161064490612979565b818160038181106116ab57fe5b60200291909101356002850155503660006116c68484611e50565b915091506116d48282611e6c565b8554146116f35760405162461bcd60e51b815260040161064490612487565b6116fd8282611e8a565b90945550505050565b6000808484600081811061171657fe5b905060200201359050634000000081106117425760405162461bcd60e51b81526004016106449061270f565b6001818101600088611755576004611758565b60025b905060005b82841015611a4a578382018881106117875760405162461bcd60e51b815260040161064490612402565b60008a8a8381811061179557fe5b905060200201359050634000000081106117c15760405162461bcd60e51b81526004016106449061264c565b8181016001018a8111156117e75760405162461bcd60e51b8152600401610644906127e2565b8c156118c55760008c8c8990849261180193929190612a94565b604051602001611812929190612201565b6040516020818303038152906040528051906020012090508c8c60018a0181811061183957fe5b905060200201356001600160a01b03168d8d60008b0181811061185857fe5b905060200201357f4264ac208b5fde633ccdd42e0f12c3d6d443a4f3779bbf886925b94665b63a228f8f60038d0190879261189593929190612a94565b6040516118a39291906122ab565b60405180910390a3600090815260208b90526040902080546001019055611a40565b60008c8c899084926118d993929190612a94565b6040516020016118ea929190612201565b60408051601f1981840301815291815281516020928301206000818152928e90529120549091508061192e5760405162461bcd60e51b8152600401610644906128ee565b600091825260208c9052604082208290559490940160001901938c8c60028a0181811061195757fe5b90506020020135905060608d8d60058b0190859261197793929190612a94565b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505090508d8d60038b018181106119c857fe5b905060200201358e8e60018c018181106119de57fe5b905060200201358f8f60008d018181106119f457fe5b905060200201356001600160a01b03167f9592d37825c744e33fa80c469683bbd04d336241bb600b574758efd182abe26a8486604051611a3592919061230a565b60405180910390a450505b955061175d915050565b828414611a695760405162461bcd60e51b81526004016106449061270f565b8015611aed576000336001600160a01b031682604051611a8890612232565b60006040518083038185875af1925050503d8060008114611ac5576040519150601f19603f3d011682016040523d82523d6000602084013e611aca565b606091505b5050905080611aeb5760405162461bcd60e51b815260040161064490612925565b505b509198975050505050505050565b611b0433611183565b611b205760405162461bcd60e51b81526004016106449061283c565b6000611b2a611d0c565b90506001600160a01b038216611b525760405162461bcd60e51b815260040161064490612865565b611b5b82611183565b15611b785760405162461bcd60e51b81526004016106449061245d565b60018101546001600160a01b031615611ba35760405162461bcd60e51b8152600401610644906128b7565b6001810180546001600160a01b0319166001600160a01b0384161790556040517f6166272c8d3f5f579082f2827532732f97195007983bb5b83ac12c56700b01a690611630908490612297565b6000611bfa611d0c565b60018101549091506001600160a01b03163314611c295760405162461bcd60e51b8152600401610644906126ac565b611c3233611dca565b60010180546001600160a01b0319169055565b6107706040518060600160405280602d8152602001612bf1602d913982611260565b611c7033611183565b611c8c5760405162461bcd60e51b81526004016106449061283c565b6000611c96611d0c565b60018101549091506001600160a01b031615610770576001810180546001600160a01b03191690556040517f7a8dc7dd7fffb43c4807438fa62729225156941e641fd877938f4edade3429f590600090a150565b610770604051806060016040528060238152602001612bce6023913982611260565b6000806040518060400160405280601c81526020017f535441524b4e45545f312e305f474f5645524e414e43455f494e464f000000008152506040516020016112019190612216565b60008082604051602001611d699190612216565b60408051601f1981840301815291905280516020909101209392505050565b3b151590565b610770604051806060016040528060228152602001612b2d6022913982611e99565b805182556020810151600183015560400151600290910155565b611dd381611183565b15611df05760405162461bcd60e51b81526004016106449061245d565b6000611dfa611d0c565b6001600160a01b03831660009081526020829052604090819020805460ff19166001179055519091507fcfb473e6c03f9a29ddaf990e736fa3de5188a0bd85d684f5b6e164ebfbfff5d290611630908490612297565b366000611e606002828587612a94565b915091505b9250929050565b600082826000818110611e7b57fe5b90506020020135905092915050565b600082826001818110611e7b57fe5b6000611ea48361114f565b6001600160a01b031614611eca5760405162461bcd60e51b81526004016106449061258b565b610a788282611260565b60405180606001604052806000815260200160008152602001600081525090565b60008083601f840112611f06578182fd5b50813567ffffffffffffffff811115611f1d578182fd5b6020830191508360208083028501011115611e6557600080fd5b600060208284031215611f48578081fd5b8135611f5381612b17565b9392505050565b60008060208385031215611f6c578081fd5b823567ffffffffffffffff811115611f82578182fd5b611f8e85828601611ef5565b90969095509350505050565b600060208284031215611fab578081fd5b5035919050565b60008060208385031215611fc4578182fd5b823567ffffffffffffffff80821115611fdb578384fd5b818501915085601f830112611fee578384fd5b813581811115611ffc578485fd5b86602082850101111561200d578485fd5b60209290920196919550909350505050565b60008060008084860360c0811215612035578283fd5b85359450602086013561204781612b17565b9350604086013592506060605f1982011215612061578182fd5b506040516060810181811067ffffffffffffffff82111715612081578283fd5b8060405250606086013581526080860135602082015260a086013560408201528091505092959194509250565b6000806000604084860312156120c2578283fd5b83359250602084013567ffffffffffffffff8111156120df578283fd5b6120eb86828701611ef5565b9497909650939450505050565b6000806000806060858703121561210d578384fd5b8435935060208501359250604085013567ffffffffffffffff811115612131578283fd5b61213d87828801611ef5565b95989497509550505050565b600080600080600060808688031215612160578081fd5b8535945060208601359350604086013567ffffffffffffffff811115612184578182fd5b61219088828901611ef5565b96999598509660600135949350505050565b81835260006001600160fb1b038311156121ba578081fd5b6020830280836020870137939093016020019283525090919050565b60006001600160fb1b038311156121eb578081fd5b6020830280838637939093019283525090919050565b600061220e8284866121d6565b949350505050565b60008251612228818460208701612ae7565b9190910192915050565b90565b60008682528560208301528460408301526122546060830184866121d6565b979650505050505050565b600088825287602083015286604083015285606083015284608083015261228a60a0830184866121d6565b9998505050505050505050565b6001600160a01b0391909116815260200190565b60006020825261220e6020830184866121a2565b6000604082526122d36040830185876121a2565b9050826020830152949350505050565b6000606082526122f76060830186886121a2565b6020830194909452506040015292915050565b604080825283519082018190526000906020906060840190828701845b8281101561234357815184529284019290840190600101612327565b50505092019290925292915050565b901515815260200190565b90815260200190565b918252602082015260400190565b60006020825282602083015282846040840137818301604090810191909152601f909201601f19160101919050565b60006020825282518060208401526123c2816040850160208701612ae7565b601f01601f19169190910160400192915050565b602080825260129082015271115250d7d393d517d057d0d3d395149050d560721b604082015260600190565b602080825260119082015270135154d4d051d157d513d3d7d4d213d495607a1b604082015260600190565b602080825260169082015275494c4c4547414c5f494e49545f444154415f53495a4560501b604082015260600190565b60208082526010908201526f20a62922a0a22cafa3a7ab22a92727a960811b604082015260600190565b6020808252601590820152741253959053125117d41491559253d554d7d493d3d5605a1b604082015260600190565b6020808252601390820152720929cac82989288be869e9c8c928ebe9082a69606b1b604082015260600190565b6020808252601390820152721053149150511657d253925512505312569151606a1b604082015260600190565b6020808252601c908201527f43414e43454c5f414c4c4f5745445f54494d455f4f564552464c4f5700000000604082015260600190565b60208082526024908201527f4d4553534147455f43414e43454c4c4154494f4e5f4e4f545f414c4c4f57454460408201526317d6515560e21b606082015260800190565b6020808252600b908201526a1053149150511657d4d15560aa1b604082015260600190565b60208082526017908201527f4d41585f4c315f4d53475f4645455f4558434545444544000000000000000000604082015260600190565b6020808252601a908201527f494e56414c49445f46494e414c5f424c4f434b5f4e554d424552000000000000604082015260600190565b602080825260149082015273554e45585045435445445f494e49545f4441544160601b604082015260600190565b6020808252601690820152750929cac82989288bea082b2989e8288be988a9c8ea8960531b604082015260600190565b6020808252601690820152751112549150d517d0d0531317d11254d0531313d5d15160521b604082015260600190565b60208082526017908201527f4f4e4c595f43414e4449444154455f474f5645524e4f52000000000000000000604082015260600190565b6020808252601290820152712120a22fa4a724aa24a0a624ad20aa24a7a760711b604082015260600190565b6020808252601c908201527f494e56414c49445f4d4553534147455f5345474d454e545f53495a4500000000604082015260600190565b60208082526018908201527f535441524b4e45545f4f55545055545f544f4f5f4c4f4e470000000000000000604082015260600190565b6020808252601490820152731393d7d35154d4d051d157d513d7d0d05390d15360621b604082015260600190565b60208082526019908201527f535441524b4e45545f4f55545055545f544f4f5f53484f525400000000000000604082015260600190565b60208082526019908201527f5452554e43415445445f4d4553534147455f5041594c4f414400000000000000604082015260600190565b60208082526009908201526811925390531256915160ba1b604082015260600190565b6020808252600f908201526e4f4e4c595f474f5645524e414e434560881b604082015260600190565b6020808252600b908201526a4241445f4144445245535360a81b604082015260600190565b6020808252601390820152721253925517d110551057d513d3d7d4d3505313606a1b604082015260600190565b60208082526017908201527f4f544845525f43414e4449444154455f50454e44494e47000000000000000000604082015260600190565b6020808252601a908201527f494e56414c49445f4d4553534147455f544f5f434f4e53554d45000000000000604082015260600190565b60208082526013908201527211551217d514905394d1915497d19052531151606a1b604082015260600190565b6020808252600d908201526c27a7262cafa7a822a920aa27a960991b604082015260600190565b60208082526014908201527324a72b20a624a22fa12627a1a5afa72aa6a122a960611b604082015260600190565b602080825260149082015273474f5645524e4f525f53454c465f52454d4f564560601b604082015260600190565b6020808252600c908201526b2727aa2fa3a7ab22a92727a960a11b604082015260600190565b60208082526022908201527f4d4553534147455f43414e43454c4c4154494f4e5f4e4f545f52455155455354604082015261115160f21b606082015260800190565b60208082526021908201527f4c315f4d53475f4645455f4d5553545f42455f475245415445525f5448414e5f6040820152600360fc1b606082015260800190565b9283526020830191909152604082015260600190565b60008085851115612aa3578182fd5b83861115612aaf578182fd5b5050602083020193919092039150565b60008085851115612ace578081fd5b83861115612ada578081fd5b5050820193919092039150565b60005b83811015612b02578181015183820152602001612aea565b83811115612b11576000848401525b50505050565b6001600160a01b038116811461077057600080fdfe535441524b4e45545f312e305f494e49545f56455249464945525f41444452455353535441524b4e45545f312e305f524f4c45535f4f50455241544f52535f4d415050494e475f544147535441524b4e45545f312e305f4d5347494e475f4c31544f4c325f43414e43454c4c4154494f4e5f4d41505050494e47535441524b4e45545f312e305f494e49545f535441524b4e45545f53544154455f535452554354535441524b4e45545f312e305f494e49545f50524f4752414d5f484153485f55494e54535441524b4e45545f312e305f4d5347494e475f4c31544f4c325f43414e43454c4c4154494f4e5f44454c4159535441524b4e45545f312e305f535441524b4e45545f434f4e4649475f48415348535441524b4e45545f312e305f4d5347494e475f4c32544f4c315f4d41505050494e47535441524b4e45545f312e305f4d5347494e475f4c31544f4c325f4d41505050494e475f5632535441524b574152455f434f4e5452414354535f474f564552454e45445f46494e414c495a41424c455f312e305f544147a2646970667358221220749105af4323f28521c03a1b6b128ff7ceb5750ce7bcf9475b742af277f1611264736f6c634300060c0033", + "sourceMap": "729:7138:37:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1928:133:17;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;599:112:16;;;;;;;;;;-1:-1:-1;599:112:16;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;4556:497:17:-;;;;;;;;;;-1:-1:-1;4556:497:17;;;;;:::i;:::-;;:::i;778:86:10:-;;;;;;;;;;;;;:::i;5456:102:37:-;;;;;;;;;;;;;:::i;540:233:3:-;;;;;;;;;;-1:-1:-1;540:233:3;;;;;:::i;:::-;;:::i;:::-;;5617:99:37;;;;;;;;;;;;;:::i;2248:198::-;;;;;;;;;;-1:-1:-1;2248:198:37;;;;;:::i;:::-;;:::i;3591:844:17:-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;1486:1028:10:-;;;;;;;;;;-1:-1:-1;1486:1028:10;;;;;:::i;:::-;;:::i;705:144:1:-;;;;;;;;;;;;;:::i;1074:103:17:-;;;;;;;;;;;;;:::i;5649:1148::-;;;;;;;;;;-1:-1:-1;5649:1148:17;;;;;:::i;:::-;;:::i;1038:114:3:-;;;;;;;;;;-1:-1:-1;1038:114:3;;;;;:::i;:::-;;:::i;1324:122:17:-;;;;;;;;;;-1:-1:-1;1324:122:17;;;;;:::i;:::-;;:::i;5059:584::-;;;;;;;;;;-1:-1:-1;5059:584:17;;;;;:::i;:::-;;:::i;2067:152::-;;;;;;;;;;;;;:::i;840:121:16:-;;;;;;;;;;-1:-1:-1;840:121:16;;;;;:::i;:::-;;:::i;6058:1807:37:-;;;;;;;;;;-1:-1:-1;6058:1807:37;;;;;:::i;:::-;;:::i;2699:120::-;;;;;;;;;;;;;:::i;493:112:1:-;;;;;;;;;;;;;:::i;717:117:16:-;;;;;;;;;;-1:-1:-1;717:117:16;;;;;:::i;:::-;;:::i;967:81::-;;;;;;;;;;;;;:::i;5300:95:37:-;;;;;;;;;;;;;:::i;779:253:3:-;;;;;;;;;;-1:-1:-1;779:253:3;;;;;:::i;:::-;;:::i;2591:146:17:-;;;;;;;;;;-1:-1:-1;2591:146:17;;;;;:::i;:::-;;:::i;1452:122::-;;;;;;;;;;-1:-1:-1;1452:122:17;;;;;:::i;:::-;;:::i;2452:183:37:-;;;;;;;;;;-1:-1:-1;2452:183:37;;;;;:::i;:::-;;:::i;3415:118::-;;;;;;;;;;;;;:::i;1054:81:16:-;;;;;;;;;;;;;:::i;2037:205:37:-;;;;;;;;;;-1:-1:-1;2037:205:37;;;;;:::i;:::-;;:::i;5123:118::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;1928:133:17:-;1979:7;2005:49;2031:22;;;;;;;;;;;;;;;;;2005:25;:49::i;:::-;1998:56;;1928:133;:::o;599:112:16:-;664:4;687:17;699:4;687:11;:17::i;:::-;680:24;599:112;-1:-1:-1;;599:112:16:o;4556:497:17:-;4750:75;;4686:7;;;;4750:75;;4767:11;;4788:10;;4801:7;;;;;;4750:75;;;:::i;:::-;;;;;;;;;;;;;4727:108;;;;;;4709:126;;4882:1;4854:16;:14;:16::i;:::-;:25;;;;;;;;;;;;;:29;4846:68;;;;-1:-1:-1;;;4846:68:17;;;;;;;:::i;:::-;;;;;;;;;4929:53;;4962:10;;4949:11;;4929:53;;;;4974:7;;;;4929:53;:::i;:::-;;;;;;;;5021:1;4992:16;:14;:16::i;:::-;:25;;;;;;;;;;;;:30;;;;;;;;:25;4556:497;-1:-1:-1;;;;4556:497:17:o;778:86:10:-;829:4;778:86;:::o;5456:102:37:-;5507:6;5532:7;:5;:7::i;:::-;:19;;;5525:26;;5456:102;:::o;540:233:3:-;292:23:8;304:10;292:11;:23::i;:::-;284:51;;;;-1:-1:-1;;;284:51:8;;;;;;;:::i;:::-;635:23:3::1;646:11;635:10;:23::i;:::-;630:137;;704:4;674:14;:12;:14::i;:::-;-1:-1:-1::0;;;;;674:27:3;::::1;;::::0;;;::::1;::::0;;;;;;;;;:34;;-1:-1:-1;;674:34:3::1;::::0;::::1;;::::0;;;::::1;::::0;;;727:29;::::1;::::0;::::1;::::0;674:27;;727:29:::1;:::i;:::-;;;;;;;;630:137;540:233:::0;:::o;5617:99:37:-;5666:7;5692;:5;:7::i;:::-;:17;;;5685:24;;5617:99;:::o;2248:198::-;654:13:1;:11;:13::i;:::-;653:14;645:36;;;;-1:-1:-1;;;645:36:1;;;;;;;:::i;:::-;292:23:8::1;304:10;292:11;:23::i;:::-;284:51;;;::::0;-1:-1:-1;;;284:51:8;;::::1;::::0;::::1;;;:::i;:::-;2364:10:37::2;2346:58;2376:12;:10;:12::i;:::-;2390:13;2346:58;;;;;;;:::i;:::-;;;;;;;;2414:25;2425:13;2414:10;:25::i;3591:844:17:-:0;3746:7;3755;3794:1;3782:9;:13;3774:59;;;;-1:-1:-1;;;3774:59:17;;;;;;;:::i;:::-;3864:16;:14;:16::i;:::-;3851:9;:29;;3843:65;;;;-1:-1:-1;;;3843:65:17;;;;;;;:::i;:::-;3918:13;3934:20;:18;:20::i;:::-;3918:36;;3964:60;3990:22;;;;;;;;;;;;;;;;;4014:5;4022:1;4014:9;3964:25;:60::i;:::-;4039:74;;4077:8;;4066:9;;4054:10;;4039:74;;;;4087:7;;;;4096:5;;4103:9;;4039:74;:::i;:::-;;;;;;;;4123:15;4141:53;4158:9;4169:8;4179:7;;4188:5;4141:16;:53::i;:::-;4123:71;;4382:9;4394:1;4382:13;4354:16;:14;:16::i;:::-;:25;;;;;;;;;;;;:41;:25;4422:5;;-1:-1:-1;3591:844:17;-1:-1:-1;;;;;3591:844:17:o;1486:1028:10:-;571:4:4;-1:-1:-1;;;;;554:5:4;:22;;;546:57;;;;-1:-1:-1;;;546:57:4;;;;;;;:::i;:::-;1564:17:10::1;1589:19;:17;:19::i;:::-;1584:2;:24:::0;;::::1;::::0;-1:-1:-1;1645:14:10;::::1;1677:31:::0;;::::1;;1669:63;;;::::0;-1:-1:-1;;;1669:63:10;;::::1;::::0;::::1;;;:::i;:::-;1742:18;1774:32;1789:16:::0;1779:9;1774:4;;:32:::1;:::i;:::-;1763:55;;;;;;;:::i;:::-;1742:76:::0;-1:-1:-1;1829:35:10::1;;1867:16;1873:9:::0;1829:35;1867:4;;:16:::1;:::i;:::-;1829:54;;;;1894:49;1922:20;;1894:27;:49::i;:::-;1954:23;;1980;:4:::0;1985:16;1980:4;;:23:::1;:::i;:::-;1954:49:::0;;-1:-1:-1;1954:49:10;-1:-1:-1;;;;;;2098:26:10;::::1;::::0;2094:122:::1;;2140:45;2164:10;2176:8;;2140:23;:45::i;:::-;2199:7;;;;;;;;;2094:122;2230:15;:13;:15::i;:::-;2226:282;;;2269:20:::0;;2261:53:::1;;;::::0;-1:-1:-1;;;2261:53:10;;::::1;::::0;::::1;;;:::i;:::-;2226:282;;;2394:26;2411:8;;2394:16;:26::i;:::-;2434:33;2458:8;;2434:23;:33::i;:::-;2481:16;:14;:16::i;:::-;613:1:4;;;;;;;;1486:1028:10::0;;:::o;705:144:1:-;292:23:8;304:10;292:11;:23::i;:::-;284:51;;;;-1:-1:-1;;;284:51:8;;;;;;;:::i;:::-;654:13:1::1;:11;:13::i;:::-;653:14;645:36;;;::::0;-1:-1:-1;;;645:36:1;;::::1;::::0;::::1;;;:::i;:::-;772:44:::2;798:11;;;;;;;;;;;;;;;;;811:4;772:25;:44::i;:::-;831:11;::::0;::::2;::::0;;;::::2;705:144::o:0;1074:103:17:-;1060:7;1074:103;:::o;5649:1148::-;5847:68;;5823:7;;5890:8;;5879:9;;5867:10;;5847:68;;;;5900:7;;;;5909:5;;5847:68;:::i;:::-;;;;;;;;6133:15;6151:53;6168:9;6179:8;6189:7;;6198:5;6151:16;:53::i;:::-;6133:71;;6214:21;6238:16;:14;:16::i;:::-;:25;;;;;;;;;;;;;;-1:-1:-1;6281:18:17;6273:51;;;;-1:-1:-1;;;6273:51:17;;;;;;;:::i;:::-;6335:19;6357:28;:26;:28::i;:::-;:37;;;;;;;;;;;;;;-1:-1:-1;6412:16:17;6404:63;;;;-1:-1:-1;;;6404:63:17;;;;;;;:::i;:::-;6478:25;6520:26;:24;:26::i;:::-;6506:11;:40;6478:68;;6585:11;6564:17;:32;;6556:73;;;;-1:-1:-1;;;6556:73:17;;;;;;;:::i;:::-;6666:17;6647:15;:36;;6639:85;;;;-1:-1:-1;;;6639:85:17;;;;;;;:::i;:::-;6763:1;6735:16;:14;:16::i;:::-;:25;;;;;;;;;;;;:29;-1:-1:-1;6735:25:17;;5649:1148;-1:-1:-1;;;;;;;;5649:1148:17:o;1038:114:3:-;1102:4;1125:14;:12;:14::i;:::-;-1:-1:-1;;;;;1125:20:3;;;;;;;;;;;;;-1:-1:-1;1125:20:3;;;;;;;1038:114::o;1324:122:17:-;1388:7;1414:16;:14;:16::i;:::-;:25;;;;;;-1:-1:-1;1414:25:17;;;;;1324:122::o;5059:584::-;5268:79;;5244:7;;5322:8;;5311:9;;5299:10;;5268:79;;;;5332:7;;;;5341:5;;5268:79;:::i;:::-;;;;;;;;5357:15;5375:53;5392:9;5403:8;5413:7;;5422:5;5375:16;:53::i;:::-;5357:71;;5438:21;5462:16;:14;:16::i;:::-;:25;;;;;;;;;;;;;;-1:-1:-1;5505:17:17;5497:50;;;;-1:-1:-1;;;5497:50:17;;;;;;;:::i;:::-;5597:15;5557:28;:26;:28::i;:::-;:37;;;;;;;;;;;;:55;-1:-1:-1;5557:37:17;5059:584;-1:-1:-1;;;;;;5059:584:17:o;2067:152::-;2124:7;2150:62;2176:35;;;;;;;;;;;;;;;;;2150:25;:62::i;840:121:16:-;919:35;935:18;919:15;:35::i;6058:1807:37:-;341:22:9;352:10;341;:22::i;:::-;333:48;;;;-1:-1:-1;;;333:48:9;;;;;;;:::i;:::-;6331:25:37::1;6359:7;:5;:7::i;:::-;:19;;;6331:47;;6425:38;6449:13;;6425:23;:38::i;:::-;6544:13;;833:1:15;6544:48:37;;;;;;;;;;;;;6528:12;:10;:12::i;:::-;:64;6507:130;;;::::0;-1:-1:-1;;;6507:130:37;;::::1;::::0;::::1;;;:::i;:::-;6648:29;6663:13;;6648:7;:5;:7::i;:::-;:14:::0;:29;:14:::1;:29::i;:::-;880:1:15;6985:155:37;7054:4;7072:28;:13:::0;880:1:15;7072:13:37;;:28:::1;:::i;:::-;7114:16;:14;:16::i;:::-;6985:30;:155::i;:::-;6969:171;7205:156;7274:5;7293:28;:13:::0;6969:171;7293:13;;:28:::1;:::i;:::-;7335:16;:14;:16::i;7205:156::-;7189:172;7379:36:::0;;::::1;7371:73;;;::::0;-1:-1:-1;;;7371:73:37;;::::1;::::0;::::1;;;:::i;:::-;7588:34;7625:7;:5;:7::i;:::-;7588:44;;7647:71;7662:6;:17;;;7681:6;:18;;;7701:6;:16;;;7647:71;;;;;;;;:::i;:::-;;;;;;;;7805:18;7826:1;7805:22;7783:6;:18;;;:44;7775:83;;;::::0;-1:-1:-1;;;7775:83:37;;::::1;::::0;::::1;;;:::i;:::-;391:1:9;;;6058:1807:37::0;;:::o;2699:120::-;2743:7;2769:43;2795:16;;;;;;;;;;;;;;;;;2769:25;:43::i;493:112:1:-;537:4;560:38;586:11;;;;;;;;;;;;;;;;;560:25;:38::i;717:117:16:-;794:33;815:11;794:20;:33::i;967:81::-;1022:19;:17;:19::i;:::-;967:81::o;5300:95:37:-;5344:7;5370;:5;:7::i;:::-;:18;;-1:-1:-1;5300:95:37;:::o;779:253:3:-;292:23:8;304:10;292:11;:23::i;:::-;284:51;;;;-1:-1:-1;;;284:51:8;;;;;;;:::i;:::-;879:27:3::1;890:15;879:10;:27::i;:::-;875:151;;;956:5;922:14;:12;:14::i;:::-;-1:-1:-1::0;;;;;922:31:3;::::1;;::::0;;;::::1;::::0;;;;;;;;;:39;;-1:-1:-1;;922:39:3::1;::::0;::::1;;::::0;;;::::1;::::0;;;980:35;::::1;::::0;::::1;::::0;922:31;;980:35:::1;:::i;2591:146:17:-:0;2667:7;2693:28;:26;:28::i;1452:122::-;1516:7;1542:16;:14;:16::i;2452:183:37:-;654:13:1;:11;:13::i;:::-;653:14;645:36;;;;-1:-1:-1;;;645:36:1;;;;;;;:::i;:::-;292:23:8::1;304:10;292:11;:23::i;:::-;284:51;;;::::0;-1:-1:-1;;;284:51:8;;::::1;::::0;::::1;;;:::i;:::-;2588:40:37::2;2613:14;2588:24;:40::i;3415:118::-:0;3458:7;3484:42;3510:15;;;;;;;;;;;;;;;;;3484:25;:42::i;1054:81:16:-;1109:19;:17;:19::i;2037:205:37:-;654:13:1;:11;:13::i;:::-;653:14;645:36;;;;-1:-1:-1;;;645:36:1;;;;;;;:::i;:::-;292:23:8::1;304:10;292:11;:23::i;:::-;284:51;;;::::0;-1:-1:-1;;;284:51:8;;::::1;::::0;::::1;;;:::i;:::-;2156:10:37::2;2137:61;2168:13;:11;:13::i;:::-;2183:14;2137:61;;;;;;;:::i;:::-;;;;;;;;2208:27;2220:14;2208:11;:27::i;5123:118::-:0;5200:34;;;;;;;;;;;;;;;;;5123:118;:::o;1465:209:12:-;1530:14;1556:12;1598:4;1581:22;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;1581:22:12;;;;;;1571:33;;1581:22;1571:33;;;;1647:11;;;-1:-1:-1;;;1623:45:12:o;1988:189:0:-;2055:4;2071:32;2106:19;:17;:19::i;:::-;-1:-1:-1;;;;;2142:28:0;;;;:22;:28;;;;;;;;-1:-1:-1;;2142:28:0;;;;;;;1988:189::o;1754:168:17:-;1803:35;1857:58;1894:20;;;;;;;;;;;;;;;;;1857:36;:58::i;3722:232:37:-;3762:39;3813:16;3859;;;;;;;;;;;;;;;;;3842:34;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;3842:34:37;;;;;;3832:45;;3842:34;3832:45;;;;;;-1:-1:-1;;3896:52:37:o;318:170:18:-;374:32;425:56;459:21;;;;;;;;;;;;;;;;;425:33;:56::i;3242:110:37:-;3296:49;3322:15;;;;;;;;;;;;;;;;;3339:5;1680:192:12;1756:12;1798:4;1781:22;;;;;;;;:::i;:::-;;;;;;;;;;;;;1771:33;;;;;;1756:48;;1850:5;1844:4;1837:19;1823:43;;;:::o;3048:481:17:-;3280:228;;3215:7;;3280:228;;3326:10;;3359:9;;3390:5;;3417:8;;3447:7;;;;;;3280:228;;;:::i;:::-;;;;;;;;;;;;;3253:269;;;;;;3234:288;;3048:481;;;;;;;:::o;1580:168::-;1629:35;1683:58;1720:20;;;;;;;;;;;;;;;;;1683:36;:58::i;2520:540:10:-;2648:36;-1:-1:-1;;;;;2648:34:10;;;:36::i;:::-;2640:67;;;;-1:-1:-1;;;2640:67:10;;;;;;;:::i;:::-;2879:57;;2788:12;;2802:23;;-1:-1:-1;;;;;2829:36:10;;;-1:-1:-1;;;2902:24:10;2879:57;;2928:7;;;;2879:57;;;:::i;:::-;;;;-1:-1:-1;;2879:57:10;;;;;;;;;;;;;;-1:-1:-1;;;;;2879:57:10;-1:-1:-1;;;;;;2879:57:10;;;;;;;;;;;2829:117;;;;2879:57;2829:117;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2787:159;;;;2964:7;2980:10;2956:36;;;;;-1:-1:-1;;;2956:36:10;;;;;;;;:::i;:::-;-1:-1:-1;3010:17:10;;:10;;:22;3002:51;;;;-1:-1:-1;;;3002:51:10;;;;;;;;:::i;:::-;;2520:540;;;;;:::o;3960:105:37:-;4017:4;4040:13;:11;:13::i;:::-;:18;;;-1:-1:-1;3960:105:37;:::o;4172:266::-;4275:6;4260:21;;4252:56;;;;-1:-1:-1;;;4252:56:37;;;;;;;:::i;:::-;4318:20;4352:9;4358:2;4318:20;4352:4;;:9;:::i;:::-;4341:32;;;;;;;:::i;:::-;4318:55;-1:-1:-1;4391:17:37;4383:48;;;;-1:-1:-1;;;4383:48:37;;;;;;;:::i;:::-;4172:266;;;:::o;4544:505::-;4640:20;4674:17;4705:19;4738:39;;:::i;:::-;4790:66;;;;4801:4;4790:66;:::i;:::-;4626:230;;;;;;;;4867:25;4879:12;4867:11;:25::i;:::-;4902:29;4921:9;4902:18;:29::i;:::-;4941:26;4954:12;4941:7;:5;:7::i;:::-;:12;;:26::i;:::-;4977:23;4988:11;4977:10;:23::i;:::-;5010:32;5035:6;5010:24;:32::i;1665:317:0:-;1710:32;1745:19;:17;:19::i;:::-;1783:15;;;;;;-1:-1:-1;;;;1783:15:0;;;;1782:16;1774:48;;;;-1:-1:-1;;;1774:48:0;;;;;;;:::i;:::-;1850:4;1832:15;;:22;;-1:-1:-1;;;;1832:22:0;-1:-1:-1;;;1832:22:0;;;1946:29;1964:10;1946:17;:29::i;2743:221:17:-;2828:35;2886:71;2923:33;;;;;;;;;;;;;;;;;2886:36;:71::i;4088:402:0:-;292:23:8;304:10;292:11;:23::i;:::-;284:51;;;;-1:-1:-1;;;284:51:8;;;;;;;:::i;:::-;-1:-1:-1;;;;;4183:32:0;::::1;:10;:32;;4175:65;;;::::0;-1:-1:-1;;;4175:65:0;;::::1;::::0;::::1;;;:::i;:::-;4250:32;4285:19;:17;:19::i;:::-;4250:54;;4322:31;4334:18;4322:11;:31::i;:::-;4314:56;;;::::0;-1:-1:-1;;;4314:56:0;;::::1;::::0;::::1;;;:::i;:::-;-1:-1:-1::0;;;;;4380:42:0;::::1;4425:5;4380:42:::0;;;::::1;::::0;;;;;;;;:50;;-1:-1:-1;;4380:50:0::1;::::0;;4445:38;::::1;::::0;::::1;::::0;4380:42;;4445:38:::1;:::i;:::-;;;;;;;;345:1:8;4088:402:0::0;:::o;1965:151:15:-;880:1;2047:32;;2039:70;;;;-1:-1:-1;;;2039:70:15;;;;;;;:::i;598:803:19:-;808:1;787:17;;;:22;;;;;;;870:14;;726:1:15;870:50:19;;;;;;;;;;;;;848:5;:17;;;840:80;819:147;;;;-1:-1:-1;;;819:147:19;;;;;;;:::i;:::-;995:14;;779:1:15;995:48:19;;;;;;;;;;;;;;977:15;;;:66;-1:-1:-1;1054:41:19;;1098:46;1129:14;;1098:30;:46::i;:::-;1054:90;;;;1195:62;1234:22;;1195:38;:62::i;:::-;1175:16;;:82;1154:150;;;;-1:-1:-1;;;1154:150:19;;;;;;;:::i;:::-;1333:61;1371:22;;1333:37;:61::i;:::-;1314:80;;;-1:-1:-1;;;;598:803:19:o;2748:3369:15:-;2921:7;2940:26;2969:18;;2988:1;2969:21;;;;;;;;;;;;;2940:50;;3029:5;3008:18;:26;3000:67;;;;-1:-1:-1;;;3000:67:15;;;;;;;:::i;:::-;3095:1;3134:27;;;3078:14;3214:8;:80;;1399:1;3214:80;;;1059:1;3214:80;3172:132;;3315:20;3349:2443;3365:17;3356:6;:26;3349:2443;;;3428:26;;;3476:47;;;3468:77;;;;-1:-1:-1;;;3468:77:15;;;;;;;:::i;:::-;3560:21;3584:18;;3603:19;3584:39;;;;;;;;;;;;;3560:63;;3661:5;3645:13;:21;3637:56;;;;-1:-1:-1;;;3637:56:15;;;;;;;:::i;:::-;3728:39;;;3750:1;3728:39;3789:38;;;;3781:76;;;;-1:-1:-1;;;3781:76:15;;;;;;;:::i;:::-;3876:8;3872:1877;;;3904:19;3974:18;;3993:6;3974:36;4000:9;3974:36;;;;;;;:::i;:::-;3957:54;;;;;;;;;:::i;:::-;;;;;;;;;;;;;3926:103;;;;;;3904:125;;4237:18;;999:1;4256:6;:40;4237:60;;;;;;;;;;;;;-1:-1:-1;;;;;4053:394:15;4118:18;;941:1;4137:6;:42;4118:62;;;;;;;;;;;;;4053:394;4364:18;;1111:1;4383:6;:34;4364:64;4418:9;4364:64;;;;;;;:::i;:::-;4053:394;;;;;;;:::i;:::-;;;;;;;;4465:21;;;;;;;;;;;:26;;4490:1;4465:26;;;3872:1877;;;4552:19;4626:18;;4645:6;4626:36;4652:9;4626:36;;;;;;;:::i;:::-;4609:54;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;4609:54:15;;;;;;4574:111;;4609:54;4574:111;;;;4708:21;4732;;;;;;;;;;4574:111;;-1:-1:-1;4732:21:15;4775:56;;;;-1:-1:-1;;;4775:56:15;;;;;;;:::i;:::-;4932:1;4908:21;;;;;;;;;;:25;;;4853:33;;;;-1:-1:-1;;4853:33:15;;4986:18;;1283:1;5005:35;;4986:55;;;;;;;;;;;;;4970:71;;5059:29;5124:18;;1451:1;5143:6;:34;5124:64;5178:9;5124:64;;;;;;;:::i;:::-;5059:147;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5534:18;;1339:1;5553:6;:38;5534:58;;;;;;;;;;;;;5419:18;;1230:1;5438:6;:40;5419:60;;;;;;;;;;;;;5307:18;;1172:1;5326:6;:42;5307:62;;;;;;;;;;;;;-1:-1:-1;;;;;5229:505:15;;5646:12;5711:5;5229:505;;;;;;;:::i;:::-;;;;;;;;3872:1877;;;5772:9;-1:-1:-1;3349:2443:15;;-1:-1:-1;;3349:2443:15;;5819:17;5809:6;:27;5801:68;;;;-1:-1:-1;;;5801:68:15;;;;;;;:::i;:::-;5884:16;;5880:207;;5983:40;;5965:12;;5983:10;;6006:12;;5983:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5964:59;;;6045:7;6037:39;;;;-1:-1:-1;;;6037:39:15;;;;;;;:::i;:::-;5880:207;;-1:-1:-1;6104:6:15;;2748:3369;-1:-1:-1;;;;;;;;2748:3369:15:o;2537:447:0:-;292:23:8;304:10;292:11;:23::i;:::-;284:51;;;;-1:-1:-1;;;284:51:8;;;;;;;:::i;:::-;2622:32:0::1;2657:19;:17;:19::i;:::-;2622:54:::0;-1:-1:-1;;;;;;2694:27:0;::::1;2686:51;;;::::0;-1:-1:-1;;;2686:51:0;;::::1;::::0;::::1;;;:::i;:::-;2756:24;2768:11;2756;:24::i;:::-;2755:25;2747:54;;;::::0;-1:-1:-1;;;2747:54:0;;::::1;::::0;::::1;;;:::i;:::-;2819:21;::::0;::::1;::::0;-1:-1:-1;;;;;2819:21:0::1;:37:::0;2811:73:::1;;;::::0;-1:-1:-1;;;2811:73:0;;::::1;::::0;::::1;;;:::i;:::-;2894:21;::::0;::::1;:35:::0;;-1:-1:-1;;;;;;2894:35:0::1;-1:-1:-1::0;;;;;2894:35:0;::::1;;::::0;;2944:33:::1;::::0;::::1;::::0;::::1;::::0;2894:35;;2944:33:::1;:::i;3649:382::-:0;3778:32;3813:19;:17;:19::i;:::-;3864:21;;;;;;-1:-1:-1;;;;;;3864:21:0;3850:10;:35;3842:71;;;;-1:-1:-1;;;3842:71:0;;;;;;;:::i;:::-;3949:29;3967:10;3949:17;:29::i;:::-;3988:21;;:36;;-1:-1:-1;;;;;;3988:36:0;;;3649:382::o;2225:162:17:-;2302:78;2328:35;;;;;;;;;;;;;;;;;2365:14;2302:25;:78::i;2251:280:0:-;292:23:8;304:10;292:11;:23::i;:::-;284:51;;;;-1:-1:-1;;;284:51:8;;;;;;;:::i;:::-;2314:32:0::1;2349:19;:17;:19::i;:::-;2382:21;::::0;::::1;::::0;;;-1:-1:-1;;;;;;2382:21:0::1;:37:::0;2378:147:::1;;2435:21;::::0;::::1;:36:::0;;-1:-1:-1;;;;;;2435:36:0::1;::::0;;2490:24:::1;::::0;::::1;::::0;-1:-1:-1;;2490:24:0::1;345:1:8;2251:280:0:o:0;2884:112:37:-;2939:50;2965:16;;;;;;;;;;;;;;;;;2983:5;2939:25;:50::i;343:250:16:-;404:32;448:16;494:28;;;;;;;;;;;;;;;;;477:46;;;;;;;;:::i;258:298:12:-;358:50;424:16;470:4;453:22;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;453:22:12;;;;;;443:33;;453:22;443:33;;;;;;-1:-1:-1;;;495:55:12:o;346:190:11:-;475:20;521:8;;;346:190::o;3539:130:37:-;3601:61;3634:20;;;;;;;;;;;;;;;;;3656:5;3601:32;:61::i;227:222:19:-;324:20;;305:39;;374:21;;;;354:17;;;:41;423:19;;;405:15;;;;:37;227:222::o;3309:334:0:-;3384:24;3396:11;3384;:24::i;:::-;3383:25;3375:54;;;;-1:-1:-1;;;3375:54:0;;;;;;;:::i;:::-;3439:32;3474:19;:17;:19::i;:::-;-1:-1:-1;;;;;3503:35:0;;:22;:35;;;;;;;;;;;;:42;;-1:-1:-1;;3503:42:0;-1:-1:-1;3503:42:0;;;3601:35;3503;;-1:-1:-1;3601:35:0;;;;3503;;3601;:::i;2225:210:15:-;2329:18;;2370:58;2426:1;2329:18;2370:11;;:58;:::i;:::-;2363:65;;;;2225:210;;;;;;:::o;171:177::-;284:7;314:24;;339:1;314:27;;;;;;;;;;;;;307:34;;171:177;;;;:::o;413:176::-;525:7;555:24;;580:1;555:27;;;;;;2472:189:12;2596:3;2563:21;2579:4;2563:15;:21::i;:::-;-1:-1:-1;;;;;2563:37:12;;2555:61;;;;-1:-1:-1;;;2555:61:12;;;;;;;:::i;:::-;2626:28;2642:4;2648:5;2626:15;:28::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;:::o;313:352::-;;;443:3;436:4;428:6;424:17;420:27;410:2;;-1:-1;;451:12;410:2;-1:-1;481:20;;521:18;510:30;;507:2;;;-1:-1;;543:12;507:2;587:4;579:6;575:17;563:29;;638:3;587:4;;622:6;618:17;579:6;604:32;;601:41;598:2;;;655:1;;645:12;2106:241;;2210:2;2198:9;2189:7;2185:23;2181:32;2178:2;;;-1:-1;;2216:12;2178:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;2268:63;2172:175;-1:-1;;;2172:175::o;2618:397::-;;;2757:2;2745:9;2736:7;2732:23;2728:32;2725:2;;;-1:-1;;2763:12;2725:2;2821:17;2808:31;2859:18;2851:6;2848:30;2845:2;;;-1:-1;;2881:12;2845:2;2919:80;2991:7;2982:6;2971:9;2967:22;2919:80;:::i;:::-;2901:98;;;;-1:-1;2719:296;-1:-1;;;;2719:296::o;3022:241::-;;3126:2;3114:9;3105:7;3101:23;3097:32;3094:2;;;-1:-1;;3132:12;3094:2;-1:-1;740:20;;3088:175;-1:-1;3088:175::o;3270:365::-;;;3393:2;3381:9;3372:7;3368:23;3364:32;3361:2;;;-1:-1;;3399:12;3361:2;3457:17;3444:31;3495:18;;3487:6;3484:30;3481:2;;;-1:-1;;3517:12;3481:2;3602:6;3591:9;3587:22;;;938:3;931:4;923:6;919:17;915:27;905:2;;-1:-1;;946:12;905:2;989:6;976:20;3495:18;1008:6;1005:30;1002:2;;;-1:-1;;1038:12;1002:2;1133:3;3393:2;1113:17;1074:6;1099:32;;1096:41;1093:2;;;-1:-1;;1140:12;1093:2;3393;1070:17;;;;;3537:82;;-1:-1;3355:280;;-1:-1;;;;3355:280::o;3890:679::-;;;;;4064:9;4055:7;4051:23;4076:3;4051:23;4047:33;4044:2;;;-1:-1;;4083:12;4044:2;2049:6;2036:20;4135:63;;4235:2;4286:9;4282:22;217:20;242:41;277:5;242:41;:::i;:::-;4243:71;-1:-1;4351:2;4390:22;;2036:20;;-1:-1;4459:2;-1:-1;;1427:19;;1423:30;1420:2;;;-1:-1;;1456:12;1420:2;;4351;45663:9;4459:2;45699:6;45695:17;45806:6;45794:10;45791:22;45770:18;45758:10;45755:34;45752:62;45749:2;;;-1:-1;;45817:12;45749:2;45847:10;4351:2;45836:22;;4459:2;4525:9;4521:22;2036:20;1574:16;1567:75;1763:22;4525:9;1763:22;1234:20;4235:2;1729:5;1725:16;1718:74;1912:22;4525:9;1912:22;2036:20;4351:2;1877:5;1873:16;1866:75;4467:86;;;;4038:531;;;;;;;:::o;4576:522::-;;;;4732:2;4720:9;4711:7;4707:23;4703:32;4700:2;;;-1:-1;;4738:12;4700:2;2049:6;2036:20;4790:63;;4918:2;4907:9;4903:18;4890:32;4942:18;4934:6;4931:30;4928:2;;;-1:-1;;4964:12;4928:2;5002:80;5074:7;5065:6;5054:9;5050:22;5002:80;:::i;:::-;4694:404;;4984:98;;-1:-1;4984:98;;-1:-1;;;;4694:404::o;5105:647::-;;;;;5278:2;5266:9;5257:7;5253:23;5249:32;5246:2;;;-1:-1;;5284:12;5246:2;2049:6;2036:20;5336:63;;5436:2;5479:9;5475:22;2036:20;5444:63;;5572:2;5561:9;5557:18;5544:32;5596:18;5588:6;5585:30;5582:2;;;-1:-1;;5618:12;5582:2;5656:80;5728:7;5719:6;5708:9;5704:22;5656:80;:::i;:::-;5240:512;;;;-1:-1;5638:98;-1:-1;;;;5240:512::o;5759:773::-;;;;;;5949:3;5937:9;5928:7;5924:23;5920:33;5917:2;;;-1:-1;;5956:12;5917:2;2049:6;2036:20;6008:63;;6108:2;6151:9;6147:22;2036:20;6116:63;;6244:2;6233:9;6229:18;6216:32;6268:18;6260:6;6257:30;6254:2;;;-1:-1;;6290:12;6254:2;6328:80;6400:7;6391:6;6380:9;6376:22;6328:80;:::i;:::-;5911:621;;;;-1:-1;6310:98;6445:2;6484:22;2036:20;;5911:621;-1:-1;;;;5911:621::o;6872:467::-;46663:19;;;6872:467;-1:-1;;;;;7120:78;;7117:2;;;-1:-1;;7201:12;7117:2;46712:4;7236:6;7232:17;48959:6;48954:3;46712:4;46707:3;46703:14;48936:30;48997:16;;;;46712:4;48997:16;48990:27;;;-1:-1;48997:16;;7004:335;-1:-1;7004:335::o;7378:503::-;;-1:-1;;;;;7662:78;;7659:2;;;-1:-1;;7743:12;7659:2;7786:4;7778:6;7774:17;48959:6;48954:3;48949;48936:30;48997:16;;;;48990:27;;;-1:-1;48997:16;;7528:353;-1:-1;7528:353::o;22734:361::-;;22935:135;23066:3;23057:6;23049;22935:135;:::i;:::-;23080:10;22916:179;-1:-1;;;;22916:179::o;23102:271::-;;9337:5;46131:12;9448:52;9493:6;9488:3;9481:4;9474:5;9470:16;9448:52;:::i;:::-;9512:16;;;;;23236:137;-1:-1;;23236:137::o;23662:379::-;24026:10;23850:191::o;24048:772::-;;8830:5;8807:3;8800:37;8830:5;24417:2;24412:3;24408:12;8800:37;8830:5;24519:12;24412:3;24519:12;8800:37;24660:135;24630:12;24412:3;24630:12;24782:6;24774;24660:135;:::i;:::-;24805:10;24308:512;-1:-1;;;;;;;24308:512::o;24827:1050::-;;8830:5;8807:3;8800:37;8830:5;25252:2;25247:3;25243:12;8800:37;8830:5;25354:12;25247:3;25354:12;8800:37;8830:5;25465:12;25247:3;25465:12;8800:37;8830:5;25576:12;25247:3;25576:12;8800:37;25717:135;25687:12;25247:3;25687:12;25839:6;25831;25717:135;:::i;:::-;25862:10;25143:734;-1:-1;;;;;;;;;25143:734::o;25884:222::-;-1:-1;;;;;48732:54;;;;6792:37;;26011:2;25996:18;;25982:124::o;26113:390::-;;26300:2;26321:17;26314:47;26375:118;26300:2;26289:9;26285:18;26479:6;26471;26375:118;:::i;26510:501::-;;26725:2;26746:17;26739:47;26800:118;26725:2;26714:9;26710:18;26904:6;26896;26800:118;:::i;:::-;26792:126;;8830:5;26997:2;26986:9;26982:18;8800:37;26696:315;;;;;;:::o;27018:612::-;;27261:2;27282:17;27275:47;27336:118;27261:2;27250:9;27246:18;27440:6;27432;27336:118;:::i;:::-;27533:2;27518:18;;8800:37;;;;-1:-1;27616:2;27601:18;8800:37;27328:126;27232:398;-1:-1;;27232:398::o;27637:481::-;27842:2;27856:47;;;46131:12;;27827:18;;;46663:19;;;27637:481;;46712:4;;46703:14;;;;45985;;;27637:481;8328:260;8353:6;8350:1;8347:13;8328:260;;;8414:13;;8800:37;;6693:14;;;;46518;;;;8375:1;8368:9;8328:260;;;-1:-1;;;28089:18;;8800:37;;;;27909:116;27813:305;-1:-1;;27813:305::o;28125:210::-;48487:13;;48480:21;8683:34;;28246:2;28231:18;;28217:118::o;28342:222::-;8800:37;;;28469:2;28454:18;;28440:124::o;28571:333::-;8800:37;;;28890:2;28875:18;;8800:37;28726:2;28711:18;;28697:207::o;28911:326::-;;29066:2;29087:17;29080:47;46675:6;29066:2;29055:9;29051:18;46663:19;48959:6;48954:3;46703:14;29055:9;46703:14;48936:30;48997:16;;;46703:14;48997:16;;;48990:27;;;;49473:7;49457:14;;;-1:-1;;49453:28;9124:39;;;29037:200;-1:-1;29037:200::o;29469:310::-;;29616:2;29637:17;29630:47;9802:5;46131:12;46675:6;29616:2;29605:9;29601:18;46663:19;9896:52;9941:6;46703:14;29605:9;46703:14;29616:2;9922:5;9918:16;9896:52;:::i;:::-;49473:7;49457:14;-1:-1;;49453:28;9960:39;;;;46703:14;9960:39;;29587:192;-1:-1;;29587:192::o;29786:416::-;29986:2;30000:47;;;10603:2;29971:18;;;46663:19;-1:-1;;;46703:14;;;10619:41;10679:12;;;29957:245::o;30209:416::-;30409:2;30423:47;;;10930:2;30394:18;;;46663:19;-1:-1;;;46703:14;;;10946:40;11005:12;;;30380:245::o;30632:416::-;30832:2;30846:47;;;11256:2;30817:18;;;46663:19;-1:-1;;;46703:14;;;11272:45;11336:12;;;30803:245::o;31055:416::-;31255:2;31269:47;;;11587:2;31240:18;;;46663:19;-1:-1;;;46703:14;;;11603:39;11661:12;;;31226:245::o;31478:416::-;31678:2;31692:47;;;11912:2;31663:18;;;46663:19;-1:-1;;;46703:14;;;11928:44;11991:12;;;31649:245::o;31901:416::-;32101:2;32115:47;;;12242:2;32086:18;;;46663:19;-1:-1;;;46703:14;;;12258:42;12319:12;;;32072:245::o;32324:416::-;32524:2;32538:47;;;12570:2;32509:18;;;46663:19;-1:-1;;;46703:14;;;12586:42;12647:12;;;32495:245::o;32747:416::-;32947:2;32961:47;;;12898:2;32932:18;;;46663:19;12934:30;46703:14;;;12914:51;12984:12;;;32918:245::o;33170:416::-;33370:2;33384:47;;;13235:2;33355:18;;;46663:19;13271:34;46703:14;;;13251:55;-1:-1;;;13326:12;;;13319:28;13366:12;;;33341:245::o;33593:416::-;33793:2;33807:47;;;13617:2;33778:18;;;46663:19;-1:-1;;;46703:14;;;13633:34;13686:12;;;33764:245::o;34016:416::-;34216:2;34230:47;;;13937:2;34201:18;;;46663:19;13973:25;46703:14;;;13953:46;14018:12;;;34187:245::o;34439:416::-;34639:2;34653:47;;;14269:2;34624:18;;;46663:19;14305:28;46703:14;;;14285:49;14353:12;;;34610:245::o;34862:416::-;35062:2;35076:47;;;14604:2;35047:18;;;46663:19;-1:-1;;;46703:14;;;14620:43;-1:-1;14682:12;;35033:245::o;35285:416::-;35485:2;35499:47;;;14933:2;35470:18;;;46663:19;-1:-1;;;46703:14;;;14949:45;15013:12;;;35456:245::o;35708:416::-;35908:2;35922:47;;;15264:2;35893:18;;;46663:19;-1:-1;;;46703:14;;;15280:45;15344:12;;;35879:245::o;36131:416::-;36331:2;36345:47;;;15595:2;36316:18;;;46663:19;15631:25;46703:14;;;15611:46;15676:12;;;36302:245::o;36554:416::-;36754:2;36768:47;;;15927:2;36739:18;;;46663:19;-1:-1;;;46703:14;;;15943:41;16003:12;;;36725:245::o;36977:416::-;37177:2;37191:47;;;16254:2;37162:18;;;46663:19;16290:30;46703:14;;;16270:51;16340:12;;;37148:245::o;37400:416::-;37600:2;37614:47;;;16591:2;37585:18;;;46663:19;16627:26;46703:14;;;16607:47;16673:12;;;37571:245::o;37823:416::-;38023:2;38037:47;;;16924:2;38008:18;;;46663:19;-1:-1;;;46703:14;;;16940:43;17002:12;;;37994:245::o;38246:416::-;38446:2;38460:47;;;17253:2;38431:18;;;46663:19;17289:27;46703:14;;;17269:48;17336:12;;;38417:245::o;38669:416::-;38869:2;38883:47;;;17587:2;38854:18;;;46663:19;17623:27;46703:14;;;17603:48;17670:12;;;38840:245::o;39092:416::-;39292:2;39306:47;;;17921:1;39277:18;;;46663:19;-1:-1;;;46703:14;;;17936:32;17987:12;;;39263:245::o;39515:416::-;39715:2;39729:47;;;18238:2;39700:18;;;46663:19;-1:-1;;;46703:14;;;18254:38;18311:12;;;39686:245::o;39938:416::-;40138:2;40152:47;;;18562:2;40123:18;;;46663:19;-1:-1;;;46703:14;;;18578:34;18631:12;;;40109:245::o;40361:416::-;40561:2;40575:47;;;18882:2;40546:18;;;46663:19;-1:-1;;;46703:14;;;18898:42;18959:12;;;40532:245::o;40784:416::-;40984:2;40998:47;;;19210:2;40969:18;;;46663:19;19246:25;46703:14;;;19226:46;19291:12;;;40955:245::o;41207:416::-;41407:2;41421:47;;;19542:2;41392:18;;;46663:19;19578:28;46703:14;;;19558:49;19626:12;;;41378:245::o;41630:416::-;41830:2;41844:47;;;20182:2;41815:18;;;46663:19;-1:-1;;;46703:14;;;20198:42;20259:12;;;41801:245::o;42053:416::-;42253:2;42267:47;;;20510:2;42238:18;;;46663:19;-1:-1;;;46703:14;;;20526:36;20581:12;;;42224:245::o;42476:416::-;42676:2;42690:47;;;20832:2;42661:18;;;46663:19;-1:-1;;;46703:14;;;20848:43;20910:12;;;42647:245::o;42899:416::-;43099:2;43113:47;;;21161:2;43084:18;;;46663:19;-1:-1;;;46703:14;;;21177:43;-1:-1;21239:12;;43070:245::o;43322:416::-;43522:2;43536:47;;;21490:2;43507:18;;;46663:19;-1:-1;;;46703:14;;;21506:35;21560:12;;;43493:245::o;43745:416::-;43945:2;43959:47;;;21811:2;43930:18;;;46663:19;21847:34;46703:14;;;21827:55;-1:-1;;;21902:12;;;21895:26;21940:12;;;43916:245::o;44168:416::-;44368:2;44382:47;;;22191:2;44353:18;;;46663:19;22227:34;46703:14;;;22207:55;-1:-1;;;22282:12;;;22275:25;22319:12;;;44339:245::o;44820:440::-;8800:37;;;45163:2;45148:18;;8800:37;;;;45246:2;45231:18;;8800:37;45001:2;44986:18;;44972:288::o;47550:335::-;;;47716:8;47704:10;47701:24;47698:2;;;-1:-1;;47728:12;47698:2;47763:6;47753:8;47750:20;47747:2;;;-1:-1;;47773:12;47747:2;-1:-1;;47833:2;47817:19;;47805:32;;47855:25;;;;;-1:-1;47692:193::o;47892:318::-;;;48042:8;48030:10;48027:24;48024:2;;;-1:-1;;48054:12;48024:2;48089:6;48079:8;48076:20;48073:2;;;-1:-1;;48099:12;48073:2;-1:-1;;48131:31;;;48180:25;;;;;-1:-1;48018:192::o;49032:268::-;49097:1;49104:101;49118:6;49115:1;49112:13;49104:101;;;49185:11;;;49179:18;49166:11;;;49159:39;49140:2;49133:10;49104:101;;;49220:6;49217:1;49214:13;49211:2;;;49097:1;49276:6;49271:3;49267:16;49260:27;49211:2;;49081:219;;;:::o;49494:117::-;-1:-1;;;;;48732:54;;49553:35;;49543:2;;49602:1;;49592:12", + "linkReferences": {}, + "immutableReferences": { + "460": [ + { + "start": 2358, + "length": 32 + } + ] + } + }, + "methodIdentifiers": { + "cancelL1ToL2Message(uint256,uint256,uint256[],uint256)": "6170ff1b", + "configHash()": "e1f1176d", + "consumeMessageFromL2(uint256,uint256[])": "2c9dd5c0", + "finalize()": "4bb278f3", + "getMaxL1MsgFee()": "54eccba4", + "identify()": "eeb72866", + "initialize(bytes)": "439fab91", + "isFinalized()": "8d4e4083", + "isFrozen()": "33eeb147", + "isOperator(address)": "6d70f7ae", + "l1ToL2MessageCancellations(bytes32)": "9be446bf", + "l1ToL2MessageNonce()": "018cccdf", + "l1ToL2Messages(bytes32)": "77c7d7a9", + "l2ToL1Messages(bytes32)": "a46efaf3", + "messageCancellationDelay()": "8303bd8a", + "programHash()": "8a9bf090", + "registerOperator(address)": "3682a450", + "sendMessageToL2(uint256,uint256,uint256[])": "3e3aa6c5", + "setConfigHash(uint256)": "3d07b336", + "setMessageCancellationDelay(uint256)": "c99d397f", + "setProgramHash(uint256)": "e87e7332", + "starknetAcceptGovernance()": "946be3ed", + "starknetCancelNomination()": "e37fec25", + "starknetIsGovernor(address)": "01a01590", + "starknetNominateNewGovernor(address)": "91a66a26", + "starknetRemoveGovernor(address)": "84f921cd", + "startL1ToL2MessageCancellation(uint256,uint256,uint256[],uint256)": "7a98660b", + "stateBlockHash()": "382d83e3", + "stateBlockNumber()": "35befa5d", + "stateRoot()": "9588eca2", + "unregisterOperator(address)": "96115bc2", + "updateState(uint256[])": "853e2461" + }, + "rawMetadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"changedBy\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldConfigHash\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newConfigHash\",\"type\":\"uint256\"}],\"name\":\"ConfigHashChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fromAddress\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payload\",\"type\":\"uint256[]\"}],\"name\":\"ConsumedMessageToL1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"toAddress\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"selector\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payload\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"name\":\"ConsumedMessageToL2\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"Finalized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fromAddress\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payload\",\"type\":\"uint256[]\"}],\"name\":\"LogMessageToL1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"toAddress\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"selector\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payload\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"}],\"name\":\"LogMessageToL2\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"acceptedGovernor\",\"type\":\"address\"}],\"name\":\"LogNewGovernorAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"nominatedGovernor\",\"type\":\"address\"}],\"name\":\"LogNominatedGovernor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"LogNominationCancelled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"LogOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"LogOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"removedGovernor\",\"type\":\"address\"}],\"name\":\"LogRemovedGovernor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"stateTransitionFact\",\"type\":\"bytes32\"}],\"name\":\"LogStateTransitionFact\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"globalRoot\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"blockNumber\",\"type\":\"int256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"blockHash\",\"type\":\"uint256\"}],\"name\":\"LogStateUpdate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"toAddress\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"selector\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payload\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"name\":\"MessageToL2Canceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"toAddress\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"selector\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payload\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"name\":\"MessageToL2CancellationStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"changedBy\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldProgramHash\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newProgramHash\",\"type\":\"uint256\"}],\"name\":\"ProgramHashChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"toAddress\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"selector\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"payload\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"name\":\"cancelL1ToL2Message\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"configHash\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"fromAddress\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"payload\",\"type\":\"uint256[]\"}],\"name\":\"consumeMessageFromL2\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"finalize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getMaxL1MsgFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"identify\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isFinalized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isFrozen\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"isOperator\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\"}],\"name\":\"l1ToL2MessageCancellations\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1ToL2MessageNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\"}],\"name\":\"l1ToL2Messages\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\"}],\"name\":\"l2ToL1Messages\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"messageCancellationDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"programHash\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOperator\",\"type\":\"address\"}],\"name\":\"registerOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"toAddress\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"selector\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"payload\",\"type\":\"uint256[]\"}],\"name\":\"sendMessageToL2\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newConfigHash\",\"type\":\"uint256\"}],\"name\":\"setConfigHash\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"delayInSeconds\",\"type\":\"uint256\"}],\"name\":\"setMessageCancellationDelay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newProgramHash\",\"type\":\"uint256\"}],\"name\":\"setProgramHash\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"starknetAcceptGovernance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"starknetCancelNomination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"starknetIsGovernor\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"starknetNominateNewGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"governorForRemoval\",\"type\":\"address\"}],\"name\":\"starknetRemoveGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"toAddress\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"selector\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"payload\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"name\":\"startL1ToL2MessageCancellation\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stateBlockHash\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stateBlockNumber\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stateRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"removedOperator\",\"type\":\"address\"}],\"name\":\"unregisterOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"programOutput\",\"type\":\"uint256[]\"}],\"name\":\"updateState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"cancelL1ToL2Message(uint256,uint256,uint256[],uint256)\":{\"notice\":\"Cancels an L1 to L2 message, this function should be called at least messageCancellationDelay() seconds after the call to startL1ToL2MessageCancellation(). A message may only be cancelled by its sender. If the message is missing, the call will revert. Note that the message fee is not refunded.\"},\"consumeMessageFromL2(uint256,uint256[])\":{\"notice\":\"Consumes a message that was sent from an L2 contract. Returns the hash of the message.\"},\"getMaxL1MsgFee()\":{\"notice\":\"Returns the max fee (in Wei) that StarkNet will accept per single message.\"},\"identify()\":{\"notice\":\"Returns a string that identifies the contract.\"},\"l1ToL2MessageCancellations(bytes32)\":{\"notice\":\"Returns the timestamp at the time cancelL1ToL2Message was called with a message matching 'msgHash'. The function returns 0 if cancelL1ToL2Message was never called.\"},\"l1ToL2Messages(bytes32)\":{\"notice\":\"Returns the msg_fee + 1 for the message with the given 'msgHash', or 0 if no message with such a hash is pending.\"},\"sendMessageToL2(uint256,uint256,uint256[])\":{\"notice\":\"Sends a message to an L2 contract.\"},\"startL1ToL2MessageCancellation(uint256,uint256,uint256[],uint256)\":{\"notice\":\"Starts the cancellation of an L1 to L2 message. A message can be canceled messageCancellationDelay() seconds after this function is called. Note: This function may only be called for a message that is currently pending and the caller must be the sender of the that message.\"},\"stateBlockHash()\":{\"notice\":\"Returns the current block hash.\"},\"stateBlockNumber()\":{\"notice\":\"Returns the current block number.\"},\"stateRoot()\":{\"notice\":\"Returns the current state root.\"},\"updateState(uint256[])\":{\"notice\":\"Updates the state of the StarkNet, based on a proof of the StarkNet OS that the state transition is valid. Arguments: programOutput - The main part of the StarkNet OS program output. data_availability_fact - An encoding of the on-chain data associated with the 'programOutput'.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/StarknetValidium.sol\":\"Starknet\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":cairo-lang/=lib/cairo-lang/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":starknet-cc/=lib/cairo-lang/src/starkware/starknet/solidity/\",\":starknet-token/=lib/starknet-token/src/starkware/isd/\",\":starkware/isd/=lib/starknet-token/src/starkware/isd/\",\":starkware/solidity/=lib/cairo-lang/src/starkware/solidity/\"]},\"sources\":{\"lib/cairo-lang/src/starkware/solidity/components/Governance.sol\":{\"keccak256\":\"0xf95152fbacc9b6096be75c4a0f03bfc10b1a5d6219bd24ce61963b78d8ea4d7f\",\"license\":\"Apache-2.0.\",\"urls\":[\"bzz-raw://53814938c69e1ce9e911bacf16633ef2d555391e8dafd697fd7ee2f8b201c293\",\"dweb:/ipfs/QmVVXhKbDHLAnwmGHFBkRaMJ597PV4gdmHTxQFSVS7NiUu\"]},\"lib/cairo-lang/src/starkware/solidity/components/GovernedFinalizable.sol\":{\"keccak256\":\"0x99e7a7ce7494dffd1e29855ae193d8d8a8b1d8811dc5b4f65c11f53049f60718\",\"license\":\"Apache-2.0.\",\"urls\":[\"bzz-raw://82f5fb8443fdb206e0b161dd93ddd920e250fa29b1be7abc6999014cefdeb389\",\"dweb:/ipfs/QmYsdDfnxPc72HJANgRKNwdagWW3mzttrzMQ1T73abcVnx\"]},\"lib/cairo-lang/src/starkware/solidity/components/OnchainDataFactTreeEncoder.sol\":{\"keccak256\":\"0xb5fdb7ff413d7f06b0f62db39100f668fa2c89b22eb1232dd9b2b66b1df44490\",\"license\":\"Apache-2.0.\",\"urls\":[\"bzz-raw://a851defbca9032b49eae3bc5aae1f140c2ff45c8648ed56146cb738a80381a0c\",\"dweb:/ipfs/QmdKfzzP4zF5sdsZS74qo4o6YiGrWVCxzmeVj74rRnk8q4\"]},\"lib/cairo-lang/src/starkware/solidity/components/Operator.sol\":{\"keccak256\":\"0x9a6a1f3772861dc6d6645bd140bafa7f562fd630244316f754303e45a0b642b1\",\"license\":\"Apache-2.0.\",\"urls\":[\"bzz-raw://7aaf1f4d36727c33ba2c653ff1405cf4e1034ce274d87b6dfffcc1314eeac9d8\",\"dweb:/ipfs/QmYdpszZJkpZ3eybwTWx6ssWVSdTVKaEgoaPm42T1pKS36\"]},\"lib/cairo-lang/src/starkware/solidity/interfaces/BlockDirectCall.sol\":{\"keccak256\":\"0xe8d027bbe8defa2df3caded6a7c5149372475e16d5cbaee80d5b05d923536ff9\",\"license\":\"Apache-2.0.\",\"urls\":[\"bzz-raw://5f627a16e57292b1f58fad26970abb41c91be120da24712bbcd34a0b345b3f2d\",\"dweb:/ipfs/QmSk7WdEp1WwpHLZQdViuKJZ5E2C4w2YiFYKkKNiFPWc2E\"]},\"lib/cairo-lang/src/starkware/solidity/interfaces/ContractInitializer.sol\":{\"keccak256\":\"0x4899cc503a549113f495e45c1ca08a15c13f8f22d42468b1089f9279a41a9021\",\"license\":\"Apache-2.0.\",\"urls\":[\"bzz-raw://de484cf04271afc3b24a1cc0f37036a9707b6ff28efd69d9afe95d5b5bb0f4d4\",\"dweb:/ipfs/QmS2bNaTM2NpoiGZQH723z3zxtpZcfB8W5wXDTQKLqJzqM\"]},\"lib/cairo-lang/src/starkware/solidity/interfaces/IFactRegistry.sol\":{\"keccak256\":\"0xab04b296b506dfb0b4a8828f3dc463072fd50449a5ad8327d1baf01438b0fb35\",\"license\":\"Apache-2.0.\",\"urls\":[\"bzz-raw://e451abe007f98081d1adfd759cc4168f81982992d8c0554650b94d37bc009e64\",\"dweb:/ipfs/QmVBNUWFhNX8PqSMcqRkHVaTbcm7KNpgSg91Sj6MepFG6u\"]},\"lib/cairo-lang/src/starkware/solidity/interfaces/Identity.sol\":{\"keccak256\":\"0xe09f6920ecf39cfa9285164bfba092dc9fce892da3fb4e3839391b5c039c34ff\",\"license\":\"Apache-2.0.\",\"urls\":[\"bzz-raw://b68168b5efcfd7a269c1b50ca381776764ac460fe7be2354c1b2410a2c9676d5\",\"dweb:/ipfs/Qmagk5UEjwWkqMczGvxa3V2fG2h4779MbXZ23i5U98gMUo\"]},\"lib/cairo-lang/src/starkware/solidity/interfaces/MGovernance.sol\":{\"keccak256\":\"0x02dc54c223e2977a13a3e12bb60659598ce2c56bc8df3a27d8bb8e761c676c67\",\"license\":\"Apache-2.0.\",\"urls\":[\"bzz-raw://eff35423c5dc96cf0d223517c9eaca3dc028fbd8be9ec3f989299c6db8e8c5b2\",\"dweb:/ipfs/QmfDR7Yoq5Lz3zLLSj2jXoSojPYTrWp4HYhGRtXus4t1G6\"]},\"lib/cairo-lang/src/starkware/solidity/interfaces/MOperator.sol\":{\"keccak256\":\"0x00417855444c25ec8e3b119775a0f2c7407bffbf5db69a8347ce6313cda84bdf\",\"license\":\"Apache-2.0.\",\"urls\":[\"bzz-raw://0922504dd6f7d7c8011d26953b5e12a02b5af0f4308e17ea508b45686c4bd5aa\",\"dweb:/ipfs/QmcwebQGm1yLuhEYy2VnuR9vB9eWZJPRTTMWRxE3EXW43B\"]},\"lib/cairo-lang/src/starkware/solidity/interfaces/ProxySupport.sol\":{\"keccak256\":\"0xc2253392af4d0d80c55d8b45af6700353cc66a4633c931ee53f9485178758b7a\",\"license\":\"Apache-2.0.\",\"urls\":[\"bzz-raw://14c96384bd0a2924abd78fbdfbfcb9e3dc6a6ba4e26778cf18ceeb5e9ffdc758\",\"dweb:/ipfs/QmbXxostCT9v3fnH4Ao9tGcHY7A6i4KvsR7JrcNBNM8XPe\"]},\"lib/cairo-lang/src/starkware/solidity/libraries/Addresses.sol\":{\"keccak256\":\"0x05016ed8cfde52acab00e22bb6ad741b8c0a6d0c8e358b87e275314e22f64461\",\"license\":\"Apache-2.0.\",\"urls\":[\"bzz-raw://632b9cd4f05f3ce39b5cdf5d20aa68b8800c4e292fe49dd6e86ffca7bc3a75e6\",\"dweb:/ipfs/QmUnJbZSJ23yEoemcsDwaus214uymAVS1LkyGdRPvZJfnZ\"]},\"lib/cairo-lang/src/starkware/solidity/libraries/NamedStorage.sol\":{\"keccak256\":\"0x014ba48551c965e42b7e8f2e22f6f5f559f1ecaa6b1ce2dbf965e2b9808514ee\",\"license\":\"Apache-2.0.\",\"urls\":[\"bzz-raw://fb77540fd0d17b382d61e597862b29d164256f7224f0f39a534d2e1c3c161140\",\"dweb:/ipfs/QmYCombekr8CQvCCjBDFVniNCnreg9Z2TT78ZjdS3FGNsk\"]},\"lib/cairo-lang/src/starkware/starknet/solidity/IStarknetMessaging.sol\":{\"keccak256\":\"0x75d3dad61854e3115a97fa314066cd3ff4544fa712bea1a6595bbac7ef8e92f8\",\"license\":\"Apache-2.0.\",\"urls\":[\"bzz-raw://d5a07d8e15bfba827443a9f79f0465f1e24df4960a581754c6139964b56124c5\",\"dweb:/ipfs/QmUqBMSiC8b3T6L6mRFcxR83ByHK1q2KVo3nCoKsph8DJH\"]},\"lib/cairo-lang/src/starkware/starknet/solidity/IStarknetMessagingEvents.sol\":{\"keccak256\":\"0xfeac71f229049b84eb47fbdae456f9de2074016828a4529e00abd4eddc8bb844\",\"license\":\"Apache-2.0.\",\"urls\":[\"bzz-raw://c9acd4424ec21178670c3b1793f2f8d2c4d59ff0f22063ba5f60100f18f47b95\",\"dweb:/ipfs/QmTHjQARTTVRFnCeThphAVocQYSk2hXCYT2yDr6TmZccJP\"]},\"lib/cairo-lang/src/starkware/starknet/solidity/Output.sol\":{\"keccak256\":\"0x2ac3d70a983a64285d80a86e9d7aa54512b24975610331de72f097e66e62e518\",\"license\":\"Apache-2.0.\",\"urls\":[\"bzz-raw://b976a5bb24ba56e038fc3f9700c6cddf8d0c555fa2be5cd74db59cc26b8b25c0\",\"dweb:/ipfs/QmPCQPDJNmZZtpXHMm31gJz9CJshKgMviSQAXJ5V62dvbL\"]},\"lib/cairo-lang/src/starkware/starknet/solidity/StarknetGovernance.sol\":{\"keccak256\":\"0x8cbfaa3158fb569adc4cc2ac4b7c1045cce0eb180b365ecfaf2aec82f53d1ffe\",\"license\":\"Apache-2.0.\",\"urls\":[\"bzz-raw://196f9b478b3e766db7621bf6699a22cdab262203de63eed0ea29dfd614ef13d2\",\"dweb:/ipfs/QmeqGnZwcMHEHWwT4XzENy85XtFLty2y6j3o5k3JRYTpqm\"]},\"lib/cairo-lang/src/starkware/starknet/solidity/StarknetMessaging.sol\":{\"keccak256\":\"0xbab7ad137660d819316cdc502cd96b82db5ede18f580e7750bfd3ea4e65eb4fb\",\"license\":\"Apache-2.0.\",\"urls\":[\"bzz-raw://8bc3f628c8967f5179c604e77bd0cf9ad9ce9379240c130d50b38c713d6c3c21\",\"dweb:/ipfs/QmQXs5AzAbxxY6jicFNoHMepF5iAz2QppCjyZQjQZRy41J\"]},\"lib/cairo-lang/src/starkware/starknet/solidity/StarknetOperator.sol\":{\"keccak256\":\"0x2c1bdc4010e7b07a344336f1145cf8bedaced48fbfe91d065d185a2205ec3244\",\"license\":\"Apache-2.0.\",\"urls\":[\"bzz-raw://9847d7ee4b5eff9513ab3df92e3b00e16c67ddbd6e5affbc855cab3b9b9ab4ac\",\"dweb:/ipfs/QmXaKMszDZJFtCa9ujwMeAZd1FcUM68BHsXe1s5VZLSWPh\"]},\"lib/cairo-lang/src/starkware/starknet/solidity/StarknetState.sol\":{\"keccak256\":\"0x98689b355b5758e590f3b5611b6df41e87b04202ab5457127e35b030af905b4f\",\"license\":\"Apache-2.0.\",\"urls\":[\"bzz-raw://9ddafb29225921f0f985d654e634b077161fb298d6f23891ab6042e243b95233\",\"dweb:/ipfs/QmPMvx7j8SJe8tqw3cUNwDt2tiStSaz6y59cHGN7GgE6Rm\"]},\"src/StarknetValidium.sol\":{\"keccak256\":\"0xc764b87700d3e383c229e490e6b0d0167ba1f462c64597c24eff3c204185baab\",\"license\":\"Apache-2.0.\",\"urls\":[\"bzz-raw://9463375e63cc69c072ef952511973fa1d0ecdc8e8628d214a8970d4d1b8d4d14\",\"dweb:/ipfs/Qmd39hmPc8N11Ybb3auAxq6P5pcM7AgqmExbDTjaQPFx2Z\"]}},\"version\":1}", + "metadata": { + "compiler": { + "version": "0.6.12+commit.27d51765" + }, + "language": "Solidity", + "output": { + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "changedBy", + "type": "address", + "indexed": true + }, + { + "internalType": "uint256", + "name": "oldConfigHash", + "type": "uint256", + "indexed": false + }, + { + "internalType": "uint256", + "name": "newConfigHash", + "type": "uint256", + "indexed": false + } + ], + "type": "event", + "name": "ConfigHashChanged", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fromAddress", + "type": "uint256", + "indexed": true + }, + { + "internalType": "address", + "name": "toAddress", + "type": "address", + "indexed": true + }, + { + "internalType": "uint256[]", + "name": "payload", + "type": "uint256[]", + "indexed": false + } + ], + "type": "event", + "name": "ConsumedMessageToL1", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "fromAddress", + "type": "address", + "indexed": true + }, + { + "internalType": "uint256", + "name": "toAddress", + "type": "uint256", + "indexed": true + }, + { + "internalType": "uint256", + "name": "selector", + "type": "uint256", + "indexed": true + }, + { + "internalType": "uint256[]", + "name": "payload", + "type": "uint256[]", + "indexed": false + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256", + "indexed": false + } + ], + "type": "event", + "name": "ConsumedMessageToL2", + "anonymous": false + }, + { + "inputs": [], + "type": "event", + "name": "Finalized", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fromAddress", + "type": "uint256", + "indexed": true + }, + { + "internalType": "address", + "name": "toAddress", + "type": "address", + "indexed": true + }, + { + "internalType": "uint256[]", + "name": "payload", + "type": "uint256[]", + "indexed": false + } + ], + "type": "event", + "name": "LogMessageToL1", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "fromAddress", + "type": "address", + "indexed": true + }, + { + "internalType": "uint256", + "name": "toAddress", + "type": "uint256", + "indexed": true + }, + { + "internalType": "uint256", + "name": "selector", + "type": "uint256", + "indexed": true + }, + { + "internalType": "uint256[]", + "name": "payload", + "type": "uint256[]", + "indexed": false + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256", + "indexed": false + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256", + "indexed": false + } + ], + "type": "event", + "name": "LogMessageToL2", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "acceptedGovernor", + "type": "address", + "indexed": false + } + ], + "type": "event", + "name": "LogNewGovernorAccepted", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "nominatedGovernor", + "type": "address", + "indexed": false + } + ], + "type": "event", + "name": "LogNominatedGovernor", + "anonymous": false + }, + { + "inputs": [], + "type": "event", + "name": "LogNominationCancelled", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address", + "indexed": false + } + ], + "type": "event", + "name": "LogOperatorAdded", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address", + "indexed": false + } + ], + "type": "event", + "name": "LogOperatorRemoved", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "removedGovernor", + "type": "address", + "indexed": false + } + ], + "type": "event", + "name": "LogRemovedGovernor", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "stateTransitionFact", + "type": "bytes32", + "indexed": false + } + ], + "type": "event", + "name": "LogStateTransitionFact", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "globalRoot", + "type": "uint256", + "indexed": false + }, + { + "internalType": "int256", + "name": "blockNumber", + "type": "int256", + "indexed": false + }, + { + "internalType": "uint256", + "name": "blockHash", + "type": "uint256", + "indexed": false + } + ], + "type": "event", + "name": "LogStateUpdate", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "fromAddress", + "type": "address", + "indexed": true + }, + { + "internalType": "uint256", + "name": "toAddress", + "type": "uint256", + "indexed": true + }, + { + "internalType": "uint256", + "name": "selector", + "type": "uint256", + "indexed": true + }, + { + "internalType": "uint256[]", + "name": "payload", + "type": "uint256[]", + "indexed": false + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256", + "indexed": false + } + ], + "type": "event", + "name": "MessageToL2Canceled", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "fromAddress", + "type": "address", + "indexed": true + }, + { + "internalType": "uint256", + "name": "toAddress", + "type": "uint256", + "indexed": true + }, + { + "internalType": "uint256", + "name": "selector", + "type": "uint256", + "indexed": true + }, + { + "internalType": "uint256[]", + "name": "payload", + "type": "uint256[]", + "indexed": false + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256", + "indexed": false + } + ], + "type": "event", + "name": "MessageToL2CancellationStarted", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "changedBy", + "type": "address", + "indexed": true + }, + { + "internalType": "uint256", + "name": "oldProgramHash", + "type": "uint256", + "indexed": false + }, + { + "internalType": "uint256", + "name": "newProgramHash", + "type": "uint256", + "indexed": false + } + ], + "type": "event", + "name": "ProgramHashChanged", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "toAddress", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "selector", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "payload", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "cancelL1ToL2Message", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "configHash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ] + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fromAddress", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "payload", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "consumeMessageFromL2", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ] + }, + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "function", + "name": "finalize" + }, + { + "inputs": [], + "stateMutability": "pure", + "type": "function", + "name": "getMaxL1MsgFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ] + }, + { + "inputs": [], + "stateMutability": "pure", + "type": "function", + "name": "identify", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ] + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "initialize" + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "isFinalized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "isFrozen", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ] + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function", + "name": "isOperator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ] + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "msgHash", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function", + "name": "l1ToL2MessageCancellations", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "l1ToL2MessageNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ] + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "msgHash", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function", + "name": "l1ToL2Messages", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ] + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "msgHash", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function", + "name": "l2ToL1Messages", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "messageCancellationDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "programHash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ] + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOperator", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "registerOperator" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "toAddress", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "selector", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "payload", + "type": "uint256[]" + } + ], + "stateMutability": "payable", + "type": "function", + "name": "sendMessageToL2", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ] + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newConfigHash", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "setConfigHash" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "delayInSeconds", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "setMessageCancellationDelay" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newProgramHash", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "setProgramHash" + }, + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "function", + "name": "starknetAcceptGovernance" + }, + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "function", + "name": "starknetCancelNomination" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function", + "name": "starknetIsGovernor", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ] + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newGovernor", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "starknetNominateNewGovernor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "governorForRemoval", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "starknetRemoveGovernor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "toAddress", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "selector", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "payload", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "startL1ToL2MessageCancellation", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "stateBlockHash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "stateBlockNumber", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "stateRoot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ] + }, + { + "inputs": [ + { + "internalType": "address", + "name": "removedOperator", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "unregisterOperator" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "programOutput", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "updateState" + } + ], + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "cancelL1ToL2Message(uint256,uint256,uint256[],uint256)": { + "notice": "Cancels an L1 to L2 message, this function should be called at least messageCancellationDelay() seconds after the call to startL1ToL2MessageCancellation(). A message may only be cancelled by its sender. If the message is missing, the call will revert. Note that the message fee is not refunded." + }, + "consumeMessageFromL2(uint256,uint256[])": { + "notice": "Consumes a message that was sent from an L2 contract. Returns the hash of the message." + }, + "getMaxL1MsgFee()": { + "notice": "Returns the max fee (in Wei) that StarkNet will accept per single message." + }, + "identify()": { + "notice": "Returns a string that identifies the contract." + }, + "l1ToL2MessageCancellations(bytes32)": { + "notice": "Returns the timestamp at the time cancelL1ToL2Message was called with a message matching 'msgHash'. The function returns 0 if cancelL1ToL2Message was never called." + }, + "l1ToL2Messages(bytes32)": { + "notice": "Returns the msg_fee + 1 for the message with the given 'msgHash', or 0 if no message with such a hash is pending." + }, + "sendMessageToL2(uint256,uint256,uint256[])": { + "notice": "Sends a message to an L2 contract." + }, + "startL1ToL2MessageCancellation(uint256,uint256,uint256[],uint256)": { + "notice": "Starts the cancellation of an L1 to L2 message. A message can be canceled messageCancellationDelay() seconds after this function is called. Note: This function may only be called for a message that is currently pending and the caller must be the sender of the that message." + }, + "stateBlockHash()": { + "notice": "Returns the current block hash." + }, + "stateBlockNumber()": { + "notice": "Returns the current block number." + }, + "stateRoot()": { + "notice": "Returns the current state root." + }, + "updateState(uint256[])": { + "notice": "Updates the state of the StarkNet, based on a proof of the StarkNet OS that the state transition is valid. Arguments: programOutput - The main part of the StarkNet OS program output. data_availability_fact - An encoding of the on-chain data associated with the 'programOutput'." + } + }, + "version": 1 + } + }, + "settings": { + "remappings": [ + "cairo-lang/=lib/cairo-lang/src/", + "ds-test/=lib/forge-std/lib/ds-test/src/", + "forge-std/=lib/forge-std/src/", + "starknet-cc/=lib/cairo-lang/src/starkware/starknet/solidity/", + "starknet-token/=lib/starknet-token/src/starkware/isd/", + "starkware/isd/=lib/starknet-token/src/starkware/isd/", + "starkware/solidity/=lib/cairo-lang/src/starkware/solidity/" + ], + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "compilationTarget": { + "src/StarknetValidium.sol": "Starknet" + }, + "libraries": {} + }, + "sources": { + "lib/cairo-lang/src/starkware/solidity/components/Governance.sol": { + "keccak256": "0xf95152fbacc9b6096be75c4a0f03bfc10b1a5d6219bd24ce61963b78d8ea4d7f", + "urls": [ + "bzz-raw://53814938c69e1ce9e911bacf16633ef2d555391e8dafd697fd7ee2f8b201c293", + "dweb:/ipfs/QmVVXhKbDHLAnwmGHFBkRaMJ597PV4gdmHTxQFSVS7NiUu" + ], + "license": "Apache-2.0." + }, + "lib/cairo-lang/src/starkware/solidity/components/GovernedFinalizable.sol": { + "keccak256": "0x99e7a7ce7494dffd1e29855ae193d8d8a8b1d8811dc5b4f65c11f53049f60718", + "urls": [ + "bzz-raw://82f5fb8443fdb206e0b161dd93ddd920e250fa29b1be7abc6999014cefdeb389", + "dweb:/ipfs/QmYsdDfnxPc72HJANgRKNwdagWW3mzttrzMQ1T73abcVnx" + ], + "license": "Apache-2.0." + }, + "lib/cairo-lang/src/starkware/solidity/components/OnchainDataFactTreeEncoder.sol": { + "keccak256": "0xb5fdb7ff413d7f06b0f62db39100f668fa2c89b22eb1232dd9b2b66b1df44490", + "urls": [ + "bzz-raw://a851defbca9032b49eae3bc5aae1f140c2ff45c8648ed56146cb738a80381a0c", + "dweb:/ipfs/QmdKfzzP4zF5sdsZS74qo4o6YiGrWVCxzmeVj74rRnk8q4" + ], + "license": "Apache-2.0." + }, + "lib/cairo-lang/src/starkware/solidity/components/Operator.sol": { + "keccak256": "0x9a6a1f3772861dc6d6645bd140bafa7f562fd630244316f754303e45a0b642b1", + "urls": [ + "bzz-raw://7aaf1f4d36727c33ba2c653ff1405cf4e1034ce274d87b6dfffcc1314eeac9d8", + "dweb:/ipfs/QmYdpszZJkpZ3eybwTWx6ssWVSdTVKaEgoaPm42T1pKS36" + ], + "license": "Apache-2.0." + }, + "lib/cairo-lang/src/starkware/solidity/interfaces/BlockDirectCall.sol": { + "keccak256": "0xe8d027bbe8defa2df3caded6a7c5149372475e16d5cbaee80d5b05d923536ff9", + "urls": [ + "bzz-raw://5f627a16e57292b1f58fad26970abb41c91be120da24712bbcd34a0b345b3f2d", + "dweb:/ipfs/QmSk7WdEp1WwpHLZQdViuKJZ5E2C4w2YiFYKkKNiFPWc2E" + ], + "license": "Apache-2.0." + }, + "lib/cairo-lang/src/starkware/solidity/interfaces/ContractInitializer.sol": { + "keccak256": "0x4899cc503a549113f495e45c1ca08a15c13f8f22d42468b1089f9279a41a9021", + "urls": [ + "bzz-raw://de484cf04271afc3b24a1cc0f37036a9707b6ff28efd69d9afe95d5b5bb0f4d4", + "dweb:/ipfs/QmS2bNaTM2NpoiGZQH723z3zxtpZcfB8W5wXDTQKLqJzqM" + ], + "license": "Apache-2.0." + }, + "lib/cairo-lang/src/starkware/solidity/interfaces/IFactRegistry.sol": { + "keccak256": "0xab04b296b506dfb0b4a8828f3dc463072fd50449a5ad8327d1baf01438b0fb35", + "urls": [ + "bzz-raw://e451abe007f98081d1adfd759cc4168f81982992d8c0554650b94d37bc009e64", + "dweb:/ipfs/QmVBNUWFhNX8PqSMcqRkHVaTbcm7KNpgSg91Sj6MepFG6u" + ], + "license": "Apache-2.0." + }, + "lib/cairo-lang/src/starkware/solidity/interfaces/Identity.sol": { + "keccak256": "0xe09f6920ecf39cfa9285164bfba092dc9fce892da3fb4e3839391b5c039c34ff", + "urls": [ + "bzz-raw://b68168b5efcfd7a269c1b50ca381776764ac460fe7be2354c1b2410a2c9676d5", + "dweb:/ipfs/Qmagk5UEjwWkqMczGvxa3V2fG2h4779MbXZ23i5U98gMUo" + ], + "license": "Apache-2.0." + }, + "lib/cairo-lang/src/starkware/solidity/interfaces/MGovernance.sol": { + "keccak256": "0x02dc54c223e2977a13a3e12bb60659598ce2c56bc8df3a27d8bb8e761c676c67", + "urls": [ + "bzz-raw://eff35423c5dc96cf0d223517c9eaca3dc028fbd8be9ec3f989299c6db8e8c5b2", + "dweb:/ipfs/QmfDR7Yoq5Lz3zLLSj2jXoSojPYTrWp4HYhGRtXus4t1G6" + ], + "license": "Apache-2.0." + }, + "lib/cairo-lang/src/starkware/solidity/interfaces/MOperator.sol": { + "keccak256": "0x00417855444c25ec8e3b119775a0f2c7407bffbf5db69a8347ce6313cda84bdf", + "urls": [ + "bzz-raw://0922504dd6f7d7c8011d26953b5e12a02b5af0f4308e17ea508b45686c4bd5aa", + "dweb:/ipfs/QmcwebQGm1yLuhEYy2VnuR9vB9eWZJPRTTMWRxE3EXW43B" + ], + "license": "Apache-2.0." + }, + "lib/cairo-lang/src/starkware/solidity/interfaces/ProxySupport.sol": { + "keccak256": "0xc2253392af4d0d80c55d8b45af6700353cc66a4633c931ee53f9485178758b7a", + "urls": [ + "bzz-raw://14c96384bd0a2924abd78fbdfbfcb9e3dc6a6ba4e26778cf18ceeb5e9ffdc758", + "dweb:/ipfs/QmbXxostCT9v3fnH4Ao9tGcHY7A6i4KvsR7JrcNBNM8XPe" + ], + "license": "Apache-2.0." + }, + "lib/cairo-lang/src/starkware/solidity/libraries/Addresses.sol": { + "keccak256": "0x05016ed8cfde52acab00e22bb6ad741b8c0a6d0c8e358b87e275314e22f64461", + "urls": [ + "bzz-raw://632b9cd4f05f3ce39b5cdf5d20aa68b8800c4e292fe49dd6e86ffca7bc3a75e6", + "dweb:/ipfs/QmUnJbZSJ23yEoemcsDwaus214uymAVS1LkyGdRPvZJfnZ" + ], + "license": "Apache-2.0." + }, + "lib/cairo-lang/src/starkware/solidity/libraries/NamedStorage.sol": { + "keccak256": "0x014ba48551c965e42b7e8f2e22f6f5f559f1ecaa6b1ce2dbf965e2b9808514ee", + "urls": [ + "bzz-raw://fb77540fd0d17b382d61e597862b29d164256f7224f0f39a534d2e1c3c161140", + "dweb:/ipfs/QmYCombekr8CQvCCjBDFVniNCnreg9Z2TT78ZjdS3FGNsk" + ], + "license": "Apache-2.0." + }, + "lib/cairo-lang/src/starkware/starknet/solidity/IStarknetMessaging.sol": { + "keccak256": "0x75d3dad61854e3115a97fa314066cd3ff4544fa712bea1a6595bbac7ef8e92f8", + "urls": [ + "bzz-raw://d5a07d8e15bfba827443a9f79f0465f1e24df4960a581754c6139964b56124c5", + "dweb:/ipfs/QmUqBMSiC8b3T6L6mRFcxR83ByHK1q2KVo3nCoKsph8DJH" + ], + "license": "Apache-2.0." + }, + "lib/cairo-lang/src/starkware/starknet/solidity/IStarknetMessagingEvents.sol": { + "keccak256": "0xfeac71f229049b84eb47fbdae456f9de2074016828a4529e00abd4eddc8bb844", + "urls": [ + "bzz-raw://c9acd4424ec21178670c3b1793f2f8d2c4d59ff0f22063ba5f60100f18f47b95", + "dweb:/ipfs/QmTHjQARTTVRFnCeThphAVocQYSk2hXCYT2yDr6TmZccJP" + ], + "license": "Apache-2.0." + }, + "lib/cairo-lang/src/starkware/starknet/solidity/Output.sol": { + "keccak256": "0x2ac3d70a983a64285d80a86e9d7aa54512b24975610331de72f097e66e62e518", + "urls": [ + "bzz-raw://b976a5bb24ba56e038fc3f9700c6cddf8d0c555fa2be5cd74db59cc26b8b25c0", + "dweb:/ipfs/QmPCQPDJNmZZtpXHMm31gJz9CJshKgMviSQAXJ5V62dvbL" + ], + "license": "Apache-2.0." + }, + "lib/cairo-lang/src/starkware/starknet/solidity/StarknetGovernance.sol": { + "keccak256": "0x8cbfaa3158fb569adc4cc2ac4b7c1045cce0eb180b365ecfaf2aec82f53d1ffe", + "urls": [ + "bzz-raw://196f9b478b3e766db7621bf6699a22cdab262203de63eed0ea29dfd614ef13d2", + "dweb:/ipfs/QmeqGnZwcMHEHWwT4XzENy85XtFLty2y6j3o5k3JRYTpqm" + ], + "license": "Apache-2.0." + }, + "lib/cairo-lang/src/starkware/starknet/solidity/StarknetMessaging.sol": { + "keccak256": "0xbab7ad137660d819316cdc502cd96b82db5ede18f580e7750bfd3ea4e65eb4fb", + "urls": [ + "bzz-raw://8bc3f628c8967f5179c604e77bd0cf9ad9ce9379240c130d50b38c713d6c3c21", + "dweb:/ipfs/QmQXs5AzAbxxY6jicFNoHMepF5iAz2QppCjyZQjQZRy41J" + ], + "license": "Apache-2.0." + }, + "lib/cairo-lang/src/starkware/starknet/solidity/StarknetOperator.sol": { + "keccak256": "0x2c1bdc4010e7b07a344336f1145cf8bedaced48fbfe91d065d185a2205ec3244", + "urls": [ + "bzz-raw://9847d7ee4b5eff9513ab3df92e3b00e16c67ddbd6e5affbc855cab3b9b9ab4ac", + "dweb:/ipfs/QmXaKMszDZJFtCa9ujwMeAZd1FcUM68BHsXe1s5VZLSWPh" + ], + "license": "Apache-2.0." + }, + "lib/cairo-lang/src/starkware/starknet/solidity/StarknetState.sol": { + "keccak256": "0x98689b355b5758e590f3b5611b6df41e87b04202ab5457127e35b030af905b4f", + "urls": [ + "bzz-raw://9ddafb29225921f0f985d654e634b077161fb298d6f23891ab6042e243b95233", + "dweb:/ipfs/QmPMvx7j8SJe8tqw3cUNwDt2tiStSaz6y59cHGN7GgE6Rm" + ], + "license": "Apache-2.0." + }, + "src/StarknetValidium.sol": { + "keccak256": "0xc764b87700d3e383c229e490e6b0d0167ba1f462c64597c24eff3c204185baab", + "urls": [ + "bzz-raw://9463375e63cc69c072ef952511973fa1d0ecdc8e8628d214a8970d4d1b8d4d14", + "dweb:/ipfs/Qmd39hmPc8N11Ybb3auAxq6P5pcM7AgqmExbDTjaQPFx2Z" + ], + "license": "Apache-2.0." + } + }, + "version": 1 + }, + "ast": { + "absolutePath": "src/StarknetValidium.sol", + "id": 31651, + "exportedSymbols": { + "Starknet": [31650] + }, + "nodeType": "SourceUnit", + "src": "40:7828:37", + "nodes": [ + { + "id": 31173, + "nodeType": "PragmaDirective", + "src": "40:24:37", + "nodes": [], + "literals": ["solidity", "^", "0.6", ".12"] + }, + { + "id": 31174, + "nodeType": "PragmaDirective", + "src": "65:33:37", + "nodes": [], + "literals": ["experimental", "ABIEncoderV2"] + }, + { + "id": 31175, + "nodeType": "ImportDirective", + "src": "100:32:37", + "nodes": [], + "absolutePath": "lib/cairo-lang/src/starkware/starknet/solidity/Output.sol", + "file": "starknet-cc/Output.sol", + "scope": 31651, + "sourceUnit": 1654, + "symbolAliases": [], + "unitAlias": "" + }, + { + "id": 31176, + "nodeType": "ImportDirective", + "src": "133:44:37", + "nodes": [], + "absolutePath": "lib/cairo-lang/src/starkware/starknet/solidity/StarknetGovernance.sol", + "file": "starknet-cc/StarknetGovernance.sol", + "scope": 31651, + "sourceUnit": 1726, + "symbolAliases": [], + "unitAlias": "" + }, + { + "id": 31177, + "nodeType": "ImportDirective", + "src": "178:43:37", + "nodes": [], + "absolutePath": "lib/cairo-lang/src/starkware/starknet/solidity/StarknetMessaging.sol", + "file": "starknet-cc/StarknetMessaging.sol", + "scope": 31651, + "sourceUnit": 2201, + "symbolAliases": [], + "unitAlias": "" + }, + { + "id": 31178, + "nodeType": "ImportDirective", + "src": "222:42:37", + "nodes": [], + "absolutePath": "lib/cairo-lang/src/starkware/starknet/solidity/StarknetOperator.sol", + "file": "starknet-cc/StarknetOperator.sol", + "scope": 31651, + "sourceUnit": 2225, + "symbolAliases": [], + "unitAlias": "" + }, + { + "id": 31179, + "nodeType": "ImportDirective", + "src": "265:39:37", + "nodes": [], + "absolutePath": "lib/cairo-lang/src/starkware/starknet/solidity/StarknetState.sol", + "file": "starknet-cc/StarknetState.sol", + "scope": 31651, + "sourceUnit": 2334, + "symbolAliases": [], + "unitAlias": "" + }, + { + "id": 31180, + "nodeType": "ImportDirective", + "src": "305:63:37", + "nodes": [], + "absolutePath": "lib/cairo-lang/src/starkware/solidity/components/GovernedFinalizable.sol", + "file": "starkware/solidity/components/GovernedFinalizable.sol", + "scope": 31651, + "sourceUnit": 320, + "symbolAliases": [], + "unitAlias": "" + }, + { + "id": 31181, + "nodeType": "ImportDirective", + "src": "369:70:37", + "nodes": [], + "absolutePath": "lib/cairo-lang/src/starkware/solidity/components/OnchainDataFactTreeEncoder.sol", + "file": "starkware/solidity/components/OnchainDataFactTreeEncoder.sol", + "scope": 31651, + "sourceUnit": 382, + "symbolAliases": [], + "unitAlias": "" + }, + { + "id": 31182, + "nodeType": "ImportDirective", + "src": "440:63:37", + "nodes": [], + "absolutePath": "lib/cairo-lang/src/starkware/solidity/interfaces/ContractInitializer.sol", + "file": "starkware/solidity/interfaces/ContractInitializer.sol", + "scope": 31651, + "sourceUnit": 516, + "symbolAliases": [], + "unitAlias": "" + }, + { + "id": 31183, + "nodeType": "ImportDirective", + "src": "504:52:37", + "nodes": [], + "absolutePath": "lib/cairo-lang/src/starkware/solidity/interfaces/Identity.sol", + "file": "starkware/solidity/interfaces/Identity.sol", + "scope": 31651, + "sourceUnit": 534, + "symbolAliases": [], + "unitAlias": "" + }, + { + "id": 31184, + "nodeType": "ImportDirective", + "src": "557:57:37", + "nodes": [], + "absolutePath": "lib/cairo-lang/src/starkware/solidity/interfaces/IFactRegistry.sol", + "file": "starkware/solidity/interfaces/IFactRegistry.sol", + "scope": 31651, + "sourceUnit": 526, + "symbolAliases": [], + "unitAlias": "" + }, + { + "id": 31185, + "nodeType": "ImportDirective", + "src": "615:56:37", + "nodes": [], + "absolutePath": "lib/cairo-lang/src/starkware/solidity/interfaces/ProxySupport.sol", + "file": "starkware/solidity/interfaces/ProxySupport.sol", + "scope": 31651, + "sourceUnit": 774, + "symbolAliases": [], + "unitAlias": "" + }, + { + "id": 31186, + "nodeType": "ImportDirective", + "src": "672:55:37", + "nodes": [], + "absolutePath": "lib/cairo-lang/src/starkware/solidity/libraries/NamedStorage.sol", + "file": "starkware/solidity/libraries/NamedStorage.sol", + "scope": 31651, + "sourceUnit": 1107, + "symbolAliases": [], + "unitAlias": "" + }, + { + "id": 31650, + "nodeType": "ContractDefinition", + "src": "729:7138:37", + "nodes": [ + { + "id": 31203, + "nodeType": "UsingForDirective", + "src": "906:44:37", + "nodes": [], + "libraryName": { + "contractScope": null, + "id": 31201, + "name": "StarknetState", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 2333, + "src": "912:13:37", + "typeDescriptions": { + "typeIdentifier": "t_contract$_StarknetState_$2333", + "typeString": "library StarknetState" + } + }, + "typeName": { + "contractScope": null, + "id": 31202, + "name": "StarknetState.State", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 2234, + "src": "930:19:37", + "typeDescriptions": { + "typeIdentifier": "t_struct$_State_$2234_storage_ptr", + "typeString": "struct StarknetState.State" + } + } + }, + { + "id": 31211, + "nodeType": "EventDefinition", + "src": "1011:127:37", + "nodes": [], + "anonymous": false, + "documentation": null, + "name": "ConfigHashChanged", + "parameters": { + "id": 31210, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31205, + "indexed": true, + "mutability": "mutable", + "name": "changedBy", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31211, + "src": "1044:25:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 31204, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1044:7:37", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 31207, + "indexed": false, + "mutability": "mutable", + "name": "oldConfigHash", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31211, + "src": "1079:21:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 31206, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1079:7:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 31209, + "indexed": false, + "mutability": "mutable", + "name": "newConfigHash", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31211, + "src": "1110:21:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 31208, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1110:7:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1034:103:37" + } + }, + { + "id": 31219, + "nodeType": "EventDefinition", + "src": "1196:80:37", + "nodes": [], + "anonymous": false, + "documentation": null, + "name": "LogStateUpdate", + "parameters": { + "id": 31218, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31213, + "indexed": false, + "mutability": "mutable", + "name": "globalRoot", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31219, + "src": "1217:18:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 31212, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1217:7:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 31215, + "indexed": false, + "mutability": "mutable", + "name": "blockNumber", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31219, + "src": "1237:18:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_int256", + "typeString": "int256" + }, + "typeName": { + "id": 31214, + "name": "int256", + "nodeType": "ElementaryTypeName", + "src": "1237:6:37", + "typeDescriptions": { + "typeIdentifier": "t_int256", + "typeString": "int256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 31217, + "indexed": false, + "mutability": "mutable", + "name": "blockHash", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31219, + "src": "1257:17:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 31216, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1257:7:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1216:59:37" + } + }, + { + "id": 31223, + "nodeType": "EventDefinition", + "src": "1351:58:37", + "nodes": [], + "anonymous": false, + "documentation": null, + "name": "LogStateTransitionFact", + "parameters": { + "id": 31222, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31221, + "indexed": false, + "mutability": "mutable", + "name": "stateTransitionFact", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31223, + "src": "1380:27:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 31220, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "1380:7:37", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1379:29:37" + } + }, + { + "id": 31231, + "nodeType": "EventDefinition", + "src": "1474:130:37", + "nodes": [], + "anonymous": false, + "documentation": null, + "name": "ProgramHashChanged", + "parameters": { + "id": 31230, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31225, + "indexed": true, + "mutability": "mutable", + "name": "changedBy", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31231, + "src": "1508:25:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 31224, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1508:7:37", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 31227, + "indexed": false, + "mutability": "mutable", + "name": "oldProgramHash", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31231, + "src": "1543:22:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 31226, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1543:7:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 31229, + "indexed": false, + "mutability": "mutable", + "name": "newProgramHash", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31231, + "src": "1575:22:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 31228, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1575:7:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1498:105:37" + } + }, + { + "id": 31234, + "nodeType": "VariableDeclaration", + "src": "1643:81:37", + "nodes": [], + "constant": true, + "mutability": "constant", + "name": "PROGRAM_HASH_TAG", + "overrides": null, + "scope": 31650, + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 31232, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "1643:6:37", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "value": { + "argumentTypes": null, + "hexValue": "535441524b4e45545f312e305f494e49545f50524f4752414d5f484153485f55494e54", + "id": 31233, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "1687:37:37", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_8cde0e99a4532474b22bd3952cb1c6b00478babd3678337325283f4f48110fc4", + "typeString": "literal_string \"STARKNET_1.0_INIT_PROGRAM_HASH_UINT\"" + }, + "value": "STARKNET_1.0_INIT_PROGRAM_HASH_UINT" + }, + "visibility": "internal" + }, + { + "id": 31237, + "nodeType": "VariableDeclaration", + "src": "1730:84:37", + "nodes": [], + "constant": true, + "mutability": "constant", + "name": "VERIFIER_ADDRESS_TAG", + "overrides": null, + "scope": 31650, + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 31235, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "1730:6:37", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "value": { + "argumentTypes": null, + "hexValue": "535441524b4e45545f312e305f494e49545f56455249464945525f41444452455353", + "id": 31236, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "1778:36:37", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_04e7be39f2fb63cfd7d4fcfe19f108bc6b411ed972d99fca0a47dcaff878ce5e", + "typeString": "literal_string \"STARKNET_1.0_INIT_VERIFIER_ADDRESS\"" + }, + "value": "STARKNET_1.0_INIT_VERIFIER_ADDRESS" + }, + "visibility": "internal" + }, + { + "id": 31240, + "nodeType": "VariableDeclaration", + "src": "1820:85:37", + "nodes": [], + "constant": true, + "mutability": "constant", + "name": "STATE_STRUCT_TAG", + "overrides": null, + "scope": 31650, + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 31238, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "1820:6:37", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "value": { + "argumentTypes": null, + "hexValue": "535441524b4e45545f312e305f494e49545f535441524b4e45545f53544154455f535452554354", + "id": 31239, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "1864:41:37", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_71a8ef1b1265359d77973c3524afac225c0a0d829a0d4da5cac3b34532019fec", + "typeString": "literal_string \"STARKNET_1.0_INIT_STARKNET_STATE_STRUCT\"" + }, + "value": "STARKNET_1.0_INIT_STARKNET_STATE_STRUCT" + }, + "visibility": "internal" + }, + { + "id": 31243, + "nodeType": "VariableDeclaration", + "src": "1952:78:37", + "nodes": [], + "constant": true, + "mutability": "constant", + "name": "CONFIG_HASH_TAG", + "overrides": null, + "scope": 31650, + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 31241, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "1952:6:37", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "value": { + "argumentTypes": null, + "hexValue": "535441524b4e45545f312e305f535441524b4e45545f434f4e4649475f48415348", + "id": 31242, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "1995:35:37", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_b4c82a817c6e58e43d4ecb2529caab94383420d8f31e963cfe54dfe32d2cca56", + "typeString": "literal_string \"STARKNET_1.0_STARKNET_CONFIG_HASH\"" + }, + "value": "STARKNET_1.0_STARKNET_CONFIG_HASH" + }, + "visibility": "internal" + }, + { + "id": 31265, + "nodeType": "FunctionDefinition", + "src": "2037:205:37", + "nodes": [], + "body": { + "id": 31264, + "nodeType": "Block", + "src": "2122:120:37", + "nodes": [], + "statements": [ + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 31253, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "2156:3:37", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 31254, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "2156:10:37", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 31255, + "name": "programHash", + "nodeType": "Identifier", + "overloadedDeclarations": [31312, 31325], + "referencedDeclaration": 31312, + "src": "2168:11:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_uint256_$", + "typeString": "function () view returns (uint256)" + } + }, + "id": 31256, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2168:13:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 31257, + "name": "newProgramHash", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31245, + "src": "2183:14:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 31252, + "name": "ProgramHashChanged", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31231, + "src": "2137:18:37", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_uint256_$_t_uint256_$returns$__$", + "typeString": "function (address,uint256,uint256)" + } + }, + "id": 31258, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2137:61:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 31259, + "nodeType": "EmitStatement", + "src": "2132:66:37" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 31261, + "name": "newProgramHash", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31245, + "src": "2220:14:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 31260, + "name": "programHash", + "nodeType": "Identifier", + "overloadedDeclarations": [31312, 31325], + "referencedDeclaration": 31325, + "src": "2208:11:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 31262, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2208:27:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 31263, + "nodeType": "ExpressionStatement", + "src": "2208:27:37" + } + ] + }, + "documentation": null, + "functionSelector": "e87e7332", + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 31248, + "modifierName": { + "argumentTypes": null, + "id": 31247, + "name": "notFinalized", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 300, + "src": "2094:12:37", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "2094:12:37" + }, + { + "arguments": null, + "id": 31250, + "modifierName": { + "argumentTypes": null, + "id": 31249, + "name": "onlyGovernance", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 554, + "src": "2107:14:37", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "2107:14:37" + } + ], + "name": "setProgramHash", + "overrides": null, + "parameters": { + "id": 31246, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31245, + "mutability": "mutable", + "name": "newProgramHash", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31265, + "src": "2061:22:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 31244, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "2061:7:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2060:24:37" + }, + "returnParameters": { + "id": 31251, + "nodeType": "ParameterList", + "parameters": [], + "src": "2122:0:37" + }, + "scope": 31650, + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "external" + }, + { + "id": 31287, + "nodeType": "FunctionDefinition", + "src": "2248:198:37", + "nodes": [], + "body": { + "id": 31286, + "nodeType": "Block", + "src": "2331:115:37", + "nodes": [], + "statements": [ + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 31275, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "2364:3:37", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 31276, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "2364:10:37", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 31277, + "name": "configHash", + "nodeType": "Identifier", + "overloadedDeclarations": [31349, 31360], + "referencedDeclaration": 31360, + "src": "2376:10:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_uint256_$", + "typeString": "function () view returns (uint256)" + } + }, + "id": 31278, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2376:12:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 31279, + "name": "newConfigHash", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31267, + "src": "2390:13:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 31274, + "name": "ConfigHashChanged", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31211, + "src": "2346:17:37", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_uint256_$_t_uint256_$returns$__$", + "typeString": "function (address,uint256,uint256)" + } + }, + "id": 31280, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2346:58:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 31281, + "nodeType": "EmitStatement", + "src": "2341:63:37" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 31283, + "name": "newConfigHash", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31267, + "src": "2425:13:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 31282, + "name": "configHash", + "nodeType": "Identifier", + "overloadedDeclarations": [31349, 31360], + "referencedDeclaration": 31349, + "src": "2414:10:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 31284, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2414:25:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 31285, + "nodeType": "ExpressionStatement", + "src": "2414:25:37" + } + ] + }, + "documentation": null, + "functionSelector": "3d07b336", + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 31270, + "modifierName": { + "argumentTypes": null, + "id": 31269, + "name": "notFinalized", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 300, + "src": "2303:12:37", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "2303:12:37" + }, + { + "arguments": null, + "id": 31272, + "modifierName": { + "argumentTypes": null, + "id": 31271, + "name": "onlyGovernance", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 554, + "src": "2316:14:37", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "2316:14:37" + } + ], + "name": "setConfigHash", + "overrides": null, + "parameters": { + "id": 31268, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31267, + "mutability": "mutable", + "name": "newConfigHash", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31287, + "src": "2271:21:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 31266, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "2271:7:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2270:23:37" + }, + "returnParameters": { + "id": 31273, + "nodeType": "ParameterList", + "parameters": [], + "src": "2331:0:37" + }, + "scope": 31650, + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "external" + }, + { + "id": 31301, + "nodeType": "FunctionDefinition", + "src": "2452:183:37", + "nodes": [], + "body": { + "id": 31300, + "nodeType": "Block", + "src": "2578:57:37", + "nodes": [], + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 31297, + "name": "delayInSeconds", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31289, + "src": "2613:14:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 31296, + "name": "messageCancellationDelay", + "nodeType": "Identifier", + "overloadedDeclarations": [1836, 1849], + "referencedDeclaration": 1849, + "src": "2588:24:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 31298, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2588:40:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 31299, + "nodeType": "ExpressionStatement", + "src": "2588:40:37" + } + ] + }, + "documentation": null, + "functionSelector": "c99d397f", + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 31292, + "modifierName": { + "argumentTypes": null, + "id": 31291, + "name": "notFinalized", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 300, + "src": "2538:12:37", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "2538:12:37" + }, + { + "arguments": null, + "id": 31294, + "modifierName": { + "argumentTypes": null, + "id": 31293, + "name": "onlyGovernance", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 554, + "src": "2559:14:37", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "2559:14:37" + } + ], + "name": "setMessageCancellationDelay", + "overrides": null, + "parameters": { + "id": 31290, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31289, + "mutability": "mutable", + "name": "delayInSeconds", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31301, + "src": "2489:22:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 31288, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "2489:7:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2488:24:37" + }, + "returnParameters": { + "id": 31295, + "nodeType": "ParameterList", + "parameters": [], + "src": "2578:0:37" + }, + "scope": 31650, + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "external" + }, + { + "id": 31312, + "nodeType": "FunctionDefinition", + "src": "2699:120:37", + "nodes": [], + "body": { + "id": 31311, + "nodeType": "Block", + "src": "2752:67:37", + "nodes": [], + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 31308, + "name": "PROGRAM_HASH_TAG", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31234, + "src": "2795:16:37", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + ], + "expression": { + "argumentTypes": null, + "id": 31306, + "name": "NamedStorage", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1106, + "src": "2769:12:37", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_NamedStorage_$1106_$", + "typeString": "type(library NamedStorage)" + } + }, + "id": 31307, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "getUintValue", + "nodeType": "MemberAccess", + "referencedDeclaration": 968, + "src": "2769:25:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_string_memory_ptr_$returns$_t_uint256_$", + "typeString": "function (string memory) view returns (uint256)" + } + }, + "id": 31309, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2769:43:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 31305, + "id": 31310, + "nodeType": "Return", + "src": "2762:50:37" + } + ] + }, + "documentation": null, + "functionSelector": "8a9bf090", + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "programHash", + "overrides": null, + "parameters": { + "id": 31302, + "nodeType": "ParameterList", + "parameters": [], + "src": "2719:2:37" + }, + "returnParameters": { + "id": 31305, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31304, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31312, + "src": "2743:7:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 31303, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "2743:7:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2742:9:37" + }, + "scope": 31650, + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "id": 31325, + "nodeType": "FunctionDefinition", + "src": "2884:112:37", + "nodes": [], + "body": { + "id": 31324, + "nodeType": "Block", + "src": "2929:67:37", + "nodes": [], + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 31320, + "name": "PROGRAM_HASH_TAG", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31234, + "src": "2965:16:37", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + }, + { + "argumentTypes": null, + "id": 31321, + "name": "value", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31314, + "src": "2983:5:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 31317, + "name": "NamedStorage", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1106, + "src": "2939:12:37", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_NamedStorage_$1106_$", + "typeString": "type(library NamedStorage)" + } + }, + "id": 31319, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "setUintValue", + "nodeType": "MemberAccess", + "referencedDeclaration": 986, + "src": "2939:25:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_string_memory_ptr_$_t_uint256_$returns$__$", + "typeString": "function (string memory,uint256)" + } + }, + "id": 31322, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2939:50:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 31323, + "nodeType": "ExpressionStatement", + "src": "2939:50:37" + } + ] + }, + "documentation": null, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "programHash", + "overrides": null, + "parameters": { + "id": 31315, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31314, + "mutability": "mutable", + "name": "value", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31325, + "src": "2905:13:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 31313, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "2905:7:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2904:15:37" + }, + "returnParameters": { + "id": 31316, + "nodeType": "ParameterList", + "parameters": [], + "src": "2929:0:37" + }, + "scope": 31650, + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "internal" + }, + { + "id": 31336, + "nodeType": "FunctionDefinition", + "src": "3052:126:37", + "nodes": [], + "body": { + "id": 31335, + "nodeType": "Block", + "src": "3104:74:37", + "nodes": [], + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 31332, + "name": "VERIFIER_ADDRESS_TAG", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31237, + "src": "3150:20:37", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + ], + "expression": { + "argumentTypes": null, + "id": 31330, + "name": "NamedStorage", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1106, + "src": "3121:12:37", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_NamedStorage_$1106_$", + "typeString": "type(library NamedStorage)" + } + }, + "id": 31331, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "getAddressValue", + "nodeType": "MemberAccess", + "referencedDeclaration": 1026, + "src": "3121:28:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_string_memory_ptr_$returns$_t_address_$", + "typeString": "function (string memory) view returns (address)" + } + }, + "id": 31333, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3121:50:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "functionReturnParameters": 31329, + "id": 31334, + "nodeType": "Return", + "src": "3114:57:37" + } + ] + }, + "documentation": null, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "verifier", + "overrides": null, + "parameters": { + "id": 31326, + "nodeType": "ParameterList", + "parameters": [], + "src": "3069:2:37" + }, + "returnParameters": { + "id": 31329, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31328, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31336, + "src": "3095:7:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 31327, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "3095:7:37", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "3094:9:37" + }, + "scope": 31650, + "stateMutability": "view", + "virtual": false, + "visibility": "internal" + }, + { + "id": 31349, + "nodeType": "FunctionDefinition", + "src": "3242:110:37", + "nodes": [], + "body": { + "id": 31348, + "nodeType": "Block", + "src": "3286:66:37", + "nodes": [], + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 31344, + "name": "CONFIG_HASH_TAG", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31243, + "src": "3322:15:37", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + }, + { + "argumentTypes": null, + "id": 31345, + "name": "value", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31338, + "src": "3339:5:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 31341, + "name": "NamedStorage", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1106, + "src": "3296:12:37", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_NamedStorage_$1106_$", + "typeString": "type(library NamedStorage)" + } + }, + "id": 31343, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "setUintValue", + "nodeType": "MemberAccess", + "referencedDeclaration": 986, + "src": "3296:25:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_string_memory_ptr_$_t_uint256_$returns$__$", + "typeString": "function (string memory,uint256)" + } + }, + "id": 31346, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3296:49:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 31347, + "nodeType": "ExpressionStatement", + "src": "3296:49:37" + } + ] + }, + "documentation": null, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "configHash", + "overrides": null, + "parameters": { + "id": 31339, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31338, + "mutability": "mutable", + "name": "value", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31349, + "src": "3262:13:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 31337, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "3262:7:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "3261:15:37" + }, + "returnParameters": { + "id": 31340, + "nodeType": "ParameterList", + "parameters": [], + "src": "3286:0:37" + }, + "scope": 31650, + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "internal" + }, + { + "id": 31360, + "nodeType": "FunctionDefinition", + "src": "3415:118:37", + "nodes": [], + "body": { + "id": 31359, + "nodeType": "Block", + "src": "3467:66:37", + "nodes": [], + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 31356, + "name": "CONFIG_HASH_TAG", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31243, + "src": "3510:15:37", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + ], + "expression": { + "argumentTypes": null, + "id": 31354, + "name": "NamedStorage", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1106, + "src": "3484:12:37", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_NamedStorage_$1106_$", + "typeString": "type(library NamedStorage)" + } + }, + "id": 31355, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "getUintValue", + "nodeType": "MemberAccess", + "referencedDeclaration": 968, + "src": "3484:25:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_string_memory_ptr_$returns$_t_uint256_$", + "typeString": "function (string memory) view returns (uint256)" + } + }, + "id": 31357, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3484:42:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 31353, + "id": 31358, + "nodeType": "Return", + "src": "3477:49:37" + } + ] + }, + "documentation": null, + "functionSelector": "e1f1176d", + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "configHash", + "overrides": null, + "parameters": { + "id": 31350, + "nodeType": "ParameterList", + "parameters": [], + "src": "3434:2:37" + }, + "returnParameters": { + "id": 31353, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31352, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31360, + "src": "3458:7:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 31351, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "3458:7:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "3457:9:37" + }, + "scope": 31650, + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "id": 31373, + "nodeType": "FunctionDefinition", + "src": "3539:130:37", + "nodes": [], + "body": { + "id": 31372, + "nodeType": "Block", + "src": "3591:78:37", + "nodes": [], + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 31368, + "name": "VERIFIER_ADDRESS_TAG", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31237, + "src": "3634:20:37", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + }, + { + "argumentTypes": null, + "id": 31369, + "name": "value", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31362, + "src": "3656:5:37", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "expression": { + "argumentTypes": null, + "id": 31365, + "name": "NamedStorage", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1106, + "src": "3601:12:37", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_NamedStorage_$1106_$", + "typeString": "type(library NamedStorage)" + } + }, + "id": 31367, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "setAddressValueOnce", + "nodeType": "MemberAccess", + "referencedDeclaration": 1069, + "src": "3601:32:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_string_memory_ptr_$_t_address_$returns$__$", + "typeString": "function (string memory,address)" + } + }, + "id": 31370, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3601:61:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 31371, + "nodeType": "ExpressionStatement", + "src": "3601:61:37" + } + ] + }, + "documentation": null, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "setVerifierAddress", + "overrides": null, + "parameters": { + "id": 31363, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31362, + "mutability": "mutable", + "name": "value", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31373, + "src": "3567:13:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 31361, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "3567:7:37", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "3566:15:37" + }, + "returnParameters": { + "id": 31364, + "nodeType": "ParameterList", + "parameters": [], + "src": "3591:0:37" + }, + "scope": 31650, + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "internal" + }, + { + "id": 31389, + "nodeType": "FunctionDefinition", + "src": "3722:232:37", + "nodes": [], + "body": { + "id": 31388, + "nodeType": "Block", + "src": "3803:151:37", + "nodes": [], + "statements": [ + { + "assignments": [31379], + "declarations": [ + { + "constant": false, + "id": 31379, + "mutability": "mutable", + "name": "location", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31388, + "src": "3813:16:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 31378, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "3813:7:37", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 31386, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 31383, + "name": "STATE_STRUCT_TAG", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31240, + "src": "3859:16:37", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + ], + "expression": { + "argumentTypes": null, + "id": 31381, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "3842:3:37", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 31382, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "encodePacked", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "3842:16:37", + "typeDescriptions": { + "typeIdentifier": "t_function_abiencodepacked_pure$__$returns$_t_bytes_memory_ptr_$", + "typeString": "function () pure returns (bytes memory)" + } + }, + "id": 31384, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3842:34:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + ], + "id": 31380, + "name": "keccak256", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -8, + "src": "3832:9:37", + "typeDescriptions": { + "typeIdentifier": "t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$", + "typeString": "function (bytes memory) pure returns (bytes32)" + } + }, + "id": 31385, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3832:45:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "3813:64:37" + }, + { + "AST": { + "nodeType": "YulBlock", + "src": "3896:52:37", + "statements": [ + { + "nodeType": "YulAssignment", + "src": "3910:28:37", + "value": { + "name": "location", + "nodeType": "YulIdentifier", + "src": "3930:8:37" + }, + "variableNames": [ + { + "name": "stateStruct_slot", + "nodeType": "YulIdentifier", + "src": "3910:16:37" + } + ] + } + ] + }, + "evmVersion": "istanbul", + "externalReferences": [ + { + "declaration": 31379, + "isOffset": false, + "isSlot": false, + "src": "3930:8:37", + "valueSize": 1 + }, + { + "declaration": 31376, + "isOffset": false, + "isSlot": true, + "src": "3910:16:37", + "valueSize": 1 + } + ], + "id": 31387, + "nodeType": "InlineAssembly", + "src": "3887:61:37" + } + ] + }, + "documentation": null, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "state", + "overrides": null, + "parameters": { + "id": 31374, + "nodeType": "ParameterList", + "parameters": [], + "src": "3736:2:37" + }, + "returnParameters": { + "id": 31377, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31376, + "mutability": "mutable", + "name": "stateStruct", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31389, + "src": "3762:39:37", + "stateVariable": false, + "storageLocation": "storage", + "typeDescriptions": { + "typeIdentifier": "t_struct$_State_$2234_storage_ptr", + "typeString": "struct StarknetState.State" + }, + "typeName": { + "contractScope": null, + "id": 31375, + "name": "StarknetState.State", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 2234, + "src": "3762:19:37", + "typeDescriptions": { + "typeIdentifier": "t_struct$_State_$2234_storage_ptr", + "typeString": "struct StarknetState.State" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "3761:41:37" + }, + "scope": 31650, + "stateMutability": "pure", + "virtual": false, + "visibility": "internal" + }, + { + "id": 31401, + "nodeType": "FunctionDefinition", + "src": "3960:105:37", + "nodes": [], + "body": { + "id": 31400, + "nodeType": "Block", + "src": "4023:42:37", + "nodes": [], + "statements": [ + { + "expression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 31398, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 31395, + "name": "programHash", + "nodeType": "Identifier", + "overloadedDeclarations": [31312, 31325], + "referencedDeclaration": 31312, + "src": "4040:11:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_uint256_$", + "typeString": "function () view returns (uint256)" + } + }, + "id": 31396, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4040:13:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "!=", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30", + "id": 31397, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4057:1:37", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "src": "4040:18:37", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "functionReturnParameters": 31394, + "id": 31399, + "nodeType": "Return", + "src": "4033:25:37" + } + ] + }, + "baseFunctions": [499], + "documentation": null, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "isInitialized", + "overrides": { + "id": 31391, + "nodeType": "OverrideSpecifier", + "overrides": [], + "src": "3999:8:37" + }, + "parameters": { + "id": 31390, + "nodeType": "ParameterList", + "parameters": [], + "src": "3982:2:37" + }, + "returnParameters": { + "id": 31394, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31393, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31401, + "src": "4017:4:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 31392, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "4017:4:37", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4016:6:37" + }, + "scope": 31650, + "stateMutability": "view", + "virtual": false, + "visibility": "internal" + }, + { + "id": 31410, + "nodeType": "FunctionDefinition", + "src": "4071:95:37", + "nodes": [], + "body": { + "id": 31409, + "nodeType": "Block", + "src": "4141:25:37", + "nodes": [], + "statements": [ + { + "expression": { + "argumentTypes": null, + "hexValue": "30", + "id": 31407, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4158:1:37", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "functionReturnParameters": 31406, + "id": 31408, + "nodeType": "Return", + "src": "4151:8:37" + } + ] + }, + "baseFunctions": [494], + "documentation": null, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "numOfSubContracts", + "overrides": { + "id": 31403, + "nodeType": "OverrideSpecifier", + "overrides": [], + "src": "4114:8:37" + }, + "parameters": { + "id": 31402, + "nodeType": "ParameterList", + "parameters": [], + "src": "4097:2:37" + }, + "returnParameters": { + "id": 31406, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31405, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31410, + "src": "4132:7:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 31404, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4132:7:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4131:9:37" + }, + "scope": 31650, + "stateMutability": "pure", + "virtual": false, + "visibility": "internal" + }, + { + "id": 31446, + "nodeType": "FunctionDefinition", + "src": "4172:266:37", + "nodes": [], + "body": { + "id": 31445, + "nodeType": "Block", + "src": "4242:196:37", + "nodes": [], + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 31422, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 31417, + "name": "data", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31412, + "src": "4260:4:37", + "typeDescriptions": { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes calldata" + } + }, + "id": 31418, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "length", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "4260:11:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_rational_192_by_1", + "typeString": "int_const 192" + }, + "id": 31421, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "hexValue": "36", + "id": 31419, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4275:1:37", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_6_by_1", + "typeString": "int_const 6" + }, + "value": "6" + }, + "nodeType": "BinaryOperation", + "operator": "*", + "rightExpression": { + "argumentTypes": null, + "hexValue": "3332", + "id": 31420, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4279:2:37", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_32_by_1", + "typeString": "int_const 32" + }, + "value": "32" + }, + "src": "4275:6:37", + "typeDescriptions": { + "typeIdentifier": "t_rational_192_by_1", + "typeString": "int_const 192" + } + }, + "src": "4260:21:37", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "494c4c4547414c5f494e49545f444154415f53495a45", + "id": 31423, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4283:24:37", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_14356eebb71e7931cad70fa351b8bc5bd32ed3af1a9628009fb6ec382db26522", + "typeString": "literal_string \"ILLEGAL_INIT_DATA_SIZE\"" + }, + "value": "ILLEGAL_INIT_DATA_SIZE" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_14356eebb71e7931cad70fa351b8bc5bd32ed3af1a9628009fb6ec382db26522", + "typeString": "literal_string \"ILLEGAL_INIT_DATA_SIZE\"" + } + ], + "id": 31416, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [-18, -18], + "referencedDeclaration": -18, + "src": "4252:7:37", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 31424, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4252:56:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 31425, + "nodeType": "ExpressionStatement", + "src": "4252:56:37" + }, + { + "assignments": [31427], + "declarations": [ + { + "constant": false, + "id": 31427, + "mutability": "mutable", + "name": "programHash_", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31445, + "src": "4318:20:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 31426, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4318:7:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 31437, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 31430, + "name": "data", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31412, + "src": "4352:4:37", + "typeDescriptions": { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes calldata" + } + }, + "endExpression": { + "argumentTypes": null, + "hexValue": "3332", + "id": 31431, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4358:2:37", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_32_by_1", + "typeString": "int_const 32" + }, + "value": "32" + }, + "id": 31432, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexRangeAccess", + "src": "4352:9:37", + "startExpression": null, + "typeDescriptions": { + "typeIdentifier": "t_bytes_calldata_ptr_slice", + "typeString": "bytes calldata slice" + } + }, + { + "argumentTypes": null, + "components": [ + { + "argumentTypes": null, + "id": 31434, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "4364:7:37", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_uint256_$", + "typeString": "type(uint256)" + }, + "typeName": { + "id": 31433, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4364:7:37", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + } + ], + "id": 31435, + "isConstant": false, + "isInlineArray": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "TupleExpression", + "src": "4363:9:37", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_uint256_$", + "typeString": "type(uint256)" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_calldata_ptr_slice", + "typeString": "bytes calldata slice" + }, + { + "typeIdentifier": "t_type$_t_uint256_$", + "typeString": "type(uint256)" + } + ], + "expression": { + "argumentTypes": null, + "id": 31428, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "4341:3:37", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 31429, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "decode", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "4341:10:37", + "typeDescriptions": { + "typeIdentifier": "t_function_abidecode_pure$__$returns$__$", + "typeString": "function () pure" + } + }, + "id": 31436, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4341:32:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "4318:55:37" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 31441, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 31439, + "name": "programHash_", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31427, + "src": "4391:12:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "!=", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30", + "id": 31440, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4407:1:37", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "src": "4391:17:37", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "4241445f494e495449414c495a4154494f4e", + "id": 31442, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4410:20:37", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_755bbc3475835b38d7a5e4a6c96c52430dc055820776347e2e8da2916177d245", + "typeString": "literal_string \"BAD_INITIALIZATION\"" + }, + "value": "BAD_INITIALIZATION" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_755bbc3475835b38d7a5e4a6c96c52430dc055820776347e2e8da2916177d245", + "typeString": "literal_string \"BAD_INITIALIZATION\"" + } + ], + "id": 31438, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [-18, -18], + "referencedDeclaration": -18, + "src": "4383:7:37", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 31443, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4383:48:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 31444, + "nodeType": "ExpressionStatement", + "src": "4383:48:37" + } + ] + }, + "baseFunctions": [504], + "documentation": null, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "validateInitData", + "overrides": { + "id": 31414, + "nodeType": "OverrideSpecifier", + "overrides": [], + "src": "4233:8:37" + }, + "parameters": { + "id": 31413, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31412, + "mutability": "mutable", + "name": "data", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31446, + "src": "4198:19:37", + "stateVariable": false, + "storageLocation": "calldata", + "typeDescriptions": { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 31411, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "4198:5:37", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4197:21:37" + }, + "returnParameters": { + "id": 31415, + "nodeType": "ParameterList", + "parameters": [], + "src": "4242:0:37" + }, + "scope": 31650, + "stateMutability": "view", + "virtual": false, + "visibility": "internal" + }, + { + "id": 31453, + "nodeType": "FunctionDefinition", + "src": "4444:94:37", + "nodes": [], + "body": { + "id": 31452, + "nodeType": "Block", + "src": "4536:2:37", + "nodes": [], + "statements": [] + }, + "baseFunctions": [509], + "documentation": null, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "processSubContractAddresses", + "overrides": { + "id": 31450, + "nodeType": "OverrideSpecifier", + "overrides": [], + "src": "4527:8:37" + }, + "parameters": { + "id": 31449, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31448, + "mutability": "mutable", + "name": "subContractAddresses", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31453, + "src": "4481:35:37", + "stateVariable": false, + "storageLocation": "calldata", + "typeDescriptions": { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 31447, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "4481:5:37", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4480:37:37" + }, + "returnParameters": { + "id": 31451, + "nodeType": "ParameterList", + "parameters": [], + "src": "4536:0:37" + }, + "scope": 31650, + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "internal" + }, + { + "id": 31504, + "nodeType": "FunctionDefinition", + "src": "4544:505:37", + "nodes": [], + "body": { + "id": 31503, + "nodeType": "Block", + "src": "4616:433:37", + "nodes": [], + "statements": [ + { + "assignments": [31460, 31462, 31464, 31466], + "declarations": [ + { + "constant": false, + "id": 31460, + "mutability": "mutable", + "name": "programHash_", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31503, + "src": "4640:20:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 31459, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4640:7:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 31462, + "mutability": "mutable", + "name": "verifier_", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31503, + "src": "4674:17:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 31461, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "4674:7:37", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 31464, + "mutability": "mutable", + "name": "configHash_", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31503, + "src": "4705:19:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 31463, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4705:7:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 31466, + "mutability": "mutable", + "name": "initialState", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31503, + "src": "4738:39:37", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_struct$_State_$2234_memory_ptr", + "typeString": "struct StarknetState.State" + }, + "typeName": { + "contractScope": null, + "id": 31465, + "name": "StarknetState.State", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 2234, + "src": "4738:19:37", + "typeDescriptions": { + "typeIdentifier": "t_struct$_State_$2234_storage_ptr", + "typeString": "struct StarknetState.State" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 31480, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 31469, + "name": "data", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31455, + "src": "4801:4:37", + "typeDescriptions": { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes calldata" + } + }, + { + "argumentTypes": null, + "components": [ + { + "argumentTypes": null, + "id": 31471, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "4808:7:37", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_uint256_$", + "typeString": "type(uint256)" + }, + "typeName": { + "id": 31470, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4808:7:37", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + { + "argumentTypes": null, + "id": 31473, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "4817:7:37", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 31472, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "4817:7:37", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + { + "argumentTypes": null, + "id": 31475, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "4826:7:37", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_uint256_$", + "typeString": "type(uint256)" + }, + "typeName": { + "id": 31474, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4826:7:37", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 31476, + "name": "StarknetState", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2333, + "src": "4835:13:37", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_StarknetState_$2333_$", + "typeString": "type(library StarknetState)" + } + }, + "id": 31477, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "State", + "nodeType": "MemberAccess", + "referencedDeclaration": 2234, + "src": "4835:19:37", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_struct$_State_$2234_storage_ptr_$", + "typeString": "type(struct StarknetState.State storage pointer)" + } + } + ], + "id": 31478, + "isConstant": false, + "isInlineArray": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "TupleExpression", + "src": "4807:48:37", + "typeDescriptions": { + "typeIdentifier": "t_tuple$_t_type$_t_uint256_$_$_t_type$_t_address_$_$_t_type$_t_uint256_$_$_t_type$_t_struct$_State_$2234_storage_ptr_$_$", + "typeString": "tuple(type(uint256),type(address),type(uint256),type(struct StarknetState.State storage pointer))" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes calldata" + }, + { + "typeIdentifier": "t_tuple$_t_type$_t_uint256_$_$_t_type$_t_address_$_$_t_type$_t_uint256_$_$_t_type$_t_struct$_State_$2234_storage_ptr_$_$", + "typeString": "tuple(type(uint256),type(address),type(uint256),type(struct StarknetState.State storage pointer))" + } + ], + "expression": { + "argumentTypes": null, + "id": 31467, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "4790:3:37", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 31468, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "decode", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "4790:10:37", + "typeDescriptions": { + "typeIdentifier": "t_function_abidecode_pure$__$returns$__$", + "typeString": "function () pure" + } + }, + "id": 31479, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4790:66:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$_t_uint256_$_t_address_payable_$_t_uint256_$_t_struct$_State_$2234_memory_ptr_$", + "typeString": "tuple(uint256,address payable,uint256,struct StarknetState.State memory)" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "4626:230:37" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 31482, + "name": "programHash_", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31460, + "src": "4879:12:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 31481, + "name": "programHash", + "nodeType": "Identifier", + "overloadedDeclarations": [31312, 31325], + "referencedDeclaration": 31325, + "src": "4867:11:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 31483, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4867:25:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 31484, + "nodeType": "ExpressionStatement", + "src": "4867:25:37" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 31486, + "name": "verifier_", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31462, + "src": "4921:9:37", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 31485, + "name": "setVerifierAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31373, + "src": "4902:18:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$returns$__$", + "typeString": "function (address)" + } + }, + "id": 31487, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4902:29:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 31488, + "nodeType": "ExpressionStatement", + "src": "4902:29:37" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 31492, + "name": "initialState", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31466, + "src": "4954:12:37", + "typeDescriptions": { + "typeIdentifier": "t_struct$_State_$2234_memory_ptr", + "typeString": "struct StarknetState.State memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_struct$_State_$2234_memory_ptr", + "typeString": "struct StarknetState.State memory" + } + ], + "expression": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 31489, + "name": "state", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31389, + "src": "4941:5:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$__$returns$_t_struct$_State_$2234_storage_ptr_$", + "typeString": "function () pure returns (struct StarknetState.State storage pointer)" + } + }, + "id": 31490, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4941:7:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_struct$_State_$2234_storage_ptr", + "typeString": "struct StarknetState.State storage pointer" + } + }, + "id": 31491, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "copy", + "nodeType": "MemberAccess", + "referencedDeclaration": 2263, + "src": "4941:12:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_struct$_State_$2234_storage_ptr_$_t_struct$_State_$2234_memory_ptr_$returns$__$bound_to$_t_struct$_State_$2234_storage_ptr_$", + "typeString": "function (struct StarknetState.State storage pointer,struct StarknetState.State memory)" + } + }, + "id": 31493, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4941:26:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 31494, + "nodeType": "ExpressionStatement", + "src": "4941:26:37" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 31496, + "name": "configHash_", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31464, + "src": "4988:11:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 31495, + "name": "configHash", + "nodeType": "Identifier", + "overloadedDeclarations": [31349, 31360], + "referencedDeclaration": 31349, + "src": "4977:10:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 31497, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4977:23:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 31498, + "nodeType": "ExpressionStatement", + "src": "4977:23:37" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "35", + "id": 31500, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5035:6:37", + "subdenomination": "days", + "typeDescriptions": { + "typeIdentifier": "t_rational_432000_by_1", + "typeString": "int_const 432000" + }, + "value": "5" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_432000_by_1", + "typeString": "int_const 432000" + } + ], + "id": 31499, + "name": "messageCancellationDelay", + "nodeType": "Identifier", + "overloadedDeclarations": [1836, 1849], + "referencedDeclaration": 1849, + "src": "5010:24:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 31501, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5010:32:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 31502, + "nodeType": "ExpressionStatement", + "src": "5010:32:37" + } + ] + }, + "baseFunctions": [514], + "documentation": null, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "initializeContractState", + "overrides": { + "id": 31457, + "nodeType": "OverrideSpecifier", + "overrides": [], + "src": "4607:8:37" + }, + "parameters": { + "id": 31456, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31455, + "mutability": "mutable", + "name": "data", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31504, + "src": "4577:19:37", + "stateVariable": false, + "storageLocation": "calldata", + "typeDescriptions": { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 31454, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "4577:5:37", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4576:21:37" + }, + "returnParameters": { + "id": 31458, + "nodeType": "ParameterList", + "parameters": [], + "src": "4616:0:37" + }, + "scope": 31650, + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "internal" + }, + { + "id": 31514, + "nodeType": "FunctionDefinition", + "src": "5123:118:37", + "nodes": [], + "body": { + "id": 31513, + "nodeType": "Block", + "src": "5190:51:37", + "nodes": [], + "statements": [ + { + "expression": { + "argumentTypes": null, + "hexValue": "537461726b576172655f537461726b6e65745f323032335f36", + "id": 31511, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5207:27:37", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_2a1b12eb18968846aa42f0439e8341082c05ab7ac9d4e10fe505d21d0bef4c39", + "typeString": "literal_string \"StarkWare_Starknet_2023_6\"" + }, + "value": "StarkWare_Starknet_2023_6" + }, + "functionReturnParameters": 31510, + "id": 31512, + "nodeType": "Return", + "src": "5200:34:37" + } + ] + }, + "baseFunctions": [532], + "documentation": { + "id": 31505, + "nodeType": "StructuredDocumentation", + "src": "5055:63:37", + "text": "Returns a string that identifies the contract." + }, + "functionSelector": "eeb72866", + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "identify", + "overrides": { + "id": 31507, + "nodeType": "OverrideSpecifier", + "overrides": [], + "src": "5157:8:37" + }, + "parameters": { + "id": 31506, + "nodeType": "ParameterList", + "parameters": [], + "src": "5140:2:37" + }, + "returnParameters": { + "id": 31510, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31509, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31514, + "src": "5175:13:37", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 31508, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "5175:6:37", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "5174:15:37" + }, + "scope": 31650, + "stateMutability": "pure", + "virtual": false, + "visibility": "external" + }, + { + "id": 31525, + "nodeType": "FunctionDefinition", + "src": "5300:95:37", + "nodes": [], + "body": { + "id": 31524, + "nodeType": "Block", + "src": "5353:42:37", + "nodes": [], + "statements": [ + { + "expression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 31520, + "name": "state", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31389, + "src": "5370:5:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$__$returns$_t_struct$_State_$2234_storage_ptr_$", + "typeString": "function () pure returns (struct StarknetState.State storage pointer)" + } + }, + "id": 31521, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5370:7:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_struct$_State_$2234_storage_ptr", + "typeString": "struct StarknetState.State storage pointer" + } + }, + "id": 31522, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "globalRoot", + "nodeType": "MemberAccess", + "referencedDeclaration": 2229, + "src": "5370:18:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 31519, + "id": 31523, + "nodeType": "Return", + "src": "5363:25:37" + } + ] + }, + "documentation": { + "id": 31515, + "nodeType": "StructuredDocumentation", + "src": "5247:48:37", + "text": "Returns the current state root." + }, + "functionSelector": "9588eca2", + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "stateRoot", + "overrides": null, + "parameters": { + "id": 31516, + "nodeType": "ParameterList", + "parameters": [], + "src": "5318:2:37" + }, + "returnParameters": { + "id": 31519, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31518, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31525, + "src": "5344:7:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 31517, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "5344:7:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "5343:9:37" + }, + "scope": 31650, + "stateMutability": "view", + "virtual": false, + "visibility": "external" + }, + { + "id": 31536, + "nodeType": "FunctionDefinition", + "src": "5456:102:37", + "nodes": [], + "body": { + "id": 31535, + "nodeType": "Block", + "src": "5515:43:37", + "nodes": [], + "statements": [ + { + "expression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 31531, + "name": "state", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31389, + "src": "5532:5:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$__$returns$_t_struct$_State_$2234_storage_ptr_$", + "typeString": "function () pure returns (struct StarknetState.State storage pointer)" + } + }, + "id": 31532, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5532:7:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_struct$_State_$2234_storage_ptr", + "typeString": "struct StarknetState.State storage pointer" + } + }, + "id": 31533, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "blockNumber", + "nodeType": "MemberAccess", + "referencedDeclaration": 2231, + "src": "5532:19:37", + "typeDescriptions": { + "typeIdentifier": "t_int256", + "typeString": "int256" + } + }, + "functionReturnParameters": 31530, + "id": 31534, + "nodeType": "Return", + "src": "5525:26:37" + } + ] + }, + "documentation": { + "id": 31526, + "nodeType": "StructuredDocumentation", + "src": "5401:50:37", + "text": "Returns the current block number." + }, + "functionSelector": "35befa5d", + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "stateBlockNumber", + "overrides": null, + "parameters": { + "id": 31527, + "nodeType": "ParameterList", + "parameters": [], + "src": "5481:2:37" + }, + "returnParameters": { + "id": 31530, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31529, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31536, + "src": "5507:6:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_int256", + "typeString": "int256" + }, + "typeName": { + "id": 31528, + "name": "int256", + "nodeType": "ElementaryTypeName", + "src": "5507:6:37", + "typeDescriptions": { + "typeIdentifier": "t_int256", + "typeString": "int256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "5506:8:37" + }, + "scope": 31650, + "stateMutability": "view", + "virtual": false, + "visibility": "external" + }, + { + "id": 31547, + "nodeType": "FunctionDefinition", + "src": "5617:99:37", + "nodes": [], + "body": { + "id": 31546, + "nodeType": "Block", + "src": "5675:41:37", + "nodes": [], + "statements": [ + { + "expression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 31542, + "name": "state", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31389, + "src": "5692:5:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$__$returns$_t_struct$_State_$2234_storage_ptr_$", + "typeString": "function () pure returns (struct StarknetState.State storage pointer)" + } + }, + "id": 31543, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5692:7:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_struct$_State_$2234_storage_ptr", + "typeString": "struct StarknetState.State storage pointer" + } + }, + "id": 31544, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "blockHash", + "nodeType": "MemberAccess", + "referencedDeclaration": 2233, + "src": "5692:17:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 31541, + "id": 31545, + "nodeType": "Return", + "src": "5685:24:37" + } + ] + }, + "documentation": { + "id": 31537, + "nodeType": "StructuredDocumentation", + "src": "5564:48:37", + "text": "Returns the current block hash." + }, + "functionSelector": "382d83e3", + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "stateBlockHash", + "overrides": null, + "parameters": { + "id": 31538, + "nodeType": "ParameterList", + "parameters": [], + "src": "5640:2:37" + }, + "returnParameters": { + "id": 31541, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31540, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31547, + "src": "5666:7:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 31539, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "5666:7:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "5665:9:37" + }, + "scope": 31650, + "stateMutability": "view", + "virtual": false, + "visibility": "external" + }, + { + "id": 31649, + "nodeType": "FunctionDefinition", + "src": "6058:1807:37", + "nodes": [], + "body": { + "id": 31648, + "nodeType": "Block", + "src": "6149:1716:37", + "nodes": [], + "statements": [ + { + "assignments": [31557], + "declarations": [ + { + "constant": false, + "id": 31557, + "mutability": "mutable", + "name": "initialBlockNumber", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31648, + "src": "6331:25:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_int256", + "typeString": "int256" + }, + "typeName": { + "id": 31556, + "name": "int256", + "nodeType": "ElementaryTypeName", + "src": "6331:6:37", + "typeDescriptions": { + "typeIdentifier": "t_int256", + "typeString": "int256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 31561, + "initialValue": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 31558, + "name": "state", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31389, + "src": "6359:5:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$__$returns$_t_struct$_State_$2234_storage_ptr_$", + "typeString": "function () pure returns (struct StarknetState.State storage pointer)" + } + }, + "id": 31559, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6359:7:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_struct$_State_$2234_storage_ptr", + "typeString": "struct StarknetState.State storage pointer" + } + }, + "id": 31560, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "blockNumber", + "nodeType": "MemberAccess", + "referencedDeclaration": 2231, + "src": "6359:19:37", + "typeDescriptions": { + "typeIdentifier": "t_int256", + "typeString": "int256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "6331:47:37" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 31565, + "name": "programOutput", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31551, + "src": "6449:13:37", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr", + "typeString": "uint256[] calldata" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr", + "typeString": "uint256[] calldata" + } + ], + "expression": { + "argumentTypes": null, + "id": 31562, + "name": "StarknetOutput", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1653, + "src": "6425:14:37", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_StarknetOutput_$1653_$", + "typeString": "type(library StarknetOutput)" + } + }, + "id": 31564, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "validate", + "nodeType": "MemberAccess", + "referencedDeclaration": 1363, + "src": "6425:23:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_array$_t_uint256_$dyn_calldata_ptr_$returns$__$", + "typeString": "function (uint256[] calldata) pure" + } + }, + "id": 31566, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6425:38:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 31567, + "nodeType": "ExpressionStatement", + "src": "6425:38:37" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 31575, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 31569, + "name": "configHash", + "nodeType": "Identifier", + "overloadedDeclarations": [31349, 31360], + "referencedDeclaration": 31360, + "src": "6528:10:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_uint256_$", + "typeString": "function () view returns (uint256)" + } + }, + "id": 31570, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6528:12:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 31571, + "name": "programOutput", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31551, + "src": "6544:13:37", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr", + "typeString": "uint256[] calldata" + } + }, + "id": 31574, + "indexExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 31572, + "name": "StarknetOutput", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1653, + "src": "6558:14:37", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_StarknetOutput_$1653_$", + "typeString": "type(library StarknetOutput)" + } + }, + "id": 31573, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "CONFIG_HASH_OFFSET", + "nodeType": "MemberAccess", + "referencedDeclaration": 1292, + "src": "6558:33:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "6544:48:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "6528:64:37", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "494e56414c49445f434f4e4649475f48415348", + "id": 31576, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "6606:21:37", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_1e15566847ed1c19ce14d62c724c85d7702676fc6f806d61315d57d0377541dc", + "typeString": "literal_string \"INVALID_CONFIG_HASH\"" + }, + "value": "INVALID_CONFIG_HASH" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_1e15566847ed1c19ce14d62c724c85d7702676fc6f806d61315d57d0377541dc", + "typeString": "literal_string \"INVALID_CONFIG_HASH\"" + } + ], + "id": 31568, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [-18, -18], + "referencedDeclaration": -18, + "src": "6507:7:37", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 31577, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6507:130:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 31578, + "nodeType": "ExpressionStatement", + "src": "6507:130:37" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 31582, + "name": "programOutput", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31551, + "src": "6663:13:37", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr", + "typeString": "uint256[] calldata" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr", + "typeString": "uint256[] calldata" + } + ], + "expression": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 31579, + "name": "state", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31389, + "src": "6648:5:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$__$returns$_t_struct$_State_$2234_storage_ptr_$", + "typeString": "function () pure returns (struct StarknetState.State storage pointer)" + } + }, + "id": 31580, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6648:7:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_struct$_State_$2234_storage_ptr", + "typeString": "struct StarknetState.State storage pointer" + } + }, + "id": 31581, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "update", + "nodeType": "MemberAccess", + "referencedDeclaration": 2332, + "src": "6648:14:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_struct$_State_$2234_storage_ptr_$_t_array$_t_uint256_$dyn_calldata_ptr_$returns$__$bound_to$_t_struct$_State_$2234_storage_ptr_$", + "typeString": "function (struct StarknetState.State storage pointer,uint256[] calldata)" + } + }, + "id": 31583, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6648:29:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 31584, + "nodeType": "ExpressionStatement", + "src": "6648:29:37" + }, + { + "assignments": [31586], + "declarations": [ + { + "constant": false, + "id": 31586, + "mutability": "mutable", + "name": "outputOffset", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31648, + "src": "6910:20:37", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 31585, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "6910:7:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 31589, + "initialValue": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 31587, + "name": "StarknetOutput", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1653, + "src": "6933:14:37", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_StarknetOutput_$1653_$", + "typeString": "type(library StarknetOutput)" + } + }, + "id": 31588, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "HEADER_SIZE", + "nodeType": "MemberAccess", + "referencedDeclaration": 1295, + "src": "6933:26:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "6910:49:37" + }, + { + "expression": { + "argumentTypes": null, + "id": 31600, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 31590, + "name": "outputOffset", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31586, + "src": "6969:12:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "+=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "74727565", + "id": 31593, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "bool", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7054:4:37", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "value": "true" + }, + { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 31594, + "name": "programOutput", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31551, + "src": "7072:13:37", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr", + "typeString": "uint256[] calldata" + } + }, + "endExpression": null, + "id": 31596, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexRangeAccess", + "src": "7072:28:37", + "startExpression": { + "argumentTypes": null, + "id": 31595, + "name": "outputOffset", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31586, + "src": "7086:12:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr_slice", + "typeString": "uint256[] calldata slice" + } + }, + { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 31597, + "name": "l2ToL1Messages", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1814, + "src": "7114:14:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$__$returns$_t_mapping$_t_bytes32_$_t_uint256_$_$", + "typeString": "function () pure returns (mapping(bytes32 => uint256))" + } + }, + "id": 31598, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "7114:16:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_bytes32_$_t_uint256_$", + "typeString": "mapping(bytes32 => uint256)" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr_slice", + "typeString": "uint256[] calldata slice" + }, + { + "typeIdentifier": "t_mapping$_t_bytes32_$_t_uint256_$", + "typeString": "mapping(bytes32 => uint256)" + } + ], + "expression": { + "argumentTypes": null, + "id": 31591, + "name": "StarknetOutput", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1653, + "src": "6985:14:37", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_StarknetOutput_$1653_$", + "typeString": "type(library StarknetOutput)" + } + }, + "id": 31592, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "processMessages", + "nodeType": "MemberAccess", + "referencedDeclaration": 1652, + "src": "6985:30:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_bool_$_t_array$_t_uint256_$dyn_calldata_ptr_$_t_mapping$_t_bytes32_$_t_uint256_$_$returns$_t_uint256_$", + "typeString": "function (bool,uint256[] calldata,mapping(bytes32 => uint256)) returns (uint256)" + } + }, + "id": 31599, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6985:155:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "6969:171:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 31601, + "nodeType": "ExpressionStatement", + "src": "6969:171:37" + }, + { + "expression": { + "argumentTypes": null, + "id": 31612, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 31602, + "name": "outputOffset", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31586, + "src": "7189:12:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "+=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "66616c7365", + "id": 31605, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "bool", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7274:5:37", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "value": "false" + }, + { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 31606, + "name": "programOutput", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31551, + "src": "7293:13:37", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr", + "typeString": "uint256[] calldata" + } + }, + "endExpression": null, + "id": 31608, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexRangeAccess", + "src": "7293:28:37", + "startExpression": { + "argumentTypes": null, + "id": 31607, + "name": "outputOffset", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31586, + "src": "7307:12:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr_slice", + "typeString": "uint256[] calldata slice" + } + }, + { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 31609, + "name": "l1ToL2Messages", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1801, + "src": "7335:14:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$__$returns$_t_mapping$_t_bytes32_$_t_uint256_$_$", + "typeString": "function () pure returns (mapping(bytes32 => uint256))" + } + }, + "id": 31610, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "7335:16:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_bytes32_$_t_uint256_$", + "typeString": "mapping(bytes32 => uint256)" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr_slice", + "typeString": "uint256[] calldata slice" + }, + { + "typeIdentifier": "t_mapping$_t_bytes32_$_t_uint256_$", + "typeString": "mapping(bytes32 => uint256)" + } + ], + "expression": { + "argumentTypes": null, + "id": 31603, + "name": "StarknetOutput", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1653, + "src": "7205:14:37", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_StarknetOutput_$1653_$", + "typeString": "type(library StarknetOutput)" + } + }, + "id": 31604, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "processMessages", + "nodeType": "MemberAccess", + "referencedDeclaration": 1652, + "src": "7205:30:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_bool_$_t_array$_t_uint256_$dyn_calldata_ptr_$_t_mapping$_t_bytes32_$_t_uint256_$_$returns$_t_uint256_$", + "typeString": "function (bool,uint256[] calldata,mapping(bytes32 => uint256)) returns (uint256)" + } + }, + "id": 31611, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "7205:156:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "7189:172:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 31613, + "nodeType": "ExpressionStatement", + "src": "7189:172:37" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 31618, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 31615, + "name": "outputOffset", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31586, + "src": "7379:12:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 31616, + "name": "programOutput", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31551, + "src": "7395:13:37", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr", + "typeString": "uint256[] calldata" + } + }, + "id": 31617, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "length", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "7395:20:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "7379:36:37", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "535441524b4e45545f4f55545055545f544f4f5f4c4f4e47", + "id": 31619, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7417:26:37", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_81aab34693ff9205394810638bf8ae3f6aba0692d74a5c21cdfb88a363048a6c", + "typeString": "literal_string \"STARKNET_OUTPUT_TOO_LONG\"" + }, + "value": "STARKNET_OUTPUT_TOO_LONG" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_81aab34693ff9205394810638bf8ae3f6aba0692d74a5c21cdfb88a363048a6c", + "typeString": "literal_string \"STARKNET_OUTPUT_TOO_LONG\"" + } + ], + "id": 31614, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [-18, -18], + "referencedDeclaration": -18, + "src": "7371:7:37", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 31620, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "7371:73:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 31621, + "nodeType": "ExpressionStatement", + "src": "7371:73:37" + }, + { + "assignments": [31625], + "declarations": [ + { + "constant": false, + "id": 31625, + "mutability": "mutable", + "name": "state_", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31648, + "src": "7588:34:37", + "stateVariable": false, + "storageLocation": "storage", + "typeDescriptions": { + "typeIdentifier": "t_struct$_State_$2234_storage_ptr", + "typeString": "struct StarknetState.State" + }, + "typeName": { + "contractScope": null, + "id": 31624, + "name": "StarknetState.State", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 2234, + "src": "7588:19:37", + "typeDescriptions": { + "typeIdentifier": "t_struct$_State_$2234_storage_ptr", + "typeString": "struct StarknetState.State" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 31628, + "initialValue": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 31626, + "name": "state", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31389, + "src": "7625:5:37", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$__$returns$_t_struct$_State_$2234_storage_ptr_$", + "typeString": "function () pure returns (struct StarknetState.State storage pointer)" + } + }, + "id": 31627, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "7625:7:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_struct$_State_$2234_storage_ptr", + "typeString": "struct StarknetState.State storage pointer" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "7588:44:37" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 31630, + "name": "state_", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31625, + "src": "7662:6:37", + "typeDescriptions": { + "typeIdentifier": "t_struct$_State_$2234_storage_ptr", + "typeString": "struct StarknetState.State storage pointer" + } + }, + "id": 31631, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "globalRoot", + "nodeType": "MemberAccess", + "referencedDeclaration": 2229, + "src": "7662:17:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 31632, + "name": "state_", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31625, + "src": "7681:6:37", + "typeDescriptions": { + "typeIdentifier": "t_struct$_State_$2234_storage_ptr", + "typeString": "struct StarknetState.State storage pointer" + } + }, + "id": 31633, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "blockNumber", + "nodeType": "MemberAccess", + "referencedDeclaration": 2231, + "src": "7681:18:37", + "typeDescriptions": { + "typeIdentifier": "t_int256", + "typeString": "int256" + } + }, + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 31634, + "name": "state_", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31625, + "src": "7701:6:37", + "typeDescriptions": { + "typeIdentifier": "t_struct$_State_$2234_storage_ptr", + "typeString": "struct StarknetState.State storage pointer" + } + }, + "id": 31635, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "blockHash", + "nodeType": "MemberAccess", + "referencedDeclaration": 2233, + "src": "7701:16:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_int256", + "typeString": "int256" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 31629, + "name": "LogStateUpdate", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31219, + "src": "7647:14:37", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$_t_int256_$_t_uint256_$returns$__$", + "typeString": "function (uint256,int256,uint256)" + } + }, + "id": 31636, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "7647:71:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 31637, + "nodeType": "EmitStatement", + "src": "7642:76:37" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_int256", + "typeString": "int256" + }, + "id": 31644, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 31639, + "name": "state_", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31625, + "src": "7783:6:37", + "typeDescriptions": { + "typeIdentifier": "t_struct$_State_$2234_storage_ptr", + "typeString": "struct StarknetState.State storage pointer" + } + }, + "id": 31640, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "blockNumber", + "nodeType": "MemberAccess", + "referencedDeclaration": 2231, + "src": "7783:18:37", + "typeDescriptions": { + "typeIdentifier": "t_int256", + "typeString": "int256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_int256", + "typeString": "int256" + }, + "id": 31643, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 31641, + "name": "initialBlockNumber", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 31557, + "src": "7805:18:37", + "typeDescriptions": { + "typeIdentifier": "t_int256", + "typeString": "int256" + } + }, + "nodeType": "BinaryOperation", + "operator": "+", + "rightExpression": { + "argumentTypes": null, + "hexValue": "31", + "id": 31642, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7826:1:37", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + }, + "value": "1" + }, + "src": "7805:22:37", + "typeDescriptions": { + "typeIdentifier": "t_int256", + "typeString": "int256" + } + }, + "src": "7783:44:37", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "494e56414c49445f46494e414c5f424c4f434b5f4e554d424552", + "id": 31645, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7829:28:37", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_4704f665b3bc7084199f162272b6b773fa8dad10a187a1c61e90ec9d251e75ab", + "typeString": "literal_string \"INVALID_FINAL_BLOCK_NUMBER\"" + }, + "value": "INVALID_FINAL_BLOCK_NUMBER" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_4704f665b3bc7084199f162272b6b773fa8dad10a187a1c61e90ec9d251e75ab", + "typeString": "literal_string \"INVALID_FINAL_BLOCK_NUMBER\"" + } + ], + "id": 31638, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [-18, -18], + "referencedDeclaration": -18, + "src": "7775:7:37", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 31646, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "7775:83:37", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 31647, + "nodeType": "ExpressionStatement", + "src": "7775:83:37" + } + ] + }, + "documentation": { + "id": 31548, + "nodeType": "StructuredDocumentation", + "src": "5722:331:37", + "text": "Updates the state of the StarkNet, based on a proof of the\nStarkNet OS that the state transition is valid.\nArguments:\nprogramOutput - The main part of the StarkNet OS program output.\ndata_availability_fact - An encoding of the on-chain data associated\nwith the 'programOutput'." + }, + "functionSelector": "853e2461", + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 31554, + "modifierName": { + "argumentTypes": null, + "id": 31553, + "name": "onlyOperator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 585, + "src": "6136:12:37", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "6136:12:37" + } + ], + "name": "updateState", + "overrides": null, + "parameters": { + "id": 31552, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 31551, + "mutability": "mutable", + "name": "programOutput", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 31649, + "src": "6088:32:37", + "stateVariable": false, + "storageLocation": "calldata", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$dyn_calldata_ptr", + "typeString": "uint256[]" + }, + "typeName": { + "baseType": { + "id": 31549, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "6088:7:37", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 31550, + "length": null, + "nodeType": "ArrayTypeName", + "src": "6088:9:37", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$dyn_storage_ptr", + "typeString": "uint256[]" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "6078:48:37" + }, + "returnParameters": { + "id": 31555, + "nodeType": "ParameterList", + "parameters": [], + "src": "6149:0:37" + }, + "scope": 31650, + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "external" + } + ], + "abstract": false, + "baseContracts": [ + { + "arguments": null, + "baseName": { + "contractScope": null, + "id": 31187, + "name": "Identity", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 533, + "src": "754:8:37", + "typeDescriptions": { + "typeIdentifier": "t_contract$_Identity_$533", + "typeString": "contract Identity" + } + }, + "id": 31188, + "nodeType": "InheritanceSpecifier", + "src": "754:8:37" + }, + { + "arguments": null, + "baseName": { + "contractScope": null, + "id": 31189, + "name": "StarknetMessaging", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 2200, + "src": "768:17:37", + "typeDescriptions": { + "typeIdentifier": "t_contract$_StarknetMessaging_$2200", + "typeString": "contract StarknetMessaging" + } + }, + "id": 31190, + "nodeType": "InheritanceSpecifier", + "src": "768:17:37" + }, + { + "arguments": null, + "baseName": { + "contractScope": null, + "id": 31191, + "name": "StarknetGovernance", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 1725, + "src": "791:18:37", + "typeDescriptions": { + "typeIdentifier": "t_contract$_StarknetGovernance_$1725", + "typeString": "contract StarknetGovernance" + } + }, + "id": 31192, + "nodeType": "InheritanceSpecifier", + "src": "791:18:37" + }, + { + "arguments": null, + "baseName": { + "contractScope": null, + "id": 31193, + "name": "GovernedFinalizable", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 319, + "src": "815:19:37", + "typeDescriptions": { + "typeIdentifier": "t_contract$_GovernedFinalizable_$319", + "typeString": "contract GovernedFinalizable" + } + }, + "id": 31194, + "nodeType": "InheritanceSpecifier", + "src": "815:19:37" + }, + { + "arguments": null, + "baseName": { + "contractScope": null, + "id": 31195, + "name": "StarknetOperator", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 2224, + "src": "840:16:37", + "typeDescriptions": { + "typeIdentifier": "t_contract$_StarknetOperator_$2224", + "typeString": "contract StarknetOperator" + } + }, + "id": 31196, + "nodeType": "InheritanceSpecifier", + "src": "840:16:37" + }, + { + "arguments": null, + "baseName": { + "contractScope": null, + "id": 31197, + "name": "ContractInitializer", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 515, + "src": "862:19:37", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ContractInitializer_$515", + "typeString": "contract ContractInitializer" + } + }, + "id": 31198, + "nodeType": "InheritanceSpecifier", + "src": "862:19:37" + }, + { + "arguments": null, + "baseName": { + "contractScope": null, + "id": 31199, + "name": "ProxySupport", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 773, + "src": "887:12:37", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ProxySupport_$773", + "typeString": "contract ProxySupport" + } + }, + "id": 31200, + "nodeType": "InheritanceSpecifier", + "src": "887:12:37" + } + ], + "contractDependencies": [ + 266, 319, 456, 486, 515, 533, 555, 603, 773, 1174, 1249, 1725, 2200, + 2224 + ], + "contractKind": "contract", + "documentation": null, + "fullyImplemented": true, + "linearizedBaseContracts": [ + 31650, 773, 515, 486, 2224, 456, 603, 319, 1725, 266, 555, 2200, 1174, + 1249, 533 + ], + "name": "Starknet", + "scope": 31651 + } + ], + "license": "Apache-2.0." + }, + "id": 37 +} diff --git a/starknet-e2e-test/contracts/artifacts/UnsafeProxy.json b/starknet-e2e-test/contracts/artifacts/UnsafeProxy.json new file mode 100644 index 0000000000..f742fcc374 --- /dev/null +++ b/starknet-e2e-test/contracts/artifacts/UnsafeProxy.json @@ -0,0 +1,702 @@ +{ + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_delegate", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "stateMutability": "payable", + "type": "fallback" + } + ], + "bytecode": { + "object": "0x608060405234801561001057600080fd5b5060405161012f38038061012f83398101604081905261002f91610054565b600080546001600160a01b0319166001600160a01b0392909216919091179055610084565b60006020828403121561006657600080fd5b81516001600160a01b038116811461007d57600080fd5b9392505050565b609d806100926000396000f3fe6000805460a0602036601f8101829004909102820160405260808181526001600160a01b039093169392918391908190838280828437600092018290525084519495509384935091505060208401855af43d604051816000823e8280156063578282f35b8282fdfea26469706673582212206332d7f24634826be7603ca65e79a038e87d4d1c59deea05cc63ec5594f0e22764736f6c63430008100033", + "sourceMap": "0:571:0:-:0;;;51:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92:8;:20;;-1:-1:-1;;;;;;92:20:0;-1:-1:-1;;;;;92:20:0;;;;;;;;;;0:571;;14:290:1;84:6;137:2;125:9;116:7;112:23;108:32;105:52;;;153:1;150;143:12;105:52;179:16;;-1:-1:-1;;;;;224:31:1;;214:42;;204:70;;270:1;267;260:12;204:70;293:5;14:290;-1:-1:-1;;;14:290:1:o;:::-;0:571:0;;;;;;", + "linkReferences": {} + }, + "deployedBytecode": { + "object": "0x6000805460a0602036601f8101829004909102820160405260808181526001600160a01b039093169392918391908190838280828437600092018290525084519495509384935091505060208401855af43d604051816000823e8280156063578282f35b8282fdfea26469706673582212206332d7f24634826be7603ca65e79a038e87d4d1c59deea05cc63ec5594f0e22764736f6c63430008100033", + "sourceMap": "163:14:0:-:0;180:8;;198:28;;218:8;198:28;;;;;;;;;;;0:571;198:28;0:571;198:28;;;-1:-1:-1;;;;;180:8:0;;;;163:14;0:571;163:14;;218:8;;;163:14;218:8;;163:14;198:28;;;;;;;;-1:-1:-1;317:11:0;;198:28;;-1:-1:-1;198:28:0;;;-1:-1:-1;317:11:0;-1:-1:-1;;310:4:0;301:14;;293:6;286:5;273:62;360:16;406:4;400:11;445:4;443:1;439:3;424:26;470:6;489:25;;;;547:4;543:3;536:16;489:25;508:4;504:3;497:16", + "linkReferences": {} + }, + "methodIdentifiers": {}, + "rawMetadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_delegate\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/UnsafeProxy.sol\":\"UnsafeProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"src/UnsafeProxy.sol\":{\"keccak256\":\"0xc7a64fbd332c543a4a771ca835e44329325d21018d423f28c7924851af3b0011\",\"urls\":[\"bzz-raw://748d3052c21dcfe646b2d77136a2cbd82c9c8674a13d002e1a94e6599433151c\",\"dweb:/ipfs/QmWTgYdm7d4G5VA6wzQ2GujbHyyxbEPvSyddCexvMBeHPE\"]}},\"version\":1}", + "metadata": { + "compiler": { + "version": "0.8.16+commit.07a7930e" + }, + "language": "Solidity", + "output": { + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_delegate", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "stateMutability": "payable", + "type": "fallback" + } + ], + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + } + }, + "settings": { + "remappings": [], + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "compilationTarget": { + "src/UnsafeProxy.sol": "UnsafeProxy" + }, + "libraries": {} + }, + "sources": { + "src/UnsafeProxy.sol": { + "keccak256": "0xc7a64fbd332c543a4a771ca835e44329325d21018d423f28c7924851af3b0011", + "urls": [ + "bzz-raw://748d3052c21dcfe646b2d77136a2cbd82c9c8674a13d002e1a94e6599433151c", + "dweb:/ipfs/QmWTgYdm7d4G5VA6wzQ2GujbHyyxbEPvSyddCexvMBeHPE" + ], + "license": null + } + }, + "version": 1 + }, + "ast": { + "absolutePath": "src/UnsafeProxy.sol", + "id": 28, + "exportedSymbols": { + "UnsafeProxy": [27] + }, + "nodeType": "SourceUnit", + "src": "0:571:0", + "nodes": [ + { + "id": 27, + "nodeType": "ContractDefinition", + "src": "0:571:0", + "nodes": [ + { + "id": 2, + "nodeType": "VariableDeclaration", + "src": "28:16:0", + "nodes": [], + "constant": false, + "mutability": "mutable", + "name": "delegate", + "nameLocation": "36:8:0", + "scope": 27, + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "28:7:0", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + }, + { + "id": 12, + "nodeType": "FunctionDefinition", + "src": "51:68:0", + "nodes": [], + "body": { + "id": 11, + "nodeType": "Block", + "src": "82:37:0", + "nodes": [], + "statements": [ + { + "expression": { + "id": 9, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "id": 7, + "name": "delegate", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2, + "src": "92:8:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "id": 8, + "name": "_delegate", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 4, + "src": "103:9:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "92:20:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 10, + "nodeType": "ExpressionStatement", + "src": "92:20:0" + } + ] + }, + "implemented": true, + "kind": "constructor", + "modifiers": [], + "name": "", + "nameLocation": "-1:-1:-1", + "parameters": { + "id": 5, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 4, + "mutability": "mutable", + "name": "_delegate", + "nameLocation": "71:9:0", + "nodeType": "VariableDeclaration", + "scope": 12, + "src": "63:17:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 3, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "63:7:0", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + } + ], + "src": "62:19:0" + }, + "returnParameters": { + "id": 6, + "nodeType": "ParameterList", + "parameters": [], + "src": "82:0:0" + }, + "scope": 27, + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "id": 26, + "nodeType": "FunctionDefinition", + "src": "125:444:0", + "nodes": [], + "body": { + "id": 25, + "nodeType": "Block", + "src": "153:416:0", + "nodes": [], + "statements": [ + { + "assignments": [16], + "declarations": [ + { + "constant": false, + "id": 16, + "mutability": "mutable", + "name": "target", + "nameLocation": "171:6:0", + "nodeType": "VariableDeclaration", + "scope": 25, + "src": "163:14:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 15, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "163:7:0", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + } + ], + "id": 18, + "initialValue": { + "id": 17, + "name": "delegate", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2, + "src": "180:8:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "163:25:0" + }, + { + "assignments": [20], + "declarations": [ + { + "constant": false, + "id": 20, + "mutability": "mutable", + "name": "data", + "nameLocation": "211:4:0", + "nodeType": "VariableDeclaration", + "scope": 25, + "src": "198:17:0", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 19, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "198:5:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "visibility": "internal" + } + ], + "id": 23, + "initialValue": { + "expression": { + "id": 21, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "218:3:0", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 22, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "222:4:0", + "memberName": "data", + "nodeType": "MemberAccess", + "src": "218:8:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes calldata" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "198:28:0" + }, + { + "AST": { + "nodeType": "YulBlock", + "src": "245:318:0", + "statements": [ + { + "nodeType": "YulVariableDeclaration", + "src": "259:76:0", + "value": { + "arguments": [ + { + "arguments": [], + "functionName": { + "name": "gas", + "nodeType": "YulIdentifier", + "src": "286:3:0" + }, + "nodeType": "YulFunctionCall", + "src": "286:5:0" + }, + { + "name": "target", + "nodeType": "YulIdentifier", + "src": "293:6:0" + }, + { + "arguments": [ + { + "name": "data", + "nodeType": "YulIdentifier", + "src": "305:4:0" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "310:4:0", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nodeType": "YulIdentifier", + "src": "301:3:0" + }, + "nodeType": "YulFunctionCall", + "src": "301:14:0" + }, + { + "arguments": [ + { + "name": "data", + "nodeType": "YulIdentifier", + "src": "323:4:0" + } + ], + "functionName": { + "name": "mload", + "nodeType": "YulIdentifier", + "src": "317:5:0" + }, + "nodeType": "YulFunctionCall", + "src": "317:11:0" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "330:1:0", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "333:1:0", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "delegatecall", + "nodeType": "YulIdentifier", + "src": "273:12:0" + }, + "nodeType": "YulFunctionCall", + "src": "273:62:0" + }, + "variables": [ + { + "name": "result", + "nodeType": "YulTypedName", + "src": "263:6:0", + "type": "" + } + ] + }, + { + "nodeType": "YulVariableDeclaration", + "src": "348:28:0", + "value": { + "arguments": [], + "functionName": { + "name": "returndatasize", + "nodeType": "YulIdentifier", + "src": "360:14:0" + }, + "nodeType": "YulFunctionCall", + "src": "360:16:0" + }, + "variables": [ + { + "name": "size", + "nodeType": "YulTypedName", + "src": "352:4:0", + "type": "" + } + ] + }, + { + "nodeType": "YulVariableDeclaration", + "src": "389:22:0", + "value": { + "arguments": [ + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "406:4:0", + "type": "", + "value": "0x40" + } + ], + "functionName": { + "name": "mload", + "nodeType": "YulIdentifier", + "src": "400:5:0" + }, + "nodeType": "YulFunctionCall", + "src": "400:11:0" + }, + "variables": [ + { + "name": "ptr", + "nodeType": "YulTypedName", + "src": "393:3:0", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "ptr", + "nodeType": "YulIdentifier", + "src": "439:3:0" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "443:1:0", + "type": "", + "value": "0" + }, + { + "name": "size", + "nodeType": "YulIdentifier", + "src": "445:4:0" + } + ], + "functionName": { + "name": "returndatacopy", + "nodeType": "YulIdentifier", + "src": "424:14:0" + }, + "nodeType": "YulFunctionCall", + "src": "424:26:0" + }, + "nodeType": "YulExpressionStatement", + "src": "424:26:0" + }, + { + "cases": [ + { + "body": { + "nodeType": "YulBlock", + "src": "496:18:0", + "statements": [ + { + "expression": { + "arguments": [ + { + "name": "ptr", + "nodeType": "YulIdentifier", + "src": "504:3:0" + }, + { + "name": "size", + "nodeType": "YulIdentifier", + "src": "508:4:0" + } + ], + "functionName": { + "name": "revert", + "nodeType": "YulIdentifier", + "src": "497:6:0" + }, + "nodeType": "YulFunctionCall", + "src": "497:16:0" + }, + "nodeType": "YulExpressionStatement", + "src": "497:16:0" + } + ] + }, + "nodeType": "YulCase", + "src": "489:25:0", + "value": { + "kind": "number", + "nodeType": "YulLiteral", + "src": "494:1:0", + "type": "", + "value": "0" + } + }, + { + "body": { + "nodeType": "YulBlock", + "src": "535:18:0", + "statements": [ + { + "expression": { + "arguments": [ + { + "name": "ptr", + "nodeType": "YulIdentifier", + "src": "543:3:0" + }, + { + "name": "size", + "nodeType": "YulIdentifier", + "src": "547:4:0" + } + ], + "functionName": { + "name": "return", + "nodeType": "YulIdentifier", + "src": "536:6:0" + }, + "nodeType": "YulFunctionCall", + "src": "536:16:0" + }, + "nodeType": "YulExpressionStatement", + "src": "536:16:0" + } + ] + }, + "nodeType": "YulCase", + "src": "527:26:0", + "value": "default" + } + ], + "expression": { + "name": "result", + "nodeType": "YulIdentifier", + "src": "470:6:0" + }, + "nodeType": "YulSwitch", + "src": "463:90:0" + } + ] + }, + "evmVersion": "london", + "externalReferences": [ + { + "declaration": 20, + "isOffset": false, + "isSlot": false, + "src": "305:4:0", + "valueSize": 1 + }, + { + "declaration": 20, + "isOffset": false, + "isSlot": false, + "src": "323:4:0", + "valueSize": 1 + }, + { + "declaration": 16, + "isOffset": false, + "isSlot": false, + "src": "293:6:0", + "valueSize": 1 + } + ], + "id": 24, + "nodeType": "InlineAssembly", + "src": "236:327:0" + } + ] + }, + "implemented": true, + "kind": "fallback", + "modifiers": [], + "name": "", + "nameLocation": "-1:-1:-1", + "parameters": { + "id": 13, + "nodeType": "ParameterList", + "parameters": [], + "src": "133:2:0" + }, + "returnParameters": { + "id": 14, + "nodeType": "ParameterList", + "parameters": [], + "src": "153:0:0" + }, + "scope": 27, + "stateMutability": "payable", + "virtual": false, + "visibility": "external" + } + ], + "abstract": false, + "baseContracts": [], + "canonicalName": "UnsafeProxy", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "linearizedBaseContracts": [27], + "name": "UnsafeProxy", + "nameLocation": "9:11:0", + "scope": 28, + "usedErrors": [] + } + ] + }, + "id": 0 +} diff --git a/starknet-e2e-test/contracts/foundry.toml b/starknet-e2e-test/contracts/foundry.toml new file mode 100644 index 0000000000..d672a23b1d --- /dev/null +++ b/starknet-e2e-test/contracts/foundry.toml @@ -0,0 +1,3 @@ +[profile.default] +src = "src" +out = "build" diff --git a/starknet-e2e-test/contracts/src/UnsafeProxy.sol b/starknet-e2e-test/contracts/src/UnsafeProxy.sol new file mode 100644 index 0000000000..d7cedf05ec --- /dev/null +++ b/starknet-e2e-test/contracts/src/UnsafeProxy.sol @@ -0,0 +1,22 @@ +contract UnsafeProxy { + + address delegate; + + constructor(address _delegate) { + delegate = _delegate; + } + + fallback() external payable { + address target = delegate; + bytes memory data = msg.data; + assembly { + let result := delegatecall(gas(), target, add(data,0x20), mload(data), 0, 0) + let size := returndatasize() + let ptr := mload(0x40) + returndatacopy(ptr,0,size) + switch result + case 0 {revert(ptr,size)} + default {return(ptr,size)} + } + } +} \ No newline at end of file diff --git a/starknet-e2e-test/ethereum_core_contract.rs b/starknet-e2e-test/ethereum_core_contract.rs new file mode 100644 index 0000000000..bcaf47c77f --- /dev/null +++ b/starknet-e2e-test/ethereum_core_contract.rs @@ -0,0 +1,137 @@ +extern crate starknet_e2e_test; + +use madara_runtime::opaque::Block; +use mc_settlement::ethereum::StarknetContractClient; +use mc_settlement::{SettlementProvider, StarknetSpec, StarknetState}; +use mp_messages::{MessageL1ToL2, MessageL2ToL1}; +use mp_snos_output::StarknetOsOutput; +use rstest::rstest; +use starknet_api::api_core::{ContractAddress, Nonce, PatriciaKey}; +use starknet_api::hash::StarkFelt; +use starknet_e2e_test::ethereum_sandbox::EthereumSandbox; +use starknet_e2e_test::starknet_contract::{InitData, StarknetContract}; + +#[rstest] +#[tokio::test] +async fn starknet_core_contract_is_initialized() -> anyhow::Result<()> { + let sandbox = EthereumSandbox::new(); + let starknet_contract = StarknetContract::deploy(&sandbox).await; + + starknet_contract.initialize(&sandbox, InitData::one()).await; + + let starknet = StarknetContractClient::new(starknet_contract.address(), sandbox.client()); + + let spec = SettlementProvider::::get_chain_spec(&starknet).await.expect("Failed to get chain spec"); + assert_eq!(spec, StarknetSpec { program_hash: 1u64.into(), config_hash: 1u64.into() }); + + let state = SettlementProvider::::get_state(&starknet).await.expect("Failed to get state"); + assert_eq!(state, StarknetState::default()); + + Ok(()) +} + +#[rstest] +#[tokio::test] +async fn starknet_core_contract_advances_state() -> anyhow::Result<()> { + let sandbox = EthereumSandbox::new(); + let starknet_contract = StarknetContract::deploy(&sandbox).await; + + starknet_contract.initialize(&sandbox, InitData::one()).await; + + let starknet = StarknetContractClient::new(starknet_contract.address(), sandbox.client()); + + // Now let's transition the state from block 0 to 1 (state root 0 -> 1) + let program_output = StarknetOsOutput { + new_state_root: 1u64.into(), + block_number: 1u64.into(), + config_hash: 1u64.into(), + ..Default::default() + }; + + SettlementProvider::::update_state(&starknet, program_output).await.expect("Failed to update state"); + + let state = SettlementProvider::::get_state(&starknet).await.expect("Failed to get state"); + assert_eq!(state, StarknetState { block_number: 1u64.into(), state_root: 1u64.into() }); + + Ok(()) +} + +#[rstest] +#[tokio::test] +async fn starknet_core_contract_sends_messages_to_l2() -> anyhow::Result<()> { + // In this test we do not check Starknet messaging logic, but rather that all our encodings are + // correct + + let sandbox = EthereumSandbox::new(); + let starknet_contract = StarknetContract::deploy(&sandbox).await; + + starknet_contract.initialize(&sandbox, InitData::one()).await; + + // Converting our EOA address to felt + let mut from_address = [0u8; 32]; + from_address[12..32].copy_from_slice(sandbox.address().as_bytes()); + + let message = MessageL1ToL2 { + from_address: ContractAddress(PatriciaKey(StarkFelt::new(from_address).unwrap())), + to_address: 3u64.into(), + nonce: Nonce(0u64.into()), // Starknet contract maintains global nonce counter + selector: 2u64.into(), + payload: vec![1u64.into()], + }; + + // Sending message to L2 (this will update msg hash table) + starknet_contract.send_message_to_l2(&sandbox, &message).await; + assert!(starknet_contract.message_to_l2_exists(&sandbox, &message).await); + + let starknet = StarknetContractClient::new(starknet_contract.address(), sandbox.client()); + + let program_output = StarknetOsOutput { + new_state_root: 1u64.into(), + block_number: 1u64.into(), + config_hash: 1u64.into(), + messages_to_l2: vec![message.clone()], + ..Default::default() + }; + + // During the state update, the message will be consumed (removed from hash table) + SettlementProvider::::update_state(&starknet, program_output).await.expect("Failed to update state"); + + // At this point the counter has to be reset + assert!(!starknet_contract.message_to_l2_exists(&sandbox, &message).await); + + Ok(()) +} + +#[rstest] +#[tokio::test] +async fn starknet_core_contract_consumes_messages_from_l2() -> anyhow::Result<()> { + // In this test we do not check Starknet messaging logic, but rather that all our encodings are + // correct + + let sandbox = EthereumSandbox::new(); + let starknet_contract = StarknetContract::deploy(&sandbox).await; + + starknet_contract.initialize(&sandbox, InitData::one()).await; + + let message = MessageL2ToL1 { + from_address: 1u64.into(), + to_address: StarkFelt::from(2u64).try_into().unwrap(), + payload: vec![3u64.into()], + }; + let starknet = StarknetContractClient::new(starknet_contract.address(), sandbox.client()); + + let program_output = StarknetOsOutput { + new_state_root: 1u64.into(), + block_number: 1u64.into(), + config_hash: 1u64.into(), + messages_to_l1: vec![message.clone()], + ..Default::default() + }; + + // During the state update, the message will be consumed (removed from hash table) + SettlementProvider::::update_state(&starknet, program_output).await.expect("Failed to update state"); + + assert!(starknet_contract.message_to_l1_exists(&sandbox, &message).await); + + Ok(()) +} diff --git a/starknet-e2e-test/ethereum_e2e_settlement.rs b/starknet-e2e-test/ethereum_e2e_settlement.rs new file mode 100644 index 0000000000..46f1013372 --- /dev/null +++ b/starknet-e2e-test/ethereum_e2e_settlement.rs @@ -0,0 +1,172 @@ +extern crate starknet_e2e_test; + +use std::fs::{create_dir_all, File}; +use std::time::Duration; + +use assert_matches::assert_matches; +use async_trait::async_trait; +use ethers::providers::Middleware; +use madara_runtime::opaque::Block; +use madara_test_runner::{MadaraRunner, Settlement}; +use mc_settlement::ethereum::client::EthereumConfig; +use mc_settlement::ethereum::StarknetContractClient; +use mc_settlement::{SettlementProvider, StarknetState}; +use rstest::rstest; +use starknet_api::serde_utils::hex_str_from_bytes; +use starknet_e2e_test::ethereum_sandbox::EthereumSandbox; +use starknet_e2e_test::starknet_contract::{InitData, StarknetContract}; +use tempdir::TempDir; +use test_context::{test_context, AsyncTestContext}; +use tokio::time::sleep; + +struct Context { + pub madara_path: TempDir, + pub sandbox: EthereumSandbox, + pub starknet_contract: StarknetContract, +} + +impl Context { + pub async fn initialize(&self, data: InitData) { + self.starknet_contract.initialize(&self.sandbox, data).await; + } + + pub async fn launch_madara(&self) -> MadaraRunner { + MadaraRunner::new(Some(Settlement::Ethereum), Some(self.madara_path.path().to_path_buf())).await + } + + pub async fn read_state(&self) -> StarknetState { + let client = StarknetContractClient::new(self.starknet_contract.address(), self.sandbox.client()); + SettlementProvider::::get_state(&client).await.expect("Failed to get state") + } +} + +#[async_trait] +impl AsyncTestContext for Context { + async fn setup() -> Self { + let sandbox = EthereumSandbox::new(); + let starknet_contract = StarknetContract::deploy(&sandbox).await; + + let madara_path = TempDir::new("madara").expect("Failed to create Madara path"); + let config_dir = madara_path.path().join("chains/dev"); // data path + create_dir_all(&config_dir).unwrap(); + + let config = EthereumConfig { + http_provider: sandbox.client().provider().url().to_string(), + core_contracts: hex_str_from_bytes::<20, true>(starknet_contract.address().0), + chain_id: sandbox.client().get_chainid().await.expect("Failed to get sandbox chain ID").as_u64(), + poll_interval_ms: Some(10u64), // Default is 7s, we need to speed things up + ..Default::default() + }; + + let config_file = File::create(config_dir.join("eth-config.json")).expect("Failed to open file for writing"); + serde_json::to_writer(config_file, &config).expect("Failed to write eth config"); + + Self { madara_path, sandbox, starknet_contract } + } + + async fn teardown(self) { + self.madara_path.close().expect("Failed to clean up"); + } +} + +#[test_context(Context)] +#[rstest] +#[tokio::test] +async fn works_with_initialized_contract(ctx: &mut Context) -> Result<(), anyhow::Error> { + // Troubleshooting: + // RUST_LOG=mc_settlement=trace MADARA_LOG=1 cargo test --package starknet-e2e-test + // works_with_initialized_contract -- --nocapture + + // At this point we have: + // * spawned Ethereum sandbox + // * deployed settlement contract (not initialized yet) + // * temp Madara path with correct ethereum config + ctx.initialize(InitData::sn_goerli()).await; + + let mut madara = ctx.launch_madara().await; + + madara.create_n_blocks(3).await?; + sleep(Duration::from_millis(300)).await; + + assert_eq!(ctx.read_state().await, StarknetState { block_number: 3u64.into(), state_root: 0u64.into() }); + + Ok(()) +} + +#[test_context(Context)] +#[rstest] +#[tokio::test] +async fn recovers_from_non_initialized_state(ctx: &mut Context) -> Result<(), anyhow::Error> { + let mut madara = ctx.launch_madara().await; + + madara.create_empty_block().await?; + // Give the client thread some time to handle the finalized block + sleep(Duration::from_millis(100)).await; + + ctx.initialize(InitData::sn_goerli()).await; + + madara.create_empty_block().await?; + // Give the client thread some time to recover + sleep(Duration::from_millis(100)).await; + + madara.create_empty_block().await?; + sleep(Duration::from_millis(100)).await; + + assert_eq!(ctx.read_state().await, StarknetState { block_number: 3u64.into(), state_root: 0u64.into() }); + + Ok(()) +} + +#[test_context(Context)] +#[rstest] +#[tokio::test] +async fn catches_up_with_the_state_in_the_future(ctx: &mut Context) -> Result<(), anyhow::Error> { + ctx.initialize(InitData { block_number: 1u64.into(), ..InitData::sn_goerli() }).await; + + let mut madara = ctx.launch_madara().await; + + // Unless state root calculation is enabled (not by default), we should be fine + madara.create_n_blocks(2).await?; + // Give the client thread some time to handle the finalized block + sleep(Duration::from_millis(200)).await; + + assert_eq!(ctx.read_state().await, StarknetState { block_number: 2u64.into(), state_root: 0u64.into() }); + + Ok(()) +} + +#[test_context(Context)] +#[rstest] +#[tokio::test] +async fn fails_with_inconsistent_state_in_the_future(ctx: &mut Context) -> Result<(), anyhow::Error> { + ctx.initialize(InitData { block_number: 1u64.into(), state_root: 12345u64.into(), ..InitData::sn_goerli() }).await; + + let mut madara = ctx.launch_madara().await; + + madara.create_empty_block().await?; + // Give the client thread some time to handle the finalized block + sleep(Duration::from_millis(100)).await; + + // Expected connection refused because Madara is shut down at this point + assert_matches!(madara.create_empty_block().await, Err(err) => assert!(err.downcast_ref::().is_some())); + + Ok(()) +} + +#[test_context(Context)] +#[rstest] +#[tokio::test] +async fn fails_with_inconsistent_starknet_spec(ctx: &mut Context) -> Result<(), anyhow::Error> { + ctx.initialize(InitData::one()).await; + + let mut madara = ctx.launch_madara().await; + + madara.create_empty_block().await?; + // Give the client thread some time to handle the finalized block + sleep(Duration::from_millis(100)).await; + + // Expected connection refused because Madara is shut down at this point + assert_matches!(madara.create_empty_block().await, Err(err) => assert!(err.downcast_ref::().is_some())); + + Ok(()) +} diff --git a/starknet-e2e-test/src/ethereum_sandbox.rs b/starknet-e2e-test/src/ethereum_sandbox.rs new file mode 100644 index 0000000000..acb5ea20f4 --- /dev/null +++ b/starknet-e2e-test/src/ethereum_sandbox.rs @@ -0,0 +1,67 @@ +use std::env; +use std::path::PathBuf; +use std::sync::Arc; +use std::time::Duration; + +use ethers::abi::Tokenize; +use ethers::contract::{ContractFactory, ContractInstance}; +use ethers::core::utils::Anvil; +use ethers::prelude::SignerMiddleware; +use ethers::providers::{Http, Provider}; +use ethers::signers::{LocalWallet, Signer}; +use ethers::types::Address; +use ethers::utils::AnvilInstance; +use ethers_solc::artifacts::contract::ContractBytecode; + +type AnvilClient = SignerMiddleware, LocalWallet>; + +pub struct EthereumSandbox { + _anvil: AnvilInstance, + client: Arc, +} + +impl EthereumSandbox { + pub fn new() -> Self { + let anvil_path: PathBuf = env::var("ANVIL_PATH") + .map(Into::into) + .unwrap_or_else(|_| home::home_dir().unwrap().join(".foundry/bin/anvil")); + let anvil = Anvil::at(anvil_path).spawn(); + + let provider = Provider::::try_from(anvil.endpoint()) + .expect("Failed to connect to Anvil") + .interval(Duration::from_millis(10u64)); + + let wallet: LocalWallet = anvil.keys()[0].clone().into(); + let client = SignerMiddleware::new(provider.clone(), wallet.with_chain_id(anvil.chain_id())); + + Self { _anvil: anvil, client: Arc::new(client) } + } + + pub fn client(&self) -> Arc { + self.client.clone() + } + + pub fn address(&self) -> Address { + self.client.address() + } + + pub async fn deploy( + &self, + build_artifacts: &str, + contructor_args: T, + ) -> ContractInstance, AnvilClient> { + let artifacts: ContractBytecode = + serde_json::from_str(build_artifacts).expect("Failed to parse build artifacts"); + let abi = artifacts.abi.unwrap(); + let bytecode = artifacts.bytecode.unwrap().object.into_bytes().unwrap(); + + let factory = ContractFactory::new(abi, bytecode, self.client.clone()); + + factory + .deploy(contructor_args) + .expect("Failed to deploy contract") + .send() + .await + .expect("Ethereum polling error") + } +} diff --git a/starknet-e2e-test/src/lib.rs b/starknet-e2e-test/src/lib.rs new file mode 100644 index 0000000000..50ac51fa97 --- /dev/null +++ b/starknet-e2e-test/src/lib.rs @@ -0,0 +1,2 @@ +pub mod ethereum_sandbox; +pub mod starknet_contract; diff --git a/starknet-e2e-test/src/starknet_contract.rs b/starknet-e2e-test/src/starknet_contract.rs new file mode 100644 index 0000000000..88fde8e69e --- /dev/null +++ b/starknet-e2e-test/src/starknet_contract.rs @@ -0,0 +1,189 @@ +use ethers::prelude::abigen; +use ethers::types::{Address, Bytes, U256}; +use ethers::utils::keccak256; +use mc_settlement::ethereum::convert_felt_to_u256; +use mp_messages::{MessageL1ToL2, MessageL2ToL1}; +use mp_snos_output::SnosCodec; +use starknet_api::hash::StarkFelt; +use starknet_ff::FieldElement; + +use crate::ethereum_sandbox::EthereumSandbox; + +const STARKNET_VALIDIUM: &str = include_str!("../contracts/artifacts/Starknet.json"); +const UNSAFE_PROXY: &str = include_str!("../contracts/artifacts/UnsafeProxy.json"); + +// Starknet core contract cannot be initialized directly hence we use a proxy for that. +// In order to initialize the contract we need to provide the following data: +// 0. Sub-proxy contracts - none in our case +// 1. External initializer contract (EIC) - zero in our case +// 2. Program hash - non-zero, otherwise will be considered invalid +// 3. Verifier address +// 4. Config hash +// 5. Global state root (genesis) +// 6. Block number (genesis) +// 7. Block hash (genesis) +// +// Once we have an initialized contract we also need to assign operator - +// the account we will use for updating the state. +abigen!( + StarknetInitializer, + r#"[ + function initialize(bytes calldata data) external + function registerOperator(address newOperator) external + ]"#, +); + +// Starknet messaging interface for testing purposes. +abigen!( + StarknetMessaging, + r#"[ + function sendMessageToL2(uint256 toAddress, uint256 selector, uint256[] calldata payload) external payable returns (bytes32, uint256) + function l1ToL2Messages(bytes32 msgHash) external view returns (uint256) + function l2ToL1Messages(bytes32 msgHash) external view returns (uint256) + ]"#, +); + +#[derive(Clone, Debug, Default)] +pub struct InitData { + pub program_hash: StarkFelt, + pub verifier_address: StarkFelt, + pub config_hash: StarkFelt, + pub state_root: StarkFelt, + pub block_number: StarkFelt, + pub block_hash: StarkFelt, +} + +impl From for Bytes { + // No dynamic fields, so the encoding is pretty straightforward: + // + // abi.encode(data, (uint256, address, uint256, StarknetState.State)); + // where struct State { + // uint256 globalRoot; + // int256 blockNumber; + // uint256 blockHash; + // } + fn from(val: InitData) -> Self { + let mut bytes = [0u8; 7 * 32]; + // Recall: + // * None sub-proxy contracts + // * First 32 bytes are for the EIC - not specified + bytes[32..64].copy_from_slice(val.program_hash.bytes()); + bytes[64..96].copy_from_slice(val.verifier_address.bytes()); + bytes[96..128].copy_from_slice(val.config_hash.bytes()); + bytes[128..160].copy_from_slice(val.state_root.bytes()); + bytes[160..192].copy_from_slice(val.block_number.bytes()); + bytes[192..224].copy_from_slice(val.block_hash.bytes()); + bytes.into() + } +} + +impl InitData { + /// Use the same config as in Starknet Goerli testnet + pub fn sn_goerli() -> Self { + Self { + // See SN_OS_PROGRAM_HASH constant + program_hash: StarkFelt::from( + FieldElement::from_hex_be("0x41fc2a467ef8649580631912517edcab7674173f1dbfa2e9b64fbcd82bc4d79").unwrap(), + ), + // Hash version: SN_OS_CONFIG_HASH_VERSION (settlement) + // Chain ID: SN_GOERLI_CHAIN_ID (pallet config) + // Fee token address: 0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7 (genesis config) + config_hash: StarkFelt::from( + FieldElement::from_hex_be("0x036f5e4ea4dd042801c8841e3db8e654124305da0f11824fc1db60c405dbb39f") + .unwrap(), + ), + ..Default::default() + } + } + + pub fn one() -> Self { + Self { program_hash: 1u64.into(), config_hash: 1u64.into(), ..Default::default() } + } +} + +pub struct StarknetContract { + address: Address, +} + +impl StarknetContract { + pub async fn deploy(sandbox: &EthereumSandbox) -> Self { + // First we deploy the Starknet contract (no explicit contructor) + let snos_contract = sandbox.deploy(STARKNET_VALIDIUM, ()).await; + + // Then we deploy a simple delegate proxy to interact with Starknet contract (initialized with its + // address) + let proxy_contract = sandbox.deploy(UNSAFE_PROXY, snos_contract.address()).await; + + // We will use proxy to interact with the Starknet core contract + Self { address: proxy_contract.address() } + } + + pub fn address(&self) -> Address { + self.address + } + + pub async fn initialize(&self, sandbox: &EthereumSandbox, data: InitData) { + // This is the initialization interface + let initializer = StarknetInitializer::new(self.address, sandbox.client()); + + // 1. Provide Starknet OS program/config and genesis state + initializer + .initialize(data.into()) + .send() + .await + .expect("Failed to call `initialize`") + .await + .expect("Ethereum poll update error") + .unwrap(); + + // 2. Add our EOA as Starknet operator + initializer + .register_operator(sandbox.address()) + .send() + .await + .expect("Failed to call `register_operator`") + .await + .expect("Ethereum poll update error") + .unwrap(); + } + + pub async fn send_message_to_l2(&self, sandbox: &EthereumSandbox, message: &MessageL1ToL2) { + let messaging = StarknetMessaging::new(self.address, sandbox.client()); + + messaging.send_message_to_l2( + convert_felt_to_u256(message.to_address.0.0), + convert_felt_to_u256(message.selector), + message.payload.clone().into_iter().map(convert_felt_to_u256).collect()) + .value(1) // L1 message fee must be between 0 and 1 ether + .send() + .await + .expect("Failed to call `send_message_to_l2`") + .await + .expect("Ethereum poll update error") + .unwrap(); + } + + pub async fn message_to_l1_exists(&self, sandbox: &EthereumSandbox, message: &MessageL2ToL1) -> bool { + let messaging = StarknetMessaging::new(self.address, sandbox.client()); + + let mut payload: Vec = Vec::new(); + message.clone().into_encoded_vec().into_iter().for_each(|felt| payload.append(&mut felt.bytes().to_vec())); + + let msg_hash = keccak256(payload); + let res = messaging.l_2_to_l1_messages(msg_hash).call().await.expect("Failed to call `l_2_to_l1_messages`"); + + res != U256::zero() + } + + pub async fn message_to_l2_exists(&self, sandbox: &EthereumSandbox, message: &MessageL1ToL2) -> bool { + let messaging = StarknetMessaging::new(self.address, sandbox.client()); + + let mut payload: Vec = Vec::new(); + message.clone().into_encoded_vec().into_iter().for_each(|felt| payload.append(&mut felt.bytes().to_vec())); + + let msg_hash = keccak256(payload); + let res = messaging.l_1_to_l2_messages(msg_hash).call().await.expect("Failed to call `l_2_to_l1_messages`"); + + res != U256::zero() + } +} diff --git a/starknet-rpc-test/Cargo.toml b/starknet-rpc-test/Cargo.toml index 00b416dbe4..db2d607a49 100644 --- a/starknet-rpc-test/Cargo.toml +++ b/starknet-rpc-test/Cargo.toml @@ -26,9 +26,9 @@ thiserror = { workspace = true } tokio = { version = "1.34.0", features = ["rt", "macros", "parking_lot"] } url = "2.4.1" -[[test]] -name = "starknet_spec_version" -path = "spec_version.rs" +# [[test]] +# name = "starknet_spec_version" +# path = "spec_version.rs" [[test]] name = "starknet_get_block_number" diff --git a/starknet-rpc-test/call.rs b/starknet-rpc-test/call.rs index 9e4e02f51c..037f1c0784 100644 --- a/starknet-rpc-test/call.rs +++ b/starknet-rpc-test/call.rs @@ -161,12 +161,9 @@ async fn works_on_mutable_call_without_modifying_storage(madara: &ThreadSafeMada let deploy_tx = Execution::from(&contract_factory.deploy(vec![], FieldElement::ZERO, true).max_fee(max_fee).nonce(nonce)); - println!("before declare"); // declare and deploy contract madara_write_lock.create_block_with_txs(vec![Transaction::Declaration(declare_tx)]).await?; - println!("before execute"); madara_write_lock.create_block_with_txs(vec![Transaction::Execution(deploy_tx)]).await?; - println!("after block"); } // address of deployed contract (will always be the same for 0 salt) diff --git a/starknet-rpc-test/get_class.rs b/starknet-rpc-test/get_class.rs index 63f4b41256..820c5866e0 100644 --- a/starknet-rpc-test/get_class.rs +++ b/starknet-rpc-test/get_class.rs @@ -75,13 +75,13 @@ async fn work_ok_retrieving_class_for_contract_version_0(madara: &ThreadSafeMada ).await?, ContractClass::Legacy(c) => { // decompress program - let mut d = GzDecoder::new(&c.program[..]); - let mut data = String::new(); - d.read_to_string(&mut data).unwrap(); - let program: LegacyProgram = serde_json::from_str(data.as_str())?; + let mut gz = GzDecoder::new(&c.program[..]); + let mut decompressed_bytes = Vec::new(); + gz.read_to_end(&mut decompressed_bytes).unwrap(); + let program: LegacyProgram = serde_json::from_slice(decompressed_bytes.as_slice())?; assert_eq!( - program.data, - test_contract_class.program.data, + program.data.len(), + test_contract_class.program.data.len(), ); } ); @@ -109,7 +109,6 @@ async fn work_ok_retrieving_class_for_contract_version_1(madara: &ThreadSafeMada test_contract_class_hash ).await?, ContractClass::Sierra(c) => { - println!("{:#?}", c); assert_eq!( c.abi, flattened_test_contract_class.abi, diff --git a/starknet-rpc-test/get_class_at.rs b/starknet-rpc-test/get_class_at.rs index 07d7c3fa77..16f7192492 100644 --- a/starknet-rpc-test/get_class_at.rs +++ b/starknet-rpc-test/get_class_at.rs @@ -105,7 +105,6 @@ async fn work_ok_retrieving_class_for_contract_version_1(madara: &ThreadSafeMada test_contract_address ).await?, ContractClass::Sierra(c) => { - println!("{:#?}", c); assert_eq!( c.abi, flattened_test_contract_class.abi, diff --git a/starknet-rpc-test/get_transaction_receipt.rs b/starknet-rpc-test/get_transaction_receipt.rs index a1eb8d85ec..f9ba7da20a 100644 --- a/starknet-rpc-test/get_transaction_receipt.rs +++ b/starknet-rpc-test/get_transaction_receipt.rs @@ -1,9 +1,11 @@ extern crate starknet_rpc_test; +use std::vec; + use assert_matches::assert_matches; use rstest::rstest; use starknet_core::types::{ - Event, ExecutionResult, MaybePendingTransactionReceipt, TransactionFinalityStatus, TransactionReceipt, + Event, ExecutionResult, MaybePendingTransactionReceipt, MsgToL1, TransactionFinalityStatus, TransactionReceipt, }; use starknet_core::utils::get_selector_from_name; use starknet_ff::FieldElement; @@ -11,6 +13,7 @@ use starknet_providers::jsonrpc::HttpTransport; use starknet_providers::{JsonRpcClient, Provider, ProviderError}; use starknet_rpc_test::constants::{ ARGENT_CONTRACT_ADDRESS, CAIRO_1_ACCOUNT_CONTRACT_CLASS_HASH, FEE_TOKEN_ADDRESS, SEQUENCER_ADDRESS, SIGNER_PRIVATE, + UDC_ADDRESS, }; use starknet_rpc_test::fixtures::{madara, ThreadSafeMadaraClient}; use starknet_rpc_test::utils::{ @@ -302,3 +305,98 @@ async fn fail_invalid_transaction_hash(madara: &ThreadSafeMadaraClient) -> Resul Ok(()) } + +#[rstest] +#[tokio::test] +async fn work_with_messages_to_l1(madara: &ThreadSafeMadaraClient) -> Result<(), anyhow::Error> { + let rpc = madara.get_starknet_client().await; + + // 1. Declaring class for our L2 > L1 contract + + let account = build_single_owner_account(&rpc, SIGNER_PRIVATE, ARGENT_CONTRACT_ADDRESS, true); + let (declare_tx, _) = account.declare_legacy_contract("../cairo-contracts/build/send_message.json"); + + let txs = { + let mut madara_write_lock = madara.write().await; + madara_write_lock.create_block_with_txs(vec![Transaction::LegacyDeclaration(declare_tx)]).await? + }; + + // 2. Determine class hash + + let class_hash = assert_matches!( + &txs[0], + Ok(TransactionResult::Declaration(rpc_response)) => rpc_response.class_hash + ); + + // 3. Next, deploying an instance of this class using universal deployer + + let deploy_tx = account.invoke_contract( + FieldElement::from_hex_be(UDC_ADDRESS).unwrap(), + "deployContract", + vec![ + class_hash, + FieldElement::ZERO, // salt + FieldElement::ZERO, // unique + FieldElement::ZERO, // calldata len + ], + None, + ); + + let txs = { + let mut madara_write_lock = madara.write().await; + madara_write_lock.create_block_with_txs(vec![Transaction::Execution(deploy_tx)]).await? + }; + + // 4. Now, we need to get the deployed contract address + + let deploy_tx_hash = assert_matches!( + &txs[0], + Ok(TransactionResult::Execution(rpc_response)) => rpc_response.transaction_hash + ); + + let deploy_tx_receipt = get_transaction_receipt(&rpc, deploy_tx_hash).await?; + + let contract_address = assert_matches!( + deploy_tx_receipt, + MaybePendingTransactionReceipt::Receipt(TransactionReceipt::Invoke(receipt)) => receipt.events[0].data[0] + ); + + // 5. Sending message to L1 + + let invoke_tx = account.invoke_contract( + contract_address, + "send_message_l2_to_l1", + vec![FieldElement::ZERO, FieldElement::ONE, FieldElement::TWO], + None, + ); + + let txs = { + let mut madara_write_lock = madara.write().await; + madara_write_lock.create_block_with_txs(vec![Transaction::Execution(invoke_tx)]).await? + }; + + // 6. Finally, checking that there is a single MessageToL1 in the receipt + + let invoke_tx_hash = assert_matches!( + &txs[0], + Ok(TransactionResult::Execution(rpc_response)) => rpc_response.transaction_hash + ); + + let invoke_tx_receipt = get_transaction_receipt(&rpc, invoke_tx_hash).await?; + + let messages_sent = assert_matches!( + invoke_tx_receipt, + MaybePendingTransactionReceipt::Receipt(TransactionReceipt::Invoke(receipt)) => receipt.messages_sent + ); + + assert_eq_msg_to_l1( + vec![MsgToL1 { + from_address: contract_address, + to_address: FieldElement::ZERO, + payload: vec![FieldElement::TWO], + }], + messages_sent, + ); + + Ok(()) +} diff --git a/starknet-rpc-test/src/constants.rs b/starknet-rpc-test/src/constants.rs index 16157197a9..bc20e7b081 100644 --- a/starknet-rpc-test/src/constants.rs +++ b/starknet-rpc-test/src/constants.rs @@ -7,6 +7,7 @@ pub const CAIRO_1_ACCOUNT_CONTRACT_CLASS_HASH: &str = "0x35ccefcf9d5656da623468e27e682271cd327af196785df99e7fee1436b6276"; pub const ERC20_CAIRO_0_CONTRACT: &str = "0x040e59c2c182a58fb0a74349bfa4769cbbcba32547591dd3fb1def8623997d00"; pub const SEQUENCER_ADDRESS: &str = "0xdead"; +pub const UDC_ADDRESS: &str = "0x041a78e741e5af2fec34b695679bc6891742439f7afb8484ecd7766661ad02bf"; // https://github.com/keep-starknet-strange/madara/blob/main/crates/node/src/chain_spec.rs#L185-L186 pub const ACCOUNT_CONTRACT_CLASS_HASH: &str = "0x0279d77db761fba82e0054125a6fdb5f6baa6286fa3fb73450cc44d193c2d37f"; @@ -16,7 +17,7 @@ pub const SIGNER_PRIVATE: &str = "0x00c1cf1490de1352865301bb8705143f3ef938f97fdf pub const SALT: &str = "0x0000000000000000000000000000000000000000000000000000000000001111"; // https://github.com/keep-starknet-strange/madara/blob/main/crates/node/src/chain_spec.rs#L191-L192 -pub const TEST_CONTRACT_CLASS_HASH: &str = "0x05a2b92d9a36509a3d651e7df99144a4ad8301e2caf42465ee6ab0451ae91882"; +pub const TEST_CONTRACT_CLASS_HASH: &str = "0x04c5efa8dc6f0554da51f125d04e379ac41153a8b837391083a8dc3771a33388"; pub const MINT_AMOUNT: &str = "0x0000000000000000000000000000000000000000000000000000000000000001"; pub const DEPLOY_ACCOUNT_COST: &str = "0x00000000000000000000000000000000000000000000000000000000ffffffff"; pub const CONTRACT_ADDRESS: &str = "0x0000000000000000000000000000000000000000000000000000000000000001"; diff --git a/starknet-rpc-test/src/fixtures.rs b/starknet-rpc-test/src/fixtures.rs index 6feec8bd2f..9c064b2c9c 100644 --- a/starknet-rpc-test/src/fixtures.rs +++ b/starknet-rpc-test/src/fixtures.rs @@ -10,7 +10,7 @@ pub struct ThreadSafeMadaraClient(RwLock); #[fixture] #[once] pub fn madara() -> ThreadSafeMadaraClient { - ThreadSafeMadaraClient(RwLock::new(MadaraClient::new())) + ThreadSafeMadaraClient(RwLock::new(MadaraClient::default())) } impl ThreadSafeMadaraClient { diff --git a/starknet-rpc-test/src/lib.rs b/starknet-rpc-test/src/lib.rs index f4797c840a..720549938b 100644 --- a/starknet-rpc-test/src/lib.rs +++ b/starknet-rpc-test/src/lib.rs @@ -89,13 +89,13 @@ pub struct MadaraClient { impl Default for MadaraClient { fn default() -> Self { let url = Url::parse(NODE_RPC_URL).expect("Invalid JSONRPC Url"); - MadaraClient { url, rpc_request_count: Default::default() } + MadaraClient::new(url) } } impl MadaraClient { - pub fn new() -> Self { - Default::default() + pub fn new(url: Url) -> Self { + Self { url, rpc_request_count: Default::default() } } pub async fn run_to_block(&mut self, target_block: u64) -> anyhow::Result<()> { @@ -130,7 +130,7 @@ impl MadaraClient { let body = serde_json::to_string(&body).expect("the json body must be serializable"); let response = Client::new() - .post("http://localhost:9944") + .post(self.url.clone()) .header(CONTENT_TYPE, "application/json; charset=utf-8") .body(body) .send() diff --git a/starknet-rpc-test/src/utils.rs b/starknet-rpc-test/src/utils.rs index d0c159f187..8028c14d35 100644 --- a/starknet-rpc-test/src/utils.rs +++ b/starknet-rpc-test/src/utils.rs @@ -91,6 +91,14 @@ pub trait AccountActions { nonce: Option, ) -> TransactionExecution; + fn invoke_contract( + &self, + address: FieldElement, + method: &str, + calldata: Vec, + nonce: Option, + ) -> TransactionExecution; + fn declare_contract( &self, path_to_sierra: &str, @@ -122,21 +130,12 @@ impl AccountActions for SingleOwnerAccount<&JsonRpcClient, LocalW nonce: Option, ) -> TransactionExecution { let fee_token_address = FieldElement::from_hex_be(FEE_TOKEN_ADDRESS).unwrap(); - - let calls = vec![Call { - to: fee_token_address, - selector: get_selector_from_name("transfer").unwrap(), - calldata: vec![recipient, transfer_amount.low, transfer_amount.high], - }]; - - // starknet-rs calls estimateFee with incorrect version which throws an error - let max_fee = FieldElement::from_hex_be(MAX_FEE_OVERRIDE).unwrap(); - - // TODO: add support for nonce with raw execution e.g https://github.com/0xSpaceShard/starknet-devnet-rs/blob/main/crates/starknet/src/starknet/add_invoke_transaction.rs#L10 - match nonce { - Some(nonce) => self.execute(calls).max_fee(max_fee).nonce(nonce.into()), - None => self.execute(calls).max_fee(max_fee), - } + self.invoke_contract( + fee_token_address, + "transfer", + vec![recipient, transfer_amount.low, transfer_amount.high], + nonce, + ) } fn transfer_tokens( @@ -148,6 +147,23 @@ impl AccountActions for SingleOwnerAccount<&JsonRpcClient, LocalW self.transfer_tokens_u256(recipient, U256 { high: FieldElement::ZERO, low: transfer_amount }, nonce) } + fn invoke_contract( + &self, + address: FieldElement, + method: &str, + 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(); + + match nonce { + Some(nonce) => self.execute(calls).max_fee(max_fee).nonce(nonce.into()), + None => self.execute(calls).max_fee(max_fee), + } + } + fn declare_contract( &self, path_to_sierra: &str,