├── .github ├── dependabot.yml └── workflows │ ├── book.yml │ ├── cachegrind.yml │ ├── ci.yml │ ├── ethereum-tests.yml │ └── release-plz.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── Cross.toml ├── LICENSE ├── README.md ├── assets ├── logo.pdf ├── logo.png └── revm-banner.png ├── bins ├── revm-test │ ├── CHANGELOG.md │ ├── Cargo.toml │ ├── LICENSE │ └── src │ │ └── bin │ │ ├── analysis.rs │ │ ├── burntpix │ │ ├── main.rs │ │ └── static_data.rs │ │ ├── snailtracer.rs │ │ └── transfer.rs └── revme │ ├── CHANGELOG.md │ ├── Cargo.toml │ ├── LICENSE │ ├── README.md │ └── src │ ├── cmd.rs │ ├── cmd │ ├── bytecode.rs │ ├── evmrunner.rs │ ├── format_kzg_setup.rs │ ├── statetest.rs │ └── statetest │ │ ├── merkle_trie.rs │ │ ├── models │ │ ├── deserializer.rs │ │ ├── mod.rs │ │ └── spec.rs │ │ ├── runner.rs │ │ └── utils.rs │ ├── lib.rs │ └── main.rs ├── book.toml ├── crates ├── interpreter │ ├── CHANGELOG.md │ ├── Cargo.toml │ ├── LICENSE │ ├── src │ │ ├── function_stack.rs │ │ ├── gas.rs │ │ ├── gas │ │ │ ├── calc.rs │ │ │ └── constants.rs │ │ ├── host.rs │ │ ├── host │ │ │ └── dummy.rs │ │ ├── instruction_result.rs │ │ ├── instructions.rs │ │ ├── instructions │ │ │ ├── arithmetic.rs │ │ │ ├── bitwise.rs │ │ │ ├── contract.rs │ │ │ ├── contract │ │ │ │ └── call_helpers.rs │ │ │ ├── control.rs │ │ │ ├── data.rs │ │ │ ├── host.rs │ │ │ ├── host_env.rs │ │ │ ├── i256.rs │ │ │ ├── macros.rs │ │ │ ├── memory.rs │ │ │ ├── stack.rs │ │ │ ├── system.rs │ │ │ └── utility.rs │ │ ├── interpreter.rs │ │ ├── interpreter │ │ │ ├── analysis.rs │ │ │ ├── contract.rs │ │ │ ├── serde.rs │ │ │ ├── shared_memory.rs │ │ │ └── stack.rs │ │ ├── interpreter_action.rs │ │ ├── interpreter_action │ │ │ ├── call_inputs.rs │ │ │ ├── call_outcome.rs │ │ │ ├── create_inputs.rs │ │ │ ├── create_outcome.rs │ │ │ ├── eof_create_inputs.rs │ │ │ └── eof_create_outcome.rs │ │ ├── lib.rs │ │ ├── macros.rs │ │ ├── opcode.rs │ │ └── opcode │ │ │ └── eof_printer.rs │ └── tests │ │ ├── EOFTests │ │ ├── EIP3540 │ │ │ └── validInvalid.json │ │ ├── EIP3670 │ │ │ └── validInvalid.json │ │ ├── EIP4200 │ │ │ └── validInvalid.json │ │ ├── EIP4750 │ │ │ └── validInvalid.json │ │ ├── EIP5450 │ │ │ └── validInvalid.json │ │ ├── efExample │ │ │ ├── validInvalid.json │ │ │ └── ymlExample.json │ │ ├── eof_validation │ │ │ ├── EOF1_callf_truncated.json │ │ │ ├── EOF1_code_section_0_size.json │ │ │ ├── EOF1_code_section_missing.json │ │ │ ├── EOF1_code_section_offset.json │ │ │ ├── EOF1_data_section_0_size.json │ │ │ ├── EOF1_data_section_before_code_section.json │ │ │ ├── EOF1_data_section_before_types_section.json │ │ │ ├── EOF1_dataloadn_truncated.json │ │ │ ├── EOF1_embedded_container.json │ │ │ ├── EOF1_embedded_container_invalid.json │ │ │ ├── EOF1_eofcreate_invalid.json │ │ │ ├── EOF1_eofcreate_valid.json │ │ │ ├── EOF1_header_not_terminated.json │ │ │ ├── EOF1_incomplete_section_size.json │ │ │ ├── EOF1_invalid_section_0_type.json │ │ │ ├── EOF1_invalid_type_section_size.json │ │ │ ├── EOF1_multiple_data_sections.json │ │ │ ├── EOF1_multiple_type_sections.json │ │ │ ├── EOF1_no_type_section.json │ │ │ ├── EOF1_returncontract_invalid.json │ │ │ ├── EOF1_returncontract_valid.json │ │ │ ├── EOF1_rjump_invalid_destination.json │ │ │ ├── EOF1_rjump_truncated.json │ │ │ ├── EOF1_rjumpi_invalid_destination.json │ │ │ ├── EOF1_rjumpi_truncated.json │ │ │ ├── EOF1_rjumpv_invalid_destination.json │ │ │ ├── EOF1_rjumpv_truncated.json │ │ │ ├── EOF1_section_order.json │ │ │ ├── EOF1_too_many_code_sections.json │ │ │ ├── EOF1_trailing_bytes.json │ │ │ ├── EOF1_truncated_push.json │ │ │ ├── EOF1_truncated_section.json │ │ │ ├── EOF1_type_section_missing.json │ │ │ ├── EOF1_type_section_not_first.json │ │ │ ├── EOF1_types_section_0_size.json │ │ │ ├── EOF1_types_section_missing.json │ │ │ ├── EOF1_undefined_opcodes.json │ │ │ ├── EOF1_unknown_section.json │ │ │ ├── EOF1_valid_rjump.json │ │ │ ├── EOF1_valid_rjumpi.json │ │ │ ├── EOF1_valid_rjumpv.json │ │ │ ├── callf_into_nonreturning.json │ │ │ ├── callf_invalid_code_section_index.json │ │ │ ├── data_section_missing.json │ │ │ ├── dataloadn.json │ │ │ ├── deprecated_instructions.json │ │ │ ├── incomplete_section_size.json │ │ │ ├── jumpf_compatible_outputs.json │ │ │ ├── jumpf_equal_outputs.json │ │ │ ├── jumpf_incompatible_outputs.json │ │ │ ├── many_code_sections_1023.json │ │ │ ├── many_code_sections_1024.json │ │ │ ├── max_arguments_count.json │ │ │ ├── max_stack_height.json │ │ │ ├── minimal_valid_EOF1_code.json │ │ │ ├── minimal_valid_EOF1_code_with_data.json │ │ │ ├── minimal_valid_EOF1_multiple_code_sections.json │ │ │ ├── multiple_code_sections_headers.json │ │ │ ├── non_returning_status.json │ │ │ ├── stack │ │ │ │ ├── backwards_rjump.json │ │ │ │ ├── backwards_rjump_variable_stack.json │ │ │ │ ├── backwards_rjumpi.json │ │ │ │ ├── backwards_rjumpi_variable_stack.json │ │ │ │ ├── backwards_rjumpv.json │ │ │ │ ├── backwards_rjumpv_variable_stack.json │ │ │ │ ├── callf_stack_overflow.json │ │ │ │ ├── callf_stack_overflow_variable_stack.json │ │ │ │ ├── callf_stack_validation.json │ │ │ │ ├── callf_with_inputs_stack_overflow.json │ │ │ │ ├── callf_with_inputs_stack_overflow_variable_stack.json │ │ │ │ ├── dupn_stack_validation.json │ │ │ │ ├── exchange_deep_stack_validation.json │ │ │ │ ├── exchange_empty_stack_validation.json │ │ │ │ ├── exchange_stack_validation.json │ │ │ │ ├── forwards_rjump.json │ │ │ │ ├── forwards_rjump_variable_stack.json │ │ │ │ ├── forwards_rjumpi.json │ │ │ │ ├── forwards_rjumpi_variable_stack.json │ │ │ │ ├── forwards_rjumpv.json │ │ │ │ ├── forwards_rjumpv_variable_stack.json │ │ │ │ ├── jumpf_stack_overflow.json │ │ │ │ ├── jumpf_stack_overflow_variable_stack.json │ │ │ │ ├── jumpf_to_nonreturning.json │ │ │ │ ├── jumpf_to_nonreturning_variable_stack.json │ │ │ │ ├── jumpf_to_returning.json │ │ │ │ ├── jumpf_to_returning_variable_stack.json │ │ │ │ ├── jumpf_with_inputs_stack_overflow.json │ │ │ │ ├── jumpf_with_inputs_stack_overflow_variable_stack.json │ │ │ │ ├── no_terminating_instruction.json │ │ │ │ ├── non_constant_stack_height.json │ │ │ │ ├── retf_stack_validation.json │ │ │ │ ├── retf_variable_stack.json │ │ │ │ ├── self_referencing_jumps.json │ │ │ │ ├── self_referencing_jumps_variable_stack.json │ │ │ │ ├── stack_range_maximally_broad.json │ │ │ │ ├── swapn_stack_validation.json │ │ │ │ ├── underflow.json │ │ │ │ ├── underflow_variable_stack.json │ │ │ │ └── unreachable_instructions.json │ │ │ ├── too_many_code_sections.json │ │ │ ├── unreachable_code_sections.json │ │ │ ├── validate_EOF_prefix.json │ │ │ ├── validate_EOF_version.json │ │ │ └── validate_empty_code.json │ │ └── ori │ │ │ └── validInvalid.json │ │ └── eof.rs ├── precompile │ ├── CHANGELOG.md │ ├── Cargo.toml │ ├── LICENSE │ ├── README.md │ ├── benches │ │ └── bench.rs │ ├── src │ │ ├── blake2.rs │ │ ├── bls12_381.rs │ │ ├── bls12_381 │ │ │ ├── g1.rs │ │ │ ├── g1_add.rs │ │ │ ├── g1_msm.rs │ │ │ ├── g1_mul.rs │ │ │ ├── g2.rs │ │ │ ├── g2_add.rs │ │ │ ├── g2_msm.rs │ │ │ ├── g2_mul.rs │ │ │ ├── map_fp2_to_g2.rs │ │ │ ├── map_fp_to_g1.rs │ │ │ ├── msm.rs │ │ │ ├── pairing.rs │ │ │ └── utils.rs │ │ ├── bn128.rs │ │ ├── hash.rs │ │ ├── identity.rs │ │ ├── kzg_point_evaluation.rs │ │ ├── lib.rs │ │ ├── modexp.rs │ │ ├── secp256k1.rs │ │ ├── secp256r1.rs │ │ └── utilities.rs │ └── test-vectors │ │ ├── add_G1_bls.json │ │ ├── add_G2_bls.json │ │ ├── fail-add_G1_bls.json │ │ ├── fail-add_G2_bls.json │ │ ├── fail-map_fp2_to_G2_bls.json │ │ ├── fail-map_fp_to_G1_bls.json │ │ ├── fail-mul_G1_bls.json │ │ ├── fail-mul_G2_bls.json │ │ ├── fail-multiexp_G1_bls.json │ │ ├── fail-multiexp_G2_bls.json │ │ ├── fail-pairing_check_bls.json │ │ ├── map_fp2_to_G2_bls.json │ │ ├── map_fp_to_G1_bls.json │ │ ├── mul_G1_bls.json │ │ ├── mul_G2_bls.json │ │ ├── multiexp_G1_bls.json │ │ ├── multiexp_G2_bls.json │ │ └── pairing_check_bls.json ├── primitives │ ├── CHANGELOG.md │ ├── Cargo.toml │ ├── LICENSE │ └── src │ │ ├── bytecode.rs │ │ ├── bytecode │ │ ├── eof.rs │ │ ├── eof │ │ │ ├── body.rs │ │ │ ├── decode_helpers.rs │ │ │ ├── header.rs │ │ │ └── types_section.rs │ │ ├── legacy.rs │ │ └── legacy │ │ │ └── jump_map.rs │ │ ├── constants.rs │ │ ├── db.rs │ │ ├── db │ │ ├── components.rs │ │ └── components │ │ │ ├── block_hash.rs │ │ │ └── state.rs │ │ ├── env.rs │ │ ├── env │ │ └── handler_cfg.rs │ │ ├── kzg.rs │ │ ├── kzg │ │ ├── env_settings.rs │ │ ├── g1_points.bin │ │ ├── g2_points.bin │ │ ├── trusted_setup.txt │ │ └── trusted_setup_points.rs │ │ ├── lib.rs │ │ ├── precompile.rs │ │ ├── result.rs │ │ ├── specification.rs │ │ ├── state.rs │ │ └── utilities.rs └── revm │ ├── CHANGELOG.md │ ├── Cargo.toml │ ├── LICENSE │ ├── benches │ └── bench.rs │ └── src │ ├── builder.rs │ ├── context.rs │ ├── context │ ├── context_precompiles.rs │ ├── evm_context.rs │ └── inner_evm_context.rs │ ├── db.rs │ ├── db │ ├── alloydb.rs │ ├── emptydb.rs │ ├── ethersdb.rs │ ├── in_memory_db.rs │ ├── states.rs │ └── states │ │ ├── account_status.rs │ │ ├── bundle_account.rs │ │ ├── bundle_state.rs │ │ ├── cache.rs │ │ ├── cache_account.rs │ │ ├── changes.rs │ │ ├── plain_account.rs │ │ ├── reverts.rs │ │ ├── state.rs │ │ ├── state_builder.rs │ │ ├── transition_account.rs │ │ └── transition_state.rs │ ├── evm.rs │ ├── frame.rs │ ├── handler.rs │ ├── handler │ ├── handle_types.rs │ ├── handle_types │ │ ├── execution.rs │ │ ├── post_execution.rs │ │ ├── pre_execution.rs │ │ └── validation.rs │ ├── mainnet.rs │ ├── mainnet │ │ ├── execution.rs │ │ ├── post_execution.rs │ │ ├── pre_execution.rs │ │ └── validation.rs │ └── register.rs │ ├── inspector.rs │ ├── inspector │ ├── customprinter.rs │ ├── eip3155.rs │ ├── gas.rs │ ├── handler_register.rs │ └── noop.rs │ ├── journaled_state.rs │ ├── lib.rs │ ├── optimism.rs │ ├── optimism │ ├── fast_lz.rs │ ├── handler_register.rs │ └── l1block.rs │ └── test_utils.rs ├── documentation └── src │ ├── SUMMARY.md │ ├── bins │ ├── revm-test.md │ └── revme.md │ ├── crates │ ├── interpreter.md │ ├── interpreter │ │ ├── gas.md │ │ ├── host.md │ │ ├── instruction_result.md │ │ ├── instructions.md │ │ ├── interpreter_action.md │ │ └── memory.md │ ├── precompile.md │ ├── precompile │ │ ├── blake2.md │ │ ├── bn128.md │ │ ├── hash.md │ │ ├── identity.md │ │ ├── modexp.md │ │ ├── point_evaluation.md │ │ └── secp256k1.md │ ├── primitives.md │ ├── primitives │ │ ├── bits.md │ │ ├── bytecode.md │ │ ├── constants.md │ │ ├── database.md │ │ ├── environment.md │ │ ├── kzg.md │ │ ├── log.md │ │ ├── precompile.md │ │ ├── result.md │ │ ├── specifications.md │ │ ├── state.md │ │ └── utils.md │ ├── revm.md │ └── revm │ │ ├── builder.md │ │ ├── evm.md │ │ ├── handler.md │ │ ├── inspector.md │ │ ├── journaled_state.md │ │ └── state.md │ └── introduction.md ├── examples ├── db_by_ref.rs ├── fork_ref_transact.rs ├── generate_block_traces.rs └── uniswap_v2_usdc_swap.rs └── publish.sh /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: cargo 9 | directory: "/" 10 | schedule: 11 | interval: "weekly" 12 | -------------------------------------------------------------------------------- /.github/workflows/cachegrind.yml: -------------------------------------------------------------------------------- 1 | name: Valgrind Cachegrind 2 | 3 | on: 4 | pull_request: 5 | branches: [main] 6 | 7 | jobs: 8 | valgrind: 9 | runs-on: ubuntu-latest 10 | permissions: write-all 11 | 12 | steps: 13 | - name: Checkout code 14 | uses: actions/checkout@v4 15 | 16 | - name: Setup | Rust 17 | uses: dtolnay/rust-toolchain@stable 18 | 19 | - name: Install Valgrind 20 | run: | 21 | sudo apt-get update 22 | sudo apt-get install -y valgrind 23 | 24 | - name: Run Valgrind 25 | run: | 26 | cargo b -r -p revm-test --bin snailtracer 27 | valgrind --tool=cachegrind target/release/snailtracer 2>&1 | tee cachegrind_results.txt 28 | 29 | - name: Valgrind results 30 | id: valgrind_results 31 | run: | 32 | contents=$(printf "%s" "$(head -c 64000 cachegrind_results.txt)") 33 | # dump line by line into a file 34 | printf "Valgrind Results:\n\n\`\`\`\n%s\n\`\`\`" "$contents" > results.md 35 | 36 | - name: Comment on PR 37 | env: 38 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 39 | run: | 40 | # Try to edit the last comment 41 | if gh pr comment ${{ github.event.pull_request.number }} --edit-last --body-file results.md; then 42 | echo "Successfully edited last comment." 43 | else 44 | echo "Failed to edit last comment. Trying to add a new comment instead!" 45 | # If editing last comment fails, try to add a new comment 46 | if ! gh pr comment ${{ github.event.pull_request.number }} --body-file results.md; then 47 | echo "Comment failed to be made, printing out results here:" 48 | cat results.md 49 | fi 50 | fi 51 | -------------------------------------------------------------------------------- /.github/workflows/ethereum-tests.yml: -------------------------------------------------------------------------------- 1 | name: Ethereum Tests 2 | 3 | concurrency: 4 | cancel-in-progress: true 5 | group: ${{github.workflow}}-${{github.ref}} 6 | 7 | on: 8 | push: 9 | branches: [main, "release/**"] 10 | pull_request: 11 | branches: [main, "release/**"] 12 | 13 | jobs: 14 | tests-stable: 15 | name: Ethereum Tests (Stable) 16 | runs-on: ubuntu-latest 17 | timeout-minutes: 30 18 | strategy: 19 | matrix: 20 | profile: [ethtests, release] 21 | target: [i686-unknown-linux-gnu, x86_64-unknown-linux-gnu] 22 | steps: 23 | - name: Checkout sources 24 | uses: actions/checkout@v4 25 | 26 | - name: Checkout ethereum/tests 27 | uses: actions/checkout@v4 28 | with: 29 | repository: ethereum/tests 30 | path: ethtests 31 | submodules: recursive 32 | 33 | - name: Install toolchain 34 | uses: dtolnay/rust-toolchain@stable 35 | 36 | - uses: Swatinem/rust-cache@v2 37 | with: 38 | cache-on-failure: true 39 | 40 | - name: Install cross 41 | run: cargo install cross 42 | 43 | - name: Run Ethereum tests 44 | run: | 45 | cross run --target ${{matrix.target}} --profile ${{ matrix.profile }} -p revme -- statetest \ 46 | ethtests/GeneralStateTests/ \ 47 | ethtests/LegacyTests/Constantinople/GeneralStateTests/ \ 48 | ethtests/EIPTests/StateTests/stEIP1153-transientStorage/ \ 49 | ethtests/EIPTests/StateTests/stEIP4844-blobtransactions/ \ 50 | ethtests/EIPTests/StateTests/stEIP2537/ \ 51 | 52 | -------------------------------------------------------------------------------- /.github/workflows/release-plz.yml: -------------------------------------------------------------------------------- 1 | # Documentation: https://release-plz.ieni.dev/docs 2 | name: Release-plz 3 | 4 | permissions: 5 | pull-requests: write 6 | contents: write 7 | 8 | on: 9 | push: 10 | branches: 11 | - main 12 | 13 | jobs: 14 | release-plz: 15 | name: Release-plz 16 | runs-on: ubuntu-latest 17 | steps: 18 | - name: Checkout repository 19 | uses: actions/checkout@v4 20 | with: 21 | fetch-depth: 0 22 | - name: Install Rust toolchain 23 | uses: dtolnay/rust-toolchain@stable 24 | # Commits the cargo lock (generally a good practice for upstream libraries) 25 | - name: Commit Cargo.lock 26 | run: | 27 | git config --local user.email "action@github.com" 28 | git config --local user.name "GitHub Action" 29 | git add Cargo.lock 30 | git commit -m "Update Cargo.lock" || echo "No changes to commit" 31 | # This will run the release-plz action 32 | # The action dectect API breaking changes detection with cargo-semver-checks. 33 | # Semver is auto incremneted based on this 34 | # A PR with the semver bump is created with a new release tag and changelog 35 | # if you configure the cargo registry token, the action will also publish the new version to crates.io 36 | - name: Run release-plz 37 | uses: MarcoIeni/release-plz-action@v0.5 38 | with: 39 | command: release-pr 40 | env: 41 | # The admin of the repository with need to configure the following secrets: 42 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | **/*.rs.bk 3 | **/.DS_Store 4 | 5 | target 6 | .vscode 7 | .idea 8 | pkg/ 9 | 10 | bins/revme/temp_folder 11 | bins/revme/tests 12 | ethereumjs-util.js 13 | book 14 | 15 | # Generated by the block traces example 16 | traces 17 | 18 | burntpix/svgs 19 | 20 | # Rust bug report 21 | rustc-ice-* 22 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "bins/revme", 4 | "bins/revm-test", 5 | "crates/revm", 6 | "crates/primitives", 7 | "crates/interpreter", 8 | "crates/precompile", 9 | ] 10 | resolver = "2" 11 | default-members = ["crates/revm"] 12 | 13 | [workspace.metadata.docs.rs] 14 | all-features = true 15 | rustdoc-args = ["--cfg", "docsrs"] 16 | 17 | [profile.release] 18 | lto = true 19 | codegen-units = 1 20 | debug = true 21 | 22 | [profile.ethtests] 23 | inherits = "test" 24 | opt-level = 3 25 | -------------------------------------------------------------------------------- /Cross.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | pre-build = [ 3 | "apt-get update && apt-get install --assume-yes --no-install-recommends llvm-dev clang libclang-dev", 4 | ] 5 | 6 | [target.i686-unknown-linux-gnu] 7 | image = "ghcr.io/cross-rs/i686-unknown-linux-gnu:main" 8 | 9 | [target.x86_64-unknown-linux-gnu] 10 | image = "ghcr.io/cross-rs/x86_64-unknown-linux-gnu:main" 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-2024 draganrakita 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /assets/logo.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/megaeth-labs/revm/6d5256eaa9212e17da5a9fd8e9131fc85a0e7ad9/assets/logo.pdf -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/megaeth-labs/revm/6d5256eaa9212e17da5a9fd8e9131fc85a0e7ad9/assets/logo.png -------------------------------------------------------------------------------- /assets/revm-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/megaeth-labs/revm/6d5256eaa9212e17da5a9fd8e9131fc85a0e7ad9/assets/revm-banner.png -------------------------------------------------------------------------------- /bins/revm-test/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "revm-test" 3 | version = "0.1.0" 4 | edition = "2021" 5 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 6 | 7 | [dependencies] 8 | bytes = "1.6" 9 | hex = "0.4" 10 | revm = { path = "../../crates/revm", version = "9.0.0", default-features=false } 11 | microbench = "0.5" 12 | alloy-sol-macro = "0.7.0" 13 | alloy-sol-types = "0.7.0" 14 | regex = "1.10.4" 15 | eyre = "0.6.12" 16 | 17 | 18 | [[bin]] 19 | name = "analysis" 20 | 21 | [[bin]] 22 | name = "snailtracer" 23 | 24 | [[bin]] 25 | name = "transfer" 26 | 27 | [[bin]] 28 | name = "burntpix" 29 | -------------------------------------------------------------------------------- /bins/revm-test/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-2024 draganrakita 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /bins/revm-test/src/bin/transfer.rs: -------------------------------------------------------------------------------- 1 | use revm::{ 2 | db::BenchmarkDB, 3 | primitives::{Bytecode, TransactTo, U256}, 4 | Evm, 5 | }; 6 | 7 | use std::time::Duration; 8 | 9 | fn main() { 10 | // BenchmarkDB is dummy state that implements Database trait. 11 | let mut evm = Evm::builder() 12 | .with_db(BenchmarkDB::new_bytecode(Bytecode::new())) 13 | .modify_tx_env(|tx| { 14 | // execution globals block hash/gas_limit/coinbase/timestamp.. 15 | tx.caller = "0x0000000000000000000000000000000000000001" 16 | .parse() 17 | .unwrap(); 18 | tx.value = U256::from(10); 19 | tx.transact_to = TransactTo::Call( 20 | "0x0000000000000000000000000000000000000000" 21 | .parse() 22 | .unwrap(), 23 | ); 24 | }) 25 | .build(); 26 | 27 | // Microbenchmark 28 | let bench_options = microbench::Options::default().time(Duration::from_secs(3)); 29 | 30 | microbench::bench(&bench_options, "Simple value transfer", || { 31 | let _ = evm.transact().unwrap(); 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /bins/revme/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Dragan Rakita "] 3 | edition = "2021" 4 | name = "revme" 5 | keywords = ["ethereum", "evm"] 6 | license = "MIT" 7 | repository = "https://github.com/bluealloy/revm" 8 | description = "Rust Ethereum Virtual Machine Executable" 9 | version = "0.5.0" 10 | 11 | [dependencies] 12 | hash-db = "0.15" 13 | hex = "0.4" 14 | hashbrown = "0.14" 15 | indicatif = "0.17" 16 | microbench = "0.5" 17 | plain_hasher = "0.2" 18 | revm = { path = "../../crates/revm", version = "9.0.0", default-features = false, features = [ 19 | "ethersdb", 20 | "std", 21 | "serde-json", 22 | "c-kzg", 23 | "blst" 24 | ] } 25 | alloy-rlp = { version = "0.3", default-features = false, features = [ 26 | "arrayvec", 27 | "derive", 28 | ] } 29 | serde = { version = "1.0", features = ["derive", "rc"] } 30 | serde_json = { version = "1.0", features = ["preserve_order"] } 31 | structopt = "0.3" 32 | thiserror = "1.0" 33 | triehash = "0.8" 34 | walkdir = "2.5" 35 | k256 = { version = "0.13.3", features = ["ecdsa"] } 36 | -------------------------------------------------------------------------------- /bins/revme/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-2024 draganrakita 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /bins/revme/README.md: -------------------------------------------------------------------------------- 1 | # Rust EVM executor or short REVME 2 | 3 | `revme` is a binary crate to execute the evm in multiple ways. 4 | 5 | Currently it is mainly used to run ethereum tests with the `statetest` subcommand. 6 | 7 | ## State Tests 8 | 9 | `statetest` takes a path to the directory where ethereum statetest json can be found. 10 | It recursively parses all json files in the specified directory and executes them. 11 | 12 | Running all [ethereum tests][et] checks that revm is compliant to the ethereum specs. 13 | 14 | To run [ethereum tests][et] locally, clone the [tests][et] repository and provide the 15 | test directory. Below, we clone the repo and execute the `GeneralStateTests` suite of 16 | tests. 17 | 18 | ```shell 19 | git clone https://github.com/ethereum/tests 20 | cargo run -p revme statetest tests/GeneralStateTests 21 | ``` 22 | 23 | *Notice, in the [`.gitignore`](../../.gitignore), the `bins/revme/tests` directory 24 | is ignored so it won't be checked into git.* 25 | 26 | [et]: https://github.com/ethereum/tests 27 | -------------------------------------------------------------------------------- /bins/revme/src/cmd.rs: -------------------------------------------------------------------------------- 1 | pub mod bytecode; 2 | pub mod evmrunner; 3 | pub mod format_kzg_setup; 4 | pub mod statetest; 5 | 6 | use structopt::{clap::AppSettings, StructOpt}; 7 | 8 | #[derive(StructOpt, Debug)] 9 | #[structopt(setting = AppSettings::InferSubcommands)] 10 | #[allow(clippy::large_enum_variant)] 11 | pub enum MainCmd { 12 | #[structopt(about = "Launch Ethereum state tests")] 13 | Statetest(statetest::Cmd), 14 | #[structopt( 15 | about = "Format kzg settings from a trusted setup file (.txt) into binary format (.bin)" 16 | )] 17 | FormatKzgSetup(format_kzg_setup::Cmd), 18 | #[structopt( 19 | about = "Evm runner command allows running arbitrary evm bytecode.\nBytecode can be provided from cli or from file with --path option." 20 | )] 21 | Evm(evmrunner::Cmd), 22 | #[structopt(alias = "bc", about = "Prints the opcodes of an hex Bytecodes.")] 23 | Bytecode(bytecode::Cmd), 24 | } 25 | 26 | #[derive(Debug, thiserror::Error)] 27 | pub enum Error { 28 | #[error(transparent)] 29 | Statetest(#[from] statetest::Error), 30 | #[error(transparent)] 31 | KzgErrors(#[from] format_kzg_setup::KzgErrors), 32 | #[error(transparent)] 33 | EvmRunnerErrors(#[from] evmrunner::Errors), 34 | } 35 | 36 | impl MainCmd { 37 | pub fn run(&self) -> Result<(), Error> { 38 | match self { 39 | Self::Statetest(cmd) => cmd.run().map_err(Into::into), 40 | Self::FormatKzgSetup(cmd) => cmd.run().map_err(Into::into), 41 | Self::Evm(cmd) => cmd.run().map_err(Into::into), 42 | Self::Bytecode(cmd) => { 43 | cmd.run(); 44 | Ok(()) 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /bins/revme/src/cmd/bytecode.rs: -------------------------------------------------------------------------------- 1 | use revm::{ 2 | interpreter::opcode::eof_printer::print_eof_code, 3 | primitives::{Bytes, Eof}, 4 | }; 5 | use structopt::StructOpt; 6 | 7 | /// Statetest command 8 | #[derive(StructOpt, Debug)] 9 | pub struct Cmd { 10 | /// EOF bytecode in hex format. It bytes start with 0xFE it will be interpreted as a EOF. 11 | /// Otherwise, it will be interpreted as a EOF bytecode. 12 | #[structopt(required = true)] 13 | bytes: String, 14 | } 15 | 16 | impl Cmd { 17 | /// Run statetest command. 18 | pub fn run(&self) { 19 | let trimmed = self.bytes.trim_start_matches("0x"); 20 | let Ok(bytes) = hex::decode(trimmed) else { 21 | eprintln!("Invalid hex string"); 22 | return; 23 | }; 24 | let bytes: Bytes = bytes.into(); 25 | if bytes.is_empty() { 26 | eprintln!("Empty hex string"); 27 | return; 28 | } 29 | if bytes[0] == 0xEF { 30 | let Ok(eof) = Eof::decode(bytes) else { 31 | eprintln!("Invalid EOF bytecode"); 32 | return; 33 | }; 34 | println!("{:#?}", eof); 35 | } else { 36 | print_eof_code(&bytes) 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /bins/revme/src/cmd/format_kzg_setup.rs: -------------------------------------------------------------------------------- 1 | pub use revm::primitives::kzg::{parse_kzg_trusted_setup, G1Points, G2Points, KzgErrors}; 2 | use std::{env, fs, path::PathBuf}; 3 | use structopt::StructOpt; 4 | 5 | /// Statetest command 6 | #[derive(StructOpt, Debug)] 7 | pub struct Cmd { 8 | /// Input path to the kzg trusted setup file. 9 | #[structopt(required = true)] 10 | path: PathBuf, 11 | /// path to output g1 point in binary format. 12 | #[structopt(long)] 13 | g1: Option, 14 | /// Path to output g2 point in binary format. 15 | #[structopt(long)] 16 | g2: Option, 17 | } 18 | 19 | impl Cmd { 20 | /// Run statetest command. 21 | pub fn run(&self) -> Result<(), KzgErrors> { 22 | // check if path exists. 23 | if !self.path.exists() { 24 | return Err(KzgErrors::PathNotExists); 25 | } 26 | 27 | let out_dir = env::current_dir().map_err(|_| KzgErrors::FailedCurrentDirectory)?; 28 | 29 | let kzg_trusted_settings = 30 | fs::read_to_string(&self.path).map_err(|_| KzgErrors::NotValidFile)?; 31 | 32 | // format points 33 | let (g1, g2) = parse_kzg_trusted_setup(&kzg_trusted_settings)?; 34 | 35 | let g1_path = self 36 | .g1 37 | .clone() 38 | .unwrap_or_else(|| out_dir.join("g1_points.bin")); 39 | 40 | let g2_path = self 41 | .g2 42 | .clone() 43 | .unwrap_or_else(|| out_dir.join("g2_points.bin")); 44 | 45 | // output points 46 | fs::write(&g1_path, flatten(&g1.0)).map_err(|_| KzgErrors::IOError)?; 47 | fs::write(&g2_path, flatten(&g2.0)).map_err(|_| KzgErrors::IOError)?; 48 | println!("Finished formatting kzg trusted setup into binary representation."); 49 | println!("G1 points path: {:?}", g1_path); 50 | println!("G2 points path: {:?}", g2_path); 51 | Ok(()) 52 | } 53 | } 54 | 55 | fn flatten(x: &[[u8; N]; M]) -> &[u8] { 56 | // SAFETY: `x` is a valid `[[u8; N]; M]` and `N * M` is the length of the 57 | // returned slice. 58 | unsafe { core::slice::from_raw_parts(x.as_ptr().cast(), N * M) } 59 | } 60 | -------------------------------------------------------------------------------- /bins/revme/src/cmd/statetest.rs: -------------------------------------------------------------------------------- 1 | pub mod merkle_trie; 2 | pub mod models; 3 | mod runner; 4 | pub mod utils; 5 | 6 | pub use runner::TestError as Error; 7 | 8 | use runner::{find_all_json_tests, run, TestError}; 9 | use std::path::PathBuf; 10 | use structopt::StructOpt; 11 | 12 | /// Statetest command 13 | #[derive(StructOpt, Debug)] 14 | pub struct Cmd { 15 | /// Path to folder or file containing the tests. If multiple paths are specified 16 | /// they will be run in sequence. 17 | /// 18 | /// Folders will be searched recursively for files with the extension `.json`. 19 | #[structopt(required = true)] 20 | path: Vec, 21 | /// Run tests in a single thread. 22 | #[structopt(short = "s", long)] 23 | single_thread: bool, 24 | /// Output results in JSON format. 25 | /// It will stop second run of evm on failure. 26 | #[structopt(long)] 27 | json: bool, 28 | /// Output outcome in JSON format. If json is true, this is implied. 29 | /// It will stop second run of evm on failure. 30 | #[structopt(short = "o", long)] 31 | json_outcome: bool, 32 | #[structopt(long, alias = "no-fail-fast")] 33 | keep_going: bool, 34 | } 35 | 36 | impl Cmd { 37 | /// Run statetest command. 38 | pub fn run(&self) -> Result<(), TestError> { 39 | for path in &self.path { 40 | println!("\nRunning tests in {}...", path.display()); 41 | let test_files = find_all_json_tests(path); 42 | run( 43 | test_files, 44 | self.single_thread, 45 | self.json, 46 | self.json_outcome, 47 | self.keep_going, 48 | )? 49 | } 50 | Ok(()) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /bins/revme/src/cmd/statetest/merkle_trie.rs: -------------------------------------------------------------------------------- 1 | use alloy_rlp::{RlpEncodable, RlpMaxEncodedLen}; 2 | use hash_db::Hasher; 3 | use plain_hasher::PlainHasher; 4 | use revm::{ 5 | db::PlainAccount, 6 | primitives::{keccak256, Address, Log, B256, U256}, 7 | }; 8 | use triehash::sec_trie_root; 9 | 10 | pub fn log_rlp_hash(logs: &[Log]) -> B256 { 11 | let mut out = Vec::with_capacity(alloy_rlp::list_length(logs)); 12 | alloy_rlp::encode_list(logs, &mut out); 13 | keccak256(&out) 14 | } 15 | 16 | pub fn state_merkle_trie_root<'a>( 17 | accounts: impl IntoIterator, 18 | ) -> B256 { 19 | trie_root(accounts.into_iter().map(|(address, acc)| { 20 | ( 21 | address, 22 | alloy_rlp::encode_fixed_size(&TrieAccount::new(acc)), 23 | ) 24 | })) 25 | } 26 | 27 | #[derive(RlpEncodable, RlpMaxEncodedLen)] 28 | struct TrieAccount { 29 | nonce: u64, 30 | balance: U256, 31 | root_hash: B256, 32 | code_hash: B256, 33 | } 34 | 35 | impl TrieAccount { 36 | fn new(acc: &PlainAccount) -> Self { 37 | Self { 38 | nonce: acc.info.nonce, 39 | balance: acc.info.balance, 40 | root_hash: sec_trie_root::( 41 | acc.storage 42 | .iter() 43 | .filter(|(_k, &v)| v != U256::ZERO) 44 | .map(|(k, v)| (k.to_be_bytes::<32>(), alloy_rlp::encode_fixed_size(v))), 45 | ), 46 | code_hash: acc.info.code_hash, 47 | } 48 | } 49 | } 50 | 51 | #[inline] 52 | pub fn trie_root(input: I) -> B256 53 | where 54 | I: IntoIterator, 55 | A: AsRef<[u8]>, 56 | B: AsRef<[u8]>, 57 | { 58 | sec_trie_root::(input) 59 | } 60 | 61 | #[derive(Default, Debug, Clone, PartialEq, Eq, Hash)] 62 | pub struct KeccakHasher; 63 | 64 | impl Hasher for KeccakHasher { 65 | type Out = B256; 66 | type StdHasher = PlainHasher; 67 | const LENGTH: usize = 32; 68 | 69 | #[inline] 70 | fn hash(x: &[u8]) -> Self::Out { 71 | keccak256(x) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /bins/revme/src/cmd/statetest/models/deserializer.rs: -------------------------------------------------------------------------------- 1 | use revm::primitives::Address; 2 | use serde::{de, Deserialize}; 3 | 4 | pub fn deserialize_str_as_u64<'de, D>(deserializer: D) -> Result 5 | where 6 | D: de::Deserializer<'de>, 7 | { 8 | let string = String::deserialize(deserializer)?; 9 | 10 | if let Some(stripped) = string.strip_prefix("0x") { 11 | u64::from_str_radix(stripped, 16) 12 | } else { 13 | string.parse() 14 | } 15 | .map_err(serde::de::Error::custom) 16 | } 17 | 18 | pub fn deserialize_maybe_empty<'de, D>(deserializer: D) -> Result, D::Error> 19 | where 20 | D: de::Deserializer<'de>, 21 | { 22 | let string = String::deserialize(deserializer)?; 23 | if string.is_empty() { 24 | Ok(None) 25 | } else { 26 | string.parse().map_err(de::Error::custom).map(Some) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /bins/revme/src/cmd/statetest/models/spec.rs: -------------------------------------------------------------------------------- 1 | use revm::primitives::SpecId; 2 | use serde::Deserialize; 3 | 4 | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize, Hash)] 5 | pub enum SpecName { 6 | Frontier, 7 | FrontierToHomesteadAt5, 8 | Homestead, 9 | HomesteadToDaoAt5, 10 | HomesteadToEIP150At5, 11 | EIP150, 12 | EIP158, // EIP-161: State trie clearing 13 | EIP158ToByzantiumAt5, 14 | Byzantium, 15 | ByzantiumToConstantinopleAt5, // SKIPPED 16 | ByzantiumToConstantinopleFixAt5, 17 | Constantinople, // SKIPPED 18 | ConstantinopleFix, 19 | Istanbul, 20 | Berlin, 21 | BerlinToLondonAt5, 22 | London, 23 | Merge, 24 | Shanghai, 25 | Cancun, 26 | #[serde(other)] 27 | Unknown, 28 | } 29 | 30 | impl SpecName { 31 | pub fn to_spec_id(&self) -> SpecId { 32 | match self { 33 | Self::Frontier => SpecId::FRONTIER, 34 | Self::Homestead | Self::FrontierToHomesteadAt5 => SpecId::HOMESTEAD, 35 | Self::EIP150 | Self::HomesteadToDaoAt5 | Self::HomesteadToEIP150At5 => { 36 | SpecId::TANGERINE 37 | } 38 | Self::EIP158 => SpecId::SPURIOUS_DRAGON, 39 | Self::Byzantium | Self::EIP158ToByzantiumAt5 => SpecId::BYZANTIUM, 40 | Self::ConstantinopleFix | Self::ByzantiumToConstantinopleFixAt5 => SpecId::PETERSBURG, 41 | Self::Istanbul => SpecId::ISTANBUL, 42 | Self::Berlin => SpecId::BERLIN, 43 | Self::London | Self::BerlinToLondonAt5 => SpecId::LONDON, 44 | Self::Merge => SpecId::MERGE, 45 | Self::Shanghai => SpecId::SHANGHAI, 46 | Self::Cancun => SpecId::CANCUN, 47 | Self::ByzantiumToConstantinopleAt5 | Self::Constantinople => { 48 | panic!("Overridden with PETERSBURG") 49 | } 50 | Self::Unknown => panic!("Unknown spec"), 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /bins/revme/src/cmd/statetest/utils.rs: -------------------------------------------------------------------------------- 1 | use k256::ecdsa::SigningKey; 2 | use revm::primitives::Address; 3 | 4 | /// Recover the address from a private key (SigningKey). 5 | pub fn recover_address(private_key: &[u8]) -> Option
{ 6 | let key = SigningKey::from_slice(private_key).ok()?; 7 | let public_key = key.verifying_key().to_encoded_point(false); 8 | Some(Address::from_raw_public_key(&public_key.as_bytes()[1..])) 9 | } 10 | 11 | #[cfg(test)] 12 | mod tests { 13 | use super::*; 14 | use revm::primitives::{address, hex}; 15 | 16 | #[test] 17 | fn sanity_test() { 18 | assert_eq!( 19 | Some(address!("a94f5374fce5edbc8e2a8697c15331677e6ebf0b")), 20 | recover_address(&hex!( 21 | "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" 22 | )) 23 | ) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /bins/revme/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod cmd; 2 | -------------------------------------------------------------------------------- /bins/revme/src/main.rs: -------------------------------------------------------------------------------- 1 | use revme::cmd::{Error, MainCmd}; 2 | use structopt::StructOpt; 3 | 4 | pub fn main() -> Result<(), Error> { 5 | let cmd = MainCmd::from_args(); 6 | if let Err(e) = cmd.run() { 7 | println!("{:?}", e); 8 | return Err(e); 9 | } 10 | Ok(()) 11 | } 12 | -------------------------------------------------------------------------------- /book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["Colin Roberts, Waylon Jepsen", "Dragan Rakita"] 3 | language = "en" 4 | multilingual = false 5 | src = "documentation/src" 6 | title = "Rust EVM" 7 | 8 | [output.linkcheck] 9 | optional = true 10 | follow-web-links = true 11 | -------------------------------------------------------------------------------- /crates/interpreter/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-2024 draganrakita 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /crates/interpreter/src/function_stack.rs: -------------------------------------------------------------------------------- 1 | use std::vec::Vec; 2 | 3 | /// Function return frame. 4 | /// Needed information for returning from a function. 5 | #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] 6 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 7 | pub struct FunctionReturnFrame { 8 | /// The index of the code container that this frame is executing. 9 | pub idx: usize, 10 | /// The program counter where frame execution should continue. 11 | pub pc: usize, 12 | } 13 | 14 | impl FunctionReturnFrame { 15 | /// Return new function frame. 16 | pub fn new(idx: usize, pc: usize) -> Self { 17 | Self { idx, pc } 18 | } 19 | } 20 | 21 | /// Function Stack 22 | #[derive(Debug, Default)] 23 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 24 | pub struct FunctionStack { 25 | pub return_stack: Vec, 26 | pub current_code_idx: usize, 27 | } 28 | 29 | impl FunctionStack { 30 | /// Returns new function stack. 31 | pub fn new() -> Self { 32 | Self { 33 | return_stack: Vec::new(), 34 | current_code_idx: 0, 35 | } 36 | } 37 | 38 | /// Pushes a new frame to the stack. and sets current_code_idx to new value. 39 | pub fn push(&mut self, program_counter: usize, new_idx: usize) { 40 | self.return_stack.push(FunctionReturnFrame { 41 | idx: self.current_code_idx, 42 | pc: program_counter, 43 | }); 44 | self.current_code_idx = new_idx; 45 | } 46 | 47 | /// Return stack length 48 | pub fn return_stack_len(&self) -> usize { 49 | self.return_stack.len() 50 | } 51 | 52 | /// Pops a frame from the stack and sets current_code_idx to the popped frame's idx. 53 | pub fn pop(&mut self) -> Option { 54 | self.return_stack.pop().map(|frame| { 55 | self.current_code_idx = frame.idx; 56 | frame 57 | }) 58 | } 59 | 60 | /// Sets current_code_idx, this is needed for JUMPF opcode. 61 | pub fn set_current_code_idx(&mut self, idx: usize) { 62 | self.current_code_idx = idx; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /crates/interpreter/src/gas/constants.rs: -------------------------------------------------------------------------------- 1 | pub const ZERO: u64 = 0; 2 | pub const BASE: u64 = 2; 3 | 4 | pub const VERYLOW: u64 = 3; 5 | pub const DATA_LOADN_GAS: u64 = 3; 6 | 7 | pub const CONDITION_JUMP_GAS: u64 = 4; 8 | pub const RETF_GAS: u64 = 4; 9 | pub const DATA_LOAD_GAS: u64 = 4; 10 | 11 | pub const LOW: u64 = 5; 12 | pub const MID: u64 = 8; 13 | pub const HIGH: u64 = 10; 14 | pub const JUMPDEST: u64 = 1; 15 | pub const SELFDESTRUCT: i64 = 24000; 16 | pub const CREATE: u64 = 32000; 17 | pub const CALLVALUE: u64 = 9000; 18 | pub const NEWACCOUNT: u64 = 25000; 19 | pub const EXP: u64 = 10; 20 | pub const MEMORY: u64 = 3; 21 | pub const LOG: u64 = 375; 22 | pub const LOGDATA: u64 = 8; 23 | pub const LOGTOPIC: u64 = 375; 24 | pub const KECCAK256: u64 = 30; 25 | pub const KECCAK256WORD: u64 = 6; 26 | pub const COPY: u64 = 3; 27 | pub const BLOCKHASH: u64 = 20; 28 | pub const CODEDEPOSIT: u64 = 200; 29 | 30 | /// EIP-1884: Repricing for trie-size-dependent opcodes 31 | pub const INSTANBUL_SLOAD_GAS: u64 = 800; 32 | pub const SSTORE_SET: u64 = 20000; 33 | pub const SSTORE_RESET: u64 = 5000; 34 | pub const REFUND_SSTORE_CLEARS: i64 = 15000; 35 | 36 | pub const TRANSACTION_ZERO_DATA: u64 = 4; 37 | pub const TRANSACTION_NON_ZERO_DATA_INIT: u64 = 16; 38 | pub const TRANSACTION_NON_ZERO_DATA_FRONTIER: u64 = 68; 39 | 40 | pub const EOF_CREATE_GAS: u64 = 32000; 41 | 42 | // berlin eip2929 constants 43 | pub const ACCESS_LIST_ADDRESS: u64 = 2400; 44 | pub const ACCESS_LIST_STORAGE_KEY: u64 = 1900; 45 | pub const COLD_SLOAD_COST: u64 = 2100; 46 | pub const COLD_ACCOUNT_ACCESS_COST: u64 = 2600; 47 | pub const WARM_STORAGE_READ_COST: u64 = 100; 48 | pub const WARM_SSTORE_RESET: u64 = SSTORE_RESET - COLD_SLOAD_COST; 49 | 50 | /// EIP-3860 : Limit and meter initcode 51 | pub const INITCODE_WORD_COST: u64 = 2; 52 | 53 | pub const CALL_STIPEND: u64 = 2300; 54 | -------------------------------------------------------------------------------- /crates/interpreter/src/instructions.rs: -------------------------------------------------------------------------------- 1 | //! EVM opcode implementations. 2 | 3 | #[macro_use] 4 | pub mod macros; 5 | pub mod arithmetic; 6 | pub mod bitwise; 7 | pub mod contract; 8 | pub mod control; 9 | pub mod data; 10 | pub mod host; 11 | pub mod host_env; 12 | pub mod i256; 13 | pub mod memory; 14 | pub mod stack; 15 | pub mod system; 16 | pub mod utility; 17 | -------------------------------------------------------------------------------- /crates/interpreter/src/instructions/contract/call_helpers.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | gas, 3 | interpreter::Interpreter, 4 | primitives::{Bytes, Spec, SpecId::*, U256}, 5 | }; 6 | use core::{cmp::min, ops::Range}; 7 | 8 | #[inline] 9 | pub fn get_memory_input_and_out_ranges( 10 | interpreter: &mut Interpreter, 11 | ) -> Option<(Bytes, Range)> { 12 | pop_ret!(interpreter, in_offset, in_len, out_offset, out_len, None); 13 | 14 | let in_range = resize_memory_and_return_range(interpreter, in_offset, in_len)?; 15 | 16 | let mut input = Bytes::new(); 17 | if !in_range.is_empty() { 18 | input = Bytes::copy_from_slice(interpreter.shared_memory.slice_range(in_range)); 19 | } 20 | 21 | let ret_range = resize_memory_and_return_range(interpreter, out_offset, out_len)?; 22 | Some((input, ret_range)) 23 | } 24 | 25 | /// Resize memory and return range of memory. 26 | /// If `len` is 0 dont touch memory and return `usize::MAX` as offset and 0 as length. 27 | #[inline] 28 | pub fn resize_memory_and_return_range( 29 | interpreter: &mut Interpreter, 30 | offset: U256, 31 | len: U256, 32 | ) -> Option> { 33 | let len = as_usize_or_fail_ret!(interpreter, len, None); 34 | let offset = if len != 0 { 35 | let offset = as_usize_or_fail_ret!(interpreter, offset, None); 36 | resize_memory!(interpreter, offset, len, None); 37 | offset 38 | } else { 39 | usize::MAX //unrealistic value so we are sure it is not used 40 | }; 41 | Some(offset..offset + len) 42 | } 43 | 44 | #[inline] 45 | pub fn calc_call_gas( 46 | interpreter: &mut Interpreter, 47 | is_cold: bool, 48 | has_transfer: bool, 49 | new_account_accounting: bool, 50 | local_gas_limit: u64, 51 | ) -> Option { 52 | let call_cost = gas::call_cost(SPEC::SPEC_ID, has_transfer, is_cold, new_account_accounting); 53 | 54 | gas!(interpreter, call_cost, None); 55 | 56 | // EIP-150: Gas cost changes for IO-heavy operations 57 | let gas_limit = if SPEC::enabled(TANGERINE) { 58 | let gas = interpreter.gas().remaining(); 59 | // take l64 part of gas_limit 60 | min(gas - gas / 64, local_gas_limit) 61 | } else { 62 | local_gas_limit 63 | }; 64 | 65 | Some(gas_limit) 66 | } 67 | -------------------------------------------------------------------------------- /crates/interpreter/src/instructions/memory.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | gas, 3 | primitives::{Spec, U256}, 4 | Host, Interpreter, 5 | }; 6 | use core::cmp::max; 7 | 8 | pub fn mload(interpreter: &mut Interpreter, _host: &mut H) { 9 | gas!(interpreter, gas::VERYLOW); 10 | pop_top!(interpreter, top); 11 | let offset = as_usize_or_fail!(interpreter, top); 12 | resize_memory!(interpreter, offset, 32); 13 | *top = interpreter.shared_memory.get_u256(offset); 14 | } 15 | 16 | pub fn mstore(interpreter: &mut Interpreter, _host: &mut H) { 17 | gas!(interpreter, gas::VERYLOW); 18 | pop!(interpreter, offset, value); 19 | let offset = as_usize_or_fail!(interpreter, offset); 20 | resize_memory!(interpreter, offset, 32); 21 | interpreter.shared_memory.set_u256(offset, value); 22 | } 23 | 24 | pub fn mstore8(interpreter: &mut Interpreter, _host: &mut H) { 25 | gas!(interpreter, gas::VERYLOW); 26 | pop!(interpreter, offset, value); 27 | let offset = as_usize_or_fail!(interpreter, offset); 28 | resize_memory!(interpreter, offset, 1); 29 | interpreter.shared_memory.set_byte(offset, value.byte(0)) 30 | } 31 | 32 | pub fn msize(interpreter: &mut Interpreter, _host: &mut H) { 33 | gas!(interpreter, gas::BASE); 34 | push!(interpreter, U256::from(interpreter.shared_memory.len())); 35 | } 36 | 37 | // EIP-5656: MCOPY - Memory copying instruction 38 | pub fn mcopy(interpreter: &mut Interpreter, _host: &mut H) { 39 | check!(interpreter, CANCUN); 40 | pop!(interpreter, dst, src, len); 41 | 42 | // into usize or fail 43 | let len = as_usize_or_fail!(interpreter, len); 44 | // deduce gas 45 | gas_or_fail!(interpreter, gas::verylowcopy_cost(len as u64)); 46 | if len == 0 { 47 | return; 48 | } 49 | 50 | let dst = as_usize_or_fail!(interpreter, dst); 51 | let src = as_usize_or_fail!(interpreter, src); 52 | // resize memory 53 | resize_memory!(interpreter, max(dst, src), len); 54 | // copy memory in place 55 | interpreter.shared_memory.copy(dst, src, len); 56 | } 57 | -------------------------------------------------------------------------------- /crates/interpreter/src/instructions/utility.rs: -------------------------------------------------------------------------------- 1 | pub(crate) unsafe fn read_i16(ptr: *const u8) -> i16 { 2 | i16::from_be_bytes(core::slice::from_raw_parts(ptr, 2).try_into().unwrap()) 3 | } 4 | 5 | pub(crate) unsafe fn read_u16(ptr: *const u8) -> u16 { 6 | u16::from_be_bytes(core::slice::from_raw_parts(ptr, 2).try_into().unwrap()) 7 | } 8 | -------------------------------------------------------------------------------- /crates/interpreter/src/interpreter_action.rs: -------------------------------------------------------------------------------- 1 | mod call_inputs; 2 | mod call_outcome; 3 | mod create_inputs; 4 | mod create_outcome; 5 | mod eof_create_inputs; 6 | mod eof_create_outcome; 7 | 8 | pub use call_inputs::{CallInputs, CallScheme, CallValue}; 9 | pub use call_outcome::CallOutcome; 10 | pub use create_inputs::{CreateInputs, CreateScheme}; 11 | pub use create_outcome::CreateOutcome; 12 | pub use eof_create_inputs::EOFCreateInput; 13 | pub use eof_create_outcome::EOFCreateOutcome; 14 | 15 | use crate::InterpreterResult; 16 | use std::boxed::Box; 17 | 18 | #[derive(Clone, Debug, Default, PartialEq, Eq)] 19 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 20 | pub enum InterpreterAction { 21 | /// CALL, CALLCODE, DELEGATECALL, STATICCALL 22 | /// or EOF EXT instuction called. 23 | Call { inputs: Box }, 24 | /// CREATE or CREATE2 instruction called. 25 | Create { inputs: Box }, 26 | /// EOF CREATE instruction called. 27 | EOFCreate { inputs: Box }, 28 | /// Interpreter finished execution. 29 | Return { result: InterpreterResult }, 30 | /// No action 31 | #[default] 32 | None, 33 | } 34 | 35 | impl InterpreterAction { 36 | /// Returns true if action is call. 37 | pub fn is_call(&self) -> bool { 38 | matches!(self, InterpreterAction::Call { .. }) 39 | } 40 | 41 | /// Returns true if action is create. 42 | pub fn is_create(&self) -> bool { 43 | matches!(self, InterpreterAction::Create { .. }) 44 | } 45 | 46 | /// Returns true if action is return. 47 | pub fn is_return(&self) -> bool { 48 | matches!(self, InterpreterAction::Return { .. }) 49 | } 50 | 51 | /// Returns true if action is none. 52 | pub fn is_none(&self) -> bool { 53 | matches!(self, InterpreterAction::None) 54 | } 55 | 56 | /// Returns true if action is some. 57 | pub fn is_some(&self) -> bool { 58 | !self.is_none() 59 | } 60 | 61 | /// Returns result if action is return. 62 | pub fn into_result_return(self) -> Option { 63 | match self { 64 | InterpreterAction::Return { result } => Some(result), 65 | _ => None, 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /crates/interpreter/src/interpreter_action/create_inputs.rs: -------------------------------------------------------------------------------- 1 | pub use crate::primitives::CreateScheme; 2 | use crate::primitives::{Address, Bytes, TransactTo, TxEnv, U256}; 3 | use std::boxed::Box; 4 | 5 | /// Inputs for a create call. 6 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] 7 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 8 | pub struct CreateInputs { 9 | /// Caller address of the EVM. 10 | pub caller: Address, 11 | /// The create scheme. 12 | pub scheme: CreateScheme, 13 | /// The value to transfer. 14 | pub value: U256, 15 | /// The init code of the contract. 16 | pub init_code: Bytes, 17 | /// The gas limit of the call. 18 | pub gas_limit: u64, 19 | } 20 | 21 | impl CreateInputs { 22 | /// Creates new create inputs. 23 | pub fn new(tx_env: &TxEnv, gas_limit: u64) -> Option { 24 | let TransactTo::Create = tx_env.transact_to else { 25 | return None; 26 | }; 27 | 28 | Some(CreateInputs { 29 | caller: tx_env.caller, 30 | scheme: CreateScheme::Create, 31 | value: tx_env.value, 32 | init_code: tx_env.data.clone(), 33 | gas_limit, 34 | }) 35 | } 36 | 37 | /// Returns boxed create inputs. 38 | pub fn new_boxed(tx_env: &TxEnv, gas_limit: u64) -> Option> { 39 | Self::new(tx_env, gas_limit).map(Box::new) 40 | } 41 | 42 | /// Returns the address that this create call will create. 43 | pub fn created_address(&self, nonce: u64) -> Address { 44 | match self.scheme { 45 | CreateScheme::Create => self.caller.create(nonce), 46 | CreateScheme::Create2 { salt } => self 47 | .caller 48 | .create2_from_code(salt.to_be_bytes(), &self.init_code), 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /crates/interpreter/src/interpreter_action/eof_create_inputs.rs: -------------------------------------------------------------------------------- 1 | use crate::primitives::{Address, Eof, U256}; 2 | use core::ops::Range; 3 | 4 | /// Inputs for EOF create call. 5 | #[derive(Debug, Default, Clone, PartialEq, Eq)] 6 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 7 | pub struct EOFCreateInput { 8 | /// Caller of Eof Craate 9 | pub caller: Address, 10 | /// New contract address. 11 | pub created_address: Address, 12 | /// Values of ether transfered 13 | pub value: U256, 14 | /// Init eof code that is going to be executed. 15 | pub eof_init_code: Eof, 16 | /// Gas limit for the create call. 17 | pub gas_limit: u64, 18 | /// Return memory range. If EOF creation Reverts it can return the 19 | /// the memory range. 20 | pub return_memory_range: Range, 21 | } 22 | 23 | impl EOFCreateInput { 24 | /// Returns a new instance of EOFCreateInput. 25 | pub fn new( 26 | caller: Address, 27 | created_address: Address, 28 | value: U256, 29 | eof_init_code: Eof, 30 | gas_limit: u64, 31 | return_memory_range: Range, 32 | ) -> EOFCreateInput { 33 | EOFCreateInput { 34 | caller, 35 | created_address, 36 | value, 37 | eof_init_code, 38 | gas_limit, 39 | return_memory_range, 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /crates/interpreter/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # revm-interpreter 2 | //! 3 | //! REVM Interpreter. 4 | #![cfg_attr(not(test), warn(unused_crate_dependencies))] 5 | #![cfg_attr(not(feature = "std"), no_std)] 6 | 7 | #[cfg(not(feature = "std"))] 8 | extern crate alloc as std; 9 | 10 | #[macro_use] 11 | mod macros; 12 | 13 | // silence lint 14 | #[cfg(test)] 15 | use serde_json as _; 16 | 17 | #[cfg(test)] 18 | use walkdir as _; 19 | 20 | mod function_stack; 21 | pub mod gas; 22 | mod host; 23 | mod instruction_result; 24 | pub mod instructions; 25 | pub mod interpreter; 26 | pub mod interpreter_action; 27 | pub mod opcode; 28 | 29 | // Reexport primary types. 30 | pub use function_stack::{FunctionReturnFrame, FunctionStack}; 31 | pub use gas::Gas; 32 | pub use host::{DummyHost, Host, LoadAccountResult, SStoreResult, SelfDestructResult}; 33 | pub use instruction_result::*; 34 | pub use interpreter::{ 35 | analysis, num_words, Contract, Interpreter, InterpreterResult, SharedMemory, Stack, 36 | EMPTY_SHARED_MEMORY, STACK_LIMIT, 37 | }; 38 | pub use interpreter_action::{ 39 | CallInputs, CallOutcome, CallScheme, CallValue, CreateInputs, CreateOutcome, CreateScheme, 40 | EOFCreateInput, EOFCreateOutcome, InterpreterAction, 41 | }; 42 | pub use opcode::{Instruction, OpCode, OPCODE_INFO_JUMPTABLE}; 43 | pub use primitives::{MAX_CODE_SIZE, MAX_INITCODE_SIZE}; 44 | 45 | #[doc(hidden)] 46 | pub use revm_primitives as primitives; 47 | -------------------------------------------------------------------------------- /crates/interpreter/src/macros.rs: -------------------------------------------------------------------------------- 1 | macro_rules! debug_unreachable { 2 | ($($t:tt)*) => { 3 | if cfg!(debug_assertions) { 4 | unreachable!($($t)*); 5 | } else { 6 | unsafe { core::hint::unreachable_unchecked() }; 7 | } 8 | }; 9 | } 10 | 11 | macro_rules! assume { 12 | ($e:expr $(,)?) => { 13 | if !$e { 14 | debug_unreachable!(stringify!($e)); 15 | } 16 | }; 17 | 18 | ($e:expr, $($t:tt)+) => { 19 | if !$e { 20 | debug_unreachable!($($t)+); 21 | } 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /crates/interpreter/src/opcode/eof_printer.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "std")] 2 | pub fn print_eof_code(code: &[u8]) { 3 | use super::*; 4 | use crate::instructions::utility::read_i16; 5 | use revm_primitives::hex; 6 | 7 | // We can check validity and jump destinations in one pass. 8 | let mut i = 0; 9 | while i < code.len() { 10 | let op = code[i]; 11 | let opcode = &OPCODE_INFO_JUMPTABLE[op as usize]; 12 | 13 | let Some(opcode) = opcode else { 14 | println!("Unknown opcode: 0x{:02X}", op); 15 | i += 1; 16 | continue; 17 | }; 18 | 19 | if opcode.immediate_size() != 0 { 20 | // check if the opcode immediate are within the bounds of the code 21 | if i + opcode.immediate_size() as usize >= code.len() { 22 | println!("Malformed code: immediate out of bounds"); 23 | break; 24 | } 25 | } 26 | 27 | print!("{}", opcode.name()); 28 | if opcode.immediate_size() != 0 { 29 | print!( 30 | " : 0x{:}", 31 | hex::encode(&code[i + 1..i + 1 + opcode.immediate_size() as usize]) 32 | ); 33 | } 34 | 35 | let mut rjumpv_additional_immediates = 0; 36 | if op == RJUMPV { 37 | let max_index = code[i + 1] as usize; 38 | let len = max_index + 1; 39 | // and max_index+1 is to get size of vtable as index starts from 0. 40 | rjumpv_additional_immediates = len * 2; 41 | 42 | // +1 is for max_index byte 43 | if i + 1 + rjumpv_additional_immediates >= code.len() { 44 | println!("Malformed code: immediate out of bounds"); 45 | break; 46 | } 47 | 48 | for vtablei in 0..len { 49 | let offset = unsafe { read_i16(code.as_ptr().add(i + 2 + 2 * vtablei)) } as isize; 50 | println!("RJUMPV[{vtablei}]: 0x{offset:04X}({offset})"); 51 | } 52 | } 53 | 54 | i += 1 + opcode.immediate_size() as usize + rjumpv_additional_immediates; 55 | } 56 | } 57 | 58 | #[cfg(test)] 59 | mod test { 60 | use super::*; 61 | use revm_primitives::hex; 62 | 63 | #[test] 64 | fn sanity_test() { 65 | print_eof_code(&hex!("6001e200ffff00")); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/efExample/ymlExample.json: -------------------------------------------------------------------------------- 1 | { 2 | "ymlExample" : { 3 | "_info" : { 4 | "comment" : "EOF example test", 5 | "filling-rpc-server" : "evmone-t8n 0.12.0-dev+commit.14ba7529", 6 | "filling-tool-version" : "retesteth-0.3.2-cancun+commit.9d793abd.Linux.g++", 7 | "generatedTestHash" : "acafd37d166881fa1a015acb1d6ff88f0f698e14a7db9098952065aaa90e78e5", 8 | "lllcversion" : "Version: 0.5.14-develop.2022.4.6+commit.401d5358.Linux.g++", 9 | "solidity" : "Version: 0.8.18-develop.2023.1.16+commit.469d6d4d.Linux.g++", 10 | "source" : "src/EOFTestsFiller/efExample/ymlExampleFiller.yml", 11 | "sourceHash" : "3eb098795ee0f651ae94dab0674f1a6f2e9dd5d6210cf6719508d9f301b4b71d" 12 | }, 13 | "vectors" : { 14 | "ymlExample_0" : { 15 | "code" : "0x60016000f3", 16 | "results" : { 17 | "Prague" : { 18 | "exception" : "EOF_InvalidPrefix", 19 | "result" : false 20 | } 21 | } 22 | }, 23 | "ymlExample_1" : { 24 | "code" : "0xef0001010004020001000a040016000080000338600060003938601df3ef0001010004020001000304001d0000800001385000", 25 | "results" : { 26 | "Prague" : { 27 | "result" : true 28 | } 29 | } 30 | }, 31 | "ymlExample_2" : { 32 | "code" : "0xefffff", 33 | "results" : { 34 | "Prague" : { 35 | "exception" : "EOF_InvalidPrefix", 36 | "result" : false 37 | } 38 | } 39 | }, 40 | "ymlExample_3" : { 41 | "code" : "0x610badfe", 42 | "results" : { 43 | "Prague" : { 44 | "exception" : "EOF_InvalidPrefix", 45 | "result" : false 46 | } 47 | } 48 | } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_callf_truncated.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_callf_truncated": { 3 | "vectors": { 4 | "EOF1_callf_truncated_0": { 5 | "code": "0xef000101000402000100010400000000800000e3", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_TruncatedImmediate", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "EOF1_callf_truncated_1": { 14 | "code": "0xef000101000402000100020400000000800000e300", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_TruncatedImmediate", 18 | "result": false 19 | } 20 | } 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_code_section_0_size.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_code_section_0_size": { 3 | "vectors": { 4 | "EOF1_code_section_0_size_0": { 5 | "code": "0xef000101000402000000", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_ZeroSectionSize", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "EOF1_code_section_0_size_1": { 14 | "code": "0xef000101000402000004000100da", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_ZeroSectionSize", 18 | "result": false 19 | } 20 | } 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_code_section_missing.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_code_section_missing": { 3 | "vectors": { 4 | "EOF1_code_section_missing_0": { 5 | "code": "0xef000101000400", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_CodeSectionMissing", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "EOF1_code_section_missing_1": { 14 | "code": "0xef00010100040400010000800000da", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_CodeSectionMissing", 18 | "result": false 19 | } 20 | } 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_code_section_offset.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_code_section_offset": { 3 | "vectors": { 4 | "EOF1_code_section_offset_0": { 5 | "code": "0xef000101000802000200030001040004000080000000800000e50001fe00000000", 6 | "results": { 7 | "Prague": { 8 | "result": true 9 | } 10 | } 11 | } 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_data_section_0_size.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_data_section_0_size": { 3 | "vectors": { 4 | "EOF1_data_section_0_size_0": { 5 | "code": "0xef000101000402000100010400000000800000fe", 6 | "results": { 7 | "Prague": { 8 | "result": true 9 | } 10 | } 11 | } 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_data_section_before_code_section.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_data_section_before_code_section": { 3 | "vectors": { 4 | "EOF1_data_section_before_code_section_0": { 5 | "code": "0xef000101000403000102000100010000800000aafe", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_CodeSectionMissing", 9 | "result": false 10 | } 11 | } 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_data_section_before_types_section.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_data_section_before_types_section": { 3 | "vectors": { 4 | "EOF1_data_section_before_types_section_0": { 5 | "code": "0xef0001040001010004020001000100aa00800000fe", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_TypeSectionMissing", 9 | "result": false 10 | } 11 | } 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_dataloadn_truncated.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_dataloadn_truncated": { 3 | "vectors": { 4 | "EOF1_dataloadn_truncated_0": { 5 | "code": "0xef000101000402000100010400000000800000d1", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_TruncatedImmediate", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "EOF1_dataloadn_truncated_1": { 14 | "code": "0xef000101000402000100020400000000800000d100", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_TruncatedImmediate", 18 | "result": false 19 | } 20 | } 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_eofcreate_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_eofcreate_invalid": { 3 | "vectors": { 4 | "EOF1_eofcreate_invalid_0": { 5 | "code": "0xef0001010004020001000903000100140400000000800004600060ff60006000ecef000101000402000100010400000000800000fe", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_TruncatedImmediate", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "EOF1_eofcreate_invalid_1": { 14 | "code": "0xef0001010004020001000a03000100140400000000800004600060ff60006000ec00ef000101000402000100010400000000800000fe", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_InvalidCodeTermination", 18 | "result": false 19 | } 20 | } 21 | }, 22 | "EOF1_eofcreate_invalid_2": { 23 | "code": "0xef0001010004020001000c03000100140400000000800004600060ff60006000ec015000ef000101000402000100010400000000800000fe", 24 | "results": { 25 | "Prague": { 26 | "exception": "EOF_InvalidContainerSectionIndex", 27 | "result": false 28 | } 29 | } 30 | }, 31 | "EOF1_eofcreate_invalid_3": { 32 | "code": "0xef0001010004020001000c03000100140400000000800004600060ff60006000ecff5000ef000101000402000100010400000000800000fe", 33 | "results": { 34 | "Prague": { 35 | "exception": "EOF_InvalidContainerSectionIndex", 36 | "result": false 37 | } 38 | } 39 | }, 40 | "EOF1_eofcreate_invalid_4": { 41 | "code": "0xef0001010004020001000c03000100160400000000800004600060ff60006000ec005000ef000101000402000100010400030000800000feaabb", 42 | "results": { 43 | "Prague": { 44 | "exception": "EOF_EofCreateWithTruncatedContainer", 45 | "result": false 46 | } 47 | } 48 | } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_header_not_terminated.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_header_not_terminated": { 3 | "vectors": { 4 | "EOF1_header_not_terminated_0": { 5 | "code": "0xef000101", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_SectionHeadersNotTerminated", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "EOF1_header_not_terminated_1": { 14 | "code": "0xef0001010004", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_SectionHeadersNotTerminated", 18 | "result": false 19 | } 20 | } 21 | }, 22 | "EOF1_header_not_terminated_2": { 23 | "code": "0xef0001010004fe", 24 | "results": { 25 | "Prague": { 26 | "exception": "EOF_CodeSectionMissing", 27 | "result": false 28 | } 29 | } 30 | }, 31 | "EOF1_header_not_terminated_3": { 32 | "code": "0xef000101000402", 33 | "results": { 34 | "Prague": { 35 | "exception": "EOF_IncompleteSectionNumber", 36 | "result": false 37 | } 38 | } 39 | }, 40 | "EOF1_header_not_terminated_4": { 41 | "code": "0xef00010100040200", 42 | "results": { 43 | "Prague": { 44 | "exception": "EOF_IncompleteSectionNumber", 45 | "result": false 46 | } 47 | } 48 | }, 49 | "EOF1_header_not_terminated_5": { 50 | "code": "0xef0001010004020001", 51 | "results": { 52 | "Prague": { 53 | "exception": "EOF_SectionHeadersNotTerminated", 54 | "result": false 55 | } 56 | } 57 | }, 58 | "EOF1_header_not_terminated_6": { 59 | "code": "0xef00010100040200010001040001", 60 | "results": { 61 | "Prague": { 62 | "exception": "EOF_SectionHeadersNotTerminated", 63 | "result": false 64 | } 65 | } 66 | }, 67 | "EOF1_header_not_terminated_7": { 68 | "code": "0xef00010100040200010001040001feaa", 69 | "results": { 70 | "Prague": { 71 | "exception": "EOF_HeaderTerminatorMissing", 72 | "result": false 73 | } 74 | } 75 | } 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_incomplete_section_size.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_incomplete_section_size": { 3 | "vectors": { 4 | "EOF1_incomplete_section_size_0": { 5 | "code": "0xef000101", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_SectionHeadersNotTerminated", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "EOF1_incomplete_section_size_1": { 14 | "code": "0xef00010100", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_IncompleteSectionSize", 18 | "result": false 19 | } 20 | } 21 | }, 22 | "EOF1_incomplete_section_size_2": { 23 | "code": "0xef00010100040200", 24 | "results": { 25 | "Prague": { 26 | "exception": "EOF_IncompleteSectionNumber", 27 | "result": false 28 | } 29 | } 30 | }, 31 | "EOF1_incomplete_section_size_3": { 32 | "code": "0xef000101000402000100", 33 | "results": { 34 | "Prague": { 35 | "exception": "EOF_IncompleteSectionSize", 36 | "result": false 37 | } 38 | } 39 | }, 40 | "EOF1_incomplete_section_size_4": { 41 | "code": "0xef00010100040200010001", 42 | "results": { 43 | "Prague": { 44 | "exception": "EOF_SectionHeadersNotTerminated", 45 | "result": false 46 | } 47 | } 48 | }, 49 | "EOF1_incomplete_section_size_5": { 50 | "code": "0xef0001010004020001000104", 51 | "results": { 52 | "Prague": { 53 | "exception": "EOF_SectionHeadersNotTerminated", 54 | "result": false 55 | } 56 | } 57 | }, 58 | "EOF1_incomplete_section_size_6": { 59 | "code": "0xef000101000402000100010400", 60 | "results": { 61 | "Prague": { 62 | "exception": "EOF_IncompleteSectionSize", 63 | "result": false 64 | } 65 | } 66 | } 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_invalid_section_0_type.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_invalid_section_0_type": { 3 | "vectors": { 4 | "EOF1_invalid_section_0_type_0": { 5 | "code": "0xef00010100040200010001040000000000000000", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_InvalidFirstSectionType", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "EOF1_invalid_section_0_type_1": { 14 | "code": "0xef00010100040200010003040000000001000060005c", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_InvalidFirstSectionType", 18 | "result": false 19 | } 20 | } 21 | }, 22 | "EOF1_invalid_section_0_type_2": { 23 | "code": "0xef000101000402000100010400000001800000fe", 24 | "results": { 25 | "Prague": { 26 | "exception": "EOF_InvalidFirstSectionType", 27 | "result": false 28 | } 29 | } 30 | }, 31 | "EOF1_invalid_section_0_type_3": { 32 | "code": "0xef00010100040200010003040000000203000060005c", 33 | "results": { 34 | "Prague": { 35 | "exception": "EOF_InvalidFirstSectionType", 36 | "result": false 37 | } 38 | } 39 | } 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_invalid_type_section_size.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_invalid_type_section_size": { 3 | "vectors": { 4 | "EOF1_invalid_type_section_size_0": { 5 | "code": "0xef000101000102000100010400000000fe", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_InvalidTypeSectionSize", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "EOF1_invalid_type_section_size_1": { 14 | "code": "0xef00010100020200010001040000000080fe", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_InvalidTypeSectionSize", 18 | "result": false 19 | } 20 | } 21 | }, 22 | "EOF1_invalid_type_section_size_2": { 23 | "code": "0xef00010100080200010001040000000080000000000000fe", 24 | "results": { 25 | "Prague": { 26 | "exception": "EOF_InvalidTypeSectionSize", 27 | "result": false 28 | } 29 | } 30 | }, 31 | "EOF1_invalid_type_section_size_3": { 32 | "code": "0xef0001010008020003000100010001040000000080000000800000fefefe", 33 | "results": { 34 | "Prague": { 35 | "exception": "EOF_InvalidTypeSectionSize", 36 | "result": false 37 | } 38 | } 39 | }, 40 | "EOF1_invalid_type_section_size_4": { 41 | "code": "0xef00010100100200030001000100010400000000800000008000000080000000800000fefefe", 42 | "results": { 43 | "Prague": { 44 | "exception": "EOF_InvalidTypeSectionSize", 45 | "result": false 46 | } 47 | } 48 | } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_multiple_data_sections.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_multiple_data_sections": { 3 | "vectors": { 4 | "EOF1_multiple_data_sections_0": { 5 | "code": "0xef000101000402000100010400010400010000800000fedada", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_HeaderTerminatorMissing", 9 | "result": false 10 | } 11 | } 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_multiple_type_sections.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_multiple_type_sections": { 3 | "vectors": { 4 | "EOF1_multiple_type_sections_0": { 5 | "code": "0xef000101000401000402000200010001000080000000800000fefe", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_CodeSectionMissing", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "EOF1_multiple_type_sections_1": { 14 | "code": "0xef0001030002010001010001040002000000fefe0000", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_TypeSectionMissing", 18 | "result": false 19 | } 20 | } 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_no_type_section.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_no_type_section": { 3 | "vectors": { 4 | "EOF1_no_type_section_0": { 5 | "code": "0xef0001020001000100fe", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_TypeSectionMissing", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "EOF1_no_type_section_1": { 14 | "code": "0xef00010200020001000100fefe", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_TypeSectionMissing", 18 | "result": false 19 | } 20 | } 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_returncontract_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_returncontract_invalid": { 3 | "vectors": { 4 | "EOF1_returncontract_invalid_0": { 5 | "code": "0xef000101000402000100050300010014040000000080000460006000eeef000101000402000100010400000000800000fe", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_TruncatedImmediate", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "EOF1_returncontract_invalid_1": { 14 | "code": "0xef000101000402000100060300010014040000000080000460006000ee01ef000101000402000100010400000000800000fe", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_InvalidContainerSectionIndex", 18 | "result": false 19 | } 20 | } 21 | }, 22 | "EOF1_returncontract_invalid_2": { 23 | "code": "0xef000101000402000100060300010014040000000080000460006000eeffef000101000402000100010400000000800000fe", 24 | "results": { 25 | "Prague": { 26 | "exception": "EOF_InvalidContainerSectionIndex", 27 | "result": false 28 | } 29 | } 30 | }, 31 | "EOF1_returncontract_invalid_3": { 32 | "code": "0xef000101000402000100070300010014040000000080000260006000ee0000ef000101000402000100010400000000800000fe", 33 | "results": { 34 | "Prague": { 35 | "exception": "EOF_UnreachableCode", 36 | "result": false 37 | } 38 | } 39 | } 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_rjump_truncated.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_rjump_truncated": { 3 | "vectors": { 4 | "EOF1_rjump_truncated_0": { 5 | "code": "0xef000101000402000100010400000000800000e0", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_TruncatedImmediate", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "EOF1_rjump_truncated_1": { 14 | "code": "0xef000101000402000100020400000000800000e000", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_TruncatedImmediate", 18 | "result": false 19 | } 20 | } 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_rjumpi_truncated.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_rjumpi_truncated": { 3 | "vectors": { 4 | "EOF1_rjumpi_truncated_0": { 5 | "code": "0xef0001010004020001000304000000008000006000e1", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_TruncatedImmediate", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "EOF1_rjumpi_truncated_1": { 14 | "code": "0xef0001010004020001000404000000008000006000e100", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_TruncatedImmediate", 18 | "result": false 19 | } 20 | } 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_rjumpv_truncated.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_rjumpv_truncated": { 3 | "vectors": { 4 | "EOF1_rjumpv_truncated_0": { 5 | "code": "0xef0001010004020001000504000000008000006000e20000", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_TruncatedImmediate", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "EOF1_rjumpv_truncated_1": { 14 | "code": "0xef0001010004020001000704000000008000006000e201000000", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_TruncatedImmediate", 18 | "result": false 19 | } 20 | } 21 | }, 22 | "EOF1_rjumpv_truncated_2": { 23 | "code": "0xef0001010004020001000604000000008000006002e2010000", 24 | "results": { 25 | "Prague": { 26 | "exception": "EOF_TruncatedImmediate", 27 | "result": false 28 | } 29 | } 30 | }, 31 | "EOF1_rjumpv_truncated_3": { 32 | "code": "0xef0001010004020001000904000000008000006002e20200000003ff", 33 | "results": { 34 | "Prague": { 35 | "exception": "EOF_TruncatedImmediate", 36 | "result": false 37 | } 38 | } 39 | } 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_trailing_bytes.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_trailing_bytes": { 3 | "vectors": { 4 | "EOF1_trailing_bytes_0": { 5 | "code": "0xef000101000402000100010400000000800000fedeadbeef", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_InvalidSectionBodiesSize", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "EOF1_trailing_bytes_1": { 14 | "code": "0xef000101000402000100010400020000800000feaabbdeadbeef", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_InvalidSectionBodiesSize", 18 | "result": false 19 | } 20 | } 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_truncated_section.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_truncated_section": { 3 | "vectors": { 4 | "EOF1_truncated_section_0": { 5 | "code": "0xef0001010004020001000204000000", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_InvalidSectionBodiesSize", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "EOF1_truncated_section_1": { 14 | "code": "0xef0001010004020001000204000000008000", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_InvalidSectionBodiesSize", 18 | "result": false 19 | } 20 | } 21 | }, 22 | "EOF1_truncated_section_2": { 23 | "code": "0xef000101000402000100020400000000800000fe", 24 | "results": { 25 | "Prague": { 26 | "exception": "EOF_InvalidSectionBodiesSize", 27 | "result": false 28 | } 29 | } 30 | }, 31 | "EOF1_truncated_section_3": { 32 | "code": "0xef000101000402000100010400020000800000fe", 33 | "results": { 34 | "Prague": { 35 | "result": true 36 | } 37 | } 38 | }, 39 | "EOF1_truncated_section_4": { 40 | "code": "0xef000101000402000100010400020000800000feaa", 41 | "results": { 42 | "Prague": { 43 | "result": true 44 | } 45 | } 46 | } 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_type_section_missing.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_type_section_missing": { 3 | "vectors": { 4 | "EOF1_type_section_missing_0": { 5 | "code": "0xef0001020001000100fe", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_TypeSectionMissing", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "EOF1_type_section_missing_1": { 14 | "code": "0xef0001020001000103000100feda", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_TypeSectionMissing", 18 | "result": false 19 | } 20 | } 21 | }, 22 | "EOF1_type_section_missing_2": { 23 | "code": "0xef000100", 24 | "results": { 25 | "Prague": { 26 | "exception": "EOF_TypeSectionMissing", 27 | "result": false 28 | } 29 | } 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_type_section_not_first.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_type_section_not_first": { 3 | "vectors": { 4 | "EOF1_type_section_not_first_0": { 5 | "code": "0xef0001020001000101000400fe00800000", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_TypeSectionMissing", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "EOF1_type_section_not_first_1": { 14 | "code": "0xef00010200020001000101000400fefe00800000", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_TypeSectionMissing", 18 | "result": false 19 | } 20 | } 21 | }, 22 | "EOF1_type_section_not_first_2": { 23 | "code": "0xef0001020001000101000404000300fe00800000aabbcc", 24 | "results": { 25 | "Prague": { 26 | "exception": "EOF_TypeSectionMissing", 27 | "result": false 28 | } 29 | } 30 | }, 31 | "EOF1_type_section_not_first_3": { 32 | "code": "0xef0001020001000104000301000400feaabbcc00800000", 33 | "results": { 34 | "Prague": { 35 | "exception": "EOF_TypeSectionMissing", 36 | "result": false 37 | } 38 | } 39 | } 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_types_section_0_size.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_types_section_0_size": { 3 | "vectors": { 4 | "EOF1_types_section_0_size_0": { 5 | "code": "0xef0001010000020001000100fe", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_ZeroSectionSize", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "EOF1_types_section_0_size_1": { 14 | "code": "0xef0001010000020001000104000100feda", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_ZeroSectionSize", 18 | "result": false 19 | } 20 | } 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_types_section_missing.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_types_section_missing": { 3 | "vectors": { 4 | "EOF1_types_section_missing_0": { 5 | "code": "0xef0001020001000100fe", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_TypeSectionMissing", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "EOF1_types_section_missing_1": { 14 | "code": "0xef0001020001000104000100feda", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_TypeSectionMissing", 18 | "result": false 19 | } 20 | } 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_unknown_section.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_unknown_section": { 3 | "vectors": { 4 | "EOF1_unknown_section_0": { 5 | "code": "0xef000105000100fe", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_TypeSectionMissing", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "EOF1_unknown_section_1": { 14 | "code": "0xef0001ff000100fe", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_TypeSectionMissing", 18 | "result": false 19 | } 20 | } 21 | }, 22 | "EOF1_unknown_section_2": { 23 | "code": "0xef000101000402000100010500010000800000fe00", 24 | "results": { 25 | "Prague": { 26 | "exception": "EOF_DataSectionMissing", 27 | "result": false 28 | } 29 | } 30 | }, 31 | "EOF1_unknown_section_3": { 32 | "code": "0xef00010100040200010001ff00010000800000fe00", 33 | "results": { 34 | "Prague": { 35 | "exception": "EOF_DataSectionMissing", 36 | "result": false 37 | } 38 | } 39 | }, 40 | "EOF1_unknown_section_4": { 41 | "code": "0xef000101000402000100010400010500010000800000feaa00", 42 | "results": { 43 | "Prague": { 44 | "exception": "EOF_HeaderTerminatorMissing", 45 | "result": false 46 | } 47 | } 48 | }, 49 | "EOF1_unknown_section_5": { 50 | "code": "0xef00010100040200010001040001ff00010000800000feaa00", 51 | "results": { 52 | "Prague": { 53 | "exception": "EOF_HeaderTerminatorMissing", 54 | "result": false 55 | } 56 | } 57 | } 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_valid_rjump.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_valid_rjump": { 3 | "vectors": { 4 | "offset_negative": { 5 | "code": "0xef0001010004020001000404000000008000005be0fffc", 6 | "results": { 7 | "Prague": { 8 | "result": true 9 | } 10 | } 11 | }, 12 | "offset_positive": { 13 | "code": "0xef0001010004020001000d04000000008000025fe100055f5fe000035f600100", 14 | "results": { 15 | "Prague": { 16 | "result": true 17 | } 18 | } 19 | }, 20 | "offset_zero": { 21 | "code": "0xef000101000402000100040400000000800000e0000000", 22 | "results": { 23 | "Prague": { 24 | "result": true 25 | } 26 | } 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_valid_rjumpi.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_valid_rjumpi": { 3 | "vectors": { 4 | "offset_negative": { 5 | "code": "0xef0001010004020001000604000000008000016000e1fffb00", 6 | "results": { 7 | "Prague": { 8 | "result": true 9 | } 10 | } 11 | }, 12 | "offset_positive": { 13 | "code": "0xef0001010004020001000904000000008000016000e100035b5b5b00", 14 | "results": { 15 | "Prague": { 16 | "result": true 17 | } 18 | } 19 | }, 20 | "offset_zero": { 21 | "code": "0xef0001010004020001000604000000008000016000e1000000", 22 | "results": { 23 | "Prague": { 24 | "result": true 25 | } 26 | } 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/EOF1_valid_rjumpv.json: -------------------------------------------------------------------------------- 1 | { 2 | "EOF1_valid_rjumpv": { 3 | "vectors": { 4 | "single_entry_case_0": { 5 | "code": "0xef0001010004020001000904000000008000016000e2000000600100", 6 | "results": { 7 | "Prague": { 8 | "result": true 9 | } 10 | } 11 | }, 12 | "three_entries_case_2": { 13 | "code": "0xef0001010004020001001004000000008000016002e20200000003fff6600100600200", 14 | "results": { 15 | "Prague": { 16 | "result": true 17 | } 18 | } 19 | }, 20 | "two_entries_case_0": { 21 | "code": "0xef0001010004020001000e04000000008000016000e20100000003600100600200", 22 | "results": { 23 | "Prague": { 24 | "result": true 25 | } 26 | } 27 | }, 28 | "two_entries_case_2": { 29 | "code": "0xef0001010004020001000e04000000008000016002e20100000003600100600200", 30 | "results": { 31 | "Prague": { 32 | "result": true 33 | } 34 | } 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/callf_into_nonreturning.json: -------------------------------------------------------------------------------- 1 | { 2 | "callf_into_nonreturning": { 3 | "vectors": { 4 | "callf_into_nonreturning_0": { 5 | "code": "0xef000101000802000200040001040000000080000000800000e300010000", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_CallfToNonReturningFunction", 9 | "result": false 10 | } 11 | } 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/callf_invalid_code_section_index.json: -------------------------------------------------------------------------------- 1 | { 2 | "callf_invalid_code_section_index": { 3 | "vectors": { 4 | "callf_invalid_code_section_index_0": { 5 | "code": "0xef000101000402000100040400000000800000e3000100", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_InvalidCodeSectionIndex", 9 | "result": false 10 | } 11 | } 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/data_section_missing.json: -------------------------------------------------------------------------------- 1 | { 2 | "data_section_missing": { 3 | "vectors": { 4 | "data_section_missing_0": { 5 | "code": "0xef000101000402000100010000800000fe", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_DataSectionMissing", 9 | "result": false 10 | } 11 | } 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/incomplete_section_size.json: -------------------------------------------------------------------------------- 1 | { 2 | "incomplete_section_size": { 3 | "vectors": { 4 | "incomplete_section_size_0": { 5 | "code": "0xef000101010002003f0100", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_IncompleteSectionSize", 9 | "result": false 10 | } 11 | } 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/jumpf_compatible_outputs.json: -------------------------------------------------------------------------------- 1 | { 2 | "jumpf_compatible_outputs": { 3 | "vectors": { 4 | "jumpf_compatible_outputs_0": { 5 | "code": "0xef000101000c02000300040005000404000000008000050005000200030003e30001005f5fe500025f5f5fe4", 6 | "results": { 7 | "Prague": { 8 | "result": true 9 | } 10 | } 11 | } 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/jumpf_equal_outputs.json: -------------------------------------------------------------------------------- 1 | { 2 | "jumpf_equal_outputs": { 3 | "vectors": { 4 | "jumpf_equal_outputs_0": { 5 | "code": "0xef000101000c02000300040003000404000000008000030003000000030003e3000100e500025f5f5fe4", 6 | "results": { 7 | "Prague": { 8 | "result": true 9 | } 10 | } 11 | } 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/jumpf_incompatible_outputs.json: -------------------------------------------------------------------------------- 1 | { 2 | "jumpf_incompatible_outputs": { 3 | "vectors": { 4 | "jumpf_incompatible_outputs_0": { 5 | "code": "0xef000101000c02000300040005000404000000008000030003000200050003e3000100e500025f5f5f5f5fe4", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_JumpfDestinationIncompatibleOutputs", 9 | "result": false 10 | } 11 | } 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/minimal_valid_EOF1_code.json: -------------------------------------------------------------------------------- 1 | { 2 | "minimal_valid_EOF1_code": { 3 | "vectors": { 4 | "minimal_valid_EOF1_code_0": { 5 | "code": "0xef000101000402000100010400000000800000fe", 6 | "results": { 7 | "Prague": { 8 | "result": true 9 | } 10 | } 11 | } 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/minimal_valid_EOF1_code_with_data.json: -------------------------------------------------------------------------------- 1 | { 2 | "minimal_valid_EOF1_code_with_data": { 3 | "vectors": { 4 | "minimal_valid_EOF1_code_with_data_0": { 5 | "code": "0xef000101000402000100010400010000800000feda", 6 | "results": { 7 | "Prague": { 8 | "result": true 9 | } 10 | } 11 | } 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/minimal_valid_EOF1_multiple_code_sections.json: -------------------------------------------------------------------------------- 1 | { 2 | "minimal_valid_EOF1_multiple_code_sections": { 3 | "vectors": { 4 | "no_data_section": { 5 | "code": "0xef000101000802000200010001000080000000800000fefe", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_DataSectionMissing", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "non_void_input_output": { 14 | "code": "0xef0001010010020004000500060008000204000000008000010100000100010003020300035fe300010050e3000250e43080e300035050e480e4", 15 | "results": { 16 | "Prague": { 17 | "result": true 18 | } 19 | } 20 | }, 21 | "with_data_section": { 22 | "code": "0xef000101000802000200030001040001000080000000800000e50001feda", 23 | "results": { 24 | "Prague": { 25 | "result": true 26 | } 27 | } 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/multiple_code_sections_headers.json: -------------------------------------------------------------------------------- 1 | { 2 | "multiple_code_sections_headers": { 3 | "vectors": { 4 | "multiple_code_sections_headers_0": { 5 | "code": "0xef0001010008020001000402000100050400000000800000045c000000405c0000002e0005", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_DataSectionMissing", 9 | "result": false 10 | } 11 | } 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/stack/backwards_rjump.json: -------------------------------------------------------------------------------- 1 | { 2 | "backwards_rjump": { 3 | "vectors": { 4 | "backwards_rjump_0": { 5 | "code": "0xef000101000402000100030400000000800000e0fffd", 6 | "results": { 7 | "Prague": { 8 | "result": true 9 | } 10 | } 11 | }, 12 | "backwards_rjump_1": { 13 | "code": "0xef0001010004020001000504000000008000015f50e0fffb", 14 | "results": { 15 | "Prague": { 16 | "result": true 17 | } 18 | } 19 | }, 20 | "backwards_rjump_2": { 21 | "code": "0xef0001010004020001000d04000000008000015f506001e10003e0fff8e0fff5", 22 | "results": { 23 | "Prague": { 24 | "result": true 25 | } 26 | } 27 | }, 28 | "backwards_rjump_3": { 29 | "code": "0xef0001010004020001000e04000000008000015f506001e10003e0fff85fe0fff4", 30 | "results": { 31 | "Prague": { 32 | "exception": "EOF_ConflictingStackHeight", 33 | "result": false 34 | } 35 | } 36 | }, 37 | "backwards_rjump_4": { 38 | "code": "0xef0001010004020001000404000000008000015fe0fffc", 39 | "results": { 40 | "Prague": { 41 | "exception": "EOF_ConflictingStackHeight", 42 | "result": false 43 | } 44 | } 45 | }, 46 | "backwards_rjump_5": { 47 | "code": "0xef0001010004020001000504000000008000015f50e0fffc", 48 | "results": { 49 | "Prague": { 50 | "exception": "EOF_ConflictingStackHeight", 51 | "result": false 52 | } 53 | } 54 | } 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/stack/backwards_rjumpv.json: -------------------------------------------------------------------------------- 1 | { 2 | "backwards_rjumpv": { 3 | "vectors": { 4 | "backwards_rjumpv_0": { 5 | "code": "0xef0001010004020001000704000000008000016000e200fffa00", 6 | "results": { 7 | "Prague": { 8 | "result": true 9 | } 10 | } 11 | }, 12 | "backwards_rjumpv_1": { 13 | "code": "0xef0001010004020001000904000000008000015f506000e200fff800", 14 | "results": { 15 | "Prague": { 16 | "result": true 17 | } 18 | } 19 | }, 20 | "backwards_rjumpv_2": { 21 | "code": "0xef0001010004020001000f04000000008000015f506000e200fff86000e200fff200", 22 | "results": { 23 | "Prague": { 24 | "result": true 25 | } 26 | } 27 | }, 28 | "backwards_rjumpv_3": { 29 | "code": "0xef0001010004020001001004000000008000025f506000e200fff85f6000e200fff100", 30 | "results": { 31 | "Prague": { 32 | "exception": "EOF_ConflictingStackHeight", 33 | "result": false 34 | } 35 | } 36 | }, 37 | "backwards_rjumpv_4": { 38 | "code": "0xef0001010004020001000b04000000008000015f506000e200fff8e0fff5", 39 | "results": { 40 | "Prague": { 41 | "result": true 42 | } 43 | } 44 | }, 45 | "backwards_rjumpv_5": { 46 | "code": "0xef0001010004020001000c04000000008000015f506000e200fff85fe0fff4", 47 | "results": { 48 | "Prague": { 49 | "exception": "EOF_ConflictingStackHeight", 50 | "result": false 51 | } 52 | } 53 | }, 54 | "backwards_rjumpv_6": { 55 | "code": "0xef0001010004020001000e04000000008000035f6000e100015f6000e200fff400", 56 | "results": { 57 | "Prague": { 58 | "exception": "EOF_ConflictingStackHeight", 59 | "result": false 60 | } 61 | } 62 | }, 63 | "backwards_rjumpv_7": { 64 | "code": "0xef0001010004020001000f040000000080000360be6000e10001506000e200fff400", 65 | "results": { 66 | "Prague": { 67 | "exception": "EOF_ConflictingStackHeight", 68 | "result": false 69 | } 70 | } 71 | } 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/stack/callf_stack_validation.json: -------------------------------------------------------------------------------- 1 | { 2 | "callf_stack_validation": { 3 | "vectors": { 4 | "callf_stack_validation_0": { 5 | "code": "0xef000101000c02000300040006000204000000008000010001000202010002e30001005f5fe30002e450e4", 6 | "results": { 7 | "Prague": { 8 | "result": true 9 | } 10 | } 11 | }, 12 | "callf_stack_validation_1": { 13 | "code": "0xef000101000c02000300040007000204000000008000010001000302010002e30001005f5f5fe30002e450e4", 14 | "results": { 15 | "Prague": { 16 | "exception": "EOF_InvalidNumberOfOutputs", 17 | "result": false 18 | } 19 | } 20 | }, 21 | "callf_stack_validation_2": { 22 | "code": "0xef000101000c02000300040005000204000000008000010001000102010002e30001005fe30002e450e4", 23 | "results": { 24 | "Prague": { 25 | "exception": "EOF_StackUnderflow", 26 | "result": false 27 | } 28 | } 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/stack/dupn_stack_validation.json: -------------------------------------------------------------------------------- 1 | { 2 | "dupn_stack_validation": { 3 | "vectors": { 4 | "dupn_stack_validation_0": { 5 | "code": "0xef0001010004020001002b040000000080001560016001600160016001600160016001600160016001600160016001600160016001600160016001e60000", 6 | "results": { 7 | "Prague": { 8 | "result": true 9 | } 10 | } 11 | }, 12 | "dupn_stack_validation_1": { 13 | "code": "0xef0001010004020001002b040000000080001560016001600160016001600160016001600160016001600160016001600160016001600160016001e61300", 14 | "results": { 15 | "Prague": { 16 | "result": true 17 | } 18 | } 19 | }, 20 | "dupn_stack_validation_2": { 21 | "code": "0xef0001010004020001002b040000000080001560016001600160016001600160016001600160016001600160016001600160016001600160016001e61400", 22 | "results": { 23 | "Prague": { 24 | "exception": "EOF_StackUnderflow", 25 | "result": false 26 | } 27 | } 28 | }, 29 | "dupn_stack_validation_3": { 30 | "code": "0xef0001010004020001002b040000000080001560016001600160016001600160016001600160016001600160016001600160016001600160016001e6d000", 31 | "results": { 32 | "Prague": { 33 | "exception": "EOF_StackUnderflow", 34 | "result": false 35 | } 36 | } 37 | }, 38 | "dupn_stack_validation_4": { 39 | "code": "0xef0001010004020001002b040000000080001560016001600160016001600160016001600160016001600160016001600160016001600160016001e6fe00", 40 | "results": { 41 | "Prague": { 42 | "exception": "EOF_StackUnderflow", 43 | "result": false 44 | } 45 | } 46 | }, 47 | "dupn_stack_validation_5": { 48 | "code": "0xef0001010004020001002b040000000080001560016001600160016001600160016001600160016001600160016001600160016001600160016001e6ff00", 49 | "results": { 50 | "Prague": { 51 | "exception": "EOF_StackUnderflow", 52 | "result": false 53 | } 54 | } 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/stack/exchange_deep_stack_validation.json: -------------------------------------------------------------------------------- 1 | { 2 | "exchange_deep_stack_validation": { 3 | "vectors": { 4 | "exchange_deep_stack_validation_0": { 5 | "code": "0xef000101000402000100450400000000800021600160016001600160016001600160016001600160016001600160016001600160016001600160016001600160016001600160016001600160016001600160016001e8ff00", 6 | "results": { 7 | "Prague": { 8 | "result": true 9 | } 10 | } 11 | } 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/stack/exchange_empty_stack_validation.json: -------------------------------------------------------------------------------- 1 | { 2 | "exchange_empty_stack_validation": { 3 | "vectors": { 4 | "exchange_empty_stack_validation_0": { 5 | "code": "0xef000101000402000100030400000000800000e80000", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_StackUnderflow", 9 | "result": false 10 | } 11 | } 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/stack/forwards_rjump.json: -------------------------------------------------------------------------------- 1 | { 2 | "forwards_rjump": { 3 | "vectors": { 4 | "forwards_rjump_0": { 5 | "code": "0xef000101000402000100040400000000800000e0000000", 6 | "results": { 7 | "Prague": { 8 | "result": true 9 | } 10 | } 11 | }, 12 | "forwards_rjump_1": { 13 | "code": "0xef0001010004020001000b04000000008000025f6000e10003e000011900", 14 | "results": { 15 | "Prague": { 16 | "result": true 17 | } 18 | } 19 | }, 20 | "forwards_rjump_2": { 21 | "code": "0xef0001010004020001001304000000008000025f6000e100086000e10006e00004e000011900", 22 | "results": { 23 | "Prague": { 24 | "result": true 25 | } 26 | } 27 | }, 28 | "forwards_rjump_3": { 29 | "code": "0xef0001010004020001000b04000000008000025f6000e10003e000015f00", 30 | "results": { 31 | "Prague": { 32 | "result": true 33 | } 34 | } 35 | }, 36 | "forwards_rjump_4": { 37 | "code": "0xef0001010004020001001404000000008000025f6000e100086000e10007e000055fe000011900", 38 | "results": { 39 | "Prague": { 40 | "result": true 41 | } 42 | } 43 | } 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/stack/forwards_rjump_variable_stack.json: -------------------------------------------------------------------------------- 1 | { 2 | "forwards_rjump_variable_stack": { 3 | "vectors": { 4 | "forwards_rjump_variable_stack_0": { 5 | "code": "0xef0001010004020001000c04000000008000035f6000e100025f5fe0000000", 6 | "results": { 7 | "Prague": { 8 | "result": true 9 | } 10 | } 11 | }, 12 | "forwards_rjump_variable_stack_1": { 13 | "code": "0xef0001010004020001001304000000008000055f6000e100025f5f5f6000e10003e000011900", 14 | "results": { 15 | "Prague": { 16 | "result": true 17 | } 18 | } 19 | }, 20 | "forwards_rjump_variable_stack_2": { 21 | "code": "0xef0001010004020001001b04000000008000055f6000e100025f5f5f6000e100086000e10006e00004e000011900", 22 | "results": { 23 | "Prague": { 24 | "result": true 25 | } 26 | } 27 | }, 28 | "forwards_rjump_variable_stack_3": { 29 | "code": "0xef0001010004020001001304000000008000055f6000e100025f5f5f6000e10003e000015f00", 30 | "results": { 31 | "Prague": { 32 | "result": true 33 | } 34 | } 35 | }, 36 | "forwards_rjump_variable_stack_4": { 37 | "code": "0xef0001010004020001001b04000000008000045f6000e100025f5f6000e100086000e10007e000055fe000011900", 38 | "results": { 39 | "Prague": { 40 | "result": true 41 | } 42 | } 43 | } 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/stack/jumpf_to_nonreturning.json: -------------------------------------------------------------------------------- 1 | { 2 | "jumpf_to_nonreturning": { 3 | "vectors": { 4 | "jumpf_to_nonreturning_0": { 5 | "code": "0xef000101000802000200030001040000000080000000800000e5000100", 6 | "results": { 7 | "Prague": { 8 | "result": true 9 | } 10 | } 11 | }, 12 | "jumpf_to_nonreturning_1": { 13 | "code": "0xef0001010008020002000500010400000000800002008000005f5fe5000100", 14 | "results": { 15 | "Prague": { 16 | "result": true 17 | } 18 | } 19 | }, 20 | "jumpf_to_nonreturning_2": { 21 | "code": "0xef0001010008020002000600010400000000800003038000035f5f5fe5000100", 22 | "results": { 23 | "Prague": { 24 | "result": true 25 | } 26 | } 27 | }, 28 | "jumpf_to_nonreturning_3": { 29 | "code": "0xef0001010008020002000700010400000000800004038000035f5f5f5fe5000100", 30 | "results": { 31 | "Prague": { 32 | "result": true 33 | } 34 | } 35 | }, 36 | "jumpf_to_nonreturning_4": { 37 | "code": "0xef0001010008020002000500010400000000800002038000035f5fe5000100", 38 | "results": { 39 | "Prague": { 40 | "exception": "EOF_StackUnderflow", 41 | "result": false 42 | } 43 | } 44 | } 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/stack/jumpf_to_nonreturning_variable_stack.json: -------------------------------------------------------------------------------- 1 | { 2 | "jumpf_to_nonreturning_variable_stack": { 3 | "vectors": { 4 | "jumpf_to_nonreturning_variable_stack_0": { 5 | "code": "0xef0001010008020002000b00010400000000800003058000055f6000e100025f5fe50001fe", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_StackUnderflow", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "jumpf_to_nonreturning_variable_stack_1": { 14 | "code": "0xef0001010008020002000b00010400000000800003038000035f6000e100025f5fe50001fe", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_StackUnderflow", 18 | "result": false 19 | } 20 | } 21 | }, 22 | "jumpf_to_nonreturning_variable_stack_2": { 23 | "code": "0xef0001010008020002000b00010400000000800003018000015f6000e100025f5fe50001fe", 24 | "results": { 25 | "Prague": { 26 | "result": true 27 | } 28 | } 29 | }, 30 | "jumpf_to_nonreturning_variable_stack_3": { 31 | "code": "0xef0001010008020002000b00010400000000800003008000005f6000e100025f5fe50001fe", 32 | "results": { 33 | "Prague": { 34 | "result": true 35 | } 36 | } 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/stack/no_terminating_instruction.json: -------------------------------------------------------------------------------- 1 | { 2 | "no_terminating_instruction": { 3 | "vectors": { 4 | "no_terminating_instruction_0": { 5 | "code": "0xef0001010004020001000104000000008000005f", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_InvalidCodeTermination", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "no_terminating_instruction_1": { 14 | "code": "0xef0001010004020001000504000000008000006002600101", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_InvalidCodeTermination", 18 | "result": false 19 | } 20 | } 21 | }, 22 | "no_terminating_instruction_2": { 23 | "code": "0xef0001010004020001000504000000008000006001e1fffb", 24 | "results": { 25 | "Prague": { 26 | "exception": "EOF_InvalidCodeTermination", 27 | "result": false 28 | } 29 | } 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/stack/non_constant_stack_height.json: -------------------------------------------------------------------------------- 1 | { 2 | "non_constant_stack_height": { 3 | "vectors": { 4 | "non_constant_stack_height_0": { 5 | "code": "0xef0001010004020001000e04000000008000045fe100075f5f5fe10001505f5ffd", 6 | "results": { 7 | "Prague": { 8 | "result": true 9 | } 10 | } 11 | }, 12 | "non_constant_stack_height_1": { 13 | "code": "0xef0001010004020001000f04000000008000055f5fe100075f5f5fe10001505f5ffd", 14 | "results": { 15 | "Prague": { 16 | "result": true 17 | } 18 | } 19 | }, 20 | "non_constant_stack_height_2": { 21 | "code": "0xef0001010004020001000f04000000008000045fe100075f5f5fe1000150505f5ffd", 22 | "results": { 23 | "Prague": { 24 | "exception": "EOF_StackUnderflow", 25 | "result": false 26 | } 27 | } 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/stack/retf_stack_validation.json: -------------------------------------------------------------------------------- 1 | { 2 | "retf_stack_validation": { 3 | "vectors": { 4 | "retf_stack_validation_0": { 5 | "code": "0xef000101000802000200040003040000000080000200020002e30001005f5fe4", 6 | "results": { 7 | "Prague": { 8 | "result": true 9 | } 10 | } 11 | }, 12 | "retf_stack_validation_1": { 13 | "code": "0xef000101000802000200040002040000000080000200020001e30001005fe4", 14 | "results": { 15 | "Prague": { 16 | "exception": "EOF_StackUnderflow", 17 | "result": false 18 | } 19 | } 20 | }, 21 | "retf_stack_validation_2": { 22 | "code": "0xef000101000802000200040004040000000080000200020003e30001005f5f5fe4", 23 | "results": { 24 | "Prague": { 25 | "exception": "EOF_InvalidNumberOfOutputs", 26 | "result": false 27 | } 28 | } 29 | }, 30 | "retf_stack_validation_3": { 31 | "code": "0xef00010100080200020005000d0400000000800002010200025fe3000100e1000760016001e000025f5fe4", 32 | "results": { 33 | "Prague": { 34 | "result": true 35 | } 36 | } 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/stack/retf_variable_stack.json: -------------------------------------------------------------------------------- 1 | { 2 | "retf_variable_stack": { 3 | "vectors": { 4 | "retf_variable_stack_0": { 5 | "code": "0xef000101000802000200040009040000000080000500050003e30001005f6000e100025f5fe4", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_StackUnderflow", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "retf_variable_stack_1": { 14 | "code": "0xef000101000802000200040009040000000080000300030003e30001005f6000e100025f5fe4", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_StackUnderflow", 18 | "result": false 19 | } 20 | } 21 | }, 22 | "retf_variable_stack_2": { 23 | "code": "0xef000101000802000200040009040000000080000100010003e30001005f6000e100025f5fe4", 24 | "results": { 25 | "Prague": { 26 | "exception": "EOF_InvalidNumberOfOutputs", 27 | "result": false 28 | } 29 | } 30 | }, 31 | "retf_variable_stack_3": { 32 | "code": "0xef000101000802000200040009040000000080000000000003e30001005f6000e100025f5fe4", 33 | "results": { 34 | "Prague": { 35 | "exception": "EOF_InvalidNumberOfOutputs", 36 | "result": false 37 | } 38 | } 39 | } 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/stack/self_referencing_jumps.json: -------------------------------------------------------------------------------- 1 | { 2 | "self_referencing_jumps": { 3 | "vectors": { 4 | "rjump": { 5 | "code": "0xef000101000402000100030400000000800000e0fffd", 6 | "results": { 7 | "Prague": { 8 | "result": true 9 | } 10 | } 11 | }, 12 | "rjumpi": { 13 | "code": "0xef0001010004020001000604000000008000006000e1fffd00", 14 | "results": { 15 | "Prague": { 16 | "exception": "EOF_ConflictingStackHeight", 17 | "result": false 18 | } 19 | } 20 | }, 21 | "rjumpv": { 22 | "code": "0xef0001010004020001000704000000008000006000e200fffc00", 23 | "results": { 24 | "Prague": { 25 | "exception": "EOF_ConflictingStackHeight", 26 | "result": false 27 | } 28 | } 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/stack/self_referencing_jumps_variable_stack.json: -------------------------------------------------------------------------------- 1 | { 2 | "self_referencing_jumps_variable_stack": { 3 | "vectors": { 4 | "rjump": { 5 | "code": "0xef0001010004020001000b04000000008000035f6000e100025f5fe0fffd", 6 | "results": { 7 | "Prague": { 8 | "result": true 9 | } 10 | } 11 | }, 12 | "rjumpi": { 13 | "code": "0xef0001010004020001000e04000000008000045f6000e100025f5f6000e1fffd00", 14 | "results": { 15 | "Prague": { 16 | "exception": "EOF_ConflictingStackHeight", 17 | "result": false 18 | } 19 | } 20 | }, 21 | "rjumpv": { 22 | "code": "0xef0001010004020001000f04000000008000045f6000e100025f5f6000e200fffc00", 23 | "results": { 24 | "Prague": { 25 | "exception": "EOF_ConflictingStackHeight", 26 | "result": false 27 | } 28 | } 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/stack/swapn_stack_validation.json: -------------------------------------------------------------------------------- 1 | { 2 | "swapn_stack_validation": { 3 | "vectors": { 4 | "swapn_stack_validation_0": { 5 | "code": "0xef0001010004020001002b040000000080001460016001600160016001600160016001600160016001600160016001600160016001600160016001e70000", 6 | "results": { 7 | "Prague": { 8 | "result": true 9 | } 10 | } 11 | }, 12 | "swapn_stack_validation_1": { 13 | "code": "0xef0001010004020001002b040000000080001460016001600160016001600160016001600160016001600160016001600160016001600160016001e71200", 14 | "results": { 15 | "Prague": { 16 | "result": true 17 | } 18 | } 19 | }, 20 | "swapn_stack_validation_2": { 21 | "code": "0xef0001010004020001002b040000000080001460016001600160016001600160016001600160016001600160016001600160016001600160016001e71300", 22 | "results": { 23 | "Prague": { 24 | "exception": "EOF_StackUnderflow", 25 | "result": false 26 | } 27 | } 28 | }, 29 | "swapn_stack_validation_3": { 30 | "code": "0xef0001010004020001002b040000000080001460016001600160016001600160016001600160016001600160016001600160016001600160016001e7d000", 31 | "results": { 32 | "Prague": { 33 | "exception": "EOF_StackUnderflow", 34 | "result": false 35 | } 36 | } 37 | }, 38 | "swapn_stack_validation_4": { 39 | "code": "0xef0001010004020001002b040000000080001460016001600160016001600160016001600160016001600160016001600160016001600160016001e7fe00", 40 | "results": { 41 | "Prague": { 42 | "exception": "EOF_StackUnderflow", 43 | "result": false 44 | } 45 | } 46 | }, 47 | "swapn_stack_validation_5": { 48 | "code": "0xef0001010004020001002b040000000080001460016001600160016001600160016001600160016001600160016001600160016001600160016001e7ff00", 49 | "results": { 50 | "Prague": { 51 | "exception": "EOF_StackUnderflow", 52 | "result": false 53 | } 54 | } 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/stack/underflow.json: -------------------------------------------------------------------------------- 1 | { 2 | "underflow": { 3 | "vectors": { 4 | "underflow_0": { 5 | "code": "0xef0001010004020001000204000000008000000100", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_StackUnderflow", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "underflow_1": { 14 | "code": "0xef000101000802000200040002040000000080000101020002e30001005fe4", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_StackUnderflow", 18 | "result": false 19 | } 20 | } 21 | }, 22 | "underflow_2": { 23 | "code": "0xef000101000c02000300040003000204000000008000020002000001020002e3000100e500025fe4", 24 | "results": { 25 | "Prague": { 26 | "exception": "EOF_StackUnderflow", 27 | "result": false 28 | } 29 | } 30 | }, 31 | "underflow_3": { 32 | "code": "0xef000101000802000200030005040000000080000001800003e5000160006000fd", 33 | "results": { 34 | "Prague": { 35 | "exception": "EOF_StackUnderflow", 36 | "result": false 37 | } 38 | } 39 | }, 40 | "underflow_4": { 41 | "code": "0xef000101000802000200040002040000000080000200020001e30001005fe4", 42 | "results": { 43 | "Prague": { 44 | "exception": "EOF_StackUnderflow", 45 | "result": false 46 | } 47 | } 48 | } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/stack/unreachable_instructions.json: -------------------------------------------------------------------------------- 1 | { 2 | "unreachable_instructions": { 3 | "vectors": { 4 | "unreachable_instructions_0": { 5 | "code": "0xef0001010004020001000204000000008000000000", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_UnreachableCode", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "unreachable_instructions_1": { 14 | "code": "0xef000101000402000100050400000000800000e000010000", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_UnreachableCode", 18 | "result": false 19 | } 20 | } 21 | }, 22 | "unreachable_instructions_2": { 23 | "code": "0xef000101000402000100070400000000800000e0000100e0fffc", 24 | "results": { 25 | "Prague": { 26 | "exception": "EOF_UnreachableCode", 27 | "result": false 28 | } 29 | } 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/validate_EOF_prefix.json: -------------------------------------------------------------------------------- 1 | { 2 | "validate_EOF_prefix": { 3 | "vectors": { 4 | "valid_except_magic": { 5 | "code": "0xefff0101000402000100030300040000800000600000aabbccdd", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_InvalidPrefix", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "validate_EOF_prefix_0": { 14 | "code": "0x00", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_InvalidPrefix", 18 | "result": false 19 | } 20 | } 21 | }, 22 | "validate_EOF_prefix_1": { 23 | "code": "0xfe", 24 | "results": { 25 | "Prague": { 26 | "exception": "EOF_InvalidPrefix", 27 | "result": false 28 | } 29 | } 30 | }, 31 | "validate_EOF_prefix_2": { 32 | "code": "0xef", 33 | "results": { 34 | "Prague": { 35 | "exception": "EOF_InvalidPrefix", 36 | "result": false 37 | } 38 | } 39 | }, 40 | "validate_EOF_prefix_3": { 41 | "code": "0xef0101", 42 | "results": { 43 | "Prague": { 44 | "exception": "EOF_InvalidPrefix", 45 | "result": false 46 | } 47 | } 48 | }, 49 | "validate_EOF_prefix_4": { 50 | "code": "0xefef01", 51 | "results": { 52 | "Prague": { 53 | "exception": "EOF_InvalidPrefix", 54 | "result": false 55 | } 56 | } 57 | }, 58 | "validate_EOF_prefix_5": { 59 | "code": "0xefff01", 60 | "results": { 61 | "Prague": { 62 | "exception": "EOF_InvalidPrefix", 63 | "result": false 64 | } 65 | } 66 | }, 67 | "validate_EOF_prefix_6": { 68 | "code": "0xef00", 69 | "results": { 70 | "Prague": { 71 | "exception": "EOF_UnknownVersion", 72 | "result": false 73 | } 74 | } 75 | }, 76 | "validate_EOF_prefix_7": { 77 | "code": "0xef0001", 78 | "results": { 79 | "Prague": { 80 | "exception": "EOF_SectionHeadersNotTerminated", 81 | "result": false 82 | } 83 | } 84 | } 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/validate_EOF_version.json: -------------------------------------------------------------------------------- 1 | { 2 | "validate_EOF_version": { 3 | "vectors": { 4 | "valid_except_version_00": { 5 | "code": "0xef000001000402000100030200040000800000600000aabbccdd", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_UnknownVersion", 9 | "result": false 10 | } 11 | } 12 | }, 13 | "valid_except_version_02": { 14 | "code": "0xef000201000402000100030200040000800000600000aabbccdd", 15 | "results": { 16 | "Prague": { 17 | "exception": "EOF_UnknownVersion", 18 | "result": false 19 | } 20 | } 21 | }, 22 | "valid_except_version_FF": { 23 | "code": "0xef00ff01000402000100030200040000800000600000aabbccdd", 24 | "results": { 25 | "Prague": { 26 | "exception": "EOF_UnknownVersion", 27 | "result": false 28 | } 29 | } 30 | }, 31 | "validate_EOF_version_0": { 32 | "code": "0xef0002", 33 | "results": { 34 | "Prague": { 35 | "exception": "EOF_UnknownVersion", 36 | "result": false 37 | } 38 | } 39 | }, 40 | "validate_EOF_version_1": { 41 | "code": "0xef00ff", 42 | "results": { 43 | "Prague": { 44 | "exception": "EOF_UnknownVersion", 45 | "result": false 46 | } 47 | } 48 | } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /crates/interpreter/tests/EOFTests/eof_validation/validate_empty_code.json: -------------------------------------------------------------------------------- 1 | { 2 | "validate_empty_code": { 3 | "vectors": { 4 | "validate_empty_code_0": { 5 | "code": "0x", 6 | "results": { 7 | "Prague": { 8 | "exception": "EOF_InvalidPrefix", 9 | "result": false 10 | } 11 | } 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /crates/precompile/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-2024 draganrakita 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /crates/precompile/README.md: -------------------------------------------------------------------------------- 1 | ### REVM Precompiles - Ethereum compatible precompiled contracts 2 | 3 | Used inside REVM and passes all eth/tests. It supports all Ethereum hardforks. -------------------------------------------------------------------------------- /crates/precompile/src/bls12_381/g1_add.rs: -------------------------------------------------------------------------------- 1 | use super::g1::{encode_g1_point, extract_g1_input, G1_INPUT_ITEM_LENGTH}; 2 | use crate::{u64_to_address, PrecompileWithAddress}; 3 | use blst::{ 4 | blst_p1, blst_p1_add_or_double_affine, blst_p1_affine, blst_p1_from_affine, blst_p1_to_affine, 5 | }; 6 | use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileResult}; 7 | 8 | /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_G1ADD precompile. 9 | pub const PRECOMPILE: PrecompileWithAddress = 10 | PrecompileWithAddress(u64_to_address(ADDRESS), Precompile::Standard(g1_add)); 11 | /// BLS12_G1ADD precompile address. 12 | pub const ADDRESS: u64 = 0x0b; 13 | /// Base gas fee for BLS12-381 g1_add operation. 14 | const BASE_GAS_FEE: u64 = 500; 15 | 16 | /// Input length of g1_add operation. 17 | const INPUT_LENGTH: usize = 256; 18 | 19 | /// G1 addition call expects `256` bytes as an input that is interpreted as byte 20 | /// concatenation of two G1 points (`128` bytes each). 21 | /// Output is an encoding of addition operation result - single G1 point (`128` 22 | /// bytes). 23 | /// See also: 24 | pub(super) fn g1_add(input: &Bytes, gas_limit: u64) -> PrecompileResult { 25 | if BASE_GAS_FEE > gas_limit { 26 | return Err(PrecompileError::OutOfGas); 27 | } 28 | 29 | if input.len() != INPUT_LENGTH { 30 | return Err(PrecompileError::Other(format!( 31 | "G1ADD input should be {INPUT_LENGTH} bytes, was {}", 32 | input.len() 33 | ))); 34 | } 35 | 36 | // NB: There is no subgroup check for the G1 addition precompile. 37 | // 38 | // So we set the subgroup checks here to `false` 39 | let a_aff = &extract_g1_input(&input[..G1_INPUT_ITEM_LENGTH], false)?; 40 | let b_aff = &extract_g1_input(&input[G1_INPUT_ITEM_LENGTH..], false)?; 41 | 42 | let mut b = blst_p1::default(); 43 | // SAFETY: b and b_aff are blst values. 44 | unsafe { blst_p1_from_affine(&mut b, b_aff) }; 45 | 46 | let mut p = blst_p1::default(); 47 | // SAFETY: p, b and a_aff are blst values. 48 | unsafe { blst_p1_add_or_double_affine(&mut p, &b, a_aff) }; 49 | 50 | let mut p_aff = blst_p1_affine::default(); 51 | // SAFETY: p_aff and p are blst values. 52 | unsafe { blst_p1_to_affine(&mut p_aff, &p) }; 53 | 54 | let out = encode_g1_point(&p_aff); 55 | Ok((BASE_GAS_FEE, out)) 56 | } 57 | -------------------------------------------------------------------------------- /crates/precompile/src/bls12_381/g2_add.rs: -------------------------------------------------------------------------------- 1 | use super::g2::{encode_g2_point, extract_g2_input, G2_INPUT_ITEM_LENGTH}; 2 | use crate::{u64_to_address, PrecompileWithAddress}; 3 | use blst::{ 4 | blst_p2, blst_p2_add_or_double_affine, blst_p2_affine, blst_p2_from_affine, blst_p2_to_affine, 5 | }; 6 | use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileResult}; 7 | 8 | /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_G2ADD precompile. 9 | pub const PRECOMPILE: PrecompileWithAddress = 10 | PrecompileWithAddress(u64_to_address(ADDRESS), Precompile::Standard(g2_add)); 11 | /// BLS12_G2ADD precompile address. 12 | pub const ADDRESS: u64 = 0x0e; 13 | /// Base gas fee for BLS12-381 g2_add operation. 14 | const BASE_GAS_FEE: u64 = 800; 15 | 16 | /// Input length of g2_add operation. 17 | const INPUT_LENGTH: usize = 512; 18 | 19 | /// G2 addition call expects `512` bytes as an input that is interpreted as byte 20 | /// concatenation of two G2 points (`256` bytes each). 21 | /// 22 | /// Output is an encoding of addition operation result - single G2 point (`256` 23 | /// bytes). 24 | /// See also 25 | pub(super) fn g2_add(input: &Bytes, gas_limit: u64) -> PrecompileResult { 26 | if BASE_GAS_FEE > gas_limit { 27 | return Err(PrecompileError::OutOfGas); 28 | } 29 | 30 | if input.len() != INPUT_LENGTH { 31 | return Err(PrecompileError::Other(format!( 32 | "G2ADD input should be {INPUT_LENGTH} bytes, was {}", 33 | input.len() 34 | ))); 35 | } 36 | 37 | // NB: There is no subgroup check for the G2 addition precompile. 38 | // 39 | // So we set the subgroup checks here to `false` 40 | let a_aff = &extract_g2_input(&input[..G2_INPUT_ITEM_LENGTH], false)?; 41 | let b_aff = &extract_g2_input(&input[G2_INPUT_ITEM_LENGTH..], false)?; 42 | 43 | let mut b = blst_p2::default(); 44 | // SAFETY: b and b_aff are blst values. 45 | unsafe { blst_p2_from_affine(&mut b, b_aff) }; 46 | 47 | let mut p = blst_p2::default(); 48 | // SAFETY: p, b and a_aff are blst values. 49 | unsafe { blst_p2_add_or_double_affine(&mut p, &b, a_aff) }; 50 | 51 | let mut p_aff = blst_p2_affine::default(); 52 | // SAFETY: p_aff and p are blst values. 53 | unsafe { blst_p2_to_affine(&mut p_aff, &p) }; 54 | 55 | let out = encode_g2_point(&p_aff); 56 | Ok((BASE_GAS_FEE, out)) 57 | } 58 | -------------------------------------------------------------------------------- /crates/precompile/src/bls12_381/g2_mul.rs: -------------------------------------------------------------------------------- 1 | use super::{ 2 | g2::{encode_g2_point, extract_g2_input, G2_INPUT_ITEM_LENGTH}, 3 | utils::{extract_scalar_input, NBITS}, 4 | }; 5 | use crate::{u64_to_address, PrecompileWithAddress}; 6 | use blst::{blst_p2, blst_p2_affine, blst_p2_from_affine, blst_p2_mult, blst_p2_to_affine}; 7 | use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileResult}; 8 | 9 | /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_G2MUL precompile. 10 | pub const PRECOMPILE: PrecompileWithAddress = 11 | PrecompileWithAddress(u64_to_address(ADDRESS), Precompile::Standard(g2_mul)); 12 | /// BLS12_G2MUL precompile address. 13 | pub const ADDRESS: u64 = 0x0f; 14 | /// Base gas fee for BLS12-381 g2_mul operation. 15 | pub(super) const BASE_GAS_FEE: u64 = 45000; 16 | 17 | /// Input length of g2_mul operation. 18 | pub(super) const INPUT_LENGTH: usize = 288; 19 | 20 | /// G2 multiplication call expects `288` bytes as an input that is interpreted as 21 | /// byte concatenation of encoding of G2 point (`256` bytes) and encoding of a 22 | /// scalar value (`32` bytes). 23 | /// Output is an encoding of multiplication operation result - single G2 point 24 | /// (`256` bytes). 25 | /// See also: 26 | pub(super) fn g2_mul(input: &Bytes, gas_limit: u64) -> PrecompileResult { 27 | if BASE_GAS_FEE > gas_limit { 28 | return Err(PrecompileError::OutOfGas); 29 | } 30 | if input.len() != INPUT_LENGTH { 31 | return Err(PrecompileError::Other(format!( 32 | "G2MUL input should be {INPUT_LENGTH} bytes, was {}", 33 | input.len() 34 | ))); 35 | } 36 | 37 | // NB: Scalar multiplications, MSMs and pairings MUST perform a subgroup check. 38 | // 39 | // So we set the subgroup_check flag to `true` 40 | let p0_aff = &extract_g2_input(&input[..G2_INPUT_ITEM_LENGTH], true)?; 41 | let mut p0 = blst_p2::default(); 42 | // SAFETY: p0 and p0_aff are blst values. 43 | unsafe { blst_p2_from_affine(&mut p0, p0_aff) }; 44 | 45 | let input_scalar0 = extract_scalar_input(&input[G2_INPUT_ITEM_LENGTH..])?; 46 | 47 | let mut p = blst_p2::default(); 48 | // SAFETY: input_scalar0.b has fixed size, p and p0 are blst values. 49 | unsafe { blst_p2_mult(&mut p, &p0, input_scalar0.b.as_ptr(), NBITS) }; 50 | let mut p_aff = blst_p2_affine::default(); 51 | // SAFETY: p_aff and p are blst values. 52 | unsafe { blst_p2_to_affine(&mut p_aff, &p) }; 53 | 54 | let out = encode_g2_point(&p_aff); 55 | Ok((BASE_GAS_FEE, out)) 56 | } 57 | -------------------------------------------------------------------------------- /crates/precompile/src/bls12_381/map_fp2_to_g2.rs: -------------------------------------------------------------------------------- 1 | use super::{ 2 | g2::check_canonical_fp2, 3 | g2::encode_g2_point, 4 | utils::{remove_padding, PADDED_FP2_LENGTH, PADDED_FP_LENGTH}, 5 | }; 6 | use crate::{u64_to_address, PrecompileWithAddress}; 7 | use blst::{blst_map_to_g2, blst_p2, blst_p2_affine, blst_p2_to_affine}; 8 | use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileResult}; 9 | 10 | /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_MAP_FP2_TO_G2 precompile. 11 | pub const PRECOMPILE: PrecompileWithAddress = 12 | PrecompileWithAddress(u64_to_address(ADDRESS), Precompile::Standard(map_fp2_to_g2)); 13 | 14 | /// BLS12_MAP_FP2_TO_G2 precompile address. 15 | pub const ADDRESS: u64 = 0x13; 16 | 17 | /// Base gas fee for BLS12-381 map_fp2_to_g2 operation. 18 | const BASE_GAS_FEE: u64 = 75000; 19 | 20 | /// Field-to-curve call expects 128 bytes as an input that is interpreted as a 21 | /// an element of Fp2. Output of this call is 256 bytes and is an encoded G2 22 | /// point. 23 | /// See also: 24 | pub(super) fn map_fp2_to_g2(input: &Bytes, gas_limit: u64) -> PrecompileResult { 25 | if BASE_GAS_FEE > gas_limit { 26 | return Err(PrecompileError::OutOfGas); 27 | } 28 | 29 | if input.len() != PADDED_FP2_LENGTH { 30 | return Err(PrecompileError::Other(format!( 31 | "MAP_FP2_TO_G2 input should be {PADDED_FP2_LENGTH} bytes, was {}", 32 | input.len() 33 | ))); 34 | } 35 | 36 | let input_p0_x = remove_padding(&input[..PADDED_FP_LENGTH])?; 37 | let input_p0_y = remove_padding(&input[PADDED_FP_LENGTH..PADDED_FP2_LENGTH])?; 38 | let fp2 = check_canonical_fp2(input_p0_x, input_p0_y)?; 39 | 40 | let mut p = blst_p2::default(); 41 | // SAFETY: p and fp2 are blst values. 42 | // third argument is unused if null. 43 | unsafe { blst_map_to_g2(&mut p, &fp2, core::ptr::null()) }; 44 | 45 | let mut p_aff = blst_p2_affine::default(); 46 | // SAFETY: p_aff and p are blst values. 47 | unsafe { blst_p2_to_affine(&mut p_aff, &p) }; 48 | 49 | let out = encode_g2_point(&p_aff); 50 | Ok((BASE_GAS_FEE, out)) 51 | } 52 | -------------------------------------------------------------------------------- /crates/precompile/src/bls12_381/map_fp_to_g1.rs: -------------------------------------------------------------------------------- 1 | use super::{ 2 | g1::encode_g1_point, 3 | utils::{fp_from_bendian, remove_padding, PADDED_FP_LENGTH}, 4 | }; 5 | use crate::{u64_to_address, PrecompileWithAddress}; 6 | use blst::{blst_map_to_g1, blst_p1, blst_p1_affine, blst_p1_to_affine}; 7 | use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileResult}; 8 | 9 | /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_MAP_FP_TO_G1 precompile. 10 | pub const PRECOMPILE: PrecompileWithAddress = 11 | PrecompileWithAddress(u64_to_address(ADDRESS), Precompile::Standard(map_fp_to_g1)); 12 | 13 | /// BLS12_MAP_FP_TO_G1 precompile address. 14 | pub const ADDRESS: u64 = 0x12; 15 | 16 | /// Base gas fee for BLS12-381 map_fp_to_g1 operation. 17 | const MAP_FP_TO_G1_BASE: u64 = 5500; 18 | 19 | /// Field-to-curve call expects 64 bytes as an input that is interpreted as an 20 | /// element of Fp. Output of this call is 128 bytes and is an encoded G1 point. 21 | /// See also: 22 | pub(super) fn map_fp_to_g1(input: &Bytes, gas_limit: u64) -> PrecompileResult { 23 | if MAP_FP_TO_G1_BASE > gas_limit { 24 | return Err(PrecompileError::OutOfGas); 25 | } 26 | 27 | if input.len() != PADDED_FP_LENGTH { 28 | return Err(PrecompileError::Other(format!( 29 | "MAP_FP_TO_G1 input should be {PADDED_FP_LENGTH} bytes, was {}", 30 | input.len() 31 | ))); 32 | } 33 | 34 | let input_p0 = remove_padding(input)?; 35 | let fp = fp_from_bendian(input_p0)?; 36 | 37 | let mut p = blst_p1::default(); 38 | // SAFETY: p and fp are blst values. 39 | // third argument is unused if null. 40 | unsafe { blst_map_to_g1(&mut p, &fp, core::ptr::null()) }; 41 | 42 | let mut p_aff = blst_p1_affine::default(); 43 | // SAFETY: p_aff and p are blst values. 44 | unsafe { blst_p1_to_affine(&mut p_aff, &p) }; 45 | 46 | let out = encode_g1_point(&p_aff); 47 | Ok((MAP_FP_TO_G1_BASE, out)) 48 | } 49 | 50 | #[cfg(test)] 51 | mod test { 52 | use super::*; 53 | use crate::primitives::hex; 54 | 55 | #[test] 56 | fn sanity_test() { 57 | let input = Bytes::from(hex!("000000000000000000000000000000006900000000000000636f6e7472616374595a603f343061cd305a03f40239f5ffff31818185c136bc2595f2aa18e08f17")); 58 | let fail = map_fp_to_g1(&input, MAP_FP_TO_G1_BASE); 59 | assert_eq!( 60 | fail, 61 | Err(PrecompileError::Other("non-canonical fp value".to_string())) 62 | ); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /crates/precompile/src/bls12_381/msm.rs: -------------------------------------------------------------------------------- 1 | /// Amount used to calculate the multi-scalar-multiplication discount. 2 | const MSM_MULTIPLIER: u64 = 1000; 3 | 4 | /// Table of gas discounts for multi-scalar-multiplication operations. 5 | static MSM_DISCOUNT_TABLE: [u16; 128] = [ 6 | 1200, 888, 764, 641, 594, 547, 500, 453, 438, 423, 408, 394, 379, 364, 349, 334, 330, 326, 322, 7 | 318, 314, 310, 306, 302, 298, 294, 289, 285, 281, 277, 273, 269, 268, 266, 265, 263, 262, 260, 8 | 259, 257, 256, 254, 253, 251, 250, 248, 247, 245, 244, 242, 241, 239, 238, 236, 235, 233, 232, 9 | 231, 229, 228, 226, 225, 223, 222, 221, 220, 219, 219, 218, 217, 216, 216, 215, 214, 213, 213, 10 | 212, 211, 211, 210, 209, 208, 208, 207, 206, 205, 205, 204, 203, 202, 202, 201, 200, 199, 199, 11 | 198, 197, 196, 196, 195, 194, 193, 193, 192, 191, 191, 190, 189, 188, 188, 187, 186, 185, 185, 12 | 184, 183, 182, 182, 181, 180, 179, 179, 178, 177, 176, 176, 175, 174, 13 | ]; 14 | 15 | /// Implements the gas schedule for G1/G2 Multiscalar-multiplication assuming 30 16 | /// MGas/second, see also: 17 | pub(super) fn msm_required_gas(k: usize, multiplication_cost: u64) -> u64 { 18 | if k == 0 { 19 | return 0; 20 | } 21 | 22 | let index = core::cmp::min(k - 1, MSM_DISCOUNT_TABLE.len() - 1); 23 | let discount = MSM_DISCOUNT_TABLE[index] as u64; 24 | 25 | (k as u64 * discount * multiplication_cost) / MSM_MULTIPLIER 26 | } 27 | -------------------------------------------------------------------------------- /crates/precompile/src/hash.rs: -------------------------------------------------------------------------------- 1 | use super::calc_linear_cost_u32; 2 | use crate::{Error, Precompile, PrecompileResult, PrecompileWithAddress}; 3 | use revm_primitives::Bytes; 4 | use sha2::Digest; 5 | 6 | pub const SHA256: PrecompileWithAddress = 7 | PrecompileWithAddress(crate::u64_to_address(2), Precompile::Standard(sha256_run)); 8 | 9 | pub const RIPEMD160: PrecompileWithAddress = PrecompileWithAddress( 10 | crate::u64_to_address(3), 11 | Precompile::Standard(ripemd160_run), 12 | ); 13 | 14 | /// See: 15 | /// See: 16 | /// See: 17 | pub fn sha256_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { 18 | let cost = calc_linear_cost_u32(input.len(), 60, 12); 19 | if cost > gas_limit { 20 | Err(Error::OutOfGas) 21 | } else { 22 | let output = sha2::Sha256::digest(input); 23 | Ok((cost, output.to_vec().into())) 24 | } 25 | } 26 | 27 | /// See: 28 | /// See: 29 | /// See: 30 | pub fn ripemd160_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { 31 | let gas_used = calc_linear_cost_u32(input.len(), 600, 120); 32 | if gas_used > gas_limit { 33 | Err(Error::OutOfGas) 34 | } else { 35 | let mut hasher = ripemd::Ripemd160::new(); 36 | hasher.update(input); 37 | 38 | let mut output = [0u8; 32]; 39 | hasher.finalize_into((&mut output[12..]).into()); 40 | Ok((gas_used, output.to_vec().into())) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /crates/precompile/src/identity.rs: -------------------------------------------------------------------------------- 1 | use super::calc_linear_cost_u32; 2 | use crate::{Error, Precompile, PrecompileResult, PrecompileWithAddress}; 3 | use revm_primitives::Bytes; 4 | 5 | pub const FUN: PrecompileWithAddress = 6 | PrecompileWithAddress(crate::u64_to_address(4), Precompile::Standard(identity_run)); 7 | 8 | /// The base cost of the operation. 9 | pub const IDENTITY_BASE: u64 = 15; 10 | /// The cost per word. 11 | pub const IDENTITY_PER_WORD: u64 = 3; 12 | 13 | /// Takes the input bytes, copies them, and returns it as the output. 14 | /// 15 | /// See: 16 | /// See: 17 | pub fn identity_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { 18 | let gas_used = calc_linear_cost_u32(input.len(), IDENTITY_BASE, IDENTITY_PER_WORD); 19 | if gas_used > gas_limit { 20 | return Err(Error::OutOfGas); 21 | } 22 | Ok((gas_used, input.clone())) 23 | } 24 | -------------------------------------------------------------------------------- /crates/precompile/test-vectors/fail-map_fp2_to_G2_bls.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Input": "", 4 | "ExpectedError": "invalid input length", 5 | "Name": "bls_mapg2_empty_input" 6 | }, 7 | { 8 | "Input": "0000000000000000000000000000000007355d25caf6e7f2f0cb2812ca0e513bd026ed09dda65b177500fa31714e09ea0ded3a078b526bed3307f804d4b93b040000000000000000000000000000000002829ce3c021339ccb5caf3e187f6370e1e2a311dec9b75363117063ab2015603ff52c3d3b98f19c2f65575e99e8b7", 9 | "ExpectedError": "invalid input length", 10 | "Name": "bls_mapg2_short_input" 11 | }, 12 | { 13 | "Input": "000000000000000000000000000000000007355d25caf6e7f2f0cb2812ca0e513bd026ed09dda65b177500fa31714e09ea0ded3a078b526bed3307f804d4b93b040000000000000000000000000000000002829ce3c021339ccb5caf3e187f6370e1e2a311dec9b75363117063ab2015603ff52c3d3b98f19c2f65575e99e8b78c", 14 | "ExpectedError": "invalid input length", 15 | "Name": "bls_mapg2_long_input" 16 | }, 17 | { 18 | "Input": "000000000000000000000000000000000007355d25caf6e7f2f0cb2812ca0e513bd026ed09dda65b177500fa31714e09ea0ded3a078b526bed3307f804d4b93b040000000000000000000000000000000002829ce3c021339ccb5caf3e187f6370e1e2a311dec9b75363117063ab2015603ff52c3d3b98f19c2f65575e99e8b7", 19 | "ExpectedError": "invalid field element top bytes", 20 | "Name": "bls_mapg2_top_bytes" 21 | }, 22 | { 23 | "Input": "0000000000000000000000000000000021366f100476ce8d3be6cfc90d59fe13349e388ed12b6dd6dc31ccd267ff000e2c993a063ca66beced06f804d4b8e5af0000000000000000000000000000000002829ce3c021339ccb5caf3e187f6370e1e2a311dec9b75363117063ab2015603ff52c3d3b98f19c2f65575e99e8b78c", 24 | "ExpectedError": "invalid fp.Element encoding", 25 | "Name": "bls_mapg2_invalid_fq_element" 26 | } 27 | ] -------------------------------------------------------------------------------- /crates/precompile/test-vectors/fail-map_fp_to_G1_bls.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Input": "", 4 | "ExpectedError": "invalid input length", 5 | "Name": "bls_mapg1_empty_input" 6 | }, 7 | { 8 | "Input": "00000000000000000000000000000000156c8a6a2c184569d69a76be144b5cdc5141d2d2ca4fe341f011e25e3969c55ad9e9b9ce2eb833c81a908e5fa4ac5f", 9 | "ExpectedError": "invalid input length", 10 | "Name": "bls_mapg1_short_input" 11 | }, 12 | { 13 | "Input": "0000000000000000000000000000000000156c8a6a2c184569d69a76be144b5cdc5141d2d2ca4fe341f011e25e3969c55ad9e9b9ce2eb833c81a908e5fa4ac5f03", 14 | "ExpectedError": "invalid input length", 15 | "Name": "bls_mapg1_large_input" 16 | }, 17 | { 18 | "Input": "1000000000000000000000000000000000156c8a6a2c184569d69a76be144b5cdc5141d2d2ca4fe341f011e25e3969c55ad9e9b9ce2eb833c81a908e5fa4ac5f", 19 | "ExpectedError": "invalid field element top bytes", 20 | "Name": "bls_mapg1_top_bytes" 21 | }, 22 | { 23 | "Input": "000000000000000000000000000000002f6d9c5465982c0421b61e74579709b3b5b91e57bdd4f6015742b4ff301abb7ef895b9cce00c33c7d48f8e5fa4ac09ae", 24 | "ExpectedError": "invalid fp.Element encoding", 25 | "Name": "bls_invalid_fq_element" 26 | } 27 | ] -------------------------------------------------------------------------------- /crates/primitives/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-2024 draganrakita 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /crates/primitives/src/bytecode/eof/decode_helpers.rs: -------------------------------------------------------------------------------- 1 | use super::EofDecodeError; 2 | 3 | /// Consumes a u8 from the input. 4 | #[inline] 5 | pub(crate) fn consume_u8(input: &[u8]) -> Result<(&[u8], u8), EofDecodeError> { 6 | if input.is_empty() { 7 | return Err(EofDecodeError::MissingInput); 8 | } 9 | Ok((&input[1..], input[0])) 10 | } 11 | 12 | /// Consumes a u16 from the input. 13 | #[inline] 14 | pub(crate) fn consume_u16(input: &[u8]) -> Result<(&[u8], u16), EofDecodeError> { 15 | if input.len() < 2 { 16 | return Err(EofDecodeError::MissingInput); 17 | } 18 | let (int_bytes, rest) = input.split_at(2); 19 | Ok((rest, u16::from_be_bytes([int_bytes[0], int_bytes[1]]))) 20 | } 21 | -------------------------------------------------------------------------------- /crates/primitives/src/bytecode/legacy.rs: -------------------------------------------------------------------------------- 1 | mod jump_map; 2 | 3 | pub use jump_map::JumpTable; 4 | 5 | use crate::Bytes; 6 | use bitvec::{bitvec, order::Lsb0}; 7 | use std::sync::Arc; 8 | 9 | /// Legacy analyzed 10 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] 11 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 12 | pub struct LegacyAnalyzedBytecode { 13 | /// Bytecode with 32 zero bytes padding. 14 | bytecode: Bytes, 15 | /// Original bytes length. 16 | original_len: usize, 17 | /// Jump table. 18 | jump_table: JumpTable, 19 | } 20 | 21 | impl Default for LegacyAnalyzedBytecode { 22 | #[inline] 23 | fn default() -> Self { 24 | Self { 25 | bytecode: Bytes::from_static(&[0]), 26 | original_len: 0, 27 | jump_table: JumpTable(Arc::new(bitvec![u8, Lsb0; 0])), 28 | } 29 | } 30 | } 31 | 32 | impl LegacyAnalyzedBytecode { 33 | /// Create new analyzed bytecode. 34 | pub fn new(bytecode: Bytes, original_len: usize, jump_table: JumpTable) -> Self { 35 | Self { 36 | bytecode, 37 | original_len, 38 | jump_table, 39 | } 40 | } 41 | 42 | /// Returns a reference to the bytecode. 43 | /// 44 | /// The bytecode is padded with 32 zero bytes. 45 | pub fn bytecode(&self) -> &Bytes { 46 | &self.bytecode 47 | } 48 | 49 | /// Original bytes length. 50 | pub fn original_len(&self) -> usize { 51 | self.original_len 52 | } 53 | 54 | /// Original bytes without padding. 55 | pub fn original_bytes(&self) -> Bytes { 56 | self.bytecode.slice(..self.original_len) 57 | } 58 | 59 | /// Original bytes without padding. 60 | pub fn original_byte_slice(&self) -> &[u8] { 61 | &self.bytecode[..self.original_len] 62 | } 63 | 64 | /// Jumptable of analyzed bytes. 65 | pub fn jump_table(&self) -> &JumpTable { 66 | &self.jump_table 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /crates/primitives/src/bytecode/legacy/jump_map.rs: -------------------------------------------------------------------------------- 1 | use crate::hex; 2 | use bitvec::vec::BitVec; 3 | use std::{fmt::Debug, sync::Arc}; 4 | 5 | /// A map of valid `jump` destinations. 6 | #[derive(Clone, Default, PartialEq, Eq, Hash)] 7 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 8 | pub struct JumpTable(pub Arc>); 9 | 10 | impl Debug for JumpTable { 11 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 12 | f.debug_struct("JumpTable") 13 | .field("map", &hex::encode(self.0.as_raw_slice())) 14 | .finish() 15 | } 16 | } 17 | 18 | impl JumpTable { 19 | /// Get the raw bytes of the jump map 20 | #[inline] 21 | pub fn as_slice(&self) -> &[u8] { 22 | self.0.as_raw_slice() 23 | } 24 | 25 | /// Construct a jump map from raw bytes 26 | #[inline] 27 | pub fn from_slice(slice: &[u8]) -> Self { 28 | Self(Arc::new(BitVec::from_slice(slice))) 29 | } 30 | 31 | /// Check if `pc` is a valid jump destination. 32 | #[inline] 33 | pub fn is_valid(&self, pc: usize) -> bool { 34 | pc < self.0.len() && self.0[pc] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /crates/primitives/src/constants.rs: -------------------------------------------------------------------------------- 1 | use alloy_primitives::{address, Address}; 2 | 3 | /// EIP-170: Contract code size limit 4 | /// 5 | /// By default the limit is `0x6000` (~25kb) 6 | pub const MAX_CODE_SIZE: usize = 0x6000; 7 | 8 | /// Number of block hashes that EVM can access in the past (pre-Prague). 9 | pub const BLOCK_HASH_HISTORY: usize = 256; 10 | 11 | /// EIP-2935: Serve historical block hashes from state 12 | /// 13 | /// Number of block hashes the EVM can access in the past (Prague). 14 | /// 15 | /// # Note 16 | /// 17 | /// This is named `HISTORY_SERVE_WINDOW` in the EIP. 18 | pub const BLOCKHASH_SERVE_WINDOW: usize = 8192; 19 | 20 | /// EIP-2935: Serve historical block hashes from state 21 | /// 22 | /// The address where historical blockhashes are available. 23 | /// 24 | /// # Note 25 | /// 26 | /// This is named `HISTORY_STORAGE_ADDRESS` in the EIP. 27 | pub const BLOCKHASH_STORAGE_ADDRESS: Address = address!("25a219378dad9b3503c8268c9ca836a52427a4fb"); 28 | 29 | /// EIP-3860: Limit and meter initcode 30 | /// 31 | /// Limit of maximum initcode size is `2 * MAX_CODE_SIZE`. 32 | pub const MAX_INITCODE_SIZE: usize = 2 * MAX_CODE_SIZE; 33 | 34 | /// The address of precompile 3, which is handled specially in a few places. 35 | pub const PRECOMPILE3: Address = 36 | Address::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3]); 37 | 38 | // === EIP-4844 constants === 39 | 40 | /// Gas consumption of a single data blob (== blob byte size). 41 | pub const GAS_PER_BLOB: u64 = 1 << 17; 42 | 43 | /// Target number of the blob per block. 44 | pub const TARGET_BLOB_NUMBER_PER_BLOCK: u64 = 3; 45 | 46 | /// Max number of blobs per block 47 | pub const MAX_BLOB_NUMBER_PER_BLOCK: u64 = 2 * TARGET_BLOB_NUMBER_PER_BLOCK; 48 | 49 | /// Maximum consumable blob gas for data blobs per block. 50 | pub const MAX_BLOB_GAS_PER_BLOCK: u64 = MAX_BLOB_NUMBER_PER_BLOCK * GAS_PER_BLOB; 51 | 52 | /// Target consumable blob gas for data blobs per block (for 1559-like pricing). 53 | pub const TARGET_BLOB_GAS_PER_BLOCK: u64 = TARGET_BLOB_NUMBER_PER_BLOCK * GAS_PER_BLOB; 54 | 55 | /// Minimum gas price for data blobs. 56 | pub const MIN_BLOB_GASPRICE: u64 = 1; 57 | 58 | /// Controls the maximum rate of change for blob gas price. 59 | pub const BLOB_GASPRICE_UPDATE_FRACTION: u64 = 3338477; 60 | 61 | /// First version of the blob. 62 | pub const VERSIONED_HASH_VERSION_KZG: u8 = 0x01; 63 | -------------------------------------------------------------------------------- /crates/primitives/src/db/components/block_hash.rs: -------------------------------------------------------------------------------- 1 | //! BlockHash database component from [`crate::db::Database`] 2 | //! it is used inside [`crate::db::DatabaseComponents`] 3 | 4 | use crate::{B256, U256}; 5 | use auto_impl::auto_impl; 6 | use core::ops::Deref; 7 | use std::sync::Arc; 8 | 9 | #[auto_impl(&mut, Box)] 10 | pub trait BlockHash { 11 | type Error; 12 | 13 | /// Get block hash by block number 14 | fn block_hash(&mut self, number: U256) -> Result; 15 | } 16 | 17 | #[auto_impl(&, &mut, Box, Rc, Arc)] 18 | pub trait BlockHashRef { 19 | type Error; 20 | 21 | /// Get block hash by block number 22 | fn block_hash(&self, number: U256) -> Result; 23 | } 24 | 25 | impl BlockHash for &T 26 | where 27 | T: BlockHashRef, 28 | { 29 | type Error = ::Error; 30 | 31 | fn block_hash(&mut self, number: U256) -> Result { 32 | BlockHashRef::block_hash(*self, number) 33 | } 34 | } 35 | 36 | impl BlockHash for Arc 37 | where 38 | T: BlockHashRef, 39 | { 40 | type Error = ::Error; 41 | 42 | fn block_hash(&mut self, number: U256) -> Result { 43 | self.deref().block_hash(number) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /crates/primitives/src/db/components/state.rs: -------------------------------------------------------------------------------- 1 | //! State database component from [`crate::db::Database`] 2 | //! it is used inside [`crate::db::DatabaseComponents`] 3 | 4 | use crate::{AccountInfo, Address, Bytecode, B256, U256}; 5 | use auto_impl::auto_impl; 6 | use core::ops::Deref; 7 | use std::sync::Arc; 8 | 9 | #[auto_impl(&mut, Box)] 10 | pub trait State { 11 | type Error; 12 | 13 | /// Get basic account information. 14 | fn basic(&mut self, address: Address) -> Result, Self::Error>; 15 | 16 | /// Get account code by its hash 17 | fn code_by_hash(&mut self, code_hash: B256) -> Result; 18 | 19 | /// Get storage value of address at index. 20 | fn storage(&mut self, address: Address, index: U256) -> Result; 21 | } 22 | 23 | #[auto_impl(&, &mut, Box, Rc, Arc)] 24 | pub trait StateRef { 25 | type Error; 26 | 27 | /// Get basic account information. 28 | fn basic(&self, address: Address) -> Result, Self::Error>; 29 | 30 | /// Get account code by its hash 31 | fn code_by_hash(&self, code_hash: B256) -> Result; 32 | 33 | /// Get storage value of address at index. 34 | fn storage(&self, address: Address, index: U256) -> Result; 35 | } 36 | 37 | impl State for &T 38 | where 39 | T: StateRef, 40 | { 41 | type Error = ::Error; 42 | 43 | fn basic(&mut self, address: Address) -> Result, Self::Error> { 44 | StateRef::basic(*self, address) 45 | } 46 | 47 | fn code_by_hash(&mut self, code_hash: B256) -> Result { 48 | StateRef::code_by_hash(*self, code_hash) 49 | } 50 | 51 | fn storage(&mut self, address: Address, index: U256) -> Result { 52 | StateRef::storage(*self, address, index) 53 | } 54 | } 55 | 56 | impl State for Arc 57 | where 58 | T: StateRef, 59 | { 60 | type Error = ::Error; 61 | 62 | fn basic(&mut self, address: Address) -> Result, Self::Error> { 63 | self.deref().basic(address) 64 | } 65 | 66 | fn code_by_hash(&mut self, code_hash: B256) -> Result { 67 | self.deref().code_by_hash(code_hash) 68 | } 69 | 70 | fn storage(&mut self, address: Address, index: U256) -> Result { 71 | self.deref().storage(address, index) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /crates/primitives/src/kzg.rs: -------------------------------------------------------------------------------- 1 | mod env_settings; 2 | mod trusted_setup_points; 3 | 4 | pub use c_kzg::KzgSettings; 5 | pub use env_settings::EnvKzgSettings; 6 | pub use trusted_setup_points::{ 7 | parse_kzg_trusted_setup, G1Points, G2Points, KzgErrors, BYTES_PER_G1_POINT, BYTES_PER_G2_POINT, 8 | G1_POINTS, G2_POINTS, NUM_G1_POINTS, NUM_G2_POINTS, 9 | }; 10 | -------------------------------------------------------------------------------- /crates/primitives/src/kzg/env_settings.rs: -------------------------------------------------------------------------------- 1 | use super::{ 2 | trusted_setup_points::{G1_POINTS, G2_POINTS}, 3 | KzgSettings, 4 | }; 5 | use core::hash::{Hash, Hasher}; 6 | use once_cell::race::OnceBox; 7 | use std::{boxed::Box, sync::Arc}; 8 | 9 | /// KZG Settings that allow us to specify a custom trusted setup. 10 | /// or use hardcoded default settings. 11 | #[derive(Debug, Clone, Default, Eq)] 12 | pub enum EnvKzgSettings { 13 | /// Default mainnet trusted setup 14 | #[default] 15 | Default, 16 | /// Custom trusted setup. 17 | Custom(Arc), 18 | } 19 | 20 | // Implement PartialEq and Hash manually because `c_kzg::KzgSettings` does not implement them 21 | impl PartialEq for EnvKzgSettings { 22 | fn eq(&self, other: &Self) -> bool { 23 | match (self, other) { 24 | (Self::Default, Self::Default) => true, 25 | (Self::Custom(a), Self::Custom(b)) => Arc::ptr_eq(a, b), 26 | _ => false, 27 | } 28 | } 29 | } 30 | 31 | impl Hash for EnvKzgSettings { 32 | fn hash(&self, state: &mut H) { 33 | core::mem::discriminant(self).hash(state); 34 | match self { 35 | Self::Default => {} 36 | Self::Custom(settings) => Arc::as_ptr(settings).hash(state), 37 | } 38 | } 39 | } 40 | 41 | impl EnvKzgSettings { 42 | /// Return set KZG settings. 43 | /// 44 | /// In will initialize the default settings if it is not already loaded. 45 | pub fn get(&self) -> &KzgSettings { 46 | match self { 47 | Self::Default => { 48 | static DEFAULT: OnceBox = OnceBox::new(); 49 | DEFAULT.get_or_init(|| { 50 | let settings = 51 | KzgSettings::load_trusted_setup(G1_POINTS.as_ref(), G2_POINTS.as_ref()) 52 | .expect("failed to load default trusted setup"); 53 | Box::new(settings) 54 | }) 55 | } 56 | Self::Custom(settings) => settings, 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /crates/primitives/src/kzg/g1_points.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/megaeth-labs/revm/6d5256eaa9212e17da5a9fd8e9131fc85a0e7ad9/crates/primitives/src/kzg/g1_points.bin -------------------------------------------------------------------------------- /crates/primitives/src/kzg/g2_points.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/megaeth-labs/revm/6d5256eaa9212e17da5a9fd8e9131fc85a0e7ad9/crates/primitives/src/kzg/g2_points.bin -------------------------------------------------------------------------------- /crates/primitives/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # revm-primitives 2 | //! 3 | //! EVM primitive types. 4 | #![cfg_attr(not(test), warn(unused_crate_dependencies))] 5 | #![cfg_attr(not(feature = "std"), no_std)] 6 | 7 | #[cfg(not(feature = "std"))] 8 | extern crate alloc as std; 9 | 10 | mod bytecode; 11 | mod constants; 12 | pub mod db; 13 | pub mod env; 14 | 15 | #[cfg(feature = "c-kzg")] 16 | pub mod kzg; 17 | pub mod precompile; 18 | pub mod result; 19 | pub mod specification; 20 | pub mod state; 21 | pub mod utilities; 22 | pub use alloy_primitives::{ 23 | self, address, b256, bytes, fixed_bytes, hex, hex_literal, ruint, uint, Address, Bytes, 24 | FixedBytes, Log, LogData, B256, I256, U256, 25 | }; 26 | pub use bitvec; 27 | pub use bytecode::*; 28 | pub use constants::*; 29 | pub use env::*; 30 | 31 | cfg_if::cfg_if! { 32 | if #[cfg(all(not(feature = "hashbrown"), feature = "std"))] { 33 | pub use std::collections::{hash_map, hash_set, HashMap, HashSet}; 34 | use hashbrown as _; 35 | } else { 36 | pub use hashbrown::{hash_map, hash_set, HashMap, HashSet}; 37 | } 38 | } 39 | 40 | #[cfg(feature = "c-kzg")] 41 | pub use kzg::{EnvKzgSettings, KzgSettings}; 42 | pub use precompile::*; 43 | pub use result::*; 44 | pub use specification::*; 45 | pub use state::*; 46 | pub use utilities::*; 47 | -------------------------------------------------------------------------------- /crates/revm/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-2024 draganrakita 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /crates/revm/src/db.rs: -------------------------------------------------------------------------------- 1 | //! [Database] implementations. 2 | 3 | //#[cfg(feature = "alloydb")] 4 | //pub mod alloydb; 5 | pub mod emptydb; 6 | #[cfg(feature = "ethersdb")] 7 | pub mod ethersdb; 8 | pub mod in_memory_db; 9 | pub mod states; 10 | 11 | pub use crate::primitives::db::*; 12 | //#[cfg(feature = "alloydb")] 13 | //pub use alloydb::AlloyDB; 14 | pub use emptydb::{EmptyDB, EmptyDBTyped}; 15 | #[cfg(feature = "ethersdb")] 16 | pub use ethersdb::EthersDB; 17 | pub use in_memory_db::*; 18 | pub use states::{ 19 | AccountRevert, AccountStatus, BundleAccount, BundleState, CacheState, DBBox, 20 | OriginalValuesKnown, PlainAccount, RevertToSlot, State, StateBuilder, StateDBBox, 21 | StorageWithOriginalValues, TransitionAccount, TransitionState, 22 | }; 23 | -------------------------------------------------------------------------------- /crates/revm/src/db/states.rs: -------------------------------------------------------------------------------- 1 | pub mod account_status; 2 | pub mod bundle_account; 3 | pub mod bundle_state; 4 | pub mod cache; 5 | pub mod cache_account; 6 | pub mod changes; 7 | pub mod plain_account; 8 | pub mod reverts; 9 | pub mod state; 10 | pub mod state_builder; 11 | pub mod transition_account; 12 | pub mod transition_state; 13 | 14 | /// Account status for Block and Bundle states. 15 | pub use account_status::AccountStatus; 16 | pub use bundle_account::BundleAccount; 17 | pub use bundle_state::{BundleBuilder, BundleState, OriginalValuesKnown}; 18 | pub use cache::CacheState; 19 | pub use cache_account::CacheAccount; 20 | pub use changes::{PlainStateReverts, PlainStorageChangeset, PlainStorageRevert, StateChangeset}; 21 | pub use plain_account::{PlainAccount, StorageSlot, StorageWithOriginalValues}; 22 | pub use reverts::{AccountRevert, RevertToSlot}; 23 | pub use state::{DBBox, State, StateDBBox}; 24 | pub use state_builder::StateBuilder; 25 | pub use transition_account::TransitionAccount; 26 | pub use transition_state::TransitionState; 27 | -------------------------------------------------------------------------------- /crates/revm/src/db/states/transition_state.rs: -------------------------------------------------------------------------------- 1 | use super::TransitionAccount; 2 | use revm_interpreter::primitives::{hash_map::Entry, Address, HashMap}; 3 | use std::vec::Vec; 4 | 5 | #[derive(Clone, Default, Debug, PartialEq, Eq)] 6 | pub struct TransitionState { 7 | /// Block state account with account state 8 | pub transitions: HashMap, 9 | } 10 | 11 | impl TransitionState { 12 | /// Create new transition state with one transition. 13 | pub fn single(address: Address, transition: TransitionAccount) -> Self { 14 | let mut transitions = HashMap::new(); 15 | transitions.insert(address, transition); 16 | TransitionState { transitions } 17 | } 18 | 19 | /// Return transition id and all account transitions. Leave empty transition map. 20 | pub fn take(&mut self) -> TransitionState { 21 | core::mem::take(self) 22 | } 23 | 24 | pub fn add_transitions(&mut self, transitions: Vec<(Address, TransitionAccount)>) { 25 | for (address, account) in transitions { 26 | match self.transitions.entry(address) { 27 | Entry::Occupied(entry) => { 28 | let entry = entry.into_mut(); 29 | entry.update(account); 30 | } 31 | Entry::Vacant(entry) => { 32 | entry.insert(account); 33 | } 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /crates/revm/src/handler/handle_types.rs: -------------------------------------------------------------------------------- 1 | // Modules 2 | 3 | pub mod execution; 4 | pub mod post_execution; 5 | pub mod pre_execution; 6 | pub mod validation; 7 | 8 | // Exports 9 | 10 | pub use validation::{ 11 | ValidateEnvHandle, ValidateInitialTxGasHandle, ValidateTxEnvAgainstState, ValidationHandler, 12 | }; 13 | 14 | pub use execution::{ 15 | ExecutionHandler, FrameCallHandle, FrameCallReturnHandle, FrameCreateHandle, 16 | FrameCreateReturnHandle, InsertCallOutcomeHandle, InsertCreateOutcomeHandle, 17 | }; 18 | 19 | pub use pre_execution::{ 20 | DeductCallerHandle, LoadAccountsHandle, LoadPrecompilesHandle, PreExecutionHandler, 21 | }; 22 | 23 | pub use post_execution::{ 24 | EndHandle, OutputHandle, PostExecutionHandler, ReimburseCallerHandle, RewardBeneficiaryHandle, 25 | }; 26 | -------------------------------------------------------------------------------- /crates/revm/src/handler/handle_types/pre_execution.rs: -------------------------------------------------------------------------------- 1 | // Includes. 2 | use crate::{ 3 | handler::mainnet, 4 | primitives::{db::Database, EVMError, EVMResultGeneric, Spec}, 5 | Context, ContextPrecompiles, 6 | }; 7 | use std::sync::Arc; 8 | 9 | /// Loads precompiles into Evm 10 | pub type LoadPrecompilesHandle<'a, DB> = Arc ContextPrecompiles + 'a>; 11 | 12 | /// Load access list accounts and beneficiary. 13 | /// There is no need to load Caller as it is assumed that 14 | /// it will be loaded in DeductCallerHandle. 15 | pub type LoadAccountsHandle<'a, EXT, DB> = 16 | Arc) -> Result<(), EVMError<::Error>> + 'a>; 17 | 18 | /// Deduct the caller to its limit. 19 | pub type DeductCallerHandle<'a, EXT, DB> = 20 | Arc) -> EVMResultGeneric<(), ::Error> + 'a>; 21 | 22 | /// Handles related to pre execution before the stack loop is started. 23 | pub struct PreExecutionHandler<'a, EXT, DB: Database> { 24 | /// Load precompiles 25 | pub load_precompiles: LoadPrecompilesHandle<'a, DB>, 26 | /// Main load handle 27 | pub load_accounts: LoadAccountsHandle<'a, EXT, DB>, 28 | /// Deduct max value from the caller. 29 | pub deduct_caller: DeductCallerHandle<'a, EXT, DB>, 30 | } 31 | 32 | impl<'a, EXT: 'a, DB: Database + 'a> PreExecutionHandler<'a, EXT, DB> { 33 | /// Creates mainnet MainHandles. 34 | pub fn new() -> Self { 35 | Self { 36 | load_precompiles: Arc::new(mainnet::load_precompiles::), 37 | load_accounts: Arc::new(mainnet::load_accounts::), 38 | deduct_caller: Arc::new(mainnet::deduct_caller::), 39 | } 40 | } 41 | } 42 | 43 | impl<'a, EXT, DB: Database> PreExecutionHandler<'a, EXT, DB> { 44 | /// Deduct caller to its limit. 45 | pub fn deduct_caller(&self, context: &mut Context) -> Result<(), EVMError> { 46 | (self.deduct_caller)(context) 47 | } 48 | 49 | /// Main load 50 | pub fn load_accounts(&self, context: &mut Context) -> Result<(), EVMError> { 51 | (self.load_accounts)(context) 52 | } 53 | 54 | /// Load precompiles 55 | pub fn load_precompiles(&self) -> ContextPrecompiles { 56 | (self.load_precompiles)() 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /crates/revm/src/handler/handle_types/validation.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | handler::mainnet, 3 | primitives::{db::Database, EVMError, Env, Spec}, 4 | Context, 5 | }; 6 | use std::sync::Arc; 7 | 8 | /// Handle that validates env. 9 | pub type ValidateEnvHandle<'a, DB> = 10 | Arc Result<(), EVMError<::Error>> + 'a>; 11 | 12 | /// Handle that validates transaction environment against the state. 13 | /// Second parametar is initial gas. 14 | pub type ValidateTxEnvAgainstState<'a, EXT, DB> = 15 | Arc) -> Result<(), EVMError<::Error>> + 'a>; 16 | 17 | /// Initial gas calculation handle 18 | pub type ValidateInitialTxGasHandle<'a, DB> = 19 | Arc Result::Error>> + 'a>; 20 | 21 | /// Handles related to validation. 22 | pub struct ValidationHandler<'a, EXT, DB: Database> { 23 | /// Validate and calculate initial transaction gas. 24 | pub initial_tx_gas: ValidateInitialTxGasHandle<'a, DB>, 25 | /// Validate transactions against state data. 26 | pub tx_against_state: ValidateTxEnvAgainstState<'a, EXT, DB>, 27 | /// Validate Env. 28 | pub env: ValidateEnvHandle<'a, DB>, 29 | } 30 | 31 | impl<'a, EXT: 'a, DB: Database + 'a> ValidationHandler<'a, EXT, DB> { 32 | /// Create new ValidationHandles 33 | pub fn new() -> Self { 34 | Self { 35 | initial_tx_gas: Arc::new(mainnet::validate_initial_tx_gas::), 36 | env: Arc::new(mainnet::validate_env::), 37 | tx_against_state: Arc::new(mainnet::validate_tx_against_state::), 38 | } 39 | } 40 | } 41 | 42 | impl<'a, EXT, DB: Database> ValidationHandler<'a, EXT, DB> { 43 | /// Validate env. 44 | pub fn env(&self, env: &Env) -> Result<(), EVMError> { 45 | (self.env)(env) 46 | } 47 | 48 | /// Initial gas 49 | pub fn initial_tx_gas(&self, env: &Env) -> Result> { 50 | (self.initial_tx_gas)(env) 51 | } 52 | 53 | /// Validate ttansaction against the state. 54 | pub fn tx_against_state( 55 | &self, 56 | context: &mut Context, 57 | ) -> Result<(), EVMError> { 58 | (self.tx_against_state)(context) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /crates/revm/src/handler/mainnet.rs: -------------------------------------------------------------------------------- 1 | //! Mainnet related handlers. 2 | 3 | mod execution; 4 | mod post_execution; 5 | mod pre_execution; 6 | mod validation; 7 | 8 | pub use execution::{ 9 | call, call_return, create, create_return, eofcreate, eofcreate_return, execute_frame, 10 | frame_return_with_refund_flag, insert_call_outcome, insert_create_outcome, 11 | insert_eofcreate_outcome, last_frame_return, 12 | }; 13 | pub use post_execution::{clear, end, output, reimburse_caller, reward_beneficiary}; 14 | pub use pre_execution::{deduct_caller, deduct_caller_inner, load_accounts, load_precompiles}; 15 | pub use validation::{validate_env, validate_initial_tx_gas, validate_tx_against_state}; 16 | -------------------------------------------------------------------------------- /crates/revm/src/handler/mainnet/validation.rs: -------------------------------------------------------------------------------- 1 | use revm_interpreter::gas; 2 | 3 | use crate::{ 4 | primitives::{db::Database, EVMError, Env, InvalidTransaction, Spec}, 5 | Context, 6 | }; 7 | 8 | /// Validate environment for the mainnet. 9 | pub fn validate_env(env: &Env) -> Result<(), EVMError> { 10 | // Important: validate block before tx. 11 | env.validate_block_env::()?; 12 | env.validate_tx::()?; 13 | Ok(()) 14 | } 15 | 16 | /// Validates transaction against the state. 17 | pub fn validate_tx_against_state( 18 | context: &mut Context, 19 | ) -> Result<(), EVMError> { 20 | // load acc 21 | let tx_caller = context.evm.env.tx.caller; 22 | let (caller_account, _) = context 23 | .evm 24 | .inner 25 | .journaled_state 26 | .load_account(tx_caller, &mut context.evm.inner.db)?; 27 | 28 | context 29 | .evm 30 | .inner 31 | .env 32 | .validate_tx_against_state::(caller_account) 33 | .map_err(EVMError::Transaction)?; 34 | 35 | Ok(()) 36 | } 37 | 38 | /// Validate initial transaction gas. 39 | pub fn validate_initial_tx_gas( 40 | env: &Env, 41 | ) -> Result> { 42 | let input = &env.tx.data; 43 | let is_create = env.tx.transact_to.is_create(); 44 | let access_list = &env.tx.access_list; 45 | 46 | let initial_gas_spend = 47 | gas::validate_initial_tx_gas(SPEC::SPEC_ID, input, is_create, access_list); 48 | 49 | // Additional check to see if limit is big enough to cover initial gas. 50 | if initial_gas_spend > env.tx.gas_limit { 51 | return Err(InvalidTransaction::CallGasCostMoreThanGasLimit.into()); 52 | } 53 | Ok(initial_gas_spend) 54 | } 55 | -------------------------------------------------------------------------------- /crates/revm/src/handler/register.rs: -------------------------------------------------------------------------------- 1 | use crate::{db::Database, handler::Handler, Context}; 2 | use std::boxed::Box; 3 | 4 | /// EVM Handler 5 | pub type EvmHandler<'a, EXT, DB> = Handler<'a, Context, EXT, DB>; 6 | 7 | // Handle register 8 | pub type HandleRegister = for<'a> fn(&mut EvmHandler<'a, EXT, DB>); 9 | 10 | // Boxed handle register 11 | pub type HandleRegisterBox = Box Fn(&mut EvmHandler<'a, EXT, DB>)>; 12 | 13 | pub enum HandleRegisters { 14 | /// Plain function register 15 | Plain(HandleRegister), 16 | /// Boxed function register. 17 | Box(HandleRegisterBox), 18 | } 19 | 20 | impl HandleRegisters { 21 | /// Call register function to modify EvmHandler. 22 | pub fn register(&self, handler: &mut EvmHandler<'_, EXT, DB>) { 23 | match self { 24 | HandleRegisters::Plain(f) => f(handler), 25 | HandleRegisters::Box(f) => f(handler), 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /crates/revm/src/inspector/noop.rs: -------------------------------------------------------------------------------- 1 | use crate::{Database, Inspector}; 2 | /// Dummy [Inspector], helpful as standalone replacement. 3 | #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] 4 | pub struct NoOpInspector; 5 | 6 | impl Inspector for NoOpInspector {} 7 | -------------------------------------------------------------------------------- /crates/revm/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Revm is a Rust EVM implementation. 2 | #![cfg_attr(not(test), warn(unused_crate_dependencies))] 3 | #![cfg_attr(not(feature = "std"), no_std)] 4 | 5 | #[macro_use] 6 | #[cfg(not(feature = "std"))] 7 | extern crate alloc as std; 8 | 9 | // Define modules. 10 | 11 | mod builder; 12 | mod context; 13 | 14 | #[cfg(any(test, feature = "test-utils"))] 15 | pub mod test_utils; 16 | 17 | pub mod db; 18 | mod evm; 19 | mod frame; 20 | pub mod handler; 21 | mod inspector; 22 | mod journaled_state; 23 | #[cfg(feature = "optimism")] 24 | pub mod optimism; 25 | 26 | // Export items. 27 | 28 | pub use builder::EvmBuilder; 29 | pub use context::{ 30 | Context, ContextPrecompile, ContextPrecompiles, ContextStatefulPrecompile, 31 | ContextStatefulPrecompileArc, ContextStatefulPrecompileBox, ContextStatefulPrecompileMut, 32 | ContextWithHandlerCfg, EvmContext, InnerEvmContext, 33 | }; 34 | pub use db::{ 35 | CacheState, DBBox, State, StateBuilder, StateDBBox, TransitionAccount, TransitionState, 36 | }; 37 | pub use db::{Database, DatabaseCommit, DatabaseRef, InMemoryDB}; 38 | pub use evm::{Evm, CALL_STACK_LIMIT}; 39 | pub use frame::{CallFrame, CreateFrame, Frame, FrameData, FrameOrResult, FrameResult}; 40 | pub use handler::Handler; 41 | pub use inspector::{ 42 | inspector_handle_register, inspector_instruction, inspectors, GetInspector, Inspector, 43 | }; 44 | pub use journaled_state::{JournalCheckpoint, JournalEntry, JournaledState}; 45 | // export Optimism types, helpers, and constants 46 | #[cfg(feature = "optimism")] 47 | pub use optimism::{L1BlockInfo, BASE_FEE_RECIPIENT, L1_BLOCK_CONTRACT, L1_FEE_RECIPIENT}; 48 | 49 | // Reexport libraries 50 | 51 | #[doc(inline)] 52 | pub use revm_interpreter as interpreter; 53 | #[doc(inline)] 54 | pub use revm_interpreter::primitives; 55 | #[doc(inline)] 56 | pub use revm_precompile as precompile; 57 | -------------------------------------------------------------------------------- /crates/revm/src/optimism.rs: -------------------------------------------------------------------------------- 1 | //! Optimism-specific constants, types, and helpers. 2 | 3 | mod fast_lz; 4 | mod handler_register; 5 | mod l1block; 6 | 7 | pub use handler_register::{ 8 | deduct_caller, end, last_frame_return, load_accounts, load_precompiles, 9 | optimism_handle_register, output, reward_beneficiary, validate_env, validate_tx_against_state, 10 | }; 11 | pub use l1block::{L1BlockInfo, BASE_FEE_RECIPIENT, L1_BLOCK_CONTRACT, L1_FEE_RECIPIENT}; 12 | -------------------------------------------------------------------------------- /crates/revm/src/test_utils.rs: -------------------------------------------------------------------------------- 1 | #[doc(hidden)] 2 | pub use crate::context::evm_context::test_utils::*; 3 | -------------------------------------------------------------------------------- /documentation/src/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | - [Introduction](./introduction.md) 4 | - [Revm](./crates/revm.md) 5 | - [evm](./crates/revm/evm.md) 6 | - [builder](./crates/revm/builder.md) 7 | - [handler](./crates/revm/handler.md) 8 | - [inspector](./crates/revm/inspector.md) 9 | - [state](./crates/revm/state.md) 10 | - [journaled_state](./crates/revm/journaled_state.md) 11 | - [Interpreter](./crates/interpreter.md) 12 | - [gas](./crates/interpreter/gas.md) 13 | - [memory](./crates/interpreter/memory.md) 14 | - [host](./crates/interpreter/host.md) 15 | - [interpreter_action](./crates/interpreter/interpreter_action.md) 16 | - [instruction_result](./crates/interpreter/instruction_result.md) 17 | - [instructions](./crates/interpreter/instructions.md) 18 | - [Primitives](./crates/primitives.md) 19 | - [database](./crates/primitives/database.md) 20 | - [result](./crates/primitives/result.md) 21 | - [environment](./crates/primitives/environment.md) 22 | - [specifications](./crates/primitives/specifications.md) 23 | - [bytecode](./crates/primitives/bytecode.md) 24 | - [constants](./crates/primitives/constants.md) 25 | - [precompile](./crates/primitives/precompile.md) 26 | - [state](./crates/primitives/state.md) 27 | - [utils](./crates/primitives/utils.md) 28 | - [kzg](./crates/primitives/kzg.md) 29 | - [Precompile](./crates/precompile.md) 30 | - [blake2](./crates/precompile/blake2.md) 31 | - [bn128 curve](./crates/precompile/bn128.md) 32 | - [Hash functions](./crates/precompile/hash.md) 33 | - [Identity function](./crates/precompile/identity.md) 34 | - [Modular Exponentiation](./crates/precompile/modexp.md) 35 | - [Secp256k1](./crates/precompile/secp256k1.md) 36 | - [Point Evaluation](./crates/precompile/point_evaluation.md) 37 | -------------------------------------------------------------------------------- /documentation/src/bins/revm-test.md: -------------------------------------------------------------------------------- 1 | # revm-test 2 | -------------------------------------------------------------------------------- /documentation/src/bins/revme.md: -------------------------------------------------------------------------------- 1 | # revme 2 | -------------------------------------------------------------------------------- /documentation/src/crates/interpreter.md: -------------------------------------------------------------------------------- 1 | # Interpreter 2 | 3 | The `interpreter` crate is concerned with the execution of the EVM opcodes and serves as the event loop to step through the opcodes. 4 | The interpreter is concerned with attributes like gas, contracts, memory, stack, and returning execution results. 5 | It is structured as follows: 6 | 7 | ### Modules: 8 | 9 | - [gas](./interpreter/gas.md): Handles gas mechanics in the EVM, such as calculating gas costs for operations. 10 | - [host](./interpreter/host.md): Defines the EVM context `Host` trait. 11 | - [interpreter_action](./interpreter/interpreter_action.md): Contains data structures used in the EVM implementation. 12 | - [instruction_result](./interpreter/instruction_result.md): Defines results of instruction execution. 13 | - [instructions](./interpreter/instructions.md): Defines the EVM opcodes (i.e. instructions). 14 | 15 | ### External Crates: 16 | 17 | - [alloc](https://doc.rust-lang.org/alloc/): 18 | The `alloc` crate is used to provide the ability to allocate memory on the heap. 19 | It's a part of Rust's standard library that can be used in environments without a full host OS. 20 | - [core](https://doc.rust-lang.org/core/): 21 | The `core` crate is the dependency-free foundation of the Rust standard library. 22 | It includes fundamental types, macros, and traits. 23 | 24 | ### Re-exports: 25 | - Several types and functions are re-exported for easier access by users of this library, such as `Gas`, `Host`, `InstructionResult`, `OpCode`, `Interpreter`, `Memory`, `Stack`, and others. 26 | This allows users to import these items directly from the library root instead of from their individual modules. 27 | - `revm_primitives`: This crate is re-exported, providing primitive types or functionality used in the EVM implementation. 28 | -------------------------------------------------------------------------------- /documentation/src/crates/interpreter/gas.md: -------------------------------------------------------------------------------- 1 | # The `gas.rs` Module 2 | 3 | The `gas.rs` module in this Rust EVM implementation manages the concept of "gas" within the Ethereum network. In Ethereum, "gas" signifies the computational effort needed to execute operations, whether a simple transfer of ether or the execution of a smart contract function. Each operation carries a gas cost, and transactions must specify the maximum amount of gas they are willing to consume. 4 | 5 | ## Data Structures 6 | - `Gas` Struct 7 | 8 | The `Gas` struct represents the gas state for a particular operation or transaction. The struct is defined as follows: 9 | 10 | ### Fields in `Gas` Struct 11 | 12 | - `limit`: The maximum amount of gas allowed for the operation or transaction. 13 | - `all_used_gas`: The total gas used, inclusive of memory expansion costs. 14 | - `used`: The gas used, excluding memory expansion costs. 15 | - `memory`: The gas used for memory expansion. 16 | - `refunded`: The gas refunded. Certain operations in Ethereum allow for gas refunds, up to half the gas used by a transaction. 17 | 18 | ## Methods of the `Gas` Struct 19 | 20 | The `Gas` struct also includes several methods to manage the gas state. Here's a brief summary of their functions: 21 | 22 | - `new`: Creates a new `Gas` instance with a specified gas limit and zero usage and refunds. 23 | - `limit`, `memory`, `refunded`, `spend`, `remaining`: These getters return the current state of the corresponding field. 24 | - `erase_cost`: Decreases the gas usage by a specified amount. 25 | - `record_refund`: Increases the refunded gas by a specified amount. 26 | - `record_cost`: Increases the used gas by a specified amount. It also checks for gas limit overflow. If the new total used gas would exceed the gas limit, it returns `false` and doesn't change the state. 27 | - `record_memory`: This method works similarly to `record_cost`, but specifically for memory expansion gas. It only updates the state if the new memory gas usage is greater than the current usage. 28 | - `gas_refund`: Increases the refunded gas by a specified amount. 29 | 30 | -------------------------------------------------------------------------------- /documentation/src/crates/interpreter/host.md: -------------------------------------------------------------------------------- 1 | # The `host.rs` Module 2 | 3 | The `host.rs` module in this Rust EVM implementation defines a crucial trait `Host`. The `Host` trait outlines an interface for the interaction of the EVM interpreter with its environment (or "host"), encompassing essential operations such as account and storage access, creating logs, and invoking transactions. 4 | 5 | The [`Evm`](./../revm/evm.md) struct implements this `Host` trait. 6 | 7 | ## Trait Methods 8 | 9 | - `env`: This method provides access to the EVM environment, including information about the current block and transaction. 10 | 11 | - `load_account`: Retrieves information about a given Ethereum account. 12 | 13 | - `block_hash`: Retrieves the block hash for a given block number. 14 | 15 | - `balance`, `code`, `code_hash`, `sload`: These methods retrieve specific information (balance, code, code hash, and specific storage value) for a given Ethereum account. 16 | 17 | - `sstore`: This method sets the value of a specific storage slot in a given Ethereum account. 18 | 19 | - `log`: Creates a log entry with the specified address, topics, and data. Log entries are used by smart contracts to emit events. 20 | 21 | - `selfdestruct`: Marks an Ethereum account to be self-destructed, transferring its funds to a target account. 22 | 23 | 24 | The `Host` trait provides a standard interface that any host environment for the EVM must implement. This abstraction allows the EVM code to interact with the state of the Ethereum network in a generic way, thereby enhancing modularity and interoperability. Different implementations of the `Host` trait can be used to simulate different environments for testing or for connecting to different Ethereum-like networks. -------------------------------------------------------------------------------- /documentation/src/crates/interpreter/instruction_result.md: -------------------------------------------------------------------------------- 1 | # The `instruction_result.rs` Module 2 | 3 | The `instruction_result.rs` module of this Rust EVM implementation includes the definitions of the `InstructionResult` and `SuccessOrHalt` enum, which represent the possible outcomes of EVM instruction execution, and functions to work with these types. 4 | 5 | - `InstructionResult` Enum 6 | 7 | The `InstructionResult` enum categorizes the different types of results that can arise from executing an EVM instruction. This enumeration uses the `#[repr(u8)]` attribute, meaning its variants have an explicit storage representation of an 8-bit unsigned integer. The different instruction results represent outcomes such as successful continuation, stop, return, self-destruction, reversion, deep call, out of funds, out of gas, and various error conditions. 8 | 9 | - `SuccessOrHalt` Enum 10 | 11 | The `SuccessOrHalt` enum represents the outcome of a transaction execution, distinguishing successful operations, reversion, halting conditions, fatal external errors, and internal continuation. It also provides several methods to check the kind of result and to extract the value of the successful evaluation or halt. 12 | 13 | - `From for SuccessOrHalt` Implementation 14 | 15 | This implementation provides a way to convert an `InstructionResult` into a `SuccessOrHalt`. It maps each instruction result to the corresponding `SuccessOrHalt` variant. 16 | 17 | - Macros for returning instruction results 18 | 19 | The module provides two macros, `return_ok!` and `return_revert!`, which simplify returning some common sets of instruction results. 20 | -------------------------------------------------------------------------------- /documentation/src/crates/interpreter/instructions.md: -------------------------------------------------------------------------------- 1 | # The `instruction.rs` Module in the Rust Ethereum Virtual Machine (EVM) 2 | 3 | The `instruction.rs` module defines interpretation mappings for EVM bytecode. It provides the definition of the `Instruction` struct, as well as the `Opcode` enumeration and the `execute` function, which runs a specific instruction. 4 | 5 | ## `Opcode` Enum 6 | 7 | The `Opcode` enum represents the opcodes that are available in the Ethereum Virtual Machine. Each variant corresponds to an operation that can be performed, such as addition, multiplication, subtraction, jumps, and memory operations. 8 | 9 | ## `Instruction` Struct 10 | 11 | The `Instruction` struct represents a single instruction in the EVM. It contains the opcode, which is the operation to be performed, and a list of bytes representing the operands for the instruction. 12 | 13 | ## `step` Function 14 | 15 | The `step` function interprets an instruction. It uses the opcode to determine what operation to perform and then performs the operation using the operands in the instruction. -------------------------------------------------------------------------------- /documentation/src/crates/interpreter/memory.md: -------------------------------------------------------------------------------- 1 | # EVM Memory 2 | 3 | Is a memory localized to the current Interpreter context. Interpreter context is a call or create frame. It is used by opcodes to store or format data that are more then 32 bytes long, for example calls to format input, return output or for logs data. Revm has a shared memory between all the Interpreters but Interpreter loop only see the part it is allocated to it. 4 | 5 | Extending memory is paid by the gas. It consumes 3 gas per word plus square of the number of words added divided by `512` (`3*N+ N^2/512`). There is no limit on the size of the memory, but it is limited by logaritmic growth of the gas cost. For 30M there is a calculated max memory of 32MB (Blog post by ramco: [Upper bound for transaction memory](https://xn--2-umb.com/22/eth-max-mem/)). 6 | 7 | ## Opcodes 8 | 9 | Here is a list of all opcodes that are reading or writing to the memory. All read on memory can still change the memory size by extending it with zeroes. Call opcodes are specific as they read input before the call but also write their output after the call (if call is okay and there is an output to write) to the memory. 10 | 11 | These opcodes read from the memory: 12 | * RETURN 13 | * REVERT 14 | * LOG 15 | * KECCAK256 16 | * CREATE 17 | * CREATE2 18 | * CALL 19 | * CALLCODE 20 | * DELEGATECALL 21 | * STATICCALL 22 | 23 | These opcodes change the memory: 24 | * EXTCODECOPY 25 | * MLOAD 26 | * MSTORE 27 | * MSTORE8 28 | * MCOPY 29 | * CODECOPY 30 | * CALLDATACOPY 31 | * RETURNDATACOPY 32 | * CALL 33 | * CALLCODE 34 | * DELEGATECALL 35 | * STATICCALL -------------------------------------------------------------------------------- /documentation/src/crates/precompile/hash.md: -------------------------------------------------------------------------------- 1 | ## SHA256 and RIPEMD160 2 | 3 | REVM includes precompiled contracts for `SHA256` and `RIPEMD160`, cryptographic hashing functions integral for data integrity and security. The addresses for these precompiled contracts are `0x0000000000000000000000000000000000000002` for `SHA256` and `0x0000000000000000000000000000000000000003` for `RIPEMD160`. 4 | 5 | Each function (`sha256_run` and `ripemd160_run`) accepts two arguments, the input data to be hashed and the gas_limit representing the maximum amount of computational work permissible for the function. They both calculate the gas cost of the operation based on the input data length. If the computed cost surpasses the `gas_limit`, an `Error::OutOfGas` is triggered. 6 | 7 | The `sha256_run` function, corresponding to the `SHA256` precompiled contract, computes the `SHA256` hash of the input data. The `ripemd160_run` function computes the `RIPEMD160` hash of the input and pads it to match Ethereum's 256-bit word size. These precompiled contracts offer a computationally efficient way for Ethereum contracts to perform necessary cryptographic operations. 8 | -------------------------------------------------------------------------------- /documentation/src/crates/precompile/identity.md: -------------------------------------------------------------------------------- 1 | ## Identity function 2 | 3 | This precompiled contract performs the identity function. In mathematics, an identity function is a function that always returns the same value as its argument. In this context, the contract takes the input data and returns it as is. This precompiled contract resides at the hardcoded Ethereum address `0x0000000000000000000000000000000000000004`. 4 | 5 | The `identity_run` function takes two arguments: input data, which it returns unaltered, and `gas_limit` which defines the maximum computational work the function is allowed to do. A linear gas cost calculation based on the size of the input data and two constants, `IDENTITY_BASE` (the base cost of the operation) and `IDENTITY_PER_WORD` (the cost per word), is performed. If the calculated gas cost exceeds the `gas_limit`, an `Error::OutOfGas` is returned. 6 | 7 | This identity function can be useful in various scenarios such as forwarding data or acting as a data validation check within a contract. Despite its simplicity, it contributes to the flexibility and broad utility of the Ethereum platform. 8 | -------------------------------------------------------------------------------- /documentation/src/crates/precompile/modexp.md: -------------------------------------------------------------------------------- 1 | # Modular Exponentiation 2 | 3 | REVM also implements two versions of a precompiled contract (Modular Exponential operation), each corresponding to different Ethereum hard forks: Byzantium and Berlin. The contract addresses are `0x0000000000000000000000000000000000000005` for both versions, as they replaced each other in subsequent network upgrades. This operation is used for cryptographic computations and is a crucial part of Ethereum's toolkit. 4 | 5 | The byzantium_run and berlin_run functions each run the modular exponential operation using the `run_inner` function, but each uses a different gas calculation method: `byzantium_gas_calc` for Byzantium and `berlin_gas_calc` for Berlin. The gas calculation method used is chosen based on the Ethereum network's current version. The `run_inner` function is a core function that reads the inputs and performs the modular exponential operation. If the calculated gas cost is higher than the gas limit, an error `Error::OutOfGas` is returned. If all computations are successful, the function returns the result of the operation and the gas cost. 6 | 7 | The calculate_iteration_count function calculates the number of iterations required to compute the operation, based on the length and value of the exponent. The `read_u64_with_overflow` macro reads input data and checks for potential overflows. 8 | 9 | The byzantium_gas_calc function calculates the gas cost for the modular exponential operation as defined in the Byzantium version of the Ethereum protocol. The `berlin_gas_calc` function calculates the gas cost according to the Berlin version, as defined in [EIP-2565](https://eips.ethereum.org/EIPS/eip-2565). These two versions have different formulas to calculate the gas cost of the operation, reflecting the evolution of the Ethereum network. 10 | -------------------------------------------------------------------------------- /documentation/src/crates/precompile/point_evaluation.md: -------------------------------------------------------------------------------- 1 | # Point Evaluation Precompile 2 | 3 | This precompile is introduced in [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) and is used to verify KZG commitments of blobs. The precompile allows for efficient verification of commitments to blob transactions. Blob transactions contain a large amount of data that cannot be accessed by EVM execution, but has a commitment that can be accessed and verified. The EIP is designed to be forward compatible with [Danksharding](https://ethereum.org/en/roadmap/danksharding/) architecture while giving L2s access to cheaper L1 commitments. This precompiled contract resides at the hardcoded Ethereum address `0x000000000000000000000000000000000000000A`. 4 | 5 | A useful resource is the Python reference implementation for the precompile, which can be found [here](https://github.com/ethereum/consensus-specs/blob/86fb82b221474cc89387fa6436806507b3849d88/specs/deneb/polynomial-commitments.md). The implementation in REVM uses [c-kzg-4844](https://github.com/ethereum/c-kzg-4844), via its [foreign function interface](https://en.wikipedia.org/wiki/Foreign_function_interface) bindings, from the Ethereum Foundation. -------------------------------------------------------------------------------- /documentation/src/crates/precompile/secp256k1.md: -------------------------------------------------------------------------------- 1 | # Secp256k1 2 | 3 | This implements Ethereum's precompiled contract `ECRECOVER`, an elliptic curve digital signature algorithm (ECDSA) recovery function that recovers the Ethereum address (public key hash) associated with a given signature. The implementation features two versions, each contingent on whether the secp256k1 cryptographic library is enabled, which depends on the build configuration. 4 | 5 | Both versions define a `secp256k1` module that includes an `ecrecover` function. This function takes a digital signature and a message as input, both represented as byte arrays, and returns the recovered Ethereum address. It performs this operation by using the signature to recover the original public key used for signing, then hashing this public key with `Keccak256`, Ethereum's chosen hash function. The hash is then truncated to match Ethereum's 20-byte address size. 6 | 7 | When `secp256k1` is not enabled, the ecrecover function uses the `k256` library to parse the signature, recover the public key, and perform the hashing. When `secp256k1` is enabled, the function uses the `secp256k1` library for these operations. Although both versions perform the same fundamental operation, they use different cryptographic libraries, which can offer different optimizations and security properties. 8 | 9 | The `ec_recover_run` function is the primary entry point for this precompiled contract. It parses the input to extract the message and signature, checks if enough gas is provided for execution, and calls the appropriate ecrecover function. The result of the recovery operation is returned as a `PrecompileResult`, a type that represents the outcome of a precompiled contract execution in Ethereum. 10 | -------------------------------------------------------------------------------- /documentation/src/crates/primitives/bits.md: -------------------------------------------------------------------------------- 1 | # Bits 2 | 3 | > NOTE: This module's types have been replaced by [`alloy_primitives`](https://github.com/alloy-rs/core)'s `Address` and `FixedBytes`. 4 | 5 | This module houses the definitions for fixed-size bit arrays, `Address` and `B256`, showcasing its role in managing bits-related operations, to represent 256-bit and 160-bit fixed-size hashes respectively. These are defined using the `construct_fixed_hash!` macro from the `fixed_hash` crate. 6 | 7 | The `AsRef` and `Deref` traits from `derive_more` crate are derived for both of these structures, providing convenient methods for converting these types to and from references of their underlying data. 8 | 9 | The `Arbitrary` trait from the `arbitrary` crate and the `PropTestArbitrary` trait from `proptest_derive` crate are derived conditionally when either testing or the "arbitrary" feature is enabled. 10 | 11 | The code also provides conversions between `B256`, `Address` and various other types such as `u64`, `primitive_types::H256`, `primitive_types::H160`, `primitive_types::U256`, and `ruint::aliases::U256`. The `impl` From blocks specify how to convert from one type to another. 12 | 13 | `impl_fixed_hash_conversions!` macro is used to define conversions between `B256` and `Address` types. 14 | 15 | If the "serde" feature is enabled, the Serialize and Deserialize traits from the serde crate are implemented for `B256` and `Address` using a custom serialization method that outputs/reads these types as hexadecimal strings. This includes a custom serialization/deserialization module for handling hexadecimal data. 16 | 17 | This module (serialize) provides functionality to serialize a slice of bytes to a hexadecimal string, and deserialize a hexadecimal string to a byte vector with size checks. It handles both "0x" prefixed and non-prefixed hexadecimal strings. It also provides functions to convert raw bytes to hexadecimal strings and vice versa, handling potential errors related to non-hexadecimal characters. The module also defines the `ExpectedLen` enum which is used to specify the expected length of the byte vectors during deserialization. 18 | -------------------------------------------------------------------------------- /documentation/src/crates/primitives/bytecode.md: -------------------------------------------------------------------------------- 1 | # Bytecode 2 | 3 | This module defines structures and methods to manipulate Ethereum bytecode and manage its state. It's built around three main components: `JumpTable`, `BytecodeState`, and `Bytecode`. 4 | 5 | The `JumpTable` structure stores a map of valid `jump` destinations within a given Ethereum bytecode sequence. It is essentially an `Arc` (Atomic Reference Counter) wrapping a `BitVec` (bit vector), which can be accessed and modified using the defined methods, such as `as_slice()`, `from_slice()`, and `is_valid()`. 6 | 7 | The `BytecodeState` is an enumeration, capturing the three possible states of the bytecode: `Raw`, `Checked`, and `Analysed`. In the `Checked` and `Analysed` states, additional data is provided, such as the length of the bytecode and, in the `Analysed` state, a `JumpTable`. 8 | 9 | The `Bytecode` struct holds the actual bytecode, its hash, and its current state (`BytecodeState`). It provides several methods to interact with the bytecode, such as getting the length of the bytecode, checking if it's empty, retrieving its state, and converting the bytecode to a checked state. It also provides methods to create new instances of the `Bytecode` struct in different states. 10 | -------------------------------------------------------------------------------- /documentation/src/crates/primitives/constants.md: -------------------------------------------------------------------------------- 1 | # Constants 2 | 3 | Holds constant values used throughout the system. This module defines important constants that help limit and manage resources in the Ethereum Virtual Machine (EVM). The constants include `STACK_LIMIT` and `CALL_STACK_LIMIT`, which restrict the size of the interpreter stack and the EVM call stack, respectively. Both are set to 1024. 4 | 5 | The module also defines `MAX_CODE_SIZE`, which is set according to [EIP-170](https://eips.ethereum.org/EIPS/eip-170)'s specification. [EIP-170](https://eips.ethereum.org/EIPS/eip-170) imposes a maximum limit on the contract code size to mitigate potential vulnerabilities and inefficiencies in Ethereum. Without this cap, the act of calling a contract can trigger costly operations that scale with the size of the contract's code. These operations include reading the code from disk, preprocessing the code for VM execution, and adding data to the block's proof-of-validity. By implementing `MAX_CODE_SIZE` (set to `0x6000` or ~25kb), the EVM ensures that the cost of these operations remains manageable, even under high gas levels that could be encountered in the future. [EIP-170](https://eips.ethereum.org/EIPS/eip-170)'s implementation thus offers crucial protection against potential DoS attacks and maintains efficiency, especially for future light clients verifying proofs of validity or invalidity. 6 | 7 | Another constant defined here is `MAX_INITCODE_SIZE`, set in accordance with [EIP-3860](https://eips.ethereum.org/EIPS/eip-3860). [EIP-3860](https://eips.ethereum.org/EIPS/eip-3860) extends EIP-170 by introducing a maximum size limit for initialization code (initcode) and enforcing a gas charge for every 32-byte chunk of initcode, to account for the cost of jump destination analysis. Before [EIP-3860](https://eips.ethereum.org/EIPS/eip-3860), initcode analysis during contract creation wasn't metered, nor was there an upper limit for its size, resulting in potential inefficiencies and vulnerabilities. By setting `MAX_INITCODE_SIZE` to 2 \* `MAX_CODE_SIZE` and introducing the said gas charge, [EIP-3860](https://eips.ethereum.org/EIPS/eip-3860) ensures that the cost of initcode analysis scales proportionately with its size. This constant, therefore, facilitates fair charging, simplifies EVM engines by setting explicit limits, and helps to create an extendable cost system for the future. 8 | -------------------------------------------------------------------------------- /documentation/src/crates/primitives/database.md: -------------------------------------------------------------------------------- 1 | # Database 2 | 3 | Responsible for database operations. This module is where the blockchain's state persistence is managed. 4 | The module defines three primary traits (`Database`, `DatabaseCommit`, and `DatabaseRef`), a structure `RefDBWrapper`, and their associated methods. 5 | 6 | The `Database` trait defines an interface for mutable interaction with the database. It has a generic associated type `Error` to handle different kinds of errors that might occur during these interactions. It provides methods to retrieve basic account information (`basic`), retrieve account code by its hash (`code_by_hash`), retrieve the storage value of an address at a certain index (`storage`), and retrieve the block hash for a certain block number (`block_hash`). 7 | 8 | The `DatabaseCommit` trait defines a single `commit` method for committing changes to the database. The changes are a map between Ethereum-like addresses (type `Address`) and accounts. 9 | 10 | The `DatabaseRef` trait is similar to the `Database` trait but is designed for read-only or immutable interactions. It has the same `Error` associated type and the same set of methods as `Database`, but these methods take `&self` instead of `&mut self`, indicating that they do not mutate the database. 11 | 12 | The `RefDBWrapper` structure is a wrapper around a reference to a `DatabaseRef` type. It implements the `Database` trait, essentially providing a way to treat a `DatabaseRef` as a `Database` by forwarding the `Database` methods to the corresponding `DatabaseRef` methods. 13 | -------------------------------------------------------------------------------- /documentation/src/crates/primitives/environment.md: -------------------------------------------------------------------------------- 1 | # Environment 2 | 3 | A significant module that manages the execution environment of the EVM. The module contains objects and methods associated with processing transactions and blocks within such a blockchain environment. It defines several structures: `Env`, `BlockEnv`, `TxEnv`, `CfgEnv`, `TransactTo`, and `CreateScheme`. These structures contain various fields representing the block data, transaction data, environmental configurations, transaction recipient details, and the method of contract creation respectively. 4 | 5 | The `Env` structure, which encapsulates the environment of the EVM, contains methods for calculating effective gas prices and for validating block and transaction data. It also checks transactions against the current state of the associated account, which is necessary to validate the transaction's nonce and the account balance. Various Ethereum Improvement Proposals (EIPs) are also considered in these validations, such as [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) for the base fee, [EIP-3607](https://eips.ethereum.org/EIPS/eip-3607) for rejecting transactions from senders with deployed code, and [EIP-3298](https://eips.ethereum.org/EIPS/eip-3298) for disabling gas refunds. The code is structured to include optional features and to allow for changes in the EVM specifications. 6 | -------------------------------------------------------------------------------- /documentation/src/crates/primitives/kzg.md: -------------------------------------------------------------------------------- 1 | # KZG 2 | 3 | With the introduction of [EIP4844](https://eips.ethereum.org/EIPS/eip-4844), this use of blobs for a more efficent short term storage is employed, the validity of this blob stored in the consensus layer is verified using the `Point Evaluation` pre-compile, a fancy way of verifing that and evaluation at a given point of a commited polynomial is vaild, in a much more bigger scale, implies that `Data is Available`. 4 | 5 | This module houses; 6 | 7 | 1. `KzgSettings`: Stores the setup and parameters needed for computing and verify KZG proofs. 8 | 9 | The `KZG` premitive provides a default `KZGSettings` obtained from [this]( https://ceremony.ethereum.org/) trusted setup ceremony, a provision is also made for using a custom `KZGSettings` if need be, this is available in the `env.cfg`. 10 | 11 | 12 | 2. `trusted_setup_points`: This module contains functions and types used for parsing and utilizing the [Trusted Setup]( https://ceremony.ethereum.org/) for the `KzgSettings`. -------------------------------------------------------------------------------- /documentation/src/crates/primitives/log.md: -------------------------------------------------------------------------------- 1 | # Log 2 | 3 | > NOTE: This module's types have been replaced by [`alloy_primitives`](https://github.com/alloy-rs/core)'s `Log` and `LogData`. 4 | 5 | This piece of Rust code defines a structure called Log which represents an Ethereum log entry. These logs are integral parts of the Ethereum network and are typically produced by smart contracts during execution. Each Log has three components: 6 | 7 | - `address`: This field represents the address of the log originator, typically the smart contract that generated the log. The `Address` data type signifies a 160-bit Ethereum address. 8 | 9 | - `topics`: This field is a vector of `B256` type. In Ethereum, logs can have multiple '`topics`'. These are events that can be used to categorize and filter logs. The `B256` type denotes a 256-bit hash, which corresponds to the size of a topic in Ethereum. 10 | 11 | - `data`: This is the actual data of the log entry. The Bytes type is a dynamically-sized byte array, and it can contain any arbitrary data. It contains additional information associated with the event logged by a smart contract. 12 | -------------------------------------------------------------------------------- /documentation/src/crates/primitives/precompile.md: -------------------------------------------------------------------------------- 1 | # precompile 2 | 3 | This module implements precompiled contracts in the EVM, adding a layer of pre-set functionalities. These are documented in more detail in the next section. The module defines the types and the enum that are used to handle precompiled contracts. 4 | 5 | `PrecompileResult`: This is a type alias for a `Result` type. The `Ok` variant of this type contains a tuple (`u64`, `Vec`), where the `u64` integer likely represents gas used by the precompiled contract, and the `Vec` holds the output data. The Err variant contains a PrecompileError. 6 | 7 | `StandardPrecompileFn` and `CustomPrecompileFn`: These are type aliases for function pointers. Both functions take a byte slice and a `u64` (probably the available gas) as arguments and return a `PrecompileResult`. The naming suggests that the former refers to built-in precompiled contracts, while the latter may refer to custom, user-defined contracts. 8 | 9 | `PrecompileError`: This is an enumeration (enum) which describes the different types of errors that could occur while executing a precompiled contract. The listed variants suggest these errors are related to gas consumption, `Blake2` hash function, modular exponentiation ("`Modexp`"), and `Bn128`, which is a specific elliptic curve used in cryptography. 10 | -------------------------------------------------------------------------------- /documentation/src/crates/primitives/result.md: -------------------------------------------------------------------------------- 1 | # Result 2 | 3 | At the core of this module is the `ExecutionResult` enum, which describes the possible outcomes of an EVM execution: `Success`, `Revert`, and `Halt`. `Success` represents a successful transaction execution, and it holds important information such as the reason for `success` (an Eval enum), the gas used, the gas refunded, a vector of logs (`Vec`), and the output of the execution. This aligns with the stipulation in [EIP-658](https://eips.ethereum.org/EIPS/eip-658) that introduces a status code in the receipt of a transaction, indicating whether the top-level call was successful or failed. 4 | 5 | `Revert` represents a transaction that was reverted by the `REVERT` opcode without spending all of its gas. It stores the gas used and the output. `Halt` represents a transaction that was reverted for various reasons and consumed all its gas. It stores the reason for halting (a `Halt` enum) and the gas used. 6 | 7 | The `ExecutionResult` enum provides several methods to extract important data from an execution result, such as `is_success()`, `logs()`, `output()`, `into_output()`, `into_logs()`, and `gas_used()`. These methods facilitate accessing key details of a transaction execution. 8 | 9 | The `EVMError` and `InvalidTransaction` enums handle different kinds of errors that can occur in an EVM, including database errors, errors specific to the transaction itself, and errors that occur due to issues with gas, among others. 10 | 11 | The `Output` enum handles different kinds of outputs of an EVM execution, including `Call` and `Create`. This is where the output data from a successful execution or a reverted transaction is stored. 12 | -------------------------------------------------------------------------------- /documentation/src/crates/primitives/specifications.md: -------------------------------------------------------------------------------- 1 | # Specifications 2 | 3 | Holds data related to Ethereum's technical specifications, serving as a reference point for Ethereum's rules and procedures obtained from the [Ethereum execution specifications](https://github.com/ethereum/execution-specs). The module is primarily used to enumerate and handle Ethereum's network upgrades or "hard forks" within the Ethereum Virtual Machine (EVM). These hard forks are referred to as `SpecId` in the code, representing different phases of Ethereum's development. 4 | 5 | The `SpecId` enum assigns a unique numerical value and a unique string identifier to each Ethereum hard fork. These upgrades range from the earliest ones such as `FRONTIER` and `HOMESTEAD`, through to the most recent ones, including `LONDON`, `MERGE`, `SHANGHAI`, and `LATEST`. 6 | 7 | The code also includes conversion methods such as `try_from_u8()` and `from()`. The former attempts to create a `SpecId` from a given u8 integer, while the latter creates a `SpecId` based on a string representing the name of the hard fork. 8 | 9 | The `enabled()` method in `SpecId` is used to check if one spec is enabled on another, considering the order in which the hard forks were enacted. 10 | 11 | The `Spec` trait is used to abstract the process of checking whether a given spec is enabled. It only has one method, `enabled()`, and a constant `SPEC_ID`. 12 | 13 | The module then defines various `Spec` structs, each representing a different hard fork. These structs implement the `Spec` trait and each struct's `SPEC_ID` corresponds to the correct `SpecId` variant. 14 | 15 | This module provides the necessary framework to handle and interact with the different Ethereum hard forks within the EVM, making it possible to handle transactions and contracts differently depending on which hard fork rules apply. It also simplifies the process of adapting to future hard forks by creating a new `SpecId` and corresponding `Spec` struct. 16 | -------------------------------------------------------------------------------- /documentation/src/crates/primitives/state.md: -------------------------------------------------------------------------------- 1 | # State 2 | 3 | Manages the EVM's state, including account balances, contract storage, and more. 4 | 5 | This module models an Ethereum account and its state, which includes balance, nonce, code, storage, and status flags. The module also includes methods for interacting with the account's state. 6 | 7 | The `Account` struct includes fields for info (of type `AccountInfo`), storage (a `HashMap` mapping a `U256` value to a `StorageSlot`), and status (of type `AccountStatus`). `AccountInfo` represents the basic information about an Ethereum account, including its balance (`balance`), nonce (`nonce`), code (`code`), and a hash of its code (`code_hash`). 8 | 9 | The `AccountStatus` is a set of bitflags, representing the state of the account. The flags include `Loaded`, `Created`, `SelfDestructed`, `Touched`, and `LoadedAsNotExisting`. The different methods provided within the `Account` struct allow for manipulating these statuses. 10 | 11 | The `StorageSlot` struct represents a storage slot in the Ethereum Virtual Machine. It holds an `original_value` and a `present_value` and includes methods for creating a new slot and checking if the slot's value has been modified. 12 | 13 | Two `HashMap` type aliases are created: `State` and `Storage`. `State` maps from a `Address` address to an `Account` and `Storage` maps from a `U256` key to a `StorageSlot`. 14 | 15 | The module includes a series of methods implemented for `Account` to manipulate and query the account's status. These include methods like `mark_selfdestruct`, `unmark_selfdestruct`, `is_selfdestructed`, `mark_touch`, `unmark_touch`, `is_touched`, `mark_created`, `is_newly_created`, `is_empty`, and `new_not_existing`. 16 | -------------------------------------------------------------------------------- /documentation/src/crates/primitives/utils.md: -------------------------------------------------------------------------------- 1 | # Utilities 2 | 3 | This Rust module provides utility functions and constants for handling Keccak hashing (used in Ethereum) and creating Ethereum addresses via legacy and `CREATE2` methods. It also includes serialization and deserialization methods for hexadecimal strings representing byte arrays. 4 | 5 | The `KECCAK_EMPTY` constant represents the Keccak-256 hash of an empty input. 6 | 7 | The `keccak256` function takes a byte slice input and returns its Keccak-256 hash as a `B256` value. 8 | -------------------------------------------------------------------------------- /documentation/src/crates/revm/inspector.md: -------------------------------------------------------------------------------- 1 | # Inspectors 2 | 3 | This module contains various inspectors that can be used to execute and monitor transactions on the Ethereum Virtual Machine (EVM) through the `revm` library. 4 | 5 | ## Overview 6 | 7 | There are several built-in inspectors in this module: 8 | 9 | - `NoOpInspector`: A basic inspector that does nothing, which can be used when you don't need to monitor transactions. 10 | - `GasInspector`: Monitors the gas usage of transactions. 11 | - `CustomPrintTracer`: 12 | Traces and prints custom messages during EVM execution. 13 | Available only when the `std` feature is enabled. 14 | - `TracerEip3155`: 15 | This is an inspector that conforms to the [EIP-3155](https://eips.ethereum.org/EIPS/eip-3155) standard for tracing Ethereum transactions. 16 | It's used to generate detailed trace data of transaction execution, which can be useful for debugging, analysis, or for building tools that need to understand the inner workings of Ethereum transactions. 17 | This is only available when both `std` and `serde-json` features are enabled. 18 | 19 | ## Inspector trait 20 | 21 | The `Inspector` trait defines methods that are called during various stages of EVM execution. 22 | You can implement this trait to create your own custom inspectors. 23 | 24 | Each of these methods is called at different stages of the execution of a transaction. 25 | They can be used to monitor, debug, or modify the execution of the EVM. 26 | 27 | For example, the `step` method is called on each step of the interpreter, and the `log` method is called when a log is emitted. 28 | 29 | You can implement this trait for a custom database type `DB` that implements the `Database` trait. 30 | 31 | ## Usage 32 | 33 | To use an inspector, you need to implement the `Inspector` trait. 34 | For each method, you can decide what you want to do at each point in the EVM execution. 35 | For example, to capture all `SELFDESTRUCT` operations, implement the `selfdestruct` method. 36 | 37 | All methods in the `Inspector` trait are optional to implement; if you do not need specific functionality, you can use the provided default implementations. 38 | -------------------------------------------------------------------------------- /documentation/src/crates/revm/state.md: -------------------------------------------------------------------------------- 1 | # State implementations 2 | 3 | State inherits the `Database` trait and implements fetching of external state and storage, and various functionality on output of the EVM execution. 4 | Most notably, caching changes while execution multiple transactions. 5 | 6 | ## Database Abstractions 7 | 8 | You can implement the traits `Database`, `DatabaseRef` or `Database + DatabaseCommit` depending on the desired handling of the struct. 9 | 10 | - `Database`: 11 | Has mutable `self` in its functions. 12 | It is useful if you want to modify your cache or update some statistics on `get` calls. 13 | This trait enables `preverify_transaction`, `transact_preverified`, `transact` and `inspect` functions. 14 | - `DatabaseRef`: 15 | Takes a reference on the object. 16 | It is useful if you only have a reference on the state and don't want to update anything on it. 17 | It enables `preverify_transaction`, `transact_preverified_ref`, `transact_ref` and `inspect_ref` functions. 18 | - `Database + DatabaseCommit`: 19 | Allows directly committing changes of a transaction. 20 | It enables `transact_commit` and `inspect_commit` functions. 21 | -------------------------------------------------------------------------------- /documentation/src/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | `revm` is an Ethereum Virtual Machine (EVM) written in Rust that is focused on speed and simplicity. This documentation is very much a work in progress and a community effort. If you would like to contribute and improve these docs please make a pr to the [github repo](https://github.com/bluealloy/revm/tree/main). Most importantly, Revm is just the execution environment for ethereum; there is no networking or consensus related work in this repository. 4 | 5 | ## Crates 6 | 7 | The project has 4 main crates that are used to build revm. These are: 8 | 9 | - `revm`: The main EVM library. 10 | - `interpreter`: Execution loop with instructions. 11 | - `primitives`: Primitive data types. 12 | - `precompile`: EVM precompiles. 13 | 14 | ## Testing with the binaries 15 | 16 | There are two binaries both of which are used for testing. To install them run `cargo install --path bins/`. The binaries are: 17 | 18 | - `revme`: A CLI binary, used for running state test json. Currently it is used to run [ethereum tests](https://github.com/ethereum/tests) to check if revm is compliant. For example if you have the eth tests cloned into a directory called eth tests and the EIP tests in the following directories you can run 19 | ```bash 20 | cargo run --profile ethtests -p revme -- \ 21 | statetest \ 22 | ../ethtests/GeneralStateTests/ \ 23 | ../ethtests/LegacyTests/Constantinople/GeneralStateTests/ \ 24 | bins/revme/tests/EIPTests/StateTests/stEIP5656-MCOPY/ \ 25 | bins/revme/tests/EIPTests/StateTests/stEIP1153-transientStorage/ 26 | ``` 27 | 28 | - `revm-test`: test binaries with contracts; used mostly to check performance 29 | 30 | If you are interested in contributing, be sure to run the statetests. It is recommended to read about the [ethereum tests](https://ethereum-tests.readthedocs.io/en/latest/). 31 | -------------------------------------------------------------------------------- /publish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # stop on error 4 | set -e 5 | 6 | cargo publish --package revm-primitives 7 | cargo publish --package revm-precompile 8 | cargo publish --package revm-interpreter 9 | cargo publish --package revm 10 | cargo publish --package revme 11 | 12 | echo "All crates published" 13 | --------------------------------------------------------------------------------