From 4634579db23199910790c4276dbe7cebc4970c40 Mon Sep 17 00:00:00 2001 From: apoorvsadana <95699312+apoorvsadana@users.noreply.github.com> Date: Sat, 25 May 2024 16:52:21 +0530 Subject: [PATCH] Fix gas price (#1601) --- CHANGELOG.md | 2 + Cargo.lock | 48 +- Cargo.toml | 15 +- .../MultiplyNumsContract.casm.json | 660 ++++++++++++++++ .../MultiplyNumsContract.sierra.json | 711 ++++++++++++++++++ configs/genesis-assets/genesis.json | 15 + configs/index.json | 10 +- crates/client/eth-client/src/config.rs | 18 +- crates/client/l1-gas-price/Cargo.toml | 22 + crates/client/l1-gas-price/src/lib.rs | 2 + crates/client/l1-gas-price/src/types.rs | 50 ++ crates/client/l1-gas-price/src/worker.rs | 105 +++ crates/client/l1-messages/src/worker.rs | 6 +- crates/client/rpc/src/errors.rs | 1 + crates/client/rpc/src/lib.rs | 46 +- crates/client/rpc/src/runtime_api.rs | 31 +- crates/client/rpc/src/trace_api.rs | 28 +- crates/node/Cargo.toml | 3 +- crates/node/src/commands/run.rs | 40 +- crates/node/src/genesis_block.rs | 6 +- crates/node/src/service.rs | 72 +- crates/pallets/starknet/Cargo.toml | 5 +- .../pallets/starknet/runtime_api/Cargo.toml | 4 + .../pallets/starknet/runtime_api/src/lib.rs | 12 +- crates/pallets/starknet/src/lib.rs | 55 +- crates/pallets/starknet/src/simulations.rs | 218 ++++-- crates/pallets/starknet/src/tests/block.rs | 8 +- .../starknet/src/tests/deploy_account_tx.rs | 4 +- crates/pallets/starknet/src/tests/erc20.rs | 4 +- .../pallets/starknet/src/tests/invoke_tx.rs | 4 +- .../starknet/src/tests/mock/setup_mock.rs | 15 +- crates/pallets/starknet/src/tests/mod.rs | 2 +- crates/pallets/starknet/src/tests/query_tx.rs | 23 +- .../starknet/src/tests/sequencer_address.rs | 120 --- .../starknet/src/tests/starknet_inherent.rs | 98 +++ .../primitives/sequencer-address/src/lib.rs | 120 --- crates/primitives/simulations/Cargo.toml | 2 +- crates/primitives/simulations/src/lib.rs | 59 +- .../Cargo.toml | 5 +- .../primitives/starknet-inherent/src/lib.rs | 147 ++++ .../primitives/transactions/src/execution.rs | 46 +- crates/runtime/Cargo.toml | 1 + crates/runtime/src/lib.rs | 20 +- crates/runtime/src/pallets.rs | 4 - docs/genesis.md | 4 +- examples/messaging/eth-config.json | 9 + examples/messaging/l1-messaging-config.json | 4 - starknet-rpc-test/estimate_fee.rs | 91 ++- starknet-rpc-test/get_state_update.rs | 15 +- starknet-rpc-test/get_transaction_receipt.rs | 8 +- starknet-rpc-test/simulate_transaction.rs | 55 +- starknet-rpc-test/src/constants.rs | 3 +- starknet-test-utils/src/constants.rs | 2 +- 53 files changed, 2485 insertions(+), 573 deletions(-) create mode 100644 configs/genesis-assets/MultiplyNumsContract.casm.json create mode 100644 configs/genesis-assets/MultiplyNumsContract.sierra.json create mode 100644 crates/client/l1-gas-price/Cargo.toml create mode 100644 crates/client/l1-gas-price/src/lib.rs create mode 100644 crates/client/l1-gas-price/src/types.rs create mode 100644 crates/client/l1-gas-price/src/worker.rs delete mode 100644 crates/pallets/starknet/src/tests/sequencer_address.rs create mode 100644 crates/pallets/starknet/src/tests/starknet_inherent.rs delete mode 100644 crates/primitives/sequencer-address/src/lib.rs rename crates/primitives/{sequencer-address => starknet-inherent}/Cargo.toml (81%) create mode 100644 crates/primitives/starknet-inherent/src/lib.rs create mode 100644 examples/messaging/eth-config.json delete mode 100644 examples/messaging/l1-messaging-config.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 28d74b7bf2..33eabbe4e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Next release +- feat: actual estimate_fee added, brought back l1 messages and refactored + simulate tx - dev: impl get_state_updates using get_transaction_re_execution_state_diff - feat: support strk as fee token - dev: pallet test for estimate_fee that skip validation diff --git a/Cargo.lock b/Cargo.lock index 6511ea1ff6..8d48947a64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -883,7 +883,7 @@ dependencies = [ [[package]] name = "blockifier" version = "0.5.0-rc.3" -source = "git+https://github.com/bidzyyys/blockifier?branch=feature/scale-codec#59950ded347f60bfcbbc31300ff713e5423448e2" +source = "git+https://github.com/bidzyyys/blockifier?branch=feature/scale-codec#3b2682b949cc691150a682bf26debe6f6e264361" dependencies = [ "anyhow", "ark-ec", @@ -5535,6 +5535,7 @@ dependencies = [ "mc-db", "mc-eth-client", "mc-genesis-data-provider", + "mc-l1-gas-price", "mc-l1-messages", "mc-mapping-sync", "mc-rpc", @@ -5543,7 +5544,7 @@ dependencies = [ "mp-block", "mp-digest-log", "mp-felt", - "mp-sequencer-address", + "mp-starknet-inherent", "num-bigint", "pallet-starknet", "pallet-starknet-runtime-api", @@ -5607,6 +5608,7 @@ dependencies = [ "mp-hashers", "mp-program-hash", "mp-simulations", + "mp-starknet-inherent", "pallet-aura", "pallet-grandpa", "pallet-starknet", @@ -5748,6 +5750,21 @@ dependencies = [ "thiserror", ] +[[package]] +name = "mc-l1-gas-price" +version = "0.1.0" +dependencies = [ + "anyhow", + "ethers", + "futures", + "log", + "mc-eth-client", + "mp-starknet-inherent", + "reqwest", + "serde", + "tokio", +] + [[package]] name = "mc-l1-messages" version = "0.1.0" @@ -6190,17 +6207,6 @@ dependencies = [ "starknet-ff 0.3.7", ] -[[package]] -name = "mp-sequencer-address" -version = "0.7.0" -dependencies = [ - "async-trait", - "parity-scale-codec", - "sp-core", - "sp-inherents", - "thiserror", -] - [[package]] name = "mp-simulations" version = "0.7.0" @@ -6225,6 +6231,19 @@ dependencies = [ "starknet_api", ] +[[package]] +name = "mp-starknet-inherent" +version = "0.7.0" +dependencies = [ + "async-trait", + "blockifier", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-inherents", + "thiserror", +] + [[package]] name = "mp-storage" version = "0.7.0" @@ -6889,8 +6908,8 @@ dependencies = [ "mp-genesis-config", "mp-hashers", "mp-program-hash", - "mp-sequencer-address", "mp-simulations", + "mp-starknet-inherent", "mp-storage", "mp-transactions", "pallet-timestamp", @@ -6918,6 +6937,7 @@ dependencies = [ "blockifier", "mp-felt", "mp-simulations", + "mp-starknet-inherent", "parity-scale-codec", "scale-info", "sp-api", diff --git a/Cargo.toml b/Cargo.toml index 857d2aa772..0e60e79d07 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ members = [ "crates/primitives/felt", "crates/primitives/hashers", "crates/primitives/block", - "crates/primitives/sequencer-address", + "crates/primitives/starknet-inherent", "crates/primitives/storage", "crates/primitives/chain-id", "crates/primitives/messages", @@ -43,7 +43,7 @@ default-members = [ "crates/primitives/felt", "crates/primitives/hashers", "crates/primitives/block", - "crates/primitives/sequencer-address", + "crates/primitives/starknet-inherent", "crates/primitives/storage", "crates/primitives/chain-id", "crates/primitives/messages", @@ -164,7 +164,7 @@ mp-block = { path = "crates/primitives/block" } mp-fee = { path = "crates/primitives/fee" } mp-felt = { path = "crates/primitives/felt" } mp-hashers = { path = "crates/primitives/hashers" } -mp-sequencer-address = { path = "crates/primitives/sequencer-address" } +mp-starknet-inherent = { path = "crates/primitives/starknet-inherent" } mp-snos-output = { path = "crates/primitives/snos-output" } mp-storage = { path = "crates/primitives/storage" } mp-transactions = { path = "crates/primitives/transactions" } @@ -185,6 +185,7 @@ mc-rpc = { path = "crates/client/rpc" } mc-rpc-core = { path = "crates/client/rpc-core" } mc-commitment-state-diff = { path = "crates/client/commitment-state-diff" } mc-l1-messages = { path = "crates/client/l1-messages" } +mc-l1-gas-price = { path = "crates/client/l1-gas-price" } mc-eth-client = { path = "crates/client/eth-client" } mc-starknet-block-import = { path = "crates/client/starknet-block-import" } @@ -225,15 +226,7 @@ ethers = { git = "https://github.com/gakonst/ethers-rs", rev = "f0e5b194f09c533f ethers-solc = { git = "https://github.com/gakonst/ethers-rs", rev = "f0e5b194f09c533feb10d1a686ddb9e5946ec107" } # Zaun -ethereum-instance = { git = "https://github.com/keep-starknet-strange/zaun", package = "ethereum-instance", branch = "main" } -starkgate-manager-client = { git = "https://github.com/keep-starknet-strange/zaun", package = "starkgate-manager-client", branch = "main" } -starkgate-registry-client = { git = "https://github.com/keep-starknet-strange/zaun", package = "starkgate-registry-client", branch = "main" } starknet-core-contract-client = { git = "https://github.com/keep-starknet-strange/zaun", package = "starknet-core-contract-client", branch = "main" } -starknet-erc20-client = { git = "https://github.com/keep-starknet-strange/zaun", package = "starknet-erc20-client", branch = "main" } -starknet-eth-bridge-client = { git = "https://github.com/keep-starknet-strange/zaun", package = "starknet-eth-bridge-client", branch = "main" } -starknet-proxy-client = { git = "https://github.com/keep-starknet-strange/zaun", package = "starknet-proxy-client", branch = "main" } -starknet-token-bridge-client = { git = "https://github.com/keep-starknet-strange/zaun", package = "starknet-token-bridge-client", branch = "main" } -zaun-utils = { git = "https://github.com/keep-starknet-strange/zaun", package = "utils", branch = "main" } # Other third party dependencies diff --git a/configs/genesis-assets/MultiplyNumsContract.casm.json b/configs/genesis-assets/MultiplyNumsContract.casm.json new file mode 100644 index 0000000000..a433194bc3 --- /dev/null +++ b/configs/genesis-assets/MultiplyNumsContract.casm.json @@ -0,0 +1,660 @@ +{ + "prime": "0x800000000000011000000000000000000000000000000000000000000000001", + "compiler_version": "2.5.0", + "bytecode": [ + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0x100000000000000000000000000000000", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0xba", + "0x4825800180007ffa", + "0x0", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x48297ffc80007ffd", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482680017ffc8000", + "0x1", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x480a7ffc7fff8000", + "0x10780017fff7fff", + "0x8", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x20680017fff7ffe", + "0x8f", + "0x48127ffa7fff8000", + "0x480080007ffe8000", + "0x1104800180018000", + "0x113", + "0x20680017fff7ffe", + "0x86", + "0x48127fee7fff8000", + "0x48127fee7fff8000", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0xa", + "0x482480017ffd8000", + "0x1", + "0x48127ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x10780017fff7fff", + "0x8", + "0x48127ffd7fff8000", + "0x48127ffd7fff8000", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x20680017fff7ffe", + "0x5e", + "0x48127ff67fff8000", + "0x480080007ffe8000", + "0x1104800180018000", + "0xf6", + "0x20680017fff7ffe", + "0x55", + "0x48127fee7fff8000", + "0x48127fee7fff8000", + "0x48307ffe80007fff", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ff87fff8000", + "0x48127fd07fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x1b7", + "0x482480017fff8000", + "0x1b6", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007fce", + "0x3d72", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007ff37fff", + "0x10780017fff7fff", + "0x23", + "0x4824800180007fce", + "0x3d72", + "0x400080007ff47fff", + "0x482480017ff48000", + "0x1", + "0x48127ffe7fff8000", + "0x480a7ffb7fff8000", + "0x48127fde7fff8000", + "0x48127ff27fff8000", + "0x1104800180018000", + "0xeb", + "0x20680017fff7ffd", + "0xe", + "0x40780017fff7fff", + "0x1", + "0x400080007fff7ffe", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x482480017ffa8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017ff18000", + "0x1", + "0x48127fc97fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ffd7fff8000", + "0x10780017fff7fff", + "0x5", + "0x40780017fff7fff", + "0xe", + "0x48127fe87fff8000", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202332", + "0x400080007ffe7fff", + "0x48127ffd7fff8000", + "0x48127fd27fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x48127ffd7fff8000", + "0x10780017fff7fff", + "0x5", + "0x40780017fff7fff", + "0xe", + "0x48127fec7fff8000", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x400080007ffe7fff", + "0x48127ffd7fff8000", + "0x48127fe77fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x482680017ffa8000", + "0x100000000000000000000000000000000", + "0x400280007ff97fff", + "0x10780017fff7fff", + "0x54", + "0x4825800180007ffa", + "0x0", + "0x400280007ff97fff", + "0x482680017ff98000", + "0x1", + "0x48297ffc80007ffd", + "0x20680017fff7fff", + "0x4", + "0x10780017fff7fff", + "0x10", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x400080007ffe7fff", + "0x48127ffc7fff8000", + "0x48127ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x1104800180018000", + "0x123", + "0x482480017fff8000", + "0x122", + "0x480080007fff8000", + "0xa0680017fff8000", + "0x9", + "0x4824800180007ff8", + "0x1a54", + "0x482480017fff8000", + "0x100000000000000000000000000000000", + "0x400080007ff77fff", + "0x10780017fff7fff", + "0x1f", + "0x4824800180007ff8", + "0x1a54", + "0x400080007ff87fff", + "0x48127fff7fff8000", + "0x480a7ffb7fff8000", + "0x1104800180018000", + "0x84", + "0x482480017fd78000", + "0x1", + "0x20680017fff7ffc", + "0xc", + "0x40780017fff7fff", + "0x1", + "0x48127ffe7fff8000", + "0x48127ff87fff8000", + "0x48127ff87fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x48127fff7fff8000", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ff97fff8000", + "0x48127ff97fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482480017ff58000", + "0x1", + "0x48127ff37fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x4f7574206f6620676173", + "0x400080007ffe7fff", + "0x482680017ff98000", + "0x1", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x482480017ff98000", + "0x1", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x12", + "0x4825800180007ffd", + "0x100000000", + "0x4844800180008002", + "0x8000000000000110000000000000000", + "0x4830800080017ffe", + "0x480280007ffc7fff", + "0x482480017ffe8000", + "0xefffffffffffffde00000000ffffffff", + "0x480280017ffc7fff", + "0x400280027ffc7ffb", + "0x402480017fff7ffb", + "0xffffffffffffffffffffffffffffffff", + "0x20680017fff7fff", + "0x10", + "0x402780017fff7fff", + "0x1", + "0x400380007ffc7ffd", + "0x482680017ffd8000", + "0xffffffffffffffffffffffff00000000", + "0x400280017ffc7fff", + "0x40780017fff7fff", + "0x5", + "0x482680017ffc8000", + "0x2", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffc8000", + "0x3", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480a7ff97fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x3e", + "0x20680017fff7ffd", + "0x1a", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x48127ffd7fff8000", + "0x1104800180018000", + "0x52", + "0x20680017fff7ffd", + "0xb", + "0x48127fe47fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127fe27fff8000", + "0x208b7fff7fff7ffe", + "0x48127fe47fff8000", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffa7fff8000", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x18", + "0x48127fe47fff8000", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127fe27fff8000", + "0x48127fe27fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x0", + "0x1104800180018000", + "0x2f", + "0x20680017fff7ffd", + "0xb", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x484a7ffd7ffc8000", + "0x1104800180018000", + "0x4d", + "0x20680017fff7ffe", + "0xb", + "0x40780017fff7fff", + "0x2", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x48127ffa7fff8000", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x480680017fff8000", + "0x7533325f6d756c204f766572666c6f77", + "0x400080007ffe7fff", + "0x48127ffb7fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffc7fff8000", + "0x482480017ffb8000", + "0x1", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x2a4a183f82db747ab399ca476ab84cc3def6abe3ac63748d03b4584af38d057", + "0x480680017fff8000", + "0x53746f726167655772697465", + "0x400280007ffc7fff", + "0x400380017ffc7ffb", + "0x400280027ffc7ffd", + "0x400280037ffc7ffe", + "0x400380047ffc7ffd", + "0x480280067ffc8000", + "0x20680017fff7fff", + "0xd", + "0x480280057ffc8000", + "0x482680017ffc8000", + "0x7", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x10780017fff7fff", + "0x9", + "0x480280057ffc8000", + "0x482680017ffc8000", + "0x9", + "0x480680017fff8000", + "0x1", + "0x480280077ffc8000", + "0x480280087ffc8000", + "0x1104800180018000", + "0x2b", + "0x20680017fff7ffd", + "0xb", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x480680017fff8000", + "0x1", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0xa0680017fff8000", + "0x7", + "0x4825800180007ffd", + "0x100000000", + "0x400280007ffc7fff", + "0x10780017fff7fff", + "0xb", + "0x482680017ffd8000", + "0xffffffffffffffffffffffff00000000", + "0x400280007ffc7fff", + "0x482680017ffc8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe", + "0x482680017ffc8000", + "0x1", + "0x480680017fff8000", + "0x1", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x20780017fff7ffb", + "0x9", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x480680017fff8000", + "0x0", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x1", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x208b7fff7fff7ffe" + ], + "hints": [ + [ + 0, + [ + { + "TestLessThanOrEqual": { + "lhs": { "Immediate": "0x0" }, + "rhs": { "Deref": { "register": "FP", "offset": -6 } }, + "dst": { "register": "AP", "offset": 0 } + } + } + ] + ], + [75, [{ "AllocSegment": { "dst": { "register": "AP", "offset": 0 } } }]], + [ + 94, + [ + { + "TestLessThanOrEqual": { + "lhs": { "Immediate": "0x3d72" }, + "rhs": { "Deref": { "register": "AP", "offset": -49 } }, + "dst": { "register": "AP", "offset": 0 } + } + } + ] + ], + [116, [{ "AllocSegment": { "dst": { "register": "AP", "offset": 0 } } }]], + [136, [{ "AllocSegment": { "dst": { "register": "AP", "offset": 0 } } }]], + [157, [{ "AllocSegment": { "dst": { "register": "AP", "offset": 0 } } }]], + [177, [{ "AllocSegment": { "dst": { "register": "AP", "offset": 0 } } }]], + [191, [{ "AllocSegment": { "dst": { "register": "AP", "offset": 0 } } }]], + [ + 206, + [ + { + "TestLessThanOrEqual": { + "lhs": { "Immediate": "0x0" }, + "rhs": { "Deref": { "register": "FP", "offset": -6 } }, + "dst": { "register": "AP", "offset": 0 } + } + } + ] + ], + [223, [{ "AllocSegment": { "dst": { "register": "AP", "offset": 0 } } }]], + [ + 242, + [ + { + "TestLessThanOrEqual": { + "lhs": { "Immediate": "0x1a54" }, + "rhs": { "Deref": { "register": "AP", "offset": -7 } }, + "dst": { "register": "AP", "offset": 0 } + } + } + ] + ], + [262, [{ "AllocSegment": { "dst": { "register": "AP", "offset": 0 } } }]], + [280, [{ "AllocSegment": { "dst": { "register": "AP", "offset": 0 } } }]], + [295, [{ "AllocSegment": { "dst": { "register": "AP", "offset": 0 } } }]], + [ + 310, + [ + { + "TestLessThan": { + "lhs": { "Deref": { "register": "FP", "offset": -3 } }, + "rhs": { "Immediate": "0x100000000" }, + "dst": { "register": "AP", "offset": 0 } + } + } + ] + ], + [ + 314, + [ + { + "LinearSplit": { + "value": { "Deref": { "register": "AP", "offset": -1 } }, + "scalar": { "Immediate": "0x8000000000000110000000000000000" }, + "max_x": { "Immediate": "0xfffffffffffffffffffffffffffffffe" }, + "x": { "register": "AP", "offset": 0 }, + "y": { "register": "AP", "offset": 1 } + } + } + ] + ], + [427, [{ "AllocSegment": { "dst": { "register": "AP", "offset": 0 } } }]], + [ + 450, + [ + { + "SystemCall": { + "system": { "Deref": { "register": "FP", "offset": -4 } } + } + } + ] + ], + [ + 491, + [ + { + "TestLessThan": { + "lhs": { "Deref": { "register": "FP", "offset": -3 } }, + "rhs": { "Immediate": "0x100000000" }, + "dst": { "register": "AP", "offset": 0 } + } + } + ] + ] + ], + "entry_points_by_type": { + "EXTERNAL": [ + { + "selector": "0x39674cadb16109ec414e371cc8f04eb60a540c52d4880cadb49dfafb8d79797", + "offset": 0, + "builtins": ["range_check"] + } + ], + "L1_HANDLER": [], + "CONSTRUCTOR": [ + { + "selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194", + "offset": 206, + "builtins": ["range_check"] + } + ] + } +} diff --git a/configs/genesis-assets/MultiplyNumsContract.sierra.json b/configs/genesis-assets/MultiplyNumsContract.sierra.json new file mode 100644 index 0000000000..fd388e634c --- /dev/null +++ b/configs/genesis-assets/MultiplyNumsContract.sierra.json @@ -0,0 +1,711 @@ +{ + "sierra_program": [ + "0x1", + "0x4", + "0x0", + "0x2", + "0x5", + "0x0", + "0xd9", + "0x27", + "0x21", + "0x52616e6765436865636b", + "0x800000000000000100000000000000000000000000000000", + "0x537472756374", + "0x800000000000000f00000000000000000000000000000001", + "0x0", + "0x2ee1e2b1b89f8c495f200e4956278a4d47395fe262f27b52e5865c9524c08c3", + "0x800000000000000f00000000000000000000000000000002", + "0x1", + "0x16a4c8d7c05909052238a862d8cc3e7975bf05a07b3a69c6b28951083a6d672", + "0x4172726179", + "0x800000000000000300000000000000000000000000000001", + "0x1d", + "0x800000000000000300000000000000000000000000000003", + "0x3", + "0x4", + "0x456e756d", + "0xcc5e86243f861d2d64b08c35db21013e773ac5cf10097946fe0011304886d5", + "0x2", + "0x5", + "0x101dc0399934cc08fa0d6f6f2daead4e4a38cabeea1c743e1fc28d2d6e58e99", + "0x53746f7261676541646472657373", + "0x800000000000000700000000000000000000000000000000", + "0x53746f726167654261736541646472657373", + "0x753634", + "0x105da2b4e27de569d85a3962e8c84e0d75055a91ac1a9cb1cbf3150cfecec8a", + "0x800000000000000f00000000000000000000000000000003", + "0xb", + "0x3561ddf415a895d3c747f8976c09715e6a1840916a4f84f48a35c1e14a810b5", + "0xc", + "0x753332", + "0x800000000000000700000000000000000000000000000002", + "0xe", + "0x3ab802bcce3a9ca953b0e1f31a5b29eb27a9b727c891e24300e1b5cc57387ba", + "0xf", + "0x39fe7e2f05475a9afeee1fa9ff3d5beb4311975ef57a7023f6585b4f791d1c", + "0x11", + "0x1d9568edb93b79ccceefd66fc7325b339819ea8b7338e70425e59e8e35c410c", + "0x12", + "0x536e617073686f74", + "0x800000000000000700000000000000000000000000000001", + "0x1baeba72e79e9db2587cf44fedb2f3700b2075a5e8e39a562584862c4b71f62", + "0x14", + "0x15", + "0x800000000000000700000000000000000000000000000003", + "0x1afe071b8c7c79454318fcdeb7697f21321f6319e490cbbeab1b56c5ce96390", + "0x17", + "0x4275696c74696e436f737473", + "0x53797374656d", + "0x9931c641b913035ae674b400b61a51476d506bbe8bba2ff8a6272790aba9e6", + "0x16", + "0x19b9ae4ba181a54f9e7af894a81b44a60aea4c9803939708d6cc212759ee94c", + "0x66656c74323532", + "0x426f78", + "0x29d7d57c04a880978e7b3689f6218e507f3be17588744b58dc17762447ad0e7", + "0x1e", + "0x4761734275696c74696e", + "0x6d", + "0x7265766f6b655f61705f747261636b696e67", + "0x77697468647261775f676173", + "0x6272616e63685f616c69676e", + "0x7374727563745f6465636f6e737472756374", + "0x656e61626c655f61705f747261636b696e67", + "0x73746f72655f74656d70", + "0x61727261795f736e617073686f745f706f705f66726f6e74", + "0x656e756d5f696e6974", + "0x1f", + "0x6a756d70", + "0x7374727563745f636f6e737472756374", + "0x656e756d5f6d61746368", + "0x756e626f78", + "0x72656e616d65", + "0x66756e6374696f6e5f63616c6c", + "0x1c", + "0x64697361626c655f61705f747261636b696e67", + "0x64726f70", + "0x61727261795f6e6577", + "0x66656c743235325f636f6e7374", + "0x496e70757420746f6f206c6f6e6720666f7220617267756d656e7473", + "0x61727261795f617070656e64", + "0x1b", + "0x20", + "0x1a", + "0x6765745f6275696c74696e5f636f737473", + "0x19", + "0x77697468647261775f6761735f616c6c", + "0x18", + "0x736e617073686f745f74616b65", + "0x7533325f746f5f66656c74323532", + "0x4f7574206f6620676173", + "0x4661696c656420746f20646573657269616c697a6520706172616d202332", + "0x4661696c656420746f20646573657269616c697a6520706172616d202331", + "0x13", + "0x7533325f7472795f66726f6d5f66656c74323532", + "0x10", + "0x647570", + "0x6", + "0xd", + "0x7533325f636f6e7374", + "0x7533325f776964655f6d756c", + "0xa", + "0x7", + "0x7533325f6d756c204f766572666c6f77", + "0x73746f726167655f626173655f616464726573735f636f6e7374", + "0x2a4a183f82db747ab399ca476ab84cc3def6abe3ac63748d03b4584af38d057", + "0x73746f726167655f616464726573735f66726f6d5f62617365", + "0x8", + "0x73746f726167655f77726974655f73797363616c6c", + "0x646f776e63617374", + "0x1b0", + "0xffffffffffffffff", + "0xaf", + "0x9", + "0x9e", + "0x99", + "0x23", + "0x28", + "0x22", + "0x87", + "0x24", + "0x25", + "0x26", + "0x27", + "0x29", + "0x81", + "0x2a", + "0x2b", + "0x2c", + "0x2d", + "0x2e", + "0x47", + "0x2f", + "0x30", + "0x31", + "0x32", + "0x33", + "0x34", + "0x35", + "0x36", + "0x37", + "0x38", + "0x71", + "0x39", + "0x3a", + "0x3b", + "0x3c", + "0x3d", + "0x3e", + "0x3f", + "0x40", + "0x41", + "0x6a", + "0x42", + "0x43", + "0x44", + "0x45", + "0x46", + "0x48", + "0x49", + "0x4a", + "0x4b", + "0x4c", + "0x4d", + "0x4e", + "0x4f", + "0x50", + "0x51", + "0x52", + "0x53", + "0x54", + "0x55", + "0x56", + "0x57", + "0x8c", + "0x58", + "0x59", + "0x5a", + "0x5b", + "0x5c", + "0x5d", + "0x5e", + "0xa2", + "0x5f", + "0x60", + "0x61", + "0x62", + "0x63", + "0x64", + "0x65", + "0x66", + "0x67", + "0x68", + "0x69", + "0x100", + "0xd2", + "0xf3", + "0xec", + "0x114", + "0x13b", + "0x133", + "0x155", + "0x166", + "0x182", + "0x187", + "0x191", + "0x19e", + "0x1aa", + "0x6b", + "0x6c", + "0xbd", + "0x10e", + "0x11a", + "0x143", + "0x15b", + "0x172", + "0x198", + "0x1a4", + "0xff4", + "0xd100f080e0806050d030c080b0a0905040308080605070306050403020100", + "0x81b0806051a03190504031618161716150f08080814050d10130812081105", + "0x1b08230507031308220821050d10200806051f03161e13081d081c050d1008", + "0x806051f032a0829051f030f0828271308260825050d100808240806051a03", + "0x2c101308320831050d100230162f13082e082d050d102008240806052c032b", + "0x83d053c053b053a3902380808370836052c100c0828351634080820083305", + "0x8084405434208083f2a08083f0512420812410c0808400508083f053e2b08", + "0x49080845120e08480c08083f0c0808470c0808464208084508124208124108", + "0x440c08084f4e12084d0c08084c2008084b3708084b2a08084b054a2b080844", + "0x5408083f05535008083f5208083f5108083f081250081241130808440e0808", + "0x572408084b2e08083d560808450e0e08482008083f240808441b0808440555", + "0x5912084d051250081241320808440f08084b0f080857055820080847200808", + "0x41055d2608084b5c0808450f0e08482b08084b5b12084d5a12084d0808084b", + "0x2408083d2208083d5e080845130e08480812490812414908083f0512490812", + "0x415608083f0512560812412e0808441d08083d61080845600e08482008085f", + "0x56308125c0812415c08083f05125c08124126080844051208620812560812", + "0x125e0812416612084d5e08083f05125e08124122080844650e08486408083f", + "0x6508083f051265081241056b6a08083f1b08084b1b08085705696812086708", + "0x8083f0512610812411d0808441208083d600808456a0e0848081265081241", + "0x6008083f051260081241120808446508084520086408126c08126108124161", + "0x80512056560126f130f126e120805120805056e080505056d081260081241", + "0x126e126a0860050f086e080f081305056e08050f056a086e080e080e05056e", + "0x1d08700561086e0870086a051d086e0864086505056e080512051b081d6470", + "0x5e086e0822081d0522086e08051b05056e0805120505240805640520086e08", + "0x805120526087124086e122008610520086e085e08700561086e081b086a05", + "0x82a085e050f086e080f0813052a086e085c0822055c086e0824082005056e", + "0x5056e080512055608722e086e1232082605322b126e082a0f1224052a086e", + "0x50126e125208600552086e0852086a0552086e0854080e0554086e0861085c", + "0x83708700542086e0850086a0537086e0849086505056e080512050c087349", + "0x575086e0800081d0500086e08051b05056e0805120505740805640551086e", + "0x6e0805120577087673086e125108610551086e087508700542086e080c086a", + "0x6e0879085e052b086e082b08130579086e087808220578086e087308200505", + "0x5c05056e080512057d087c7b086e1274082605747a126e08792b1224057908", + "0x8180126e127f0860057f086e087f086a057f086e087e080e057e086e084208", + "0x2e05056e0881083205056e0880082b05056e08052a05056e08051205830882", + "0x885085e0585086e0805540584086e08055605056e082e082e05056e087b08", + "0x80c0588086e08868712490587086e0805500586086e08858412520585086e", + "0x510512086e081208420513086e08130837057a086e087a08130589086e0888", + "0x86e08050005056e0883082b05056e080512058912137a0f0889086e088908", + "0x5056e080512058f8e128d8c8b126e128a137a0e73058a086e088a0875058a", + "0x837058b086e088b08130591086e089008780590086e08057705056e08052a", + "0x7a057b086e087b0879052e086e082e08790512086e08120842058c086e088c", + "0x56e0805120598089796086e1295087405959493920f6e087b2e91128c8b60", + "0x9c126e089b087e05056e089a087d059b9a126e0896087b0599086e08055605", + "0x6e089e991252059e086e089d0880059d086e0882087f05056e089c082e0582", + "0x8a2088405a2086e08a1085c05056e08a0088305a1a0126e089f0881059f08", + "0x9408420593086e089308370592086e0892081305a4086e08a3088505a3086e", + "0x86e0898080c05056e08051205a49493920f08a4086e08a408510594086e08", + "0x6e08a508510594086e089408420593086e089308370592086e0892081305a5", + "0x2e082e05056e087b082e05056e08052a05056e08051205a59493920f08a508", + "0x8a7a6125205a7086e08a7085e05a7086e08058605a6086e08055605056e08", + "0x8e081305ab086e08aa080c05aa086e08a8a9124905a9086e08055005a8086e", + "0x8e0f08ab086e08ab08510512086e08120842058f086e088f0837058e086e08", + "0x5056e082e082e05056e0842082b05056e087d088705056e08051205ab128f", + "0x82e082e05056e0877088705056e0805120505ad08056405ac086e087a0813", + "0x5ae086e08055605056e08052a05ac086e082b081305056e0842082b05056e", + "0x5b1086e08055005b0086e08afae125205af086e08af085e05af086e080588", + "0x86e0813083705ac086e08ac081305b3086e08b2080c05b2086e08b0b11249", + "0x8705056e08051205b31213ac0f08b3086e08b308510512086e081208420513", + "0x6e0805120505b508056405b4086e082b081305056e0861082b05056e085608", + "0x5605056e08052a05b4086e080f081305056e0861082b05056e082608870505", + "0x5005b8086e08b7b6125205b7086e08b7085e05b7086e08058905b6086e0805", + "0x5b4086e08b4081305bb086e08ba080c05ba086e08b8b9124905b9086e0805", + "0x1205bb1213b40f08bb086e08bb08510512086e081208420513086e08130837", + "0x6e08bd085e05bd086e08058605bc086e08055605056e080e088a05056e0805", + "0xc0080c05c0086e08bebf124905bf086e08055005be086e08bdbc125205bd08", + "0x8510512086e081208420565086e086508370560086e086008130597086e08", + "0x656012c1130f126e120805120805056e08050505971265600f0897086e0897", + "0x6470126e126a0860050f086e080f0813056a086e080e080e05056e08051205", + "0x51d086e08055605056e0864083205056e0870082b05056e080512051b08c2", + "0x522086e0805500520086e08611d12520561086e0861085e0561086e080554", + "0x86e08130837050f086e080f08130524086e085e080c055e086e0820221249", + "0x2b05056e080512052412130f0f0824086e082408510512086e081208420513", + "0x2a5c126e1226130f0e730526086e082608750526086e08050005056e081b08", + "0x6e082a08370556086e082e0878052e086e08057705056e08051205322b12c3", + "0x55c086e085c0813055052540e6e0856122a0e8b0512086e08120842052a08", + "0x537086e08055605056e0849088e05056e080512050c08c449086e1250088c", + "0x75086e080008840500086e0851085c05056e08420883055142126e08370881", + "0x86e085208420554086e08540837055c086e085c08130573086e0875088505", + "0x130577086e080c080c05056e080512057352545c0f0873086e087308510552", + "0x877086e087708510552086e085208420554086e08540837055c086e085c08", + "0x6e0879085e0579086e0805860578086e08055605056e080512057752545c0f", + "0x7b080c057b086e087a7412490574086e080550057a086e0879781252057908", + "0x8510512086e081208420532086e08320837052b086e082b0813057d086e08", + "0x7e086e08055605056e080e088a05056e080512057d12322b0f087d086e087d", + "0x81086e0805500580086e087f7e1252057f086e087f085e057f086e08058605", + "0x6e086508370560086e086008130584086e0883080c0583086e088081124905", + "0x6e120805128f05841265600f0884086e088408510512086e08120842056508", + "0x8910512086e081208130513086e080e089005056e080512050f08c50e1212", + "0x565086e086008920560086e08051b05056e080512051312120813086e0813", + "0xf08790505086e0805081305650f120865086e08650891050f086e080f0813", + "0x6a086e12650894056560126e08130f050e930513086e08130879050f086e08", + "0x6e08080837051b086e080e08960564086e086a089505056e080512057008c6", + "0x80f99051d086e081d0879051d64126e086408980512086e08120842050808", + "0x85e089b05056e080512052408c75e086e1222089a052220610e6e081d1b12", + "0x882052b086e08642a129c052a086e0826087805056e085c0887055c26126e", + "0x9d0520086e082008420561086e086108370560086e086008130532086e082b", + "0x6e0824089e05056e0864082e05056e08051205322061600f0832086e083208", + "0x82e089d0520086e082008420561086e086108370560086e08600813052e08", + "0x556086e0870089e05056e080e087d05056e080512052e2061600f082e086e", + "0x56086e0856089d0512086e081208420508086e080808370560086e08600813", + "0x420505086e08050837050f086e08120896050e086e08059f05561208600f08", + "0x65089a056560130e6e080e0f08050f99050e086e080e08790508086e080808", + "0x1b05056e081b0887051b64126e086a089b05056e080512057008c86a086e12", + "0x522086e082008a10520086e081d6112a00561086e08640878051d086e0805", + "0x512052260130e0822086e082208a20560086e086008420513086e08130837", + "0x5e08a20560086e086008420513086e08130837055e086e087008a305056e08", + "0x80e08a50505086e08050813050e086e08120812a4055e60130e085e086e08", + "0x5056e080512056508c960086e1213082605130f126e080e0512a6050e086e", + "0x70086e087008a9050f086e080f08130570086e086a08a8056a086e086008a7", + "0x1b086e0805aa0564086e08055605056e0865088705056e08051205700f1208", + "0x6e081d6112490561086e080550051d086e081b641252051b086e081b085e05", + "0x5220f120822086e082208a9050f086e080f08130522086e082008ab052008", + "0xaf0565086e08059f0560086e080f08ae0513086e080e0880050f086e0805ac", + "0x560086e086008b10565086e0865087905056e087008b005706a126e081208", + "0x522086e08051b05056e0805120520611d0eca1b64126e12136065080513b2", + "0x5c086e085e08b40526086e081b08420524086e08640837055e086e082208b3", + "0x8420524086e081d0837052a086e082008b605056e0805120505cb08056405", + "0x8cc32086e122b08b8052b086e085c08b7055c086e082a08b40526086e0861", + "0x86e085408bb0554086e08566a12ba0556086e083208b905056e080512052e", + "0x55226240e0852086e085208bc0526086e082608420524086e082408370552", + "0x8420524086e082408370550086e082e08bd05056e086a08b005056e080512", + "0xf08cd0e12126e12080512be055026240e0850086e085008bc0526086e0826", + "0x813086e081308910512086e081208130513086e080e089005056e08051205", + "0x86e080f08130565086e086008920560086e08051b05056e08051205131212", + "0x5056e080512051208ce08086e120508bf05650f120865086e08650891050f", + "0x6e080512050f08080f086e080f08cf050f086e080e0897050e086e080808c0", + "0x6e086508cf0565086e086008d00560086e08121312490513086e0805500505", + "0x505251050f2b5251050f050e120805505251050f2b5251050f706508086508", + "0xf0e120805565251050f20202452510560d208054905120c0512d10e120805", + "0xe201b52510fd51208055e05122020050ed41208055c52510e2452510ed313", + "0xd80560086508d70805490512640512d60e120805615251" + ], + "sierra_program_debug_info": { + "type_names": [ + [0, "RangeCheck"], + [1, "Unit"], + [2, "Tuple"], + [3, "core::panics::Panic"], + [4, "Array"], + [5, "Tuple>"], + [6, "core::panics::PanicResult::<((),)>"], + [7, "core::result::Result::<(), core::array::Array::>"], + [8, "StorageAddress"], + [9, "StorageBaseAddress"], + [10, "u64"], + [ + 11, + "product::MultiplyNumsContract::__member_module_product::ContractMemberState" + ], + [ + 12, + "Tuple" + ], + [ + 13, + "core::panics::PanicResult::<(product::MultiplyNumsContract::__member_module_product::ContractMemberState, ())>" + ], + [14, "u32"], + [15, "Tuple"], + [16, "core::panics::PanicResult::<(core::integer::u32,)>"], + [17, "product::MultiplyNumsContract::ContractState"], + [18, "Tuple"], + [ + 19, + "core::panics::PanicResult::<(product::MultiplyNumsContract::ContractState, ())>" + ], + [20, "Snapshot>"], + [21, "core::array::Span::"], + [22, "Tuple>"], + [23, "Tuple"], + [ + 24, + "core::panics::PanicResult::<(product::MultiplyNumsContract::ContractState, core::integer::u32)>" + ], + [25, "BuiltinCosts"], + [26, "System"], + [ + 27, + "core::panics::PanicResult::<(core::array::Span::,)>" + ], + [28, "core::option::Option::"], + [29, "felt252"], + [30, "Box"], + [31, "core::option::Option::>"], + [32, "GasBuiltin"] + ], + "libfunc_names": [ + [0, "revoke_ap_tracking"], + [1, "withdraw_gas"], + [2, "branch_align"], + [3, "struct_deconstruct>"], + [4, "enable_ap_tracking"], + [5, "store_temp"], + [6, "array_snapshot_pop_front"], + [ + 7, + "enum_init>, 0>" + ], + [8, "store_temp>>"], + [ + 9, + "store_temp>>" + ], + [10, "jump"], + [11, "struct_construct"], + [ + 12, + "enum_init>, 1>" + ], + [ + 13, + "enum_match>>" + ], + [14, "unbox"], + [15, "rename"], + [16, "store_temp"], + [17, "function_call"], + [18, "enum_match>"], + [19, "struct_construct>"], + [20, "disable_ap_tracking"], + [21, "drop>>"], + [22, "drop>"], + [23, "drop"], + [24, "array_new"], + [ + 25, + "felt252_const<7733229381460288120802334208475838166080759535023995805565484692595>" + ], + [26, "array_append"], + [27, "struct_construct"], + [28, "struct_construct>>"], + [ + 29, + "enum_init,)>, 1>" + ], + [30, "store_temp"], + [31, "store_temp"], + [ + 32, + "store_temp,)>>" + ], + [33, "get_builtin_costs"], + [34, "store_temp"], + [35, "withdraw_gas_all"], + [ + 36, + "struct_construct" + ], + [37, "struct_construct"], + [38, "store_temp"], + [ + 39, + "function_call" + ], + [ + 40, + "enum_match>" + ], + [ + 41, + "struct_deconstruct>" + ], + [42, "drop"], + [43, "snapshot_take"], + [44, "rename"], + [45, "u32_to_felt252"], + [46, "snapshot_take>"], + [47, "drop>"], + [48, "struct_construct>>"], + [ + 49, + "enum_init,)>, 0>" + ], + [50, "felt252_const<375233589013918064796019>"], + [51, "drop"], + [ + 52, + "felt252_const<485748461484230571791265682659113160264223489397539653310998840191492914>" + ], + [ + 53, + "felt252_const<485748461484230571791265682659113160264223489397539653310998840191492913>" + ], + [54, "drop>"], + [55, "function_call"], + [ + 56, + "enum_match>" + ], + [57, "drop>"], + [58, "u32_try_from_felt252"], + [59, "enum_init, 0>"], + [60, "store_temp>"], + [61, "enum_init, 1>"], + [62, "function_call"], + [63, "enum_match>"], + [64, "struct_deconstruct>"], + [65, "struct_deconstruct"], + [66, "dup"], + [ + 67, + "function_call" + ], + [ + 68, + "enum_match>" + ], + [ + 69, + "struct_deconstruct>" + ], + [ + 70, + "struct_construct>" + ], + [ + 71, + "enum_init, 0>" + ], + [ + 72, + "store_temp>" + ], + [ + 73, + "enum_init, 1>" + ], + [74, "u32_const<0>"], + [ + 75, + "struct_construct>" + ], + [ + 76, + "enum_init, 0>" + ], + [ + 77, + "store_temp>" + ], + [ + 78, + "enum_init, 1>" + ], + [79, "u32_wide_mul"], + [80, "store_temp"], + [ + 81, + "function_call::try_into>" + ], + [82, "struct_construct>"], + [83, "enum_init, 0>"], + [84, "store_temp>"], + [85, "felt252_const<155785504327651875780457110017927835511>"], + [86, "enum_init, 1>"], + [ + 87, + "storage_base_address_const<1195503354841289263908693606374238119068019599734980372857665784709941612631>" + ], + [88, "storage_address_from_base"], + [ + 89, + "snapshot_take" + ], + [ + 90, + "drop" + ], + [91, "store_temp"], + [92, "storage_write_syscall"], + [ + 93, + "enum_init>, 0>" + ], + [ + 94, + "store_temp>>" + ], + [ + 95, + "enum_init>, 1>" + ], + [ + 96, + "function_call::unwrap_syscall>" + ], + [97, "enum_match>"], + [98, "struct_deconstruct>"], + [ + 99, + "struct_construct>" + ], + [ + 100, + "enum_init, 0>" + ], + [ + 101, + "store_temp>" + ], + [ + 102, + "enum_init, 1>" + ], + [103, "downcast"], + [ + 104, + "enum_match>>" + ], + [105, "struct_construct>"], + [106, "enum_init, 0>"], + [107, "store_temp>"], + [108, "enum_init, 1>"] + ], + "user_func_names": [ + [ + 0, + "product::MultiplyNumsContract::__wrapper__MultiplyNumsContract__multiply" + ], + [1, "product::MultiplyNumsContract::__wrapper__constructor"], + [2, "core::integer::Felt252TryIntoU32::try_into"], + [3, "product::MultiplyNumsContract::MultiplyNumsContract::multiply"], + [4, "product::MultiplyNumsContract::constructor"], + [5, "core::integer::U32Mul::mul"], + [ + 6, + "product::MultiplyNumsContract::__member_module_product::InternalContractMemberStateImpl::write" + ], + [ + 7, + "core::integer::DowncastableIntTryInto::::try_into" + ], + [8, "core::starknet::SyscallResultTraitImpl::<()>::unwrap_syscall"] + ] + }, + "contract_class_version": "0.1.0", + "entry_points_by_type": { + "EXTERNAL": [ + { + "selector": "0x39674cadb16109ec414e371cc8f04eb60a540c52d4880cadb49dfafb8d79797", + "function_idx": 0 + } + ], + "L1_HANDLER": [], + "CONSTRUCTOR": [ + { + "selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194", + "function_idx": 1 + } + ] + }, + "abi": [ + { + "type": "impl", + "name": "MultiplyNumsContract", + "interface_name": "product::IMultiplyNumsContract" + }, + { + "type": "interface", + "name": "product::IMultiplyNumsContract", + "items": [ + { + "type": "function", + "name": "multiply", + "inputs": [ + { "name": "first_num", "type": "core::integer::u32" }, + { "name": "second_num", "type": "core::integer::u32" } + ], + "outputs": [{ "type": "core::integer::u32" }], + "state_mutability": "external" + } + ] + }, + { "type": "constructor", "name": "constructor", "inputs": [] }, + { + "type": "event", + "name": "product::MultiplyNumsContract::Event", + "kind": "enum", + "variants": [] + } + ] +} diff --git a/configs/genesis-assets/genesis.json b/configs/genesis-assets/genesis.json index e21addbaaa..1323f59002 100644 --- a/configs/genesis-assets/genesis.json +++ b/configs/genesis-assets/genesis.json @@ -11,6 +11,10 @@ [ "0x04c6d6cf894f8bc96bb9c525e6853e5483177841f7388f74a46cfda6f028c755", "0x06910afff92798e29b93649f7627cd34a852e0f9b04b52c51850b438a730224e" + ], + [ + "0x015b7c90a4fab33812dc9e2ef525a329e22e591327f006f826b71271099637cd", + "0x07155e1b37c5c35dcad0017562066f7d80b610af83dadf925064efcb2ea6b86a" ] ], "contract_classes": [ @@ -83,6 +87,13 @@ "path": "genesis-assets/OpenZeppelinAccountCairoOne.casm.json", "version": 1 } + ], + [ + "0x015b7c90a4fab33812dc9e2ef525a329e22e591327f006f826b71271099637cd", + { + "path": "genesis-assets/MultiplyNumsContract.casm.json", + "version": 1 + } ] ], "contracts": [ @@ -125,6 +136,10 @@ [ "0x041a78e741e5af2fec34b695679bc6891742439f7afb8484ecd7766661ad02bf", "0x07b3e05f48f0c69e4a65ce5e076a66271a527aff2c34ce1083ec6e1526997a69" + ], + [ + "0x123", + "0x015b7c90a4fab33812dc9e2ef525a329e22e591327f006f826b71271099637cd" ] ], "predeployed_accounts": [ diff --git a/configs/index.json b/configs/index.json index f5fd10a6cd..e2d2ed974c 100644 --- a/configs/index.json +++ b/configs/index.json @@ -15,7 +15,7 @@ }, { "name": "genesis.json", - "sha3_256": "c35bcc00b70f9d6bfee3416fae0a0ec1e7a1fffe01c3d7fbb660db93a7bed87a" + "sha3_256": "bca50369e627d1101e4d693fa6fac9bee6cce2889b324dee3204179a3960ef5e" }, { "name": "NoValidateAccount.casm.json", @@ -52,6 +52,14 @@ { "name": "OpenZeppelinAccountCairoOne.sierra.json", "sha3_256": "145fdf2668cf6c36deb295ceea57c6005e43dd7b36be26d020928d1cc3462b5e" + }, + { + "name": "MultiplyNumsContract.sierra.json", + "sha3_256": "88830cfbad634684d6f18f22b1ade94c9340cffdabd5f3d74bb10ed212389064" + }, + { + "name": "MultiplyNumsContract.casm.json", + "sha3_256": "113105426f708ab01988f19aa020120c87b82682a94f06b40340ff05c4044f89" } ] } diff --git a/crates/client/eth-client/src/config.rs b/crates/client/eth-client/src/config.rs index abb47b5770..3b2aabb1ef 100644 --- a/crates/client/eth-client/src/config.rs +++ b/crates/client/eth-client/src/config.rs @@ -66,6 +66,8 @@ pub struct HttpProviderConfig { pub rpc_endpoint: String, #[serde(default, skip_serializing_if = "Option::is_none")] pub tx_poll_interval_ms: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub gas_price_poll_ms: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -90,7 +92,7 @@ fn default_private_key() -> String { impl Default for HttpProviderConfig { fn default() -> Self { - Self { rpc_endpoint: default_rpc_endpoint(), tx_poll_interval_ms: None } + Self { rpc_endpoint: default_rpc_endpoint(), tx_poll_interval_ms: None, gas_price_poll_ms: None } } } @@ -100,6 +102,20 @@ impl Default for EthereumProviderConfig { } } +impl EthereumProviderConfig { + pub fn rpc_endpoint(&self) -> &String { + match self { + Self::Http(config) => &config.rpc_endpoint, + } + } + + pub fn gas_price_poll_ms(&self) -> Option { + match self { + Self::Http(config) => config.gas_price_poll_ms, + } + } +} + impl Default for LocalWalletConfig { fn default() -> Self { Self { chain_id: default_chain_id(), private_key: default_private_key() } diff --git a/crates/client/l1-gas-price/Cargo.toml b/crates/client/l1-gas-price/Cargo.toml new file mode 100644 index 0000000000..5a8daabcf8 --- /dev/null +++ b/crates/client/l1-gas-price/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "mc-l1-gas-price" +version = "0.1.0" +description = "L1 gas price fetching library." +homepage = "https://github.com/keep-starknet-strange/madara" +edition = "2021" +license = "MIT" +publish = false +repository = "https://github.com/keep-starknet-strange/madara" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = { workspace = true } +ethers = { workspace = true } +futures = { workspace = true } +log = { workspace = true } +mc-eth-client = { workspace = true } +mp-starknet-inherent = { workspace = true } +reqwest = { workspace = true } +serde = { workspace = true } +tokio = { workspace = true } diff --git a/crates/client/l1-gas-price/src/lib.rs b/crates/client/l1-gas-price/src/lib.rs new file mode 100644 index 0000000000..48466dad9f --- /dev/null +++ b/crates/client/l1-gas-price/src/lib.rs @@ -0,0 +1,2 @@ +mod types; +pub mod worker; diff --git a/crates/client/l1-gas-price/src/types.rs b/crates/client/l1-gas-price/src/types.rs new file mode 100644 index 0000000000..d867acb28d --- /dev/null +++ b/crates/client/l1-gas-price/src/types.rs @@ -0,0 +1,50 @@ +use serde::{Deserialize, Serialize}; + +// Took this code from alloy-rs and did some modifications. This type can be removed once we've +// migrated to alloy-rs from ethers-rs. +// FIXME: 1528 + +/// Response type for `eth_feeHistory` +#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct FeeHistory { + /// An array of block base fees per gas. + /// This includes the next block after the newest of the returned range, + /// because this value can be derived from the newest block. Zeroes are + /// returned for pre-EIP-1559 blocks. + /// + /// # Note + /// + /// Empty list is skipped only for compatibility with Erigon and Geth. + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub base_fee_per_gas: Vec, + /// An array of block gas used ratios. These are calculated as the ratio + /// of `gasUsed` and `gasLimit`. + /// + /// # Note + /// + /// The `Option` is only for compatibility with Erigon and Geth. + pub gas_used_ratio: Vec, + /// An array of block base fees per blob gas. This includes the next block after the newest + /// of the returned range, because this value can be derived from the newest block. Zeroes + /// are returned for pre-EIP-4844 blocks. + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub base_fee_per_blob_gas: Vec, + /// An array of block blob gas used ratios. These are calculated as the ratio of gasUsed and + /// gasLimit. + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub blob_gas_used_ratio: Vec, + /// Lowest number block of the returned range. + pub oldest_block: String, + /// An (optional) array of effective priority fee per gas data points from a single + /// block. All zeroes are returned if the block is empty. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub reward: Option>>, +} + +#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] +pub struct EthRpcResponse { + pub jsonrpc: String, + pub id: u64, + pub result: T, +} diff --git a/crates/client/l1-gas-price/src/worker.rs b/crates/client/l1-gas-price/src/worker.rs new file mode 100644 index 0000000000..2198c7d639 --- /dev/null +++ b/crates/client/l1-gas-price/src/worker.rs @@ -0,0 +1,105 @@ +use std::num::NonZeroU128; +use std::sync::Arc; +use std::time::Duration; + +use anyhow::{format_err, Result}; +use ethers::utils::__serde_json::json; +use futures::lock::Mutex; +use mc_eth_client::config::EthereumClientConfig; +use mp_starknet_inherent::L1GasPrices; +use tokio::time::sleep; + +use crate::types::{EthRpcResponse, FeeHistory}; + +const DEFAULT_GAS_PRICE_POLL_MS: u64 = 10_000; + +pub async fn run_worker(config: Arc, gas_price: Arc>, infinite_loop: bool) { + let rpc_endpoint = config.provider.rpc_endpoint().clone(); + let client = reqwest::Client::new(); + let poll_time = config.provider.gas_price_poll_ms().unwrap_or(DEFAULT_GAS_PRICE_POLL_MS); + + loop { + match update_gas_price(rpc_endpoint.clone(), &client, gas_price.clone()).await { + Ok(_) => log::trace!("Updated gas prices"), + Err(e) => log::error!("Failed to update gas prices: {:?}", e), + } + + let gas_price = gas_price.lock().await; + let last_update_timestamp = gas_price.last_update_timestamp; + drop(gas_price); + let current_timestamp = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .expect("Failed to get current timestamp") + .as_millis(); + + if current_timestamp - last_update_timestamp > 10 * poll_time as u128 { + panic!( + "Gas prices have not been updated for {} ms. Last update was at {}", + current_timestamp - last_update_timestamp, + last_update_timestamp + ); + } + + if !infinite_loop { + break; + } + + sleep(Duration::from_millis(poll_time)).await; + } +} + +async fn update_gas_price( + rpc_endpoint: String, + client: &reqwest::Client, + gas_price: Arc>, +) -> Result<()> { + let fee_history: EthRpcResponse = client + .post(rpc_endpoint.clone()) + .json(&json!({ + "jsonrpc": "2.0", + "method": "eth_feeHistory", + "params": [300, "latest", []], + "id": 83 + })) + .send() + .await? + .json() + .await?; + + // The RPC responds with 301 elements for some reason. It's also just safer to manually + // take the last 300. We choose 300 to get average gas caprice for last one hour (300 * 12 sec block + // time). + let (_, blob_fee_history_one_hour) = + fee_history.result.base_fee_per_blob_gas.split_at(fee_history.result.base_fee_per_blob_gas.len() - 300); + + let avg_blob_base_fee = blob_fee_history_one_hour.iter().sum::() / blob_fee_history_one_hour.len() as u128; + + let eth_gas_price = u128::from_str_radix( + fee_history + .result + .base_fee_per_gas + .last() + .ok_or(format_err!("Failed to get last element of `base_fee_per_gas`"))? + .trim_start_matches("0x"), + 16, + )?; + + // TODO: fetch this from the oracle + let eth_strk_price = 2425; + + let mut gas_price = gas_price.lock().await; + gas_price.eth_l1_gas_price = + NonZeroU128::new(eth_gas_price).ok_or(format_err!("Failed to convert `eth_gas_price` to NonZeroU128"))?; + gas_price.eth_l1_data_gas_price = NonZeroU128::new(avg_blob_base_fee) + .ok_or(format_err!("Failed to convert `eth_l1_data_gas_price` to NonZeroU128"))?; + gas_price.strk_l1_gas_price = NonZeroU128::new(eth_gas_price.saturating_mul(eth_strk_price)) + .ok_or(format_err!("Failed to convert `strk_l1_gas_price` to NonZeroU128"))?; + gas_price.strk_l1_data_gas_price = NonZeroU128::new(avg_blob_base_fee.saturating_mul(eth_strk_price)) + .ok_or(format_err!("Failed to convert `strk_l1_data_gas_price` to NonZeroU128"))?; + gas_price.last_update_timestamp = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH)?.as_millis(); + // explicitly dropping gas price here to avoid long waits when fetching the value + // on the inherent side which would increase block time + drop(gas_price); + + Ok(()) +} diff --git a/crates/client/l1-messages/src/worker.rs b/crates/client/l1-messages/src/worker.rs index 938a0192ff..d77c8cf906 100644 --- a/crates/client/l1-messages/src/worker.rs +++ b/crates/client/l1-messages/src/worker.rs @@ -17,15 +17,15 @@ use crate::contract::parse_handle_l1_message_transaction; use crate::error::L1MessagesWorkerError; fn create_event_listener( - config: EthereumClientConfig, + config: Arc, ) -> Result>, mc_eth_client::error::Error> { let address = config.contracts.core_contract()?; - let provider: Provider = config.provider.try_into()?; + let provider: Provider = config.provider.clone().try_into()?; Ok(StarknetMessagingEvents::new(address, Arc::new(provider))) } pub async fn run_worker( - config: EthereumClientConfig, + config: Arc, client: Arc, pool: Arc

, backend: Arc>, diff --git a/crates/client/rpc/src/errors.rs b/crates/client/rpc/src/errors.rs index 9b98272ac8..37da44f656 100644 --- a/crates/client/rpc/src/errors.rs +++ b/crates/client/rpc/src/errors.rs @@ -111,6 +111,7 @@ impl From for StarknetRpcApiError { SimulationError::ContractNotFound => StarknetRpcApiError::ContractNotFound, SimulationError::TransactionExecutionFailed(e) => StarknetRpcApiError::ContractError(e.into()), SimulationError::MissingL1GasUsage | SimulationError::StateDiff => StarknetRpcApiError::InternalServerError, + SimulationError::EstimateFeeFailed(_) => StarknetRpcApiError::InternalServerError, } } } diff --git a/crates/client/rpc/src/lib.rs b/crates/client/rpc/src/lib.rs index f8427451ba..4065b278a3 100644 --- a/crates/client/rpc/src/lib.rs +++ b/crates/client/rpc/src/lib.rs @@ -206,6 +206,18 @@ where Ok(starknet_block.header().block_number) } + + fn get_current_resource_price(&self) -> Result { + let current_prices = + self.client.runtime_api().current_l1_gas_prices(self.client.info().best_hash).map_err(|e| { + log::error!("Failed to get current L1 gas prices: {e}"); + StarknetRpcApiError::InternalServerError + })?; + Ok(ResourcePrice { + price_in_wei: current_prices.eth_l1_gas_price.get().into(), + price_in_fri: current_prices.strk_l1_gas_price.get().into(), + }) + } } /// Taken from https://github.com/paritytech/substrate/blob/master/client/rpc/src/author/mod.rs#L78 @@ -843,8 +855,7 @@ where new_root: Felt252Wrapper::from(self.backend.temporary_global_state_root_getter()).into(), timestamp: starknet_block.header().block_timestamp, sequencer_address: Felt252Wrapper::from(starknet_block.header().sequencer_address).into(), - // TODO: real value - l1_gas_price: ResourcePrice { price_in_fri: Default::default(), price_in_wei: Default::default() }, + l1_gas_price: self.get_current_resource_price()?, starknet_version: starknet_version.to_string(), }; @@ -942,18 +953,7 @@ where let fee_estimates = self.estimate_fee(substrate_block_hash, transactions, SimulationFlags::from(simulation_flags))?; - let estimates = fee_estimates - .into_iter() - // FIXME: https://github.com/keep-starknet-strange/madara/issues/329 - .map(|x| FeeEstimate { - gas_price: FieldElement::from(10u128), - gas_consumed: FieldElement::from(x.1), - overall_fee: FieldElement::from(x.0), - unit: PriceUnit::Wei, - }) - .collect(); - - Ok(estimates) + Ok(fee_estimates) } /// Estimate the L2 fee of a message sent on L1 @@ -1000,14 +1000,7 @@ where let fee_estimate = self.do_estimate_message_fee(substrate_block_hash, transaction)?; - let estimate = FeeEstimate { - gas_price: fee_estimate.0.try_into().map_err(|_| StarknetRpcApiError::InternalServerError)?, - gas_consumed: FieldElement::from(fee_estimate.2), - overall_fee: FieldElement::from(fee_estimate.1), - unit: PriceUnit::Wei, - }; - - Ok(estimate) + Ok(fee_estimate) } /// Get the details of a transaction by a given block id and index. @@ -1090,8 +1083,7 @@ where timestamp: starknet_block.header().block_timestamp, sequencer_address: Felt252Wrapper::from(starknet_block.header().sequencer_address).into(), transactions, - // TODO: fill real prices - l1_gas_price: ResourcePrice { price_in_fri: Default::default(), price_in_wei: Default::default() }, + l1_gas_price: self.get_current_resource_price()?, starknet_version: starknet_version.to_string(), }; @@ -1360,8 +1352,7 @@ where let pending_block = PendingBlockWithTxHashes { transactions: transaction_hashes, - // TODO: fill real prices - l1_gas_price: ResourcePrice { price_in_fri: Default::default(), price_in_wei: Default::default() }, + l1_gas_price: self.get_current_resource_price()?, parent_hash: latest_block_header.hash().into(), sequencer_address: Felt252Wrapper::from(latest_block_header.sequencer_address).into(), starknet_version: latest_block_header.protocol_version.to_string(), @@ -1381,8 +1372,7 @@ where let pending_block = PendingBlockWithTxs { transactions, - // TODO: fill real prices - l1_gas_price: ResourcePrice { price_in_fri: Default::default(), price_in_wei: Default::default() }, + l1_gas_price: self.get_current_resource_price()?, parent_hash: latest_block_header.hash().into(), sequencer_address: Felt252Wrapper::from(latest_block_header.sequencer_address).into(), starknet_version: latest_block_header.protocol_version.to_string(), diff --git a/crates/client/rpc/src/runtime_api.rs b/crates/client/rpc/src/runtime_api.rs index 69aeac8f95..ca903c170b 100644 --- a/crates/client/rpc/src/runtime_api.rs +++ b/crates/client/rpc/src/runtime_api.rs @@ -19,6 +19,7 @@ use sp_blockchain::HeaderBackend; use sp_runtime::traits::Block as BlockT; use starknet_api::core::{ContractAddress, EntryPointSelector}; use starknet_api::transaction::{Calldata, Event, TransactionHash}; +use starknet_core::types::FeeEstimate; use crate::{Starknet, StarknetRpcApiError}; @@ -53,11 +54,12 @@ where &self, block_hash: B::Hash, message: L1HandlerTransaction, - ) -> RpcApiResult<(u128, u128, u128)> { - Ok(self.client.runtime_api().estimate_message_fee(block_hash, message).map_err(|e| { + ) -> RpcApiResult { + Ok((&self.client.runtime_api().estimate_message_fee(block_hash, message).map_err(|e| { error!("Runtime Api error: {e}"); StarknetRpcApiError::InternalServerError })???) + .into()) } pub fn do_get_tx_execution_outcome( @@ -104,13 +106,19 @@ where block_hash: B::Hash, transactions: Vec, simulation_flags: SimulationFlags, - ) -> RpcApiResult> { - Ok(self.client.runtime_api().estimate_fee(block_hash, transactions, simulation_flags).map_err( - |e: ApiError| { + ) -> RpcApiResult> { + let fee_estimates = self + .client + .runtime_api() + .estimate_fee(block_hash, transactions, simulation_flags) + .map_err(|e: ApiError| { error!("Request parameters error: {e}"); StarknetRpcApiError::InternalServerError - }, - )???) + })??? + .iter() + .map(|estimate| estimate.into()) + .collect(); + Ok(fee_estimates) } pub fn get_best_block_hash(&self) -> B::Hash { @@ -173,7 +181,8 @@ where ) -> RpcApiResult { // Simulate a single User Transaction // So the result should have single element in vector (index 0) - self.client + let simulation = self + .client .runtime_api() .simulate_transactions(block_hash, vec![tx], simulations_flags) .map_err(|e| { @@ -183,13 +192,13 @@ where .map_err(|e| { error!("Failed to call function: {:#?}", e); StarknetRpcApiError::from(e) - })?? + })? .swap_remove(0) - .1 .map_err(|e| { error!("Failed to simulate User Transaction: {:?}", e); StarknetRpcApiError::InternalServerError - }) + })?; + Ok(simulation.execution_info) } fn simulate_l1_tx( diff --git a/crates/client/rpc/src/trace_api.rs b/crates/client/rpc/src/trace_api.rs index 86a2a0ca6e..65d1ba24d1 100644 --- a/crates/client/rpc/src/trace_api.rs +++ b/crates/client/rpc/src/trace_api.rs @@ -26,8 +26,8 @@ use sp_runtime::traits::Block as BlockT; use starknet_api::transaction::TransactionHash; use starknet_core::types::{ BlockId, BroadcastedTransaction, DeclareTransactionTrace, DeployAccountTransactionTrace, ExecuteInvocation, - FeeEstimate, InvokeTransactionTrace, L1HandlerTransactionTrace, PriceUnit, RevertedInvocation, - SimulatedTransaction, SimulationFlag, StateDiff, TransactionTrace, TransactionTraceWithHash, + InvokeTransactionTrace, L1HandlerTransactionTrace, RevertedInvocation, SimulatedTransaction, SimulationFlag, + StateDiff, TransactionTrace, TransactionTraceWithHash, }; use starknet_ff::FieldElement; @@ -101,28 +101,18 @@ where })?; let mut simulated_transactions = vec![]; - for (tx_type, (state_diff, res)) in tx_types.into_iter().zip(res.into_iter().flatten()) { - match res { - Ok(tx_exec_info) => { - let state_diff = blockifier_to_rpc_state_diff_types(state_diff) + for (tx_type, simulation_result) in tx_types.into_iter().zip(res.into_iter()) { + match simulation_result { + Ok(simulation) => { + let state_diff = blockifier_to_rpc_state_diff_types(simulation.state_diff) .map_err(|_| StarknetRpcApiError::InternalServerError)?; - let transaction_trace = tx_execution_infos_to_tx_trace(tx_type, &tx_exec_info, Some(state_diff))?; - - let gas_consumed = - tx_exec_info.execute_call_info.as_ref().map(|x| x.execution.gas_consumed).unwrap_or_default(); - let overall_fee = tx_exec_info.actual_fee.0 as u64; - // TODO: Shouldn't the gas price be taken from the block header instead? - let gas_price = if gas_consumed > 0 { overall_fee / gas_consumed } else { 0 }; + let transaction_trace = + tx_execution_infos_to_tx_trace(tx_type, &simulation.execution_info, Some(state_diff))?; simulated_transactions.push(SimulatedTransaction { transaction_trace, - fee_estimation: FeeEstimate { - gas_consumed: FieldElement::from(gas_consumed), - gas_price: FieldElement::from(gas_price), - overall_fee: FieldElement::from(overall_fee), - unit: PriceUnit::Wei, - }, + fee_estimation: simulation.fee_estimate.into(), }); } Err(e) => { diff --git a/crates/node/Cargo.toml b/crates/node/Cargo.toml index c575676022..58948f4c73 100644 --- a/crates/node/Cargo.toml +++ b/crates/node/Cargo.toml @@ -80,6 +80,7 @@ madara-runtime = { workspace = true, features = ["std"] } mc-commitment-state-diff = { workspace = true } mc-db = { workspace = true } mc-eth-client = { workspace = true } +mc-l1-gas-price = { workspace = true } mc-l1-messages = { workspace = true } mc-mapping-sync = { workspace = true } mc-rpc = { workspace = true } @@ -95,7 +96,7 @@ mc-genesis-data-provider = { workspace = true } mp-block = { workspace = true } mp-digest-log = { workspace = true } mp-felt = { workspace = true } -mp-sequencer-address = { workspace = true, features = ["client"] } +mp-starknet-inherent = { workspace = true, features = ["client"] } # Starknet blockifier = { workspace = true } diff --git a/crates/node/src/commands/run.rs b/crates/node/src/commands/run.rs index 3de375a100..c5612d2131 100644 --- a/crates/node/src/commands/run.rs +++ b/crates/node/src/commands/run.rs @@ -1,3 +1,6 @@ +use std::path::PathBuf; + +use clap::ValueHint::FilePath; use madara_runtime::SealingMode; use sc_cli::{Result, RpcMethods, RunCmd, SubstrateCli}; use sc_service::BasePath; @@ -29,6 +32,12 @@ impl From for SealingMode { } } +#[derive(Debug, Copy, Clone, PartialEq, clap::ValueEnum)] +pub enum SettlementLayer { + /// Use Ethereum core contract + Ethereum, +} + #[derive(Clone, Debug, clap::Args)] pub struct ExtendedRunCmd { #[clap(flatten)] @@ -37,6 +46,18 @@ pub struct ExtendedRunCmd { /// Choose sealing method. #[clap(long, value_enum, ignore_case = true)] pub sealing: 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 + /// + /// If `settlement` is `Some` and `settlement_conf` is `None` we will try to read one at + /// `/settlement_conf.json`. If it's not there, an error will be + /// returned. + #[clap(long, value_hint = FilePath, requires = "settlement")] + pub settlement_conf: Option, } impl ExtendedRunCmd { @@ -58,9 +79,26 @@ pub fn run_node(mut cli: Cli) -> Result<()> { } let runner = cli.create_runner(&cli.run.base)?; + let settlement_config: Option<(SettlementLayer, PathBuf)> = match cli.run.settlement { + Some(SettlementLayer::Ethereum) => { + let settlement_conf = match cli.run.clone().settlement_conf { + Some(settlement_conf) => settlement_conf, + None => panic!("Settlement layer Ethereum requires a settlement configuration"), + }; + + log::info!("Initializing settlement client with layer: {:?}", SettlementLayer::Ethereum); + 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(); - service::new_full(config, sealing).map_err(sc_cli::Error::Service) + service::new_full(config, sealing, settlement_config).map_err(sc_cli::Error::Service) }) } diff --git a/crates/node/src/genesis_block.rs b/crates/node/src/genesis_block.rs index ffeb791da1..18de998a88 100644 --- a/crates/node/src/genesis_block.rs +++ b/crates/node/src/genesis_block.rs @@ -60,8 +60,10 @@ fn construct_genesis_block(state_root: Block::Hash, state_version let mut digest = vec![]; let block = StarknetBlock::try_new( - // TODO: Decide what values to put here - // This is just filler values for now + // The genesis block values don't really matter because when you start a node, + // you need to disable fees completely to do the setup process. So we need some blocks + // of txs without any fees. And the 1st block will set the correct L1 gas prices through + // inherents. Header { l1_gas_price: unsafe { GasPrices { diff --git a/crates/node/src/service.rs b/crates/node/src/service.rs index 423bbaabe8..08a016cce0 100644 --- a/crates/node/src/service.rs +++ b/crates/node/src/service.rs @@ -8,14 +8,17 @@ use std::time::Duration; use futures::channel::mpsc; use futures::future; use futures::future::BoxFuture; +use futures::lock::Mutex; use futures::prelude::*; use madara_runtime::opaque::Block; use madara_runtime::{self, Hash, RuntimeApi, SealingMode, StarknetHasher}; +use mc_eth_client::config::EthereumClientConfig; use mc_genesis_data_provider::OnDiskGenesisConfig; use mc_mapping_sync::MappingSyncWorker; use mc_storage::overrides_handle; -use mp_sequencer_address::{ - InherentDataProvider as SeqAddrInherentDataProvider, DEFAULT_SEQUENCER_ADDRESS, SEQ_ADDR_STORAGE_KEY, +use mp_starknet_inherent::{ + InherentDataProvider as StarknetInherentDataProvider, InherentError as StarknetInherentError, L1GasPrices, + StarknetInherentData, DEFAULT_SEQUENCER_ADDRESS, SEQ_ADDR_STORAGE_KEY, }; use prometheus_endpoint::Registry; use sc_basic_authorship::ProposerFactory; @@ -34,6 +37,7 @@ use sp_api::ConstructRuntimeApi; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use sp_offchain::STORAGE_PREFIX; +use crate::commands::SettlementLayer; use crate::genesis_block::MadaraGenesisBlockBuilder; use crate::import_queue::{ build_aura_queue_grandpa_pipeline, build_manual_seal_queue_pipeline, BlockImportPipeline, @@ -174,7 +178,11 @@ where /// # Arguments /// /// - `cache`: whether more information should be cached when storing the block in the database. -pub fn new_full(config: Configuration, sealing: SealingMode) -> Result { +pub fn new_full( + config: Configuration, + sealing: SealingMode, + settlement_config: Option<(SettlementLayer, PathBuf)>, +) -> Result { let sc_service::PartialComponents { client, backend, @@ -316,6 +324,43 @@ pub fn new_full(config: Configuration, sealing: SealingMode) -> Result Result Result FeeTokenAddresses; /// Returns fee estimate - fn estimate_fee(transactions: Vec, simulation_flags: SimulationFlags) -> Result, SimulationError>, InternalSubstrateError>; + fn estimate_fee(transactions: Vec, simulation_flags: SimulationFlags) -> Result, SimulationError>, InternalSubstrateError>; /// Returns message fee estimate - fn estimate_message_fee(message: L1HandlerTransaction) -> Result, InternalSubstrateError>; + fn estimate_message_fee(message: L1HandlerTransaction) -> Result, InternalSubstrateError>; /// Simulates single L1 Message and returns its trace fn simulate_message(message: L1HandlerTransaction, simulation_flags: SimulationFlags) -> Result, InternalSubstrateError>; /// Simulates transactions and returns their trace - fn simulate_transactions(transactions: Vec, simulation_flags: SimulationFlags) -> Result, SimulationError>, InternalSubstrateError>; + fn simulate_transactions(transactions: Vec, simulation_flags: SimulationFlags) -> Result, InternalSubstrateError>; /// Filters extrinsic transactions to return only Starknet transactions /// /// To support runtime upgrades, the client must be unaware of the specific extrinsic @@ -88,6 +90,8 @@ sp_api::decl_runtime_apis! { 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; + /// Get current L1 gas prices + fn current_l1_gas_prices() -> L1GasPrices; } pub trait ConvertTransactionRuntimeApi { diff --git a/crates/pallets/starknet/src/lib.rs b/crates/pallets/starknet/src/lib.rs index e30c381720..65295bc386 100644 --- a/crates/pallets/starknet/src/lib.rs +++ b/crates/pallets/starknet/src/lib.rs @@ -58,7 +58,7 @@ use std::collections::BTreeSet; use std::ops::Deref; use std::str::from_utf8_unchecked; -use blockifier::blockifier::block::{BlockInfo, GasPrices}; +use blockifier::blockifier::block::BlockInfo; use blockifier::context::{BlockContext, ChainInfo, FeeTokenAddresses, TransactionContext}; use blockifier::execution::call_info::CallInfo; use blockifier::execution::contract_class::ContractClass; @@ -79,7 +79,7 @@ use mp_block::{Block as StarknetBlock, Header as StarknetHeader}; use mp_chain_id::MADARA_CHAIN_ID; use mp_digest_log::MADARA_ENGINE_ID; use mp_felt::Felt252Wrapper; -use mp_sequencer_address::{InherentError, InherentType, DEFAULT_SEQUENCER_ADDRESS, INHERENT_IDENTIFIER}; +use mp_starknet_inherent::{InherentError, InherentType, STARKNET_INHERENT_IDENTIFIER}; use mp_storage::{StarknetStorageSchemaVersion, PALLET_STARKNET_SCHEMA}; use mp_transactions::execution::{ execute_l1_handler_transaction, run_non_revertible_transaction, run_revertible_transaction, @@ -118,6 +118,7 @@ macro_rules! log { #[frame_support::pallet] pub mod pallet { + use mp_starknet_inherent::L1GasPrices; use super::*; @@ -131,9 +132,6 @@ pub mod pallet { pub trait Config: frame_system::Config { /// The block time type TimestampProvider: Time; - /// The gas price - #[pallet::constant] - type L1GasPrices: Get; /// A configuration for base priority of unsigned transactions. /// /// This is exposed so that it can be tuned for particular runtime, when @@ -167,7 +165,7 @@ pub mod pallet { impl Hooks> for Pallet { /// The block is being finalized. fn on_finalize(_n: BlockNumberFor) { - assert!(SeqAddrUpdate::::take(), "Sequencer address must be set for the block"); + assert!(InherentUpdate::::take(), "Sequencer address must be set for the block"); // Create a new Starknet block and store it. >::store_block(UniqueSaturatedInto::::unique_saturated_into( @@ -300,11 +298,17 @@ pub mod pallet { #[pallet::getter(fn sequencer_address)] pub type SequencerAddress = StorageValue<_, ContractAddress, ValueQuery>; + /// Current sequencer address. + #[pallet::storage] + #[pallet::unbounded] + #[pallet::getter(fn current_l1_gas_prices)] + pub type CurrentL1GasPrice = StorageValue<_, L1GasPrices, ValueQuery>; + /// Ensure the sequencer address was updated for this block. #[pallet::storage] #[pallet::unbounded] - #[pallet::getter(fn seq_addr_update)] - pub type SeqAddrUpdate = StorageValue<_, bool, ValueQuery>; + #[pallet::getter(fn inherent_update)] + pub type InherentUpdate = StorageValue<_, bool, ValueQuery>; /// Information about processed L1 Messages /// Based on Nonce value. @@ -413,7 +417,7 @@ pub mod pallet { strk_fee_token_address: self.strk_fee_token_address, eth_fee_token_address: self.eth_fee_token_address, }); - SeqAddrUpdate::::put(true); + InherentUpdate::::put(true); ChainIdStorage::::put(self.chain_id) } @@ -463,20 +467,22 @@ pub mod pallet { /// The dispatch origin for this call must be `Inherent`. #[pallet::call_index(0)] #[pallet::weight((0, DispatchClass::Mandatory))] - pub fn set_sequencer_address(origin: OriginFor, addr: [u8; 32]) -> DispatchResult { + pub fn set_starknet_inherent_data(origin: OriginFor, data: InherentType) -> DispatchResult { ensure_none(origin)?; - // The `SeqAddrUpdate` storage item is initialized to `true` in the genesis build. In + // The `InherentUpdate` storage item is initialized to `true` in the genesis build. In // block 1 we skip the storage update check, and the `on_finalize` hook // updates the storage item to `false`. Initializing the storage item with // `false` causes the `on_finalize` hook to panic. if UniqueSaturatedInto::::unique_saturated_into(frame_system::Pallet::::block_number()) > 1 { - assert!(!SeqAddrUpdate::::exists(), "Sequencer address can be updated only once in the block"); + assert!(!InherentUpdate::::exists(), "Inherent data can be updated only once in the block"); } - let addr = StarkFelt::new(addr).map_err(|_| Error::::SequencerAddressNotValid)?; + let addr = StarkFelt::new(data.sequencer_address).map_err(|_| Error::::SequencerAddressNotValid)?; let addr = ContractAddress(addr.try_into().map_err(|_| Error::::SequencerAddressNotValid)?); SequencerAddress::::put(addr); - SeqAddrUpdate::::put(true); + CurrentL1GasPrice::::put(data.l1_gas_price); + + InherentUpdate::::put(true); Ok(()) } @@ -699,18 +705,23 @@ pub mod pallet { impl ProvideInherent for Pallet { type Call = Call; type Error = InherentError; - const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; + const INHERENT_IDENTIFIER: InherentIdentifier = STARKNET_INHERENT_IDENTIFIER; fn create_inherent(data: &InherentData) -> Option { let inherent_data = data - .get_data::(&INHERENT_IDENTIFIER) - .expect("Sequencer address inherent data not correctly encoded") - .unwrap_or(DEFAULT_SEQUENCER_ADDRESS); - Some(Call::set_sequencer_address { addr: inherent_data }) + .get_data::(&STARKNET_INHERENT_IDENTIFIER) + .expect("Starknet inherent data not correctly encoded") + // if we run in manual sealing, then it goes into the default case + // it's usually used in test cases. + .unwrap_or_default(); + + // TODO: should we have a safety check here that the L1 gas price isn't + // very old? We've this check in the l1-gas-prices worker already. + Some(Call::set_starknet_inherent_data { data: inherent_data }) } fn is_inherent(call: &Self::Call) -> bool { - matches!(call, Call::set_sequencer_address { .. }) + matches!(call, Call::set_starknet_inherent_data { .. }) } } @@ -849,7 +860,7 @@ impl Pallet { let sequencer_address = Self::sequencer_address(); let chain_id = ChainId(Self::chain_id_str()); - let gas_prices = T::L1GasPrices::get(); + let gas_prices = Self::current_l1_gas_prices().into(); BlockContext::new_unchecked( &BlockInfo { @@ -995,7 +1006,7 @@ impl Pallet { let protocol_version = T::ProtocolVersion::get(); let extra_data = None; - let l1_gas_price = T::L1GasPrices::get(); + let l1_gas_price = Self::current_l1_gas_prices().into(); let block = StarknetBlock::try_new( StarknetHeader::new( diff --git a/crates/pallets/starknet/src/simulations.rs b/crates/pallets/starknet/src/simulations.rs index 3454365d11..99f4ea5cf5 100644 --- a/crates/pallets/starknet/src/simulations.rs +++ b/crates/pallets/starknet/src/simulations.rs @@ -1,31 +1,32 @@ +use blockifier::blockifier::block::GasPrices; use blockifier::context::BlockContext; use blockifier::state::cached_state::{CachedState, CommitmentStateDiff, GlobalContractCache}; use blockifier::state::state_api::State; use blockifier::transaction::account_transaction::AccountTransaction; use blockifier::transaction::errors::TransactionExecutionError; -use blockifier::transaction::objects::TransactionExecutionInfo; +use blockifier::transaction::objects::{FeeType, GasVector, HasRelatedFeeType, TransactionExecutionInfo}; use blockifier::transaction::transaction_execution::Transaction; use blockifier::transaction::transactions::{ExecutableTransaction, L1HandlerTransaction}; use frame_support::storage; use mp_simulations::{ - InternalSubstrateError, ReExecutionResult, SimulationError, SimulationFlags, TransactionSimulationResult, + FeeEstimate, InternalSubstrateError, ReExecutionResult, SimulationError, SimulationFlags, TransactionSimulation, + TransactionSimulationResult, }; use mp_transactions::execution::{ commit_transactional_state, execute_l1_handler_transaction, run_non_revertible_transaction, - run_revertible_transaction, MutRefState, SetArbitraryNonce, + run_revertible_transaction, CheckFeeBounds, MutRefState, SetArbitraryNonce, }; -use sp_core::Get; use sp_runtime::DispatchError; use starknet_api::transaction::TransactionVersion; use crate::blockifier_state_adapter::BlockifierStateAdapter; -use crate::{log, Config, Error, Pallet}; +use crate::{log, Config, Pallet}; impl Pallet { pub fn estimate_fee( transactions: Vec, simulation_flags: &SimulationFlags, - ) -> Result, SimulationError>, InternalSubstrateError> { + ) -> Result, SimulationError>, InternalSubstrateError> { storage::transactional::with_transaction(|| { storage::TransactionOutcome::Rollback(Result::<_, DispatchError>::Ok(Self::estimate_fee_inner( transactions, @@ -41,17 +42,16 @@ impl Pallet { fn estimate_fee_inner( transactions: Vec, simulation_flags: &SimulationFlags, - ) -> Result, SimulationError> { + ) -> Result, SimulationError> { let transactions_len = transactions.len(); let block_context = Self::get_block_context(); let mut state = BlockifierStateAdapter::::default(); - let fee_res_iterator = transactions - .into_iter() - .map(|tx| match Self::execute_account_transaction(&tx, &mut state, &block_context, simulation_flags) { - Ok(execution_info) => { + let fee_res_iterator = transactions.into_iter().map(|tx| { + match Self::execute_account_transaction(&tx, &mut state, &block_context, simulation_flags) { + Ok(mut execution_info) => { if !execution_info.is_reverted() { - Ok(execution_info) + Self::execution_info_to_fee_estimate(&tx, &mut execution_info, &block_context) } else { log!( debug, @@ -67,21 +67,12 @@ impl Pallet { log!(debug, "Transaction execution failed during fee estimation: {:?}", e); Err(SimulationError::from(e)) } - }) - .map(|exec_info_res| { - exec_info_res.map(|exec_info| { - exec_info - .actual_resources - .0 - .get("l1_gas_usage") - .ok_or_else(|| DispatchError::from(Error::::MissingL1GasUsage)) - .map(|l1_gas_usage| (exec_info.actual_fee.0, *l1_gas_usage)) - }) - }); + } + }); let mut fees = Vec::with_capacity(transactions_len); for fee_res in fee_res_iterator { - let res = fee_res?.map_err(|_| SimulationError::StateDiff)?; + let res = fee_res?; fees.push(res); } @@ -91,8 +82,7 @@ impl Pallet { pub fn simulate_transactions( transactions: Vec, simulation_flags: &SimulationFlags, - ) -> Result, SimulationError>, InternalSubstrateError> - { + ) -> Result, InternalSubstrateError> { storage::transactional::with_transaction(|| { storage::TransactionOutcome::Rollback(Result::<_, DispatchError>::Ok(Self::simulate_transactions_inner( transactions, @@ -104,33 +94,53 @@ impl Pallet { InternalSubstrateError::FailedToCreateATransactionalStorageExecution }) } + fn simulate_transactions_inner( transactions: Vec, simulation_flags: &SimulationFlags, - ) -> Result, SimulationError> { + ) -> Vec { let block_context = Self::get_block_context(); let mut state = BlockifierStateAdapter::::default(); - let tx_execution_results: Vec<(CommitmentStateDiff, TransactionSimulationResult)> = transactions + let tx_execution_results = transactions .into_iter() .map(|tx| { - let res = Self::execute_account_transaction_with_state_diff( - &tx, - &mut state, - &block_context, - simulation_flags, - )?; - - let result = res.0.map_err(|e| { - log::error!("Transaction execution failed during simulation: {e}"); - SimulationError::from(e) - }); + // In order to produce a state diff for this specific tx we execute on a transactional state + let mut transactional_state = + CachedState::new(MutRefState::new(&mut state), GlobalContractCache::new(1)); + + let exec_info = + Self::execute_account_transaction(&tx, &mut transactional_state, &block_context, simulation_flags) + .map_err(|e| { + log!(debug, "Failed to execute transaction: {:?}", e); + SimulationError::from(e) + }); + + let mut exec_info = match exec_info { + Ok(exec_info) => exec_info, + Err(e) => return Err(e), + }; + + let state_diff = transactional_state.to_state_diff(); + // Once the state diff of this tx is generated, we apply those changes on the original state + // so that next txs being simulated are ontop of this one (avoid nonce error) + match commit_transactional_state(transactional_state) { + Ok(_) => (), + Err(e) => { + log::error!("Failed to commit state changes: {:?}", e); + return Err(SimulationError::from(e)); + } + }; - Ok((res.1, result)) + let fee_estimate = match Self::execution_info_to_fee_estimate(&tx, &mut exec_info, &block_context) { + Ok(fee_estimate) => fee_estimate, + Err(e) => return Err(e), + }; + Ok(TransactionSimulation { fee_estimate, execution_info: exec_info, state_diff }) }) - .collect::, SimulationError>>()?; + .collect(); - Ok(tx_execution_results) + tx_execution_results } pub fn simulate_message( @@ -164,7 +174,7 @@ impl Pallet { pub fn estimate_message_fee( message: L1HandlerTransaction, - ) -> Result, InternalSubstrateError> { + ) -> Result, InternalSubstrateError> { storage::transactional::with_transaction(|| { storage::TransactionOutcome::Rollback(Result::<_, DispatchError>::Ok(Self::estimate_message_fee_inner( message, @@ -176,10 +186,11 @@ impl Pallet { }) } - fn estimate_message_fee_inner(message: L1HandlerTransaction) -> Result<(u128, u128, u128), SimulationError> { + fn estimate_message_fee_inner(message: L1HandlerTransaction) -> Result { let mut cached_state = Self::init_cached_state(); + let fee_type = message.fee_type(); - let tx_execution_infos = match message.execute(&mut cached_state, &Self::get_block_context(), true, true) { + let mut tx_execution_info = match message.execute(&mut cached_state, &Self::get_block_context(), true, true) { Ok(execution_info) if !execution_info.is_reverted() => Ok(execution_info), Err(e) => { log!( @@ -201,11 +212,14 @@ impl Pallet { } }?; - if let Some(l1_gas_usage) = tx_execution_infos.actual_resources.0.get("l1_gas_usage") { - Ok((T::L1GasPrices::get().eth_l1_gas_price.into(), tx_execution_infos.actual_fee.0 as u128, *l1_gas_usage)) - } else { - Err(SimulationError::MissingL1GasUsage) - } + let current_l1_gas_price: GasPrices = Self::current_l1_gas_prices().into(); + Self::from_tx_info_and_gas_price( + &mut tx_execution_info, + ¤t_l1_gas_price, + fee_type, + None, + &Self::get_block_context(), + ) } pub fn re_execute_transactions( @@ -239,21 +253,18 @@ impl Pallet { Ok::<(), SimulationError>(()) })?; + let simulation_flags = + SimulationFlags { charge_fee: !Self::is_transaction_fee_disabled(), ..Default::default() }; let execution_infos = transactions_to_trace .iter() .map(|tx| { let mut transactional_state = CachedState::new(MutRefState::new(&mut state), GlobalContractCache::new(1)); - let res = Self::execute_transaction( - tx, - &mut transactional_state, - &block_context, - &SimulationFlags::default(), - ) - .map_err(|e| { - log::error!("Failed to reexecute a tx: {}", e); - SimulationError::from(e) - }); + let res = Self::execute_transaction(tx, &mut transactional_state, &block_context, &simulation_flags) + .map_err(|e| { + log::error!("Failed to reexecute a tx: {}", e); + SimulationError::from(e) + }); let res = res .map(|r| if with_state_diff { (r, Some(transactional_state.to_state_diff())) } else { (r, None) }); @@ -373,28 +384,25 @@ impl Pallet { } } - fn execute_account_transaction_with_state_diff( + fn execution_info_to_fee_estimate( transaction: &AccountTransaction, - state: &mut S, + execution_info: &mut TransactionExecutionInfo, block_context: &BlockContext, - simulation_flags: &SimulationFlags, - ) -> Result<(Result, CommitmentStateDiff), SimulationError> - { - // In order to produce a state diff for this specific tx we execute on a transactional state - let mut transactional_state = CachedState::new(MutRefState::new(state), GlobalContractCache::new(1)); - - let result = - Self::execute_account_transaction(transaction, &mut transactional_state, block_context, simulation_flags); - - let state_diff = transactional_state.to_state_diff(); - // Once the state diff of this tx is generated, we apply those changes on the original state - // so that next txs being simulated are ontop of this one (avoid nonce error) - commit_transactional_state(transactional_state).map_err(|e| { - log::error!("Failed to commit state changes: {:?}", e); - SimulationError::from(e) - })?; - - Ok((result, state_diff)) + ) -> Result { + let tx_context = block_context.to_tx_context(transaction); + let gas_vector = match transaction.clone() { + AccountTransaction::Declare(tx) => tx.estimate_minimal_gas_vector(&tx_context)?, + AccountTransaction::DeployAccount(tx) => tx.estimate_minimal_gas_vector(&tx_context)?, + AccountTransaction::Invoke(tx) => tx.estimate_minimal_gas_vector(&tx_context)?, + }; + let current_l1_gas_price: GasPrices = Self::current_l1_gas_prices().into(); + Self::from_tx_info_and_gas_price( + execution_info, + ¤t_l1_gas_price, + transaction.fee_type(), + Some(gas_vector), + block_context, + ) } fn execute_message( @@ -405,3 +413,53 @@ impl Pallet { execute_l1_handler_transaction(transaction, state, block_context) } } + +// Took inspiration from here - https://github.com/eqlabs/pathfinder/blob/4a18125cae2c8fb1284e9e8fd23acf5d5bcfde18/crates/executor/src/types.rs#L41-L41 +impl Pallet { + /// Computes fee estimate from the transaction execution information. + /// + /// `TransactionExecutionInfo` contains two related fields: + /// - `TransactionExecutionInfo::actual_fee` is the overall cost of the transaction (in WEI/FRI) + /// - `TransactionExecutionInfo::da_gas` is the gas usage for _data availability_. + /// + /// The problem is that we have to return both `gas_usage` and + /// `data_gas_usage` but we don't directly have the value of `gas_usage` + /// from the execution info, so we have to calculate that from other + /// fields. + fn from_tx_info_and_gas_price( + tx_info: &mut TransactionExecutionInfo, + gas_prices: &GasPrices, + fee_type: FeeType, + minimal_l1_gas_amount_vector: Option, + block_context: &BlockContext, + ) -> Result { + let gas_price = gas_prices.get_gas_price_by_fee_type(&fee_type).get(); + let data_gas_price = gas_prices.get_data_gas_price_by_fee_type(&fee_type).get(); + if tx_info.actual_fee.0 == 0 { + // fee is not calculated by default for L1 handler transactions and if max_fee + // is zero, we have to do that explicitly + tx_info.actual_fee = + match blockifier::fee::fee_utils::calculate_tx_fee(&tx_info.actual_resources, block_context, &fee_type) + { + Ok(fee) => fee, + Err(e) => { + log!(debug, "Failed to calculate tx fee: {:?}", e); + return Err(SimulationError::from(e)); + } + }; + } + let data_gas_consumed = tx_info.da_gas.l1_data_gas; + let data_gas_fee = data_gas_consumed.saturating_mul(data_gas_price); + let gas_consumed = tx_info.actual_fee.0.saturating_sub(data_gas_fee) / gas_price.max(1); + + let (minimal_gas_consumed, minimal_data_gas_consumed) = + minimal_l1_gas_amount_vector.map(|v| (v.l1_gas, v.l1_data_gas)).unwrap_or_default(); + + let gas_consumed = gas_consumed.max(minimal_gas_consumed); + let data_gas_consumed = data_gas_consumed.max(minimal_data_gas_consumed); + let overall_fee = + gas_consumed.saturating_mul(gas_price).saturating_add(data_gas_consumed.saturating_mul(data_gas_price)); + + Ok(FeeEstimate { gas_consumed, gas_price, data_gas_consumed, data_gas_price, overall_fee, fee_type }) + } +} diff --git a/crates/pallets/starknet/src/tests/block.rs b/crates/pallets/starknet/src/tests/block.rs index c1517a9ecb..a2d40e8889 100644 --- a/crates/pallets/starknet/src/tests/block.rs +++ b/crates/pallets/starknet/src/tests/block.rs @@ -5,7 +5,7 @@ use blockifier::blockifier::block::GasPrices; use blockifier::transaction::objects::FeeType; use frame_support::assert_ok; use mp_digest_log::{ensure_log, find_starknet_block}; -use mp_sequencer_address::DEFAULT_SEQUENCER_ADDRESS; +use mp_starknet_inherent::DEFAULT_SEQUENCER_ADDRESS; use starknet_api::block::{BlockNumber, BlockTimestamp}; use starknet_api::core::{ChainId, ContractAddress, Nonce, PatriciaKey}; use starknet_api::hash::StarkFelt; @@ -14,7 +14,7 @@ use super::mock::default_mock::*; use super::mock::*; use crate::tests::constants::ETH_FEE_TOKEN_ADDRESS; use crate::tests::get_invoke_dummy; -use crate::{SeqAddrUpdate, SequencerAddress}; +use crate::{InherentUpdate, SequencerAddress}; #[test] fn store_block_no_pending_transactions_works() { @@ -52,7 +52,7 @@ fn store_block_with_pending_transactions_works() { const BLOCK_NUMBER: u64 = 1; System::initialize(&BLOCK_NUMBER, &header.hash(), &Default::default()); - SeqAddrUpdate::::put(true); + InherentUpdate::::put(true); let default_addr = ContractAddress(PatriciaKey(StarkFelt::new(DEFAULT_SEQUENCER_ADDRESS).unwrap())); SequencerAddress::::put(default_addr); @@ -93,7 +93,7 @@ fn get_block_context_works() { const BLOCK_NUMBER: u64 = 1; System::initialize(&BLOCK_NUMBER, &header.hash(), &Default::default()); - SeqAddrUpdate::::put(true); + InherentUpdate::::put(true); let default_addr = ContractAddress(PatriciaKey(StarkFelt::new(DEFAULT_SEQUENCER_ADDRESS).unwrap())); SequencerAddress::::put(default_addr); diff --git a/crates/pallets/starknet/src/tests/deploy_account_tx.rs b/crates/pallets/starknet/src/tests/deploy_account_tx.rs index f3c7e96d9e..149d89f881 100644 --- a/crates/pallets/starknet/src/tests/deploy_account_tx.rs +++ b/crates/pallets/starknet/src/tests/deploy_account_tx.rs @@ -90,7 +90,7 @@ fn given_contract_run_deploy_account_tx_works() { data: EventData(vec![ contract_address.0.0, // From StarkFelt::try_from("0xdead").unwrap(), // To - StarkFelt::try_from("0xa17c").unwrap(), // Amount low + StarkFelt::try_from("0x2ee").unwrap(), // Amount low StarkFelt::from(0u128), // Amount high ]), }, @@ -98,7 +98,7 @@ fn given_contract_run_deploy_account_tx_works() { }; let events = Starknet::tx_events(tx_hash); - assert_eq!(expected_fee_transfer_event, events.last().unwrap().clone()); + pretty_assertions::assert_eq!(expected_fee_transfer_event, events.last().unwrap().clone()); }); } diff --git a/crates/pallets/starknet/src/tests/erc20.rs b/crates/pallets/starknet/src/tests/erc20.rs index 24cff1da01..d05c46b797 100644 --- a/crates/pallets/starknet/src/tests/erc20.rs +++ b/crates/pallets/starknet/src/tests/erc20.rs @@ -111,7 +111,7 @@ fn given_erc20_transfer_when_invoke_then_it_works() { data: EventData(vec![ sender_address.0 .0, // From StarkFelt::try_from("0xdead").unwrap(), // Sequencer address - StarkFelt::try_from("0x18ab0").unwrap(), // Amount low + StarkFelt::try_from("0x18ba").unwrap(), // Amount low StarkFelt::from(0u128), // Amount high ]), }, @@ -207,7 +207,7 @@ fn given_erc20_transfer_when_invoke_then_it_works() { data: EventData(vec![ sender_address.0 .0, // From StarkFelt::try_from("0xdead").unwrap(), // Sequencer address - StarkFelt::try_from("0x11652").unwrap(), // Amount low + StarkFelt::try_from("0xab4").unwrap(), // Amount low StarkFelt::from(0u128), // Amount high ]), }, diff --git a/crates/pallets/starknet/src/tests/invoke_tx.rs b/crates/pallets/starknet/src/tests/invoke_tx.rs index e6a8fb9ab5..baa0292918 100644 --- a/crates/pallets/starknet/src/tests/invoke_tx.rs +++ b/crates/pallets/starknet/src/tests/invoke_tx.rs @@ -92,7 +92,7 @@ fn given_hardcoded_contract_run_invoke_tx_then_it_works() { data: EventData(vec![ StarkFelt::try_from(BLOCKIFIER_ACCOUNT_ADDRESS).unwrap(), StarkFelt::try_from("0xdead").unwrap(), - StarkFelt::try_from("0xb932").unwrap(), + StarkFelt::try_from("0x2f8").unwrap(), StarkFelt::from(0u128), ]), }, @@ -132,7 +132,7 @@ fn given_hardcoded_contract_run_invoke_tx_then_event_is_emitted() { data: EventData(vec![ StarkFelt::try_from("0x01a3339ec92ac1061e3e0f8e704106286c642eaf302e94a582e5f95ef5e6b4d0").unwrap(), // From StarkFelt::try_from("0xdead").unwrap(), // To - StarkFelt::try_from("0xbc84").unwrap(), // Amount low + StarkFelt::try_from("0x2f8").unwrap(), // Amount low StarkFelt::from(0u128), // Amount high ]), }, diff --git a/crates/pallets/starknet/src/tests/mock/setup_mock.rs b/crates/pallets/starknet/src/tests/mock/setup_mock.rs index 67d06fed50..09455bf65e 100644 --- a/crates/pallets/starknet/src/tests/mock/setup_mock.rs +++ b/crates/pallets/starknet/src/tests/mock/setup_mock.rs @@ -12,9 +12,9 @@ macro_rules! mock_runtime { use sp_core::H256; use sp_runtime::traits::{BlakeTwo256, IdentityLookup}; use {crate as pallet_starknet, frame_system as system}; - use crate::{ SeqAddrUpdate, SequencerAddress}; + use crate::{ InherentUpdate, SequencerAddress}; use frame_support::traits::Hooks; - use mp_sequencer_address::DEFAULT_SEQUENCER_ADDRESS; + use mp_starknet_inherent::DEFAULT_SEQUENCER_ADDRESS; use mp_felt::Felt252Wrapper; use starknet_api::core::{PatriciaKey, ContractAddress}; use starknet_api::hash::StarkFelt; @@ -86,18 +86,17 @@ macro_rules! mock_runtime { type DisableNonceValidation = DisableNonceValidation; type ProtocolVersion = ProtocolVersion; type ProgramHash = ProgramHash; - type L1GasPrices = L1GasPrices; type ExecutionConstants = ExecutionConstants; } /// Run to block n. - /// The function will repeatedly create and run blocks until the block number is equal to `n`. - /// # Arguments - /// * `n` - The block number to run to. + /// The function will repeatedly create and run blocks until the block number is equal to `n`. + /// # Arguments + /// * `n` - The block number to run to. #[allow(unused)] pub(crate) fn run_to_block(n: u64) { for b in System::block_number()..=n { - SeqAddrUpdate::::put(true); + InherentUpdate::::put(true); System::set_block_number(b); Timestamp::set_timestamp(System::block_number() * 6_000); Starknet::on_finalize(b); @@ -107,7 +106,7 @@ macro_rules! mock_runtime { /// Setup initial block and sequencer address for unit tests. #[allow(unused)] pub(crate) fn basic_test_setup(n: u64) { - SeqAddrUpdate::::put(true); + InherentUpdate::::put(true); let default_addr = ContractAddress(PatriciaKey(StarkFelt::new(DEFAULT_SEQUENCER_ADDRESS).unwrap())); SequencerAddress::::put(default_addr); System::set_block_number(0); diff --git a/crates/pallets/starknet/src/tests/mod.rs b/crates/pallets/starknet/src/tests/mod.rs index 0e64d799b6..bc18e7cf0a 100644 --- a/crates/pallets/starknet/src/tests/mod.rs +++ b/crates/pallets/starknet/src/tests/mod.rs @@ -39,7 +39,7 @@ mod l1_message; mod query_tx; mod re_execute_transactions; mod send_message; -mod sequencer_address; +mod starknet_inherent; mod block; mod constants; diff --git a/crates/pallets/starknet/src/tests/query_tx.rs b/crates/pallets/starknet/src/tests/query_tx.rs index 79e4537582..a3c29f1a96 100644 --- a/crates/pallets/starknet/src/tests/query_tx.rs +++ b/crates/pallets/starknet/src/tests/query_tx.rs @@ -1,6 +1,7 @@ use blockifier::transaction::account_transaction::AccountTransaction; use frame_support::{assert_err, assert_ok}; use mp_simulations::SimulationFlags; +use mp_starknet_inherent::L1GasPrices; use mp_transactions::compute_hash::ComputeTransactionHash; use starknet_api::core::Nonce; use starknet_api::hash::StarkFelt; @@ -26,14 +27,22 @@ fn estimates_tx_fee_successfully_no_validate() { let txs = vec![tx_1, tx_2]; let fees = Starknet::estimate_fee(txs, &Default::default()).expect("estimate should not fail").unwrap(); + let default_l1_gas_price = L1GasPrices::default(); + + let fee_estimate = fees.get(0).unwrap(); + // fee calculations checks are done in the blockifier + assert!(fee_estimate.overall_fee > 0, "actual fee is missing"); + assert!( + fee_estimate.gas_price == default_l1_gas_price.eth_l1_gas_price.get(), + "gas price is the default value" + ); - let (actual, l1_gas_usage) = fees[0]; - assert!(actual > 0, "actual fee is missing"); - assert!(l1_gas_usage == 0, "using blobstream we shouldn't pay l1 fee"); - - let (actual, l1_gas_usage) = fees[1]; - assert!(actual > 0, "actual fee is missing"); - assert!(l1_gas_usage == 0, "using blobstream we shouldn't pay l1 fee"); + let fee_estimate = fees.get(1).unwrap(); + assert!(fee_estimate.overall_fee > 0, "actual fee is missing"); + assert!( + fee_estimate.gas_price == default_l1_gas_price.eth_l1_gas_price.get(), + "gas price is the default value" + ); }); } diff --git a/crates/pallets/starknet/src/tests/sequencer_address.rs b/crates/pallets/starknet/src/tests/sequencer_address.rs deleted file mode 100644 index 48dd006c39..0000000000 --- a/crates/pallets/starknet/src/tests/sequencer_address.rs +++ /dev/null @@ -1,120 +0,0 @@ -use frame_support::assert_ok; -use frame_support::traits::Hooks; -use mp_sequencer_address::{DEFAULT_SEQUENCER_ADDRESS, SEQ_ADDR_STORAGE_KEY}; -use starknet_api::core::{ContractAddress, PatriciaKey}; -use starknet_api::hash::StarkFelt; - -use super::mock::default_mock::*; -use super::mock::*; - -pub const GOOD_SEQUENCER_ADDRESS: [u8; 32] = - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 173]; - -pub const BAD_SEQUENCER_ADDRESS: [u8; 24] = - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 173]; - -#[test] -fn sequencer_address_is_set_to_default_when_not_provided() { - let mut ext = new_test_ext::(); - ext.execute_with(|| { - basic_test_setup(0); - assert_eq!( - Starknet::sequencer_address(), - ContractAddress(PatriciaKey(StarkFelt::new(GOOD_SEQUENCER_ADDRESS).unwrap())) - ); - }); -} - -#[test] -fn sequencer_address_is_set_to_default_when_provided_in_bad_format() { - let mut ext = new_test_ext::(); - ext.execute_with(|| { - basic_test_setup(0); - sp_io::offchain_index::set(SEQ_ADDR_STORAGE_KEY, &BAD_SEQUENCER_ADDRESS); - assert_eq!( - Starknet::sequencer_address(), - ContractAddress(PatriciaKey(StarkFelt::new(DEFAULT_SEQUENCER_ADDRESS).unwrap())) - ); - }); -} - -#[test] -fn sequencer_address_is_set_correctly() { - let mut ext = new_test_ext::(); - ext.execute_with(|| { - basic_test_setup(0); - sp_io::offchain_index::set(SEQ_ADDR_STORAGE_KEY, &GOOD_SEQUENCER_ADDRESS); - assert_eq!( - Starknet::sequencer_address(), - ContractAddress(PatriciaKey(StarkFelt::new(GOOD_SEQUENCER_ADDRESS).unwrap())) - ); - }); - ext.persist_offchain_overlay(); - let offchain_db = ext.offchain_db(); - assert_eq!(offchain_db.get(SEQ_ADDR_STORAGE_KEY), Some(GOOD_SEQUENCER_ADDRESS.to_vec())); -} - -#[test] -fn sequencer_address_is_set_only_once_per_block() { - let mut ext = new_test_ext::(); - ext.execute_with(|| { - basic_test_setup(0); - assert!(!Starknet::seq_addr_update()); - sp_io::offchain_index::set(SEQ_ADDR_STORAGE_KEY, &GOOD_SEQUENCER_ADDRESS); - assert_eq!( - Starknet::sequencer_address(), - ContractAddress(PatriciaKey(StarkFelt::new(GOOD_SEQUENCER_ADDRESS).unwrap())), - ); - sp_io::offchain_index::set(SEQ_ADDR_STORAGE_KEY, &DEFAULT_SEQUENCER_ADDRESS); - assert_eq!( - Starknet::sequencer_address(), - ContractAddress(PatriciaKey(StarkFelt::new(GOOD_SEQUENCER_ADDRESS).unwrap())), - ); - }); - ext.persist_offchain_overlay(); - let offchain_db = ext.offchain_db(); - assert_eq!(offchain_db.get(SEQ_ADDR_STORAGE_KEY), Some(DEFAULT_SEQUENCER_ADDRESS.to_vec())); -} - -#[test] -fn sequencer_address_has_not_been_updated() { - let mut ext = new_test_ext::(); - ext.execute_with(|| { - basic_test_setup(0); - sp_io::offchain_index::set(SEQ_ADDR_STORAGE_KEY, &GOOD_SEQUENCER_ADDRESS); - assert_eq!( - Starknet::sequencer_address(), - ContractAddress(PatriciaKey(StarkFelt::new(GOOD_SEQUENCER_ADDRESS).unwrap())), - ); - run_to_block(1); - assert!(!Starknet::seq_addr_update()); - }); -} - -#[test] -fn on_finalize_hook_takes_storage_update() { - let mut ext = new_test_ext::(); - ext.execute_with(|| { - System::set_block_number(1); - assert!(Starknet::seq_addr_update()); - Starknet::on_finalize(1); - assert!(!Starknet::seq_addr_update()); - }); -} - -#[test] -fn inherent_updates_storage() { - let mut ext = new_test_ext::(); - ext.execute_with(|| { - let none_origin = RuntimeOrigin::none(); - - System::set_block_number(0); - assert!(Starknet::seq_addr_update()); - Starknet::on_finalize(0); - assert!(!Starknet::seq_addr_update()); - - System::set_block_number(1); - assert_ok!(Starknet::set_sequencer_address(none_origin, DEFAULT_SEQUENCER_ADDRESS)); - assert!(Starknet::seq_addr_update()); - }); -} diff --git a/crates/pallets/starknet/src/tests/starknet_inherent.rs b/crates/pallets/starknet/src/tests/starknet_inherent.rs new file mode 100644 index 0000000000..4f479dc5e8 --- /dev/null +++ b/crates/pallets/starknet/src/tests/starknet_inherent.rs @@ -0,0 +1,98 @@ +use std::num::NonZeroU128; + +use frame_support::assert_ok; +use frame_support::traits::Hooks; +use mp_starknet_inherent::{L1GasPrices, StarknetInherentData, DEFAULT_SEQUENCER_ADDRESS}; +use starknet_api::core::{ContractAddress, PatriciaKey}; +use starknet_api::hash::StarkFelt; + +use super::mock::default_mock::*; +use super::mock::*; + +pub const GOOD_SEQUENCER_ADDRESS: [u8; 32] = + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 175]; + +fn get_dummy_l1_gas_price() -> L1GasPrices { + unsafe { + L1GasPrices { + eth_l1_gas_price: NonZeroU128::new_unchecked(123), + eth_l1_data_gas_price: NonZeroU128::new_unchecked(123), + strk_l1_gas_price: NonZeroU128::new_unchecked(123), + strk_l1_data_gas_price: NonZeroU128::new_unchecked(123), + last_update_timestamp: 2, + } + } +} + +#[test] +fn inherent_updates_storage() { + let mut ext = new_test_ext::(); + ext.execute_with(|| { + let none_origin = RuntimeOrigin::none(); + + System::set_block_number(0); + assert!(Starknet::inherent_update()); + Starknet::on_finalize(0); + assert!(!Starknet::inherent_update()); + + System::set_block_number(1); + let l1_gas_price = get_dummy_l1_gas_price(); + assert_ok!(Starknet::set_starknet_inherent_data( + none_origin, + StarknetInherentData { sequencer_address: GOOD_SEQUENCER_ADDRESS, l1_gas_price: l1_gas_price.clone() } + )); + assert!(Starknet::inherent_update()); + assert_eq!( + Starknet::sequencer_address(), + ContractAddress(PatriciaKey(StarkFelt::new(GOOD_SEQUENCER_ADDRESS).unwrap())) + ); + assert_eq!(Starknet::current_l1_gas_prices(), l1_gas_price); + }); +} + +#[test] +fn on_finalize_hook_takes_storage_update() { + let mut ext = new_test_ext::(); + ext.execute_with(|| { + System::set_block_number(1); + assert!(Starknet::inherent_update()); + Starknet::on_finalize(1); + assert!(!Starknet::inherent_update()); + }); +} + +#[test] +#[should_panic] +fn inherent_updates_only_once_per_block() { + let mut ext = new_test_ext::(); + ext.execute_with(|| { + let none_origin = RuntimeOrigin::none(); + + System::set_block_number(1); + assert!(Starknet::inherent_update()); + Starknet::on_finalize(1); + assert!(!Starknet::inherent_update()); + + // setting block number to 2 as we ignore "already updated" check + // for genesis blocks + System::set_block_number(2); + let l1_gas_price = get_dummy_l1_gas_price(); + + // setting it first time works + assert_ok!(Starknet::set_starknet_inherent_data( + none_origin.clone(), + StarknetInherentData { sequencer_address: DEFAULT_SEQUENCER_ADDRESS, l1_gas_price: l1_gas_price.clone() } + )); + assert_eq!(Starknet::current_l1_gas_prices(), l1_gas_price); + + let l1_gas_price_new = L1GasPrices { last_update_timestamp: 999, ..l1_gas_price }; + // setting it second time causes it to panic + let _ = Starknet::set_starknet_inherent_data( + none_origin, + StarknetInherentData { + sequencer_address: DEFAULT_SEQUENCER_ADDRESS, + l1_gas_price: l1_gas_price_new.clone(), + }, + ); + }); +} diff --git a/crates/primitives/sequencer-address/src/lib.rs b/crates/primitives/sequencer-address/src/lib.rs deleted file mode 100644 index 68296f7ddb..0000000000 --- a/crates/primitives/sequencer-address/src/lib.rs +++ /dev/null @@ -1,120 +0,0 @@ -//! The address of the account receiving the network fee -use sp_inherents::{InherentData, InherentIdentifier, IsFatalError}; -use thiserror::Error; - -/// The identifier for the `sequencer_address` inherent. -pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"seqaddr0"; - -/// Default value in case the sequencer address is not set. -pub const DEFAULT_SEQUENCER_ADDRESS: [u8; 32] = - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 173]; - -/// The storage key for the sequencer address value. -pub const SEQ_ADDR_STORAGE_KEY: &[u8] = b"starknet::seq_addr"; - -/// The inherent type for the sequencer address. -pub type InherentType = [u8; 32]; - -#[derive(Error, sp_core::RuntimeDebug)] -#[cfg_attr(feature = "parity-scale-codec", derive(parity_scale_codec::Encode, parity_scale_codec::Decode))] -/// Error types when working with the sequencer address. -pub enum InherentError { - /// Submitted address must be `[u8; 32]`. - #[error("Inherent decoding error")] - WrongAddressFormat, -} - -impl IsFatalError for InherentError { - fn is_fatal_error(&self) -> bool { - match self { - InherentError::WrongAddressFormat => true, - } - } -} - -/// Auxiliary trait to extract sequencer address inherent data. -pub trait SequencerAddressInherentData { - /// Get sequencer address inherent data. - fn sequencer_address_inherent_data(&self) -> Result, sp_inherents::Error>; -} - -impl SequencerAddressInherentData for InherentData { - fn sequencer_address_inherent_data(&self) -> Result, sp_inherents::Error> { - self.get_data(&INHERENT_IDENTIFIER) - } -} - -#[cfg(feature = "client")] -mod reexport_for_client_only { - use std::array::TryFromSliceError; - use std::boxed::Box; - - use parity_scale_codec::{Decode, Encode}; - - use super::*; - /// Helper function to convert storage value. - fn slice_to_arr(slice: &[u8]) -> Result<[u8; 32], TryFromSliceError> { - slice.try_into() - } - - impl InherentError { - /// Try to create an instance ouf of the given identifier and data. - // TODO: Bad name. This let think that it uses the trait TryFrom - pub fn try_from(id: &InherentIdentifier, mut data: &[u8]) -> Option { - if id == &INHERENT_IDENTIFIER { ::decode(&mut data).ok() } else { None } - } - } - - #[derive(Copy, Clone, Decode, Encode, sp_core::RuntimeDebug)] - /// The inherent data provider for sequencer address. - pub struct InherentDataProvider { - /// The sequencer address field. - pub sequencer_address: InherentType, - } - - impl InherentDataProvider { - /// Create `Self` using the given `addr`. - pub fn new(addr: InherentType) -> Self { - Self { sequencer_address: addr } - } - - /// Returns the sequencer address of this inherent data provider. - pub fn sequencer_address(&self) -> InherentType { - self.sequencer_address - } - } - - impl Default for InherentDataProvider { - fn default() -> InherentDataProvider { - InherentDataProvider { sequencer_address: DEFAULT_SEQUENCER_ADDRESS } - } - } - - impl TryFrom> for InherentDataProvider { - type Error = InherentError; - fn try_from(storage_val: Vec) -> Result { - match slice_to_arr(&storage_val) { - Ok(addr) => Ok(InherentDataProvider { sequencer_address: addr }), - Err(_) => Err(InherentError::WrongAddressFormat), - } - } - } - - #[async_trait::async_trait] - impl sp_inherents::InherentDataProvider for InherentDataProvider { - async fn provide_inherent_data(&self, inherent_data: &mut InherentData) -> Result<(), sp_inherents::Error> { - inherent_data.put_data(INHERENT_IDENTIFIER, &self.sequencer_address) - } - - async fn try_handle_error( - &self, - identifier: &InherentIdentifier, - error: &[u8], - ) -> Option> { - Some(Err(sp_inherents::Error::Application(Box::from(InherentError::try_from(identifier, error)?)))) - } - } -} - -#[cfg(feature = "client")] -pub use reexport_for_client_only::*; diff --git a/crates/primitives/simulations/Cargo.toml b/crates/primitives/simulations/Cargo.toml index c547f6475d..310c370632 100644 --- a/crates/primitives/simulations/Cargo.toml +++ b/crates/primitives/simulations/Cargo.toml @@ -21,4 +21,4 @@ scale-info = { workspace = true, optional = true } [features] parity-scale-codec = ["dep:parity-scale-codec"] -scale-info = ["dep:scale-info"] +scale-info = ["dep:scale-info", "blockifier/scale-info"] diff --git a/crates/primitives/simulations/src/lib.rs b/crates/primitives/simulations/src/lib.rs index bdf482e52c..8436a7649c 100644 --- a/crates/primitives/simulations/src/lib.rs +++ b/crates/primitives/simulations/src/lib.rs @@ -1,8 +1,8 @@ use blockifier::state::cached_state::CommitmentStateDiff; use blockifier::state::errors::StateError; -use blockifier::transaction::errors::TransactionExecutionError; -use blockifier::transaction::objects::TransactionExecutionInfo; -use starknet_core::types::{SimulationFlag, SimulationFlagForEstimateFee}; +use blockifier::transaction::errors::{TransactionExecutionError, TransactionFeeError}; +use blockifier::transaction::objects::{FeeType, TransactionExecutionInfo}; +use starknet_core::types::{PriceUnit, SimulationFlag, SimulationFlagForEstimateFee}; #[derive(Debug, Clone)] #[cfg_attr(feature = "scale-info", derive(scale_info::TypeInfo))] @@ -12,6 +12,7 @@ pub enum SimulationError { TransactionExecutionFailed(String), MissingL1GasUsage, StateDiff, + EstimateFeeFailed(String), } #[derive(Debug, Clone)] @@ -27,14 +28,29 @@ impl From for SimulationError { } } +impl From for SimulationError { + fn from(e: TransactionFeeError) -> SimulationError { + SimulationError::EstimateFeeFailed(e.to_string()) + } +} + impl From for SimulationError { fn from(_e: StateError) -> SimulationError { SimulationError::StateDiff } } +#[derive(Debug)] +#[cfg_attr(feature = "parity-scale-codec", derive(parity_scale_codec::Encode, parity_scale_codec::Decode))] +#[cfg_attr(feature = "scale-info", derive(scale_info::TypeInfo))] +pub struct TransactionSimulation { + pub execution_info: TransactionExecutionInfo, + pub state_diff: CommitmentStateDiff, + pub fee_estimate: FeeEstimate, +} + +pub type TransactionSimulationResult = Result; pub type ReExecutionResult = Result)>, SimulationError>; -pub type TransactionSimulationResult = Result; #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "parity-scale-codec", derive(parity_scale_codec::Encode, parity_scale_codec::Decode))] @@ -87,3 +103,38 @@ impl core::default::Default for SimulationFlags { Self { validate: true, charge_fee: true } } } + +// We can use `FeeEstimate` from starknet-rs once we upgrade to 0.13.1 +#[derive(Debug)] +#[cfg_attr(feature = "parity-scale-codec", derive(parity_scale_codec::Encode, parity_scale_codec::Decode))] +#[cfg_attr(feature = "scale-info", derive(scale_info::TypeInfo))] +pub struct FeeEstimate { + pub gas_consumed: u128, + pub gas_price: u128, + pub data_gas_consumed: u128, + pub data_gas_price: u128, + pub overall_fee: u128, + pub fee_type: FeeType, +} + +impl From<&FeeEstimate> for starknet_core::types::FeeEstimate { + fn from(fee_estimate: &FeeEstimate) -> Self { + Self { + gas_price: fee_estimate.gas_price.into(), + // this is a rough estimate because in reality the gas is split into data gas + // and execution gas. however, since we're not on 0.13.1 yet, we're using this + gas_consumed: fee_estimate.overall_fee.saturating_div(fee_estimate.gas_price).into(), + overall_fee: fee_estimate.overall_fee.into(), + unit: match fee_estimate.fee_type { + FeeType::Strk => PriceUnit::Fri, + FeeType::Eth => PriceUnit::Wei, + }, + } + } +} + +impl From for starknet_core::types::FeeEstimate { + fn from(fee_estimate: FeeEstimate) -> Self { + Self::from(&fee_estimate) + } +} diff --git a/crates/primitives/sequencer-address/Cargo.toml b/crates/primitives/starknet-inherent/Cargo.toml similarity index 81% rename from crates/primitives/sequencer-address/Cargo.toml rename to crates/primitives/starknet-inherent/Cargo.toml index 9bc659229a..be82c5bb8d 100644 --- a/crates/primitives/sequencer-address/Cargo.toml +++ b/crates/primitives/starknet-inherent/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "mp-sequencer-address" +name = "mp-starknet-inherent" version.workspace = true edition.workspace = true license = "MIT" @@ -11,6 +11,7 @@ repository = { workspace = true } targets = ["x86_64-unknown-linux-gnu"] [dependencies] +blockifier = { workspace = true } sp-core = { workspace = true } sp-inherents = { workspace = true } thiserror = { workspace = true } @@ -20,7 +21,9 @@ async-trait = { workspace = true, optional = true } parity-scale-codec = { workspace = true, features = [ "derive", ], optional = true } +scale-info = { workspace = true, optional = true } [features] parity-scale-codec = ["dep:parity-scale-codec"] +scale-info = ["dep:scale-info"] client = ["parity-scale-codec", "dep:async-trait"] diff --git a/crates/primitives/starknet-inherent/src/lib.rs b/crates/primitives/starknet-inherent/src/lib.rs new file mode 100644 index 0000000000..443fb64d04 --- /dev/null +++ b/crates/primitives/starknet-inherent/src/lib.rs @@ -0,0 +1,147 @@ +//! The address of the account receiving the network fee +use std::num::NonZeroU128; + +use blockifier::blockifier::block::GasPrices; +use sp_inherents::{InherentData, InherentIdentifier, IsFatalError}; +use thiserror::Error; + +/// The identifier for the `sequencer_address` inherent. +pub const STARKNET_INHERENT_IDENTIFIER: InherentIdentifier = *b"starknet"; + +/// Default value in case the sequencer address is not set. +pub const DEFAULT_SEQUENCER_ADDRESS: [u8; 32] = + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 173]; + +/// The storage key for the sequencer address value. +pub const SEQ_ADDR_STORAGE_KEY: &[u8] = b"starknet::seq_addr"; + +#[derive(Clone, sp_core::RuntimeDebug, PartialEq, Eq)] +#[cfg_attr(feature = "parity-scale-codec", derive(parity_scale_codec::Encode, parity_scale_codec::Decode))] +#[cfg_attr(feature = "scale-info", derive(scale_info::TypeInfo))] +pub struct L1GasPrices { + pub eth_l1_gas_price: NonZeroU128, // In wei. + pub strk_l1_gas_price: NonZeroU128, // In fri. + pub eth_l1_data_gas_price: NonZeroU128, // In wei. + pub strk_l1_data_gas_price: NonZeroU128, // In fri. + pub last_update_timestamp: u128, +} + +impl Default for L1GasPrices { + fn default() -> Self { + L1GasPrices { + eth_l1_gas_price: NonZeroU128::new(10).unwrap(), + strk_l1_gas_price: NonZeroU128::new(10).unwrap(), + eth_l1_data_gas_price: NonZeroU128::new(10).unwrap(), + strk_l1_data_gas_price: NonZeroU128::new(10).unwrap(), + last_update_timestamp: Default::default(), + } + } +} + +#[derive(Error, sp_core::RuntimeDebug)] +pub enum L1GasPriceError { + #[error("Failed to convert {0} with value {1} to NonZeroU128")] + GasPriceCoversionError(String, u128), +} + +impl From for GasPrices { + fn from(l1_gas_prices: L1GasPrices) -> Self { + GasPrices { + eth_l1_gas_price: l1_gas_prices.eth_l1_gas_price, + strk_l1_gas_price: l1_gas_prices.strk_l1_gas_price, + eth_l1_data_gas_price: l1_gas_prices.eth_l1_data_gas_price, + strk_l1_data_gas_price: l1_gas_prices.strk_l1_data_gas_price, + } + } +} + +/// Struct to hold all data for the Starknet inherent +#[derive(Clone, sp_core::RuntimeDebug, PartialEq, Eq)] +#[cfg_attr(feature = "parity-scale-codec", derive(parity_scale_codec::Encode, parity_scale_codec::Decode))] +#[cfg_attr(feature = "scale-info", derive(scale_info::TypeInfo))] +pub struct StarknetInherentData { + /// The sequencer address field. + pub sequencer_address: [u8; 32], + /// The L1 gas price + pub l1_gas_price: L1GasPrices, +} + +impl Default for StarknetInherentData { + fn default() -> Self { + StarknetInherentData { sequencer_address: DEFAULT_SEQUENCER_ADDRESS, l1_gas_price: Default::default() } + } +} + +/// The inherent type for the sequencer address. +pub type InherentType = StarknetInherentData; + +#[derive(Error, sp_core::RuntimeDebug)] +#[cfg_attr(feature = "parity-scale-codec", derive(parity_scale_codec::Encode, parity_scale_codec::Decode))] +/// Error types when working with the sequencer address. +pub enum InherentError { + /// Submitted address must be `[u8; 32]`. + #[error("Inherent decoding error")] + WrongAddressFormat, +} + +impl IsFatalError for InherentError { + fn is_fatal_error(&self) -> bool { + match self { + InherentError::WrongAddressFormat => true, + } + } +} + +#[cfg(feature = "client")] +mod reexport_for_client_only { + + use std::boxed::Box; + + use parity_scale_codec::{Decode, Encode}; + + use super::*; + + impl InherentError { + /// Try to create an instance ouf of the given identifier and data. + // TODO: Bad name. This let think that it uses the trait TryFrom + pub fn try_from(id: &InherentIdentifier, mut data: &[u8]) -> Option { + if id == &STARKNET_INHERENT_IDENTIFIER { ::decode(&mut data).ok() } else { None } + } + } + + #[derive(Clone, Decode, Encode, sp_core::RuntimeDebug)] + /// The inherent data provider for sequencer address. + pub struct InherentDataProvider { + pub starknet_inherent_data: InherentType, + } + + impl InherentDataProvider { + /// Create `Self` using the given `addr`. + pub fn new(data: InherentType) -> Self { + Self { starknet_inherent_data: data } + } + + /// Returns the sequencer address of this inherent data provider. + pub fn starknet_inherent_data(&self) -> &InherentType { + &self.starknet_inherent_data + } + } + + #[async_trait::async_trait] + impl sp_inherents::InherentDataProvider for InherentDataProvider { + async fn provide_inherent_data(&self, inherent_data: &mut InherentData) -> Result<(), sp_inherents::Error> { + inherent_data.put_data(STARKNET_INHERENT_IDENTIFIER, &self.starknet_inherent_data) + } + + async fn try_handle_error( + &self, + identifier: &InherentIdentifier, + error: &[u8], + ) -> Option> { + Some(Err(sp_inherents::Error::Application(Box::from(InherentError::try_from(identifier, error)?)))) + } + } +} + +#[cfg(feature = "client")] +pub use reexport_for_client_only::*; diff --git a/crates/primitives/transactions/src/execution.rs b/crates/primitives/transactions/src/execution.rs index d1530ea738..74a2fbab27 100644 --- a/crates/primitives/transactions/src/execution.rs +++ b/crates/primitives/transactions/src/execution.rs @@ -197,28 +197,7 @@ pub trait CheckFeeBounds: GetCalldataLen + GetTxType { fn state_changes() -> StateChangesCount; fn check_fee_bounds(&self, tx_context: &TransactionContext) -> TransactionExecutionResult<()> { - let minimal_l1_gas_amount_vector = { - let block_info = tx_context.block_context.block_info(); - let versioned_constants = tx_context.block_context.versioned_constants(); - - let state_changes = Self::state_changes(); - - let GasVector { l1_gas: gas_cost, l1_data_gas: blob_gas_cost } = - blockifier::fee::gas_usage::get_da_gas_cost(&state_changes, block_info.use_kzg_da); - - let data_segment_length = blockifier::fee::gas_usage::get_onchain_data_segment_length(&state_changes); - let os_steps_for_type = - versioned_constants.os_resources_for_tx_type(&Self::tx_type(), self.get_calldata_len()).n_steps - + versioned_constants.os_kzg_da_resources(data_segment_length).n_steps; - - let resources = ResourcesMapping(IndexMap::from([ - (blockifier::abi::constants::L1_GAS_USAGE.to_string(), gas_cost), - (blockifier::abi::constants::BLOB_GAS_USAGE.to_string(), blob_gas_cost), - (blockifier::abi::constants::N_STEPS_RESOURCE.to_string(), os_steps_for_type as u128), - ])); - - blockifier::fee::fee_utils::calculate_tx_gas_vector(&resources, versioned_constants)? - }; + let minimal_l1_gas_amount_vector = self.estimate_minimal_gas_vector(tx_context)?; // TODO(Aner, 30/01/24): modify once data gas limit is enforced. let minimal_l1_gas_amount = blockifier::fee::gas_usage::compute_discounted_gas_from_gas_vector( @@ -270,6 +249,29 @@ pub trait CheckFeeBounds: GetCalldataLen + GetTxType { Ok(()) } + + fn estimate_minimal_gas_vector(&self, tx_context: &TransactionContext) -> TransactionExecutionResult { + let block_info = tx_context.block_context.block_info(); + let versioned_constants = tx_context.block_context.versioned_constants(); + + let state_changes = Self::state_changes(); + + let GasVector { l1_gas: gas_cost, l1_data_gas: blob_gas_cost } = + blockifier::fee::gas_usage::get_da_gas_cost(&state_changes, block_info.use_kzg_da); + + let data_segment_length = blockifier::fee::gas_usage::get_onchain_data_segment_length(&state_changes); + let os_steps_for_type = + versioned_constants.os_resources_for_tx_type(&Self::tx_type(), self.get_calldata_len()).n_steps + + versioned_constants.os_kzg_da_resources(data_segment_length).n_steps; + + let resources = ResourcesMapping(IndexMap::from([ + (blockifier::abi::constants::L1_GAS_USAGE.to_string(), gas_cost), + (blockifier::abi::constants::BLOB_GAS_USAGE.to_string(), blob_gas_cost), + (blockifier::abi::constants::N_STEPS_RESOURCE.to_string(), os_steps_for_type as u128), + ])); + + Ok(blockifier::fee::fee_utils::calculate_tx_gas_vector(&resources, versioned_constants)?) + } } impl CheckFeeBounds for DeclareTransaction { diff --git a/crates/runtime/Cargo.toml b/crates/runtime/Cargo.toml index 873445ed52..0cd21cf64e 100644 --- a/crates/runtime/Cargo.toml +++ b/crates/runtime/Cargo.toml @@ -59,6 +59,7 @@ mp-felt = { workspace = true } mp-hashers = { workspace = true } mp-program-hash = { workspace = true } mp-simulations = { workspace = true } +mp-starknet-inherent = { workspace = true } pallet-starknet = { workspace = true } pallet-starknet-runtime-api = { workspace = true } # Starknet dependencies diff --git a/crates/runtime/src/lib.rs b/crates/runtime/src/lib.rs index 81eba9ef77..cdb7f76d2c 100644 --- a/crates/runtime/src/lib.rs +++ b/crates/runtime/src/lib.rs @@ -34,8 +34,10 @@ pub use frame_support::{construct_runtime, parameter_types, StorageValue}; pub use frame_system::Call as SystemCall; use mp_felt::Felt252Wrapper; use mp_simulations::{ - InternalSubstrateError, ReExecutionResult, SimulationError, SimulationFlags, TransactionSimulationResult, + FeeEstimate, InternalSubstrateError, ReExecutionResult, SimulationError, SimulationFlags, + TransactionSimulationResult, }; +use mp_starknet_inherent::L1GasPrices; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; /// Import the Starknet pallet. pub use pallet_starknet; @@ -277,7 +279,7 @@ impl_runtime_apis! { Starknet::is_transaction_fee_disabled() } - fn estimate_fee(transactions: Vec, simulation_flags: SimulationFlags) -> Result, SimulationError>, InternalSubstrateError> { + fn estimate_fee(transactions: Vec, simulation_flags: SimulationFlags) -> Result, SimulationError>, InternalSubstrateError> { Starknet::estimate_fee(transactions, &simulation_flags) } @@ -285,15 +287,15 @@ impl_runtime_apis! { Starknet::re_execute_transactions(transactions_before, transactions_to_trace, with_state_diff) } - fn get_transaction_re_execution_state_diff( transactions_before: Vec, transactions_to_trace: Vec) -> Result, InternalSubstrateError> { - Starknet::get_transaction_re_execution_state_diff(transactions_before, transactions_to_trace) + fn estimate_message_fee(message: L1HandlerTransaction) -> Result, InternalSubstrateError> { + Starknet::estimate_message_fee(message) } - fn estimate_message_fee(message: L1HandlerTransaction) -> Result, InternalSubstrateError> { - Starknet::estimate_message_fee(message) + fn get_transaction_re_execution_state_diff( transactions_before: Vec, transactions_to_trace: Vec) -> Result, InternalSubstrateError> { + Starknet::get_transaction_re_execution_state_diff(transactions_before, transactions_to_trace) } - fn simulate_transactions(transactions: Vec, simulation_flags: SimulationFlags) -> Result, SimulationError>, InternalSubstrateError> { + fn simulate_transactions(transactions: Vec, simulation_flags: SimulationFlags) -> Result, InternalSubstrateError> { Starknet::simulate_transactions(transactions, &simulation_flags) } @@ -355,6 +357,10 @@ impl_runtime_apis! { fn l1_nonce_unused(nonce: Nonce) -> bool { Starknet::ensure_l1_message_not_executed(&nonce).is_ok() } + + fn current_l1_gas_prices() -> L1GasPrices { + Starknet::current_l1_gas_prices() + } } impl pallet_starknet_runtime_api::ConvertTransactionRuntimeApi for Runtime { diff --git a/crates/runtime/src/pallets.rs b/crates/runtime/src/pallets.rs index f0a5bf8e36..e6b22473cc 100644 --- a/crates/runtime/src/pallets.rs +++ b/crates/runtime/src/pallets.rs @@ -3,13 +3,11 @@ //! This file is used to generate the `construct_runtime!` macro. #[cfg(all(debug_assertions, feature = "dev"))] use std::env::VarError; -use std::num::NonZeroU128; use std::ops::Deref; #[cfg(all(debug_assertions, feature = "dev"))] use std::path::Path; use std::sync::Arc; -use blockifier::blockifier::block::GasPrices; use blockifier::versioned_constants::VersionedConstants; pub use frame_support::traits::{ ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, KeyOwnerProofSystem, OnTimestampSet, Randomness, StorageInfo, @@ -76,7 +74,6 @@ impl pallet_starknet::Config for Runtime { type DisableNonceValidation = ConstBool; type ProtocolVersion = ProtocolVersion; type ProgramHash = ProgramHash; - type L1GasPrices = L1GasPrices; type ExecutionConstants = ExecutionConstants; } @@ -192,7 +189,6 @@ parameter_types! { pub const TransactionLongevity: u64 = u64::MAX; pub const ProtocolVersion: u8 = 0; pub const ProgramHash: Felt252Wrapper = SN_OS_PROGRAM_HASH; - pub const L1GasPrices: GasPrices = GasPrices { eth_l1_gas_price: unsafe { NonZeroU128::new_unchecked(10) }, strk_l1_gas_price: unsafe { NonZeroU128::new_unchecked(10) }, eth_l1_data_gas_price: unsafe { NonZeroU128::new_unchecked(10) }, strk_l1_data_gas_price: unsafe { NonZeroU128::new_unchecked(10) } }; pub ExecutionConstants: Arc = get_execution_constants(); } diff --git a/docs/genesis.md b/docs/genesis.md index 6445aa7081..47cc36f983 100644 --- a/docs/genesis.md +++ b/docs/genesis.md @@ -44,6 +44,7 @@ The below defines all hardcoded values set in the geneses: | 0x04569ffd48c2a3d455437c16dc843801fb896b1af845bc8bc7ba83ebc4358b7f | Universal deployer class hash | | 0x01a736d6ed154502257f02b1ccdf4d9d1089f80811cd6acad48e6b6a9d1f2003 | Argent Cairo 1 Account | | 0x04c6d6cf894f8bc96bb9c525e6853e5483177841f7388f74a46cfda6f028c755 | OpenZepplin Cairo 1 Account | +| 0x015b7c90a4fab33812dc9e2ef525a329e22e591327f006f826b71271099637cd | Multiply 2 numbers test contract | @@ -61,7 +62,7 @@ The below defines all hardcoded values set in the geneses: where `pk` is the following vector of `u8`: ```rust -[48,120,48,48,99,49,99,102,49,52,57,48,100,101,49,51,53,50,56,54,53,51,48,49,98,98,56,55,48,53,49,52,51,102,51,101,102,57,51,56,102,57,55,102,100,102,56,57,50,102,49,48,57,48,100,99,98,53,97,99,55,98,99,100,49,100] +[48, 120, 48, 48, 99,49, 99, 102, 49, 52,57, 48, 100, 101, 49,51, 53, 50, 56, 54,53, 51, 48, 49, 98,98, 56, 55, 48, 53,49, 52, 51, 102, 51,101, 102, 57, 51, 56,102, 57, 55, 102, 100,102, 56, 57, 50, 102,49, 48, 57, 48, 100,99, 98, 53, 97, 99,55, 98, 99, 100, 49,100] ``` @@ -82,6 +83,7 @@ where `pk` is the following vector of `u8`: | 0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7 | 0x0372ee6669dc86563007245ed7343d5180b96221ce28f44408cff2898038dbd4 | | 0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d | 0x0372ee6669dc86563007245ed7343d5180b96221ce28f44408cff2898038dbd4 | | 0x041a78e741e5af2fec34b695679bc6891742439f7afb8484ecd7766661ad02bf | 0x07b3e05f48f0c69e4a65ce5e076a66271a527aff2c34ce1083ec6e1526997a69 | +| 0x123 | 0x015b7c90a4fab33812dc9e2ef525a329e22e591327f006f826b71271099637cd | diff --git a/examples/messaging/eth-config.json b/examples/messaging/eth-config.json new file mode 100644 index 0000000000..5657dfa26a --- /dev/null +++ b/examples/messaging/eth-config.json @@ -0,0 +1,9 @@ +{ + "provider": { + "rpc_endpoint": "https://eth.merkle.io", + "gas_price_poll_ms": 10000 + }, + "contracts": { + "core_contract": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512" + } +} diff --git a/examples/messaging/l1-messaging-config.json b/examples/messaging/l1-messaging-config.json deleted file mode 100644 index e14106a7ce..0000000000 --- a/examples/messaging/l1-messaging-config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "httpProvider": "http://127.0.0.1:8545", - "contractAddress": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512" -} diff --git a/starknet-rpc-test/estimate_fee.rs b/starknet-rpc-test/estimate_fee.rs index c657197dab..58daf41657 100644 --- a/starknet-rpc-test/estimate_fee.rs +++ b/starknet-rpc-test/estimate_fee.rs @@ -1,16 +1,17 @@ +use anyhow::Error; use assert_matches::assert_matches; use rstest::rstest; use starknet_core::types::{ BlockId, BlockTag, BroadcastedInvokeTransaction, BroadcastedInvokeTransactionV1, BroadcastedTransaction, - StarknetError, + FeeEstimate, MaybePendingTransactionReceipt, StarknetError, TransactionReceipt, }; use starknet_core::utils::get_selector_from_name; use starknet_ff::FieldElement; use starknet_providers::Provider; use starknet_providers::ProviderError::StarknetError as StarknetProviderError; -use starknet_rpc_test::constants::{ACCOUNT_CONTRACT_ADDRESS, TEST_CONTRACT_ADDRESS}; +use starknet_rpc_test::constants::{ACCOUNT_CONTRACT_ADDRESS, MULTIPLY_TEST_CONTRACT_ADDRESS, TEST_CONTRACT_ADDRESS}; use starknet_rpc_test::fixtures::{madara, ThreadSafeMadaraClient}; -use starknet_rpc_test::utils::is_good_error_code; +use starknet_rpc_test::utils::{get_transaction_receipt, is_good_error_code}; #[rstest] #[tokio::test] @@ -84,16 +85,20 @@ async fn fail_if_one_txn_cannot_be_executed(madara: &ThreadSafeMadaraClient) -> async fn works_ok(madara: &ThreadSafeMadaraClient) -> Result<(), anyhow::Error> { let rpc = madara.get_starknet_client().await; - let tx = BroadcastedInvokeTransactionV1 { - max_fee: FieldElement::ZERO, + let sender_address = FieldElement::from_hex_be(ACCOUNT_CONTRACT_ADDRESS).unwrap(); + let nonce = rpc.get_nonce(BlockId::Tag(BlockTag::Latest), sender_address).await.unwrap(); + + let mut tx = BroadcastedInvokeTransactionV1 { + max_fee: FieldElement::from_hex_be("0xfffffffffff").unwrap(), signature: vec![], - nonce: FieldElement::ZERO, - sender_address: FieldElement::from_hex_be(ACCOUNT_CONTRACT_ADDRESS).unwrap(), + nonce, + sender_address, calldata: vec![ - FieldElement::from_hex_be(TEST_CONTRACT_ADDRESS).unwrap(), - get_selector_from_name("sqrt").unwrap(), - FieldElement::from_hex_be("1").unwrap(), - FieldElement::from(81u8), + FieldElement::from_hex_be(MULTIPLY_TEST_CONTRACT_ADDRESS).unwrap(), + get_selector_from_name("multiply").unwrap(), + FieldElement::TWO, + FieldElement::from_hex_be("2").unwrap(), + FieldElement::from_hex_be("5").unwrap(), ], is_query: true, }; @@ -102,22 +107,68 @@ async fn works_ok(madara: &ThreadSafeMadaraClient) -> Result<(), anyhow::Error> let invoke_transaction_2 = BroadcastedTransaction::Invoke(BroadcastedInvokeTransaction::V1(BroadcastedInvokeTransactionV1 { - nonce: FieldElement::ONE, - ..tx + nonce: nonce + FieldElement::ONE, + calldata: vec![ + FieldElement::from_hex_be(MULTIPLY_TEST_CONTRACT_ADDRESS).unwrap(), + get_selector_from_name("multiply").unwrap(), + FieldElement::TWO, + FieldElement::from_hex_be("3").unwrap(), + FieldElement::from_hex_be("5").unwrap(), + ], + ..tx.clone() })); let estimates = rpc .estimate_fee(&vec![invoke_transaction, invoke_transaction_2], vec![], BlockId::Tag(BlockTag::Latest)) .await?; - // TODO: instead execute the tx and check that the actual fee are the same as the estimated ones assert_eq!(estimates.len(), 2); - // TODO: use correct values when we implement estimate fee correctly - // assert_eq!(estimates[0].overall_fee, FieldElement::from(210u128)); - // assert_eq!(estimates[1].overall_fee, FieldElement::from(210u128)); - // https://starkscan.co/block/5 - // assert_eq!(estimates[0].gas_consumed, FieldElement::ZERO); - // assert_eq!(estimates[1].gas_consumed, FieldElement::ZERO); + assert_eq!(estimates[0].overall_fee, FieldElement::from(2060u128)); + // less gas as the second transaction doesn't cause a storage change + assert_eq!(estimates[1].overall_fee, FieldElement::from(2060u128)); + // It's 271 gas on sepolia as well (15 gas and 256 data gas). The difference in gas costs + // can be due to different accounts. Also, gas calculation tests are done in the blockifier + assert_eq!(estimates[0].gas_consumed, FieldElement::from_hex_be("0xce").unwrap()); + assert_eq!(estimates[1].gas_consumed, FieldElement::from_hex_be("0xce").unwrap()); + + tx.is_query = false; + let invoke_transaction = BroadcastedInvokeTransaction::V1(tx.clone()); + let invoke_transaction_2 = BroadcastedInvokeTransaction::V1(BroadcastedInvokeTransactionV1 { + nonce: FieldElement::ONE, + calldata: vec![ + FieldElement::from_hex_be(MULTIPLY_TEST_CONTRACT_ADDRESS).unwrap(), + get_selector_from_name("multiply").unwrap(), + FieldElement::TWO, + FieldElement::from_hex_be("3").unwrap(), + FieldElement::from_hex_be("5").unwrap(), + ], + ..tx.clone() + }); + let executed_tx_1 = rpc.add_invoke_transaction(invoke_transaction).await?; + let executed_tx_2 = rpc.add_invoke_transaction(invoke_transaction_2).await?; + + madara.write().await.create_block_with_pending_txs().await?; + + let receipt_1 = get_transaction_receipt(&rpc, executed_tx_1.transaction_hash).await?; + let receipt_2 = get_transaction_receipt(&rpc, executed_tx_2.transaction_hash).await?; + + let match_estimate_and_receipt = |estimate: FeeEstimate, + receipt: MaybePendingTransactionReceipt| + -> Result<(), anyhow::Error> { + match receipt { + MaybePendingTransactionReceipt::PendingReceipt(_) => Err(Error::msg("Transaction should not be pending")), + MaybePendingTransactionReceipt::Receipt(receipt) => match receipt { + TransactionReceipt::Invoke(receipt) => { + assert_eq!(estimate.overall_fee, receipt.actual_fee.amount); + Ok(()) + } + _ => Err(Error::msg("Transaction should be an invoke transaction")), + }, + } + }; + + match_estimate_and_receipt(estimates[0].clone(), receipt_1)?; + match_estimate_and_receipt(estimates[1].clone(), receipt_2)?; Ok(()) } diff --git a/starknet-rpc-test/get_state_update.rs b/starknet-rpc-test/get_state_update.rs index 437b9659de..a3cf755132 100644 --- a/starknet-rpc-test/get_state_update.rs +++ b/starknet-rpc-test/get_state_update.rs @@ -41,12 +41,13 @@ async fn returns_correct_state_diff_transfer(madara: &ThreadSafeMadaraClient) -> let account_bob = build_single_owner_account(&rpc, SIGNER_PRIVATE, OZ_CONTRACT_ADDRESS, true); let nonce = account_alice.get_nonce().await?.try_into()?; + let receiver = FieldElement::ONE; { let mut madara_write_lock = madara.write().await; let txs = madara_write_lock .create_block_with_txs(vec![ - Transaction::Execution(account_alice.transfer_tokens(recipient, FieldElement::ONE, Some(nonce))), - Transaction::Execution(account_bob.transfer_tokens(recipient, FieldElement::ONE, None)), + Transaction::Execution(account_alice.transfer_tokens(recipient, receiver, Some(nonce))), + Transaction::Execution(account_bob.transfer_tokens(recipient, receiver, None)), ]) .await?; txs.iter().for_each(|tx| assert!(tx.is_ok())); @@ -72,13 +73,17 @@ async fn returns_correct_state_diff_transfer(madara: &ThreadSafeMadaraClient) -> .map(|item| (&item.key, &item.value)) .collect::>(), ); - for account_address in - [account_alice.address(), account_bob.address(), FieldElement::from_hex_be(SEQUENCER_CONTRACT_ADDRESS).unwrap()] - { + for account_address in [ + account_alice.address(), + account_bob.address(), + FieldElement::from_hex_be(SEQUENCER_CONTRACT_ADDRESS).unwrap(), + receiver, + ] { let balance = read_erc20_balance(&rpc, fee_token_address, account_address).await[0]; // omit the second part since it probably won't change let key = get_storage_var_address("ERC20_balances", &[account_address]).unwrap(); assert_eq!(storage_diff_map.remove(&key).unwrap(), &balance); } + println!("this is storage_diff_map {:#?}", storage_diff_map); assert!(storage_diff_map.is_empty()); assert_eq!(state_update.state_diff.nonces.len(), 2); let mut nonce_map: HashMap<&FieldElement, &FieldElement> = HashMap::from_iter( diff --git a/starknet-rpc-test/get_transaction_receipt.rs b/starknet-rpc-test/get_transaction_receipt.rs index 41a0b9486c..283e8b2690 100644 --- a/starknet-rpc-test/get_transaction_receipt.rs +++ b/starknet-rpc-test/get_transaction_receipt.rs @@ -53,7 +53,7 @@ async fn work_with_invoke_transaction(madara: &ThreadSafeMadaraClient) -> Result }; let invoke_tx_receipt = get_transaction_receipt(&rpc, rpc_response.transaction_hash).await; - let expected_fee = FeePayment { amount: FieldElement::from_hex_be("0x1219c").unwrap(), unit: PriceUnit::Wei }; + let expected_fee = FeePayment { amount: FieldElement::from_hex_be("0x5c8").unwrap(), unit: PriceUnit::Wei }; match invoke_tx_receipt { Ok(MaybePendingTransactionReceipt::Receipt(TransactionReceipt::Invoke(receipt))) => { @@ -191,7 +191,7 @@ async fn work_with_declare_transaction(madara: &ThreadSafeMadaraClient) -> Resul }; let fee_token_address = FieldElement::from_hex_be(ETH_FEE_TOKEN_ADDRESS).unwrap(); - let expected_fee = FeePayment { amount: FieldElement::from_hex_be("0x40a2e").unwrap(), unit: PriceUnit::Wei }; + let expected_fee = FeePayment { amount: FieldElement::from_hex_be("0x38216").unwrap(), unit: PriceUnit::Wei }; let expected_events = vec![Event { from_address: fee_token_address, keys: vec![get_selector_from_name("Transfer").unwrap()], @@ -298,7 +298,7 @@ async fn work_with_deploy_account_transaction(madara: &ThreadSafeMadaraClient) - let account_deployment_tx_receipt = get_transaction_receipt(&rpc, rpc_response.transaction_hash).await; let fee_token_address = FieldElement::from_hex_be(ETH_FEE_TOKEN_ADDRESS).unwrap(); - let expected_fee = FeePayment { amount: FieldElement::from_hex_be("0xac76").unwrap(), unit: PriceUnit::Wei }; + let expected_fee = FeePayment { amount: FieldElement::from_hex_be("0x2ee").unwrap(), unit: PriceUnit::Wei }; match account_deployment_tx_receipt { Ok(MaybePendingTransactionReceipt::Receipt(TransactionReceipt::DeployAccount(receipt))) => { @@ -408,7 +408,7 @@ async fn ensure_transfer_fee_event_not_messed_up_with_similar_transfer( }; let tx_receipt = get_transaction_receipt(&rpc, rpc_response.transaction_hash).await; let fee_token_address = FieldElement::from_hex_be(ETH_FEE_TOKEN_ADDRESS).unwrap(); - let expected_fee = FeePayment { amount: FieldElement::from_hex_be("0x12188").unwrap(), unit: PriceUnit::Wei }; + let expected_fee = FeePayment { amount: FieldElement::from_hex_be("0x5c8").unwrap(), unit: PriceUnit::Wei }; match tx_receipt { Ok(MaybePendingTransactionReceipt::Receipt(TransactionReceipt::Invoke(mut receipt))) => { diff --git a/starknet-rpc-test/simulate_transaction.rs b/starknet-rpc-test/simulate_transaction.rs index 5e7fe45b1f..c303bc209b 100644 --- a/starknet-rpc-test/simulate_transaction.rs +++ b/starknet-rpc-test/simulate_transaction.rs @@ -19,12 +19,15 @@ use starknet_rpc_test::utils::{build_single_owner_account, is_good_error_code, A async fn fail_non_existing_block(madara: &ThreadSafeMadaraClient) -> Result<(), anyhow::Error> { let rpc = madara.get_starknet_client().await; + let sender_address = FieldElement::from_hex_be(ACCOUNT_CONTRACT_ADDRESS).unwrap(); + let nonce = rpc.get_nonce(BlockId::Tag(BlockTag::Latest), sender_address).await.unwrap(); + let ok_invoke_transaction = BroadcastedTransaction::Invoke(BroadcastedInvokeTransaction::V1(BroadcastedInvokeTransactionV1 { max_fee: FieldElement::ZERO, signature: vec![], - nonce: FieldElement::ZERO, - sender_address: FieldElement::from_hex_be(ACCOUNT_CONTRACT_ADDRESS).unwrap(), + nonce, + sender_address, calldata: vec![ FieldElement::from_hex_be(TEST_CONTRACT_ADDRESS).unwrap(), get_selector_from_name("sqrt").unwrap(), @@ -46,12 +49,15 @@ async fn fail_non_existing_block(madara: &ThreadSafeMadaraClient) -> Result<(), async fn fail_max_fee_too_big(madara: &ThreadSafeMadaraClient) -> Result<(), anyhow::Error> { let rpc = madara.get_starknet_client().await; + let sender_address = FieldElement::from_hex_be(ACCOUNT_CONTRACT_ADDRESS).unwrap(); + let nonce = rpc.get_nonce(BlockId::Tag(BlockTag::Latest), sender_address).await.unwrap(); + let ok_invoke_transaction = BroadcastedTransaction::Invoke(BroadcastedInvokeTransaction::V1(BroadcastedInvokeTransactionV1 { max_fee: FieldElement::from_hex_be("0x100000000000000000000000000000000").unwrap(), // u128::MAX + 1 signature: vec![], - nonce: FieldElement::ZERO, - sender_address: FieldElement::from_hex_be(ACCOUNT_CONTRACT_ADDRESS).unwrap(), + nonce, + sender_address, calldata: vec![ FieldElement::from_hex_be(TEST_CONTRACT_ADDRESS).unwrap(), get_selector_from_name("sqrt").unwrap(), @@ -83,12 +89,15 @@ async fn fail_if_one_txn_cannot_be_executed(madara: &ThreadSafeMadaraClient) -> is_query: false, })); + let sender_address = FieldElement::from_hex_be(ACCOUNT_CONTRACT_ADDRESS).unwrap(); + let nonce = rpc.get_nonce(BlockId::Tag(BlockTag::Latest), sender_address).await.unwrap(); + let ok_invoke_transaction = BroadcastedTransaction::Invoke(BroadcastedInvokeTransaction::V1(BroadcastedInvokeTransactionV1 { max_fee: FieldElement::ZERO, signature: vec![], - nonce: FieldElement::ZERO, - sender_address: FieldElement::from_hex_be(ACCOUNT_CONTRACT_ADDRESS).unwrap(), + nonce, + sender_address, calldata: vec![ FieldElement::from_hex_be(TEST_CONTRACT_ADDRESS).unwrap(), get_selector_from_name("sqrt").unwrap(), @@ -113,6 +122,7 @@ async fn works_ok_on_no_validate(madara: &ThreadSafeMadaraClient) { let rpc = madara.get_starknet_client().await; let sender_address = FieldElement::from_hex_be(ACCOUNT_CONTRACT_ADDRESS).unwrap(); + let nonce = rpc.get_nonce(BlockId::Tag(BlockTag::Latest), sender_address).await.unwrap(); let mut madara_write_lock = madara.write().await; let _ = madara_write_lock.create_empty_block().await; @@ -127,7 +137,7 @@ async fn works_ok_on_no_validate(madara: &ThreadSafeMadaraClient) { ], max_fee: FieldElement::from(100_000u128), signature: vec![], - nonce: FieldElement::ZERO, + nonce, is_query: false, }; @@ -135,7 +145,7 @@ async fn works_ok_on_no_validate(madara: &ThreadSafeMadaraClient) { let invoke_transaction_2 = BroadcastedTransaction::Invoke(BroadcastedInvokeTransaction::V1(BroadcastedInvokeTransactionV1 { - nonce: FieldElement::ONE, + nonce: nonce + FieldElement::ONE, ..tx })); @@ -146,9 +156,9 @@ async fn works_ok_on_no_validate(madara: &ThreadSafeMadaraClient) { assert_eq!(simulations.len(), 2); // TODO: check again when implemented correctly - // assert_eq!(simulations[0].fee_estimation.gas_consumed, FieldElement::ZERO); - // assert_eq!(simulations[0].fee_estimation.overall_fee, FieldElement::from(210u128)); - // assert_eq!(simulations[0].fee_estimation.gas_price, FieldElement::ZERO); + assert_eq!(simulations[0].fee_estimation.gas_consumed, FieldElement::from_hex_be("0x8c").unwrap()); + assert_eq!(simulations[0].fee_estimation.overall_fee, FieldElement::from(1400u128)); + assert_eq!(simulations[0].fee_estimation.gas_price, FieldElement::from_hex_be("0xa").unwrap()); } #[rstest] @@ -172,9 +182,9 @@ async fn works_ok_on_validate_with_signature(madara: &ThreadSafeMadaraClient) -> assert_eq!(simulations.len(), 1); // TODO: check again when implemented correctly - // assert_eq!(simulations[0].fee_estimation.gas_consumed, FieldElement::ZERO); - // assert_eq!(simulations[0].fee_estimation.overall_fee, FieldElement::from(240u128)); - // assert_eq!(simulations[0].fee_estimation.gas_price, FieldElement::ZERO); + assert_eq!(simulations[0].fee_estimation.gas_consumed, FieldElement::from_hex_be("0x8f").unwrap()); + assert_eq!(simulations[0].fee_estimation.overall_fee, FieldElement::from(1430u128)); + assert_eq!(simulations[0].fee_estimation.gas_price, FieldElement::from_hex_be("0xa").unwrap()); Ok(()) } @@ -204,9 +214,9 @@ async fn works_ok_on_validate_without_signature_with_skip_validate( assert_eq!(simulations.len(), 1); // TODO: check again when implemented correctly - // assert_eq!(simulations[0].fee_estimation.gas_consumed, FieldElement::ZERO); - // assert_eq!(simulations[0].fee_estimation.overall_fee, FieldElement::from(220u128)); - // assert_eq!(simulations[0].fee_estimation.gas_price, FieldElement::ZERO); + assert_eq!(simulations[0].fee_estimation.gas_consumed, FieldElement::from_hex_be("0x8e").unwrap()); + assert_eq!(simulations[0].fee_estimation.overall_fee, FieldElement::from(1420u128)); + assert_eq!(simulations[0].fee_estimation.gas_price, FieldElement::from_hex_be("0xa").unwrap()); Ok(()) } @@ -217,11 +227,12 @@ async fn works_ok_without_max_fee_with_skip_fee_charge(madara: &ThreadSafeMadara let rpc = madara.get_starknet_client().await; let sender_address = FieldElement::from_hex_be(ACCOUNT_CONTRACT_ADDRESS).unwrap(); + let nonce = rpc.get_nonce(BlockId::Tag(BlockTag::Latest), sender_address).await.unwrap(); let tx = BroadcastedInvokeTransactionV1 { max_fee: FieldElement::from(0u8), signature: vec![], - nonce: FieldElement::ZERO, + nonce, sender_address, calldata: vec![ FieldElement::from_hex_be(TEST_CONTRACT_ADDRESS).unwrap(), @@ -236,7 +247,7 @@ async fn works_ok_without_max_fee_with_skip_fee_charge(madara: &ThreadSafeMadara let invoke_transaction_2 = BroadcastedTransaction::Invoke(BroadcastedInvokeTransaction::V1(BroadcastedInvokeTransactionV1 { - nonce: FieldElement::ONE, + nonce: nonce + FieldElement::ONE, ..tx })); @@ -250,9 +261,9 @@ async fn works_ok_without_max_fee_with_skip_fee_charge(madara: &ThreadSafeMadara assert_eq!(simulations.len(), 2); // TODO: check again when implemented correctly - // assert_eq!(simulations[0].fee_estimation.gas_consumed, FieldElement::ZERO); - // assert_eq!(simulations[0].fee_estimation.overall_fee, FieldElement::from(210u128)); - // assert_eq!(simulations[0].fee_estimation.gas_price, FieldElement::ZERO); + assert_eq!(simulations[0].fee_estimation.gas_consumed, FieldElement::from_hex_be("0x8c").unwrap()); + assert_eq!(simulations[0].fee_estimation.overall_fee, FieldElement::from(1400u128)); + assert_eq!(simulations[0].fee_estimation.gas_price, FieldElement::from_hex_be("0xa").unwrap()); Ok(()) } diff --git a/starknet-rpc-test/src/constants.rs b/starknet-rpc-test/src/constants.rs index 3653e28f09..59d53259ab 100644 --- a/starknet-rpc-test/src/constants.rs +++ b/starknet-rpc-test/src/constants.rs @@ -26,11 +26,10 @@ pub const ARGENT_CONTRACT_ADDRESS: &str = "0x2"; pub const OZ_CONTRACT_ADDRESS: &str = "0x3"; pub const CAIRO_1_ACCOUNT_CONTRACT_ADDRESS: &str = "0x4"; pub const TEST_CONTRACT_ADDRESS: &str = "0x1111"; +pub const MULTIPLY_TEST_CONTRACT_ADDRESS: &str = "0x123"; pub const L1_CONTRACT_ADDRESS: &str = "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419"; pub const UDC_CONTRACT_ADDRESS: &str = "0x041a78e741e5af2fec34b695679bc6891742439f7afb8484ecd7766661ad02bf"; // Need to use `from_mont` because this needs to be a constant function call pub const MADARA_CHAIN_ID: FieldElement = FieldElement::from_mont([18444025906882525153, 18446744073709551615, 18446744073709551615, 530251916243973616]); - -pub const SPEC_VERSION: &str = "0.4.0"; diff --git a/starknet-test-utils/src/constants.rs b/starknet-test-utils/src/constants.rs index 64a6d86fd6..ee92dec856 100644 --- a/starknet-test-utils/src/constants.rs +++ b/starknet-test-utils/src/constants.rs @@ -31,7 +31,7 @@ pub const OZ_CONTRACT_ADDRESS: &str = "0x3"; pub const L1_CONTRACT_ADDRESS: &str = "0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419"; pub const MAX_U256: &str = "0xffffffffffffffffffffffffffffffff"; -pub const MAX_FEE_OVERRIDE: &str = "0x1000000"; +pub const MAX_FEE_OVERRIDE: &str = "0xfffffffffffff"; // Need to use `from_mont` because this needs to be a constant function call pub const MADARA_CHAIN_ID: FieldElement =