Parcourir la source

feat(target_chains/ethereum): add arbirum stylus sdk (#2041)

* chore: init stylus project

* chore: added scripts

* chore: created workspace

* chore: docs setup

* chore: pyth contracts init

* chore: docs command setup

* mock: example project

* chore : created test workspace

* chore: changed toml  version

* chore: created  mock pyth  workspace

* chore: renamed project sdk

* chore: refactored files

* chore : helpers functions

* refacor : refactord code

* chore: removed struct type , implemented abstract_pyth

* chore: created storage price and storage price feed

* chore: integrating  storage price and storage price feed

* chore: fixed  error created by storage type

* chore: config changes

* chore: forge init

* forge install: forge-std

v1.9.3

* mock pyth : created mock solidity pyth contract

* chore: Renamed MockPyth Scripts

* chore: started testing

* chore: removed  projects

* feture :completed unit test and stylus contracts

* added initializtion for mock

* examples setup

* chore:fixed imports

* chore:fixed types

* completed contract

* External call and fution call sample

* chore: Changed motsu

* chore: Created Proxy call example

* feture: Example for both type of call

* chore: Added beches

* Lib Changes

* chore:Scripts modifications

* chore : fuction call and proxy call

* chore: added workflow

* chore: doc  pages docs

* chore: doc changes

* smaller chages

* chore: benches and toml changes

* chore: added foundry to e2e  workflow

* chore:set up benchmark

* Added Benches

* chore:added setup mock pyth script to bench and  e2e and logs

* changes

* feture: Added Proxy call to bench

* chore: Removed sol file

* Added deploy scripts

* chore: proxy calls

* chore: removed file

* changes

* chore:added constructor file and worked on bench

* chore: moved Ipyth to pyth-contract file

* chore: added variable to bash scripts

* chore:decode and encode helper

* chore: fixed mock pyth deploy script

* chore: removed dotenv crates

* chore: completed benches functions

* chore: examples and proxy call fixes

* changes

* chore: added create functions

* chore: completed get data benchmarks

* chore:contract changes

* chore:function calls

* chore: Ignore all broadcast

* chore: completed  get benches

* chore:changes

* chore: Added Type Test

* chore: tests

* env and examples

* Update README.md

* Update README.md

* Update README.md

* chore: worked on bench and e2e test

* removed log

* chore: completed e2e test for function call example

* chore : changed pyth script

* chore:completed e2e test

* chore:benches

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* chore: removed docs

* Update README.md

* Update README.md

* Update CODEOWNERS

* Delete target_chains/ethereum/sdk/stylus/SECURITY.md

* Delete target_chains/ethereum/sdk/stylus/lib/crypto directory

* Delete target_chains/ethereum/sdk/stylus/.linkspector.yml

* Delete target_chains/ethereum/sdk/stylus/netlify.toml

* Update Cargo.toml removed openzepline crypto

* Update README.md

* Delete target_chains/ethereum/sdk/stylus/pyth-solidity/.env.example

* Update gas-bench.yml

* chore:removed a bunch of openzeplin files

* chore: removed workflow

* chore:Added Guidlines

* chore: motsu  changes

* Create Test.md

* Update Test.md

* Rename Test.md to TEST.md

* Update README.md

* Update README.md

* Update README.md

* Delete target_chains/ethereum/sdk/stylus/TEST.md

* chore: removed mostu

* chore: changed Fixedbytes<32> to B256

* chore: removed local  e2e testing library

* chore: changes

* forge install: forge-std

v1.9.4

* forge install: openzeppelin-foundry-upgrades

v0.3.6

* forge install: openzeppelin-contracts

v4.9.6

* chore: formated code

* chore: fixed scripts

* Update target_chains/ethereum/sdk/stylus/README.md

Co-authored-by: Pavel Strakhov <ri@idzaaus.org>

* Update target_chains/ethereum/sdk/stylus/README.md

Co-authored-by: Pavel Strakhov <ri@idzaaus.org>

* chore: rustfmt changes

* chore: changed solidity licenses to  Apache 2

* chore: deleted codeowner file and link

* chore: removed comments

* solidity changes

* chore: removed folder

* chore: removed = for version

* forge install: forge-std

v1.9.4

* forge install: openzeppelin-foundry-upgrades

v0.3.6

* forge install: openzeppelin-contracts-upgradeable

v4.9.6

* chore: Remove MIT license

* chore: script changes

* chore: removed dependices

* forge install: forge-std

v1.9.4

* forge install: openzeppelin-foundry-upgrades

v0.3.6

* chore:added description to script

* Update target_chains/ethereum/sdk/stylus/README.md

Co-authored-by: Pavel Strakhov <ri@idzaaus.org>

* Update target_chains/ethereum/sdk/stylus/README.md

Co-authored-by: Pavel Strakhov <ri@idzaaus.org>

* Update target_chains/ethereum/sdk/stylus/contracts/src/pyth/mod.rs

Co-authored-by: Pavel Strakhov <ri@idzaaus.org>

* Update target_chains/ethereum/sdk/stylus/contracts/src/pyth/errors.rs

Co-authored-by: Pavel Strakhov <ri@idzaaus.org>

* chore: changed // to /// and remove licenses because of root licenese

* chore: Apache-2.0 license

* chore: renamed file name pyth-solidity to pyth-mock-solidity

* chore: removed commented code

* chore: foundry test workflow

* chore: workflows

* chore: changed readme to rust

* chore: fixed description  mock solidity

* chore: fixed zero case

* chore: change all use case of gt and lt to > and <

* chore: workflow

* chore: replaced the file with the link

* chore: refactor and removed unused code

* chore: renamed function for test

* chore: added some sort of path filters

* chore:  add cargo fmt and cargo clippy for  stylus sdk

* chore: package-json.lock moved depencies to pnpm-workspace.yaml

* chore:test attribute

* chore: git workflows

* chore:  removed functions example

* chore: switch for item in update_data

* chore: fixed example

* chore: refactor examples

* cargo changes

* chore: pyth example , and  function call example

* chore: added other example

* chore: install

* chore:installations

* chore: mock pyth

* chore: benches  and test

* smaller changes

* chore: mock

* chore: bench format

* chore: code format

* chore: code format

* chore: removed workflow

* chore: pnpm install

* chore: removed  package-lock.json

* chore: fixed commented out  job

* chore: ran  pre-commit run --all

* chore: pre-commit run --all

* chore:removed space

* Update .github/workflows/cli-foundry-test.yml

Co-authored-by: Pavel Strakhov <ri@idzaaus.org>

* chore:removed space

chore: vec changes

* chore: data changes

* Update .github/workflows/cli-stylus-nostd.yml

Co-authored-by: Pavel Strakhov <ri@idzaaus.org>

* Update .github/workflows/cli-stylus-gas-bench.yml

Co-authored-by: Pavel Strakhov <ri@idzaaus.org>

* Update .github/workflows/cli-stylus-e2e-tests.yml

Co-authored-by: Pavel Strakhov <ri@idzaaus.org>

* Update .github/workflows/cli-stylus-check.yml

Co-authored-by: Pavel Strakhov <ri@idzaaus.org>

* Update .github/workflows/cli-stylus-check-wasm.yml

Co-authored-by: Pavel Strakhov <ri@idzaaus.org>

* Update .github/workflows/cli-foundry-test.yml

Co-authored-by: Pavel Strakhov <ri@idzaaus.org>

* Update .github/workflows/cli-stylus-e2e-tests.yml

Co-authored-by: Pavel Strakhov <ri@idzaaus.org>

* Update .github/workflows/cli-stylus-check-wasm.yml

Co-authored-by: Pavel Strakhov <ri@idzaaus.org>

* Update .github/workflows/cli-stylus-check.yml

Co-authored-by: Pavel Strakhov <ri@idzaaus.org>

* Update .github/workflows/cli-stylus-nostd.yml

Co-authored-by: Pavel Strakhov <ri@idzaaus.org>

* Update .github/workflows/cli-stylus-gas-bench.yml

Co-authored-by: Pavel Strakhov <ri@idzaaus.org>

* chore: added back existing submodule

* chore: data changes

* cl fixes

* cli fixes

* chore: toolchain: nightly-2024-01-01

* chore: version changes

* toolchain

* removed typo workflow

* fixed rust issue

* changed rust version

* added foundry

* chore:  changes

* chore:bench fixes

* chore: changed cli workflow

* chore: format

* ci changes

* chore: added space

* precommit fixes

* added new line

* removed

* removed line

* chore: ci changes

* chore : changes

* changed ci script

* removed if statements for test

* chore: changes

* chore:fixes

* chore: fixes

* chore: fixes

* added evm file

* chore: checking key

* testing keys

* remove comand

* precommit fixes

* chore: removed workflow

* cl changes

* fmt

* fixed verion issue

---------

Co-authored-by: Pavel Strakhov <ri@idzaaus.org>
ifechukwudaniel.eth il y a 9 mois
Parent
commit
ee21688c45
64 fichiers modifiés avec 7851 ajouts et 0 suppressions
  1. 31 0
      .github/workflows/ci-foundry-test.yml
  2. 40 0
      .github/workflows/ci-stylus-check-wasm.yml
  3. 75 0
      .github/workflows/ci-stylus-check.yml
  4. 43 0
      .github/workflows/ci-stylus-nostd.yml
  5. 18 0
      .github/workflows/publish-pythnet-stylus-sdk.yml
  6. 18 0
      .gitmodules
  7. 12 0
      .pre-commit-config.yaml
  8. 1 0
      lib/forge-std
  9. 1 0
      lib/openzeppelin-contracts-upgradeable
  10. 1 0
      lib/openzeppelin-foundry-upgrades
  11. 11 0
      pnpm-lock.yaml
  12. 2 0
      pnpm-workspace.yaml
  13. 8 0
      target_chains/ethereum/sdk/stylus/.cargo/config.toml
  14. 11 0
      target_chains/ethereum/sdk/stylus/.gitignore
  15. 4432 0
      target_chains/ethereum/sdk/stylus/Cargo.lock
  16. 92 0
      target_chains/ethereum/sdk/stylus/Cargo.toml
  17. 5 0
      target_chains/ethereum/sdk/stylus/GUIDELINES.md
  18. 98 0
      target_chains/ethereum/sdk/stylus/README.md
  19. 21 0
      target_chains/ethereum/sdk/stylus/benches/Cargo.toml
  20. 106 0
      target_chains/ethereum/sdk/stylus/benches/src/extend_pyth_example.rs
  21. 106 0
      target_chains/ethereum/sdk/stylus/benches/src/lib.rs
  22. 15 0
      target_chains/ethereum/sdk/stylus/benches/src/main.rs
  23. 150 0
      target_chains/ethereum/sdk/stylus/benches/src/report.rs
  24. 33 0
      target_chains/ethereum/sdk/stylus/contracts/Cargo.toml
  25. 23 0
      target_chains/ethereum/sdk/stylus/contracts/src/lib.rs
  26. 120 0
      target_chains/ethereum/sdk/stylus/contracts/src/pyth/errors.rs
  27. 10 0
      target_chains/ethereum/sdk/stylus/contracts/src/pyth/events.rs
  28. 277 0
      target_chains/ethereum/sdk/stylus/contracts/src/pyth/functions.rs
  29. 383 0
      target_chains/ethereum/sdk/stylus/contracts/src/pyth/mock.rs
  30. 13 0
      target_chains/ethereum/sdk/stylus/contracts/src/pyth/mod.rs
  31. 244 0
      target_chains/ethereum/sdk/stylus/contracts/src/pyth/pyth_contract.rs
  32. 319 0
      target_chains/ethereum/sdk/stylus/contracts/src/pyth/types.rs
  33. 65 0
      target_chains/ethereum/sdk/stylus/contracts/src/utils/mod.rs
  34. 28 0
      target_chains/ethereum/sdk/stylus/examples/extend-pyth-example/Cargo.toml
  35. 1 0
      target_chains/ethereum/sdk/stylus/examples/extend-pyth-example/README.MD
  36. 10 0
      target_chains/ethereum/sdk/stylus/examples/extend-pyth-example/src/constructor.sol
  37. 24 0
      target_chains/ethereum/sdk/stylus/examples/extend-pyth-example/src/lib.rs
  38. 18 0
      target_chains/ethereum/sdk/stylus/examples/extend-pyth-example/tests/abi/mod.rs
  39. 230 0
      target_chains/ethereum/sdk/stylus/examples/extend-pyth-example/tests/extend-pyth.rs
  40. 28 0
      target_chains/ethereum/sdk/stylus/examples/function-example/Cargo.toml
  41. 1 0
      target_chains/ethereum/sdk/stylus/examples/function-example/README.MD
  42. 35 0
      target_chains/ethereum/sdk/stylus/examples/function-example/src/constructor.sol
  43. 93 0
      target_chains/ethereum/sdk/stylus/examples/function-example/src/lib.rs
  44. 28 0
      target_chains/ethereum/sdk/stylus/examples/pyth-example/Cargo.toml
  45. 1 0
      target_chains/ethereum/sdk/stylus/examples/pyth-example/README.MD
  46. 10 0
      target_chains/ethereum/sdk/stylus/examples/pyth-example/src/constructor.sol
  47. 76 0
      target_chains/ethereum/sdk/stylus/examples/pyth-example/src/lib.rs
  48. 15 0
      target_chains/ethereum/sdk/stylus/pyth-mock-solidity/.gitignore
  49. 66 0
      target_chains/ethereum/sdk/stylus/pyth-mock-solidity/README.md
  50. 4 0
      target_chains/ethereum/sdk/stylus/pyth-mock-solidity/foundry.toml
  51. 1 0
      target_chains/ethereum/sdk/stylus/pyth-mock-solidity/lib/forge-std
  52. 1 0
      target_chains/ethereum/sdk/stylus/pyth-mock-solidity/lib/openzeppelin-contracts-upgradeable
  53. 1 0
      target_chains/ethereum/sdk/stylus/pyth-mock-solidity/lib/openzeppelin-foundry-upgrades
  54. 15 0
      target_chains/ethereum/sdk/stylus/pyth-mock-solidity/package.json
  55. 1 0
      target_chains/ethereum/sdk/stylus/pyth-mock-solidity/remappings.txt
  56. 96 0
      target_chains/ethereum/sdk/stylus/pyth-mock-solidity/script/MockPyth.s.sol
  57. 12 0
      target_chains/ethereum/sdk/stylus/pyth-mock-solidity/src/MockPyth.sol
  58. 8 0
      target_chains/ethereum/sdk/stylus/pyth-mock-solidity/test/MockPyth.t.sol
  59. 4 0
      target_chains/ethereum/sdk/stylus/rust-toolchain.toml
  60. 73 0
      target_chains/ethereum/sdk/stylus/scripts/bench.sh
  61. 30 0
      target_chains/ethereum/sdk/stylus/scripts/check-wasm.sh
  62. 46 0
      target_chains/ethereum/sdk/stylus/scripts/deploy.sh
  63. 45 0
      target_chains/ethereum/sdk/stylus/scripts/e2e-tests.sh
  64. 66 0
      target_chains/ethereum/sdk/stylus/scripts/nitro-testnode.sh

+ 31 - 0
.github/workflows/ci-foundry-test.yml

@@ -0,0 +1,31 @@
+name: stylus-foundry-test
+
+on:
+  pull_request:
+    paths:
+      - target_chains/ethereum/sdk/stylus/**
+  push:
+    branches:
+      - main
+    paths:
+      - target_chains/ethereum/sdk/stylus/**
+env:
+  FOUNDRY_PROFILE: ci
+jobs:
+  check:
+    name: Foundry project
+    runs-on: ubuntu-latest
+    defaults:
+      run:
+        working-directory: target_chains/ethereum/sdk/stylus
+    steps:
+      - name: Checkout repository
+        uses: actions/checkout@v4
+        with:
+          submodules: recursive
+      - name: Install Foundry
+        uses: foundry-rs/foundry-toolchain@v1
+        with:
+          version: nightly
+      - name: Show Forge version
+        run: forge --version

+ 40 - 0
.github/workflows/ci-stylus-check-wasm.yml

@@ -0,0 +1,40 @@
+name: stylus-check-wasm
+# This workflow checks that the compiled wasm binary of every example contract
+# can be deployed to Arbitrum Stylus.
+on:
+  pull_request:
+    paths:
+      - target_chains/ethereum/sdk/stylus/**
+  push:
+    branches:
+      - main
+    paths:
+      - target_chains/ethereum/sdk/stylus/**
+permissions:
+  contents: read
+concurrency:
+  group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
+  cancel-in-progress: true
+env:
+  CARGO_TERM_COLOR: always
+jobs:
+  check-wasm:
+    name: Check WASM binary
+    runs-on: ubuntu-latest
+    defaults:
+      run:
+        working-directory: target_chains/ethereum/sdk/stylus
+    steps:
+      - uses: actions/checkout@v4
+      - name: Install rust
+        uses: actions-rust-lang/setup-rust-toolchain@v1
+        with:
+          rustflags: ""
+      - name: Install Foundry
+        uses: foundry-rs/foundry-toolchain@v1
+        with:
+          version: nightly
+      - name: Install cargo-stylus
+        run: cargo install cargo-stylus@0.5.8
+      - name: Run wasm check
+        run: ./scripts/check-wasm.sh

+ 75 - 0
.github/workflows/ci-stylus-check.yml

@@ -0,0 +1,75 @@
+name: stylus-check
+# This workflow runs whenever a PR is opened or updated, or a commit is pushed
+# to main. It runs several checks:
+# - fmt: checks that the code is formatted according to `rustfmt`.
+# - clippy: checks that the code does not contain any `clippy` warnings.
+# - doc: checks that the code can be documented without errors.
+# - hack: check combinations of feature flags.
+# - typos: checks for typos across the repo.
+permissions:
+  contents: read
+# This configuration allows maintainers of this repo to create a branch and
+# pull request based on the new branch. Restricting the push trigger to the
+# main branch ensures that the PR only gets built once.
+on:
+  pull_request:
+    paths:
+      - target_chains/ethereum/sdk/stylus/**
+  push:
+    branches:
+      - main
+    paths:
+      - target_chains/ethereum/sdk/stylus/**
+concurrency:
+  group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
+  cancel-in-progress: true
+env:
+  CARGO_TERM_COLOR: always
+jobs:
+  fmt:
+    runs-on: ubuntu-latest
+    name: nightly / fmt
+    defaults:
+      run:
+        working-directory: target_chains/ethereum/sdk/stylus
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          submodules: true
+
+      - name: Install rust
+        # We run in nightly to make use of some features only available there.
+        # Check out `rustfmt.toml` to see which ones.
+        uses: actions-rust-lang/setup-rust-toolchain@v1
+        with:
+          toolchain: nightly
+          components: rustfmt
+          rustflags: ""
+
+      - name: Check formatting
+        run: cargo fmt --all --check
+  clippy:
+    runs-on: ubuntu-latest
+    name: ${{ matrix.toolchain }} / clippy
+    defaults:
+      run:
+        working-directory: target_chains/ethereum/sdk/stylus
+    permissions:
+      contents: read
+      checks: write
+    strategy:
+      fail-fast: false
+      matrix:
+        # Get early warning of new lints which are regularly introduced in beta
+        # channels.
+        toolchain: [stable, beta]
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          submodules: true
+      - name: Install rust ${{ matrix.toolchain }}
+        uses: actions-rust-lang/setup-rust-toolchain@v1
+        with:
+          toolchain: ${{ matrix.toolchain }}
+          components: clippy
+          rustflags: ""

+ 43 - 0
.github/workflows/ci-stylus-nostd.yml

@@ -0,0 +1,43 @@
+# This workflow checks whether the library is able to run without the std
+# library. See `check.yml` for information about how the concurrency
+# cancellation and workflow triggering works.
+name: stylus-no-std
+permissions:
+  contents: read
+on:
+  pull_request:
+    paths:
+      - target_chains/ethereum/sdk/stylus/**
+  push:
+    branches:
+      - main
+    paths:
+      - target_chains/ethereum/sdk/stylus/**
+concurrency:
+  group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
+  cancel-in-progress: true
+env:
+  CARGO_TERM_COLOR: always
+jobs:
+  nostd:
+    runs-on: ubuntu-latest
+    name: ${{ matrix.target }}
+    defaults:
+      run:
+        working-directory: target_chains/ethereum/sdk/stylus
+    strategy:
+      matrix:
+        target: [wasm32-unknown-unknown]
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          submodules: true
+      - name: Install rust
+        uses: actions-rust-lang/setup-rust-toolchain@v1
+        with:
+          toolchain: stable
+          rustflags: ""
+      - name: Add rust targets ${{ matrix.target }}
+        run: rustup target add ${{ matrix.target }}
+      - name: Cargo check
+        run: cargo check --release --target ${{ matrix.target }} --no-default-features

+ 18 - 0
.github/workflows/publish-pythnet-stylus-sdk.yml

@@ -0,0 +1,18 @@
+name: Publish Pyth Stylus SDK to crates.io
+
+on:
+  push:
+    tags:
+      - pythnet-stylus-sdk-v*
+jobs:
+  publish-pythnet-stylus-sdk:
+    name: Publish Pythnet Stylus SDK
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout sources
+        uses: actions/checkout@v2
+
+      - run: cargo publish --token ${CARGO_REGISTRY_TOKEN}
+        env:
+          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
+        working-directory: target_chains/ethereum/sdk/stylus

+ 18 - 0
.gitmodules

@@ -10,3 +10,21 @@
 [submodule "lazer/contracts/evm/lib/createx"]
 	path = lazer/contracts/evm/lib/createx
 	url = https://github.com/pcaversaccio/createx
+[submodule "lib/forge-std"]
+	path = lib/forge-std
+	url = https://github.com/foundry-rs/forge-std
+[submodule "lib/openzeppelin-foundry-upgrades"]
+	path = lib/openzeppelin-foundry-upgrades
+	url = https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades
+[submodule "lib/openzeppelin-contracts-upgradeable"]
+	path = lib/openzeppelin-contracts-upgradeable
+	url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable
+[submodule "target_chains/ethereum/sdk/stylus/pyth-mock-solidity/lib/forge-std"]
+	path = target_chains/ethereum/sdk/stylus/pyth-mock-solidity/lib/forge-std
+	url = https://github.com/foundry-rs/forge-std
+[submodule "target_chains/ethereum/sdk/stylus/pyth-mock-solidity/lib/openzeppelin-foundry-upgrades"]
+	path = target_chains/ethereum/sdk/stylus/pyth-mock-solidity/lib/openzeppelin-foundry-upgrades
+	url = https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades
+[submodule "target_chains/ethereum/sdk/stylus/pyth-mock-solidity/lib/openzeppelin-contracts-upgradeable"]
+	path = target_chains/ethereum/sdk/stylus/pyth-mock-solidity/lib/openzeppelin-contracts-upgradeable
+	url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable

+ 12 - 0
.pre-commit-config.yaml

@@ -139,3 +139,15 @@ repos:
         entry: cargo +1.82.0 clippy --manifest-path ./lazer/Cargo.toml --all-targets -- --deny warnings
         pass_filenames: false
         files: lazer
+      - id: cargo-fmt-stylus-sdk
+        name: Cargo format for Stylus SDK
+        language: "rust"
+        entry: cargo +1.82.0 fmt --manifest-path ./target_chains/ethereum/sdk/stylus/Cargo.toml --all
+        pass_filenames: false
+        files: target_chains/ethereum/sdk/stylus
+      - id: cargo-clippy-stylus-sdk
+        name: Cargo clippy for Stylus SDK
+        language: "rust"
+        entry: cargo +1.82.0 clippy --manifest-path ./target_chains/ethereum/sdk/stylus/Cargo.toml  --all-targets -- --deny warnings
+        pass_filenames: false
+        files: target_chains/ethereum/sdk/stylus

+ 1 - 0
lib/forge-std

@@ -0,0 +1 @@
+Subproject commit 1eea5bae12ae557d589f9f0f0edae2faa47cb262

+ 1 - 0
lib/openzeppelin-contracts-upgradeable

@@ -0,0 +1 @@
+Subproject commit 2d081f24cac1a867f6f73d512f2022e1fa987854

+ 1 - 0
lib/openzeppelin-foundry-upgrades

@@ -0,0 +1 @@
+Subproject commit 16e0ae21e0e39049f619f2396fa28c57fad07368

+ 11 - 0
pnpm-lock.yaml

@@ -2426,6 +2426,12 @@ importers:
         specifier: ^0.8.25
         version: 0.8.26(debug@4.3.7)
 
+  target_chains/ethereum/sdk/stylus/pyth-mock-solidity:
+    dependencies:
+      '@pythnetwork/pyth-sdk-solidity':
+        specifier: ^4.0.0
+        version: 4.0.0
+
   target_chains/fuel/sdk/js:
     dependencies:
       fuels:
@@ -6277,6 +6283,9 @@ packages:
   '@pythnetwork/price-service-sdk@1.7.1':
     resolution: {integrity: sha512-xr2boVXTyv1KUt/c6llUTfbv2jpud99pWlMJbFaHGUBoygQsByuy7WbjIJKZ+0Blg1itLZl0Lp/pJGGg8SdJoQ==}
 
+  '@pythnetwork/pyth-sdk-solidity@4.0.0':
+    resolution: {integrity: sha512-Cy2MvSN1Oh5YpIYmZd2In6/gfXbGjnpazmXKioTuq07Drp4Rl2XHcvtqHdgilplCl32IG4pU+XoRafpexID08A==}
+
   '@pythnetwork/pyth-starknet-js@0.2.1':
     resolution: {integrity: sha512-hLPmWUkLJxYI/f1nGvhk37Hp76uYL+8g12PuJSSH7GIdN9V3ts/wgL4TdI55FbC2Ypnx3WXjVQgTpQyOhhrpyg==}
 
@@ -27413,6 +27422,8 @@ snapshots:
     dependencies:
       bn.js: 5.2.1
 
+  '@pythnetwork/pyth-sdk-solidity@4.0.0': {}
+
   '@pythnetwork/pyth-starknet-js@0.2.1': {}
 
   '@radix-ui/number@1.1.0': {}

+ 2 - 0
pnpm-workspace.yaml

@@ -16,6 +16,7 @@ packages:
   - "target_chains/ethereum/entropy_sdk/solidity"
   - "target_chains/ethereum/sdk/js"
   - "target_chains/ethereum/sdk/solidity"
+  - "target_chains/ethereum/sdk/stylus/pyth-mock-solidity"
   - "target_chains/ethereum/examples/coin_flip/app"
   - "target_chains/fuel/sdk/js"
   - "target_chains/starknet/sdk/js"
@@ -40,6 +41,7 @@ catalog:
   "@cprussin/tsconfig": 3.0.1
   "@next/third-parties": 15.0.2
   "@phosphor-icons/react": 2.1.7
+  "@pythnetwork/pyth-sdk-solidity": 4.0.0
   "@pythnetwork/client": 2.22.1
   "@react-hookz/web": 24.0.4
   "@solana/web3.js": 1.95.4

+ 8 - 0
target_chains/ethereum/sdk/stylus/.cargo/config.toml

@@ -0,0 +1,8 @@
+[target.wasm32-unknown-unknown]
+rustflags = ["-C", "link-arg=-zstack-size=8192", "-C", "target-cpu=mvp"]
+
+[target.aarch64-apple-darwin]
+rustflags = ["-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup"]
+
+[target.x86_64-apple-darwin]
+rustflags = ["-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup"]

+ 11 - 0
target_chains/ethereum/sdk/stylus/.gitignore

@@ -0,0 +1,11 @@
+/target
+
+.env
+
+**/node_modules/
+
+docs/build/
+
+**/.DS_Store
+
+**/nitro-testnode

+ 4432 - 0
target_chains/ethereum/sdk/stylus/Cargo.lock

@@ -0,0 +1,4432 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "addr2line"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
+dependencies = [
+ "gimli 0.29.0",
+]
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
+name = "aes"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
+dependencies = [
+ "cfg-if 1.0.0",
+ "cipher",
+ "cpufeatures",
+]
+
+[[package]]
+name = "ahash"
+version = "0.7.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9"
+dependencies = [
+ "getrandom",
+ "once_cell",
+ "version_check",
+]
+
+[[package]]
+name = "ahash"
+version = "0.8.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
+dependencies = [
+ "cfg-if 1.0.0",
+ "once_cell",
+ "version_check",
+ "zerocopy",
+]
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "allocator-api2"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
+
+[[package]]
+name = "alloy"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ba1c79677c9ce51c8d45e20845b05e6fb070ea2c863fba03ad6af2c778474bd"
+dependencies = [
+ "alloy-consensus",
+ "alloy-contract",
+ "alloy-core",
+ "alloy-eips",
+ "alloy-genesis",
+ "alloy-network",
+ "alloy-provider",
+ "alloy-rpc-client",
+ "alloy-rpc-types",
+ "alloy-serde",
+ "alloy-signer",
+ "alloy-signer-local",
+ "alloy-transport",
+ "alloy-transport-http",
+]
+
+[[package]]
+name = "alloy-chains"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1752d7d62e2665da650a36d84abbf239f812534475d51f072a49a533513b7cdd"
+dependencies = [
+ "num_enum",
+ "strum",
+]
+
+[[package]]
+name = "alloy-consensus"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f63a6c9eb45684a5468536bc55379a2af0f45ffa5d756e4e4964532737e1836"
+dependencies = [
+ "alloy-eips",
+ "alloy-primitives",
+ "alloy-rlp",
+ "alloy-serde",
+ "c-kzg",
+ "serde",
+]
+
+[[package]]
+name = "alloy-contract"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c26b7d34cb76f826558e9409a010e25257f7bfb5aa5e3dd0042c564664ae159"
+dependencies = [
+ "alloy-dyn-abi",
+ "alloy-json-abi",
+ "alloy-network",
+ "alloy-primitives",
+ "alloy-provider",
+ "alloy-rpc-types-eth",
+ "alloy-sol-types",
+ "alloy-transport",
+ "futures",
+ "futures-util",
+ "thiserror",
+]
+
+[[package]]
+name = "alloy-core"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5af3faff14c12c8b11037e0a093dd157c3702becb8435577a2408534d0758315"
+dependencies = [
+ "alloy-dyn-abi",
+ "alloy-json-abi",
+ "alloy-primitives",
+ "alloy-sol-types",
+]
+
+[[package]]
+name = "alloy-dyn-abi"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb6e6436a9530f25010d13653e206fab4c9feddacf21a54de8d7311b275bc56b"
+dependencies = [
+ "alloy-json-abi",
+ "alloy-primitives",
+ "alloy-sol-type-parser",
+ "alloy-sol-types",
+ "const-hex",
+ "itoa",
+ "serde",
+ "serde_json",
+ "winnow 0.6.13",
+]
+
+[[package]]
+name = "alloy-eips"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa4b0fc6a572ef2eebda0a31a5e393d451abda703fec917c75d9615d8c978cf2"
+dependencies = [
+ "alloy-primitives",
+ "alloy-rlp",
+ "alloy-serde",
+ "c-kzg",
+ "once_cell",
+ "serde",
+ "sha2",
+]
+
+[[package]]
+name = "alloy-genesis"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48450f9c6f0821c1eee00ed912942492ed4f11dd69532825833de23ecc7a2256"
+dependencies = [
+ "alloy-primitives",
+ "alloy-serde",
+ "serde",
+]
+
+[[package]]
+name = "alloy-json-abi"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aaeaccd50238126e3a0ff9387c7c568837726ad4f4e399b528ca88104d6c25ef"
+dependencies = [
+ "alloy-primitives",
+ "alloy-sol-type-parser",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "alloy-json-rpc"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d484c2a934d0a4d86f8ad4db8113cb1d607707a6c54f6e78f4f1b4451b47aa70"
+dependencies = [
+ "alloy-primitives",
+ "serde",
+ "serde_json",
+ "thiserror",
+ "tracing",
+]
+
+[[package]]
+name = "alloy-network"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a20eba9bc551037f0626d6d29e191888638d979943fa4e842e9e6fc72bf0565"
+dependencies = [
+ "alloy-consensus",
+ "alloy-eips",
+ "alloy-json-rpc",
+ "alloy-primitives",
+ "alloy-rpc-types-eth",
+ "alloy-serde",
+ "alloy-signer",
+ "alloy-sol-types",
+ "async-trait",
+ "auto_impl",
+ "futures-utils-wasm",
+ "thiserror",
+]
+
+[[package]]
+name = "alloy-primitives"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f783611babedbbe90db3478c120fb5f5daacceffc210b39adc0af4fe0da70bad"
+dependencies = [
+ "alloy-rlp",
+ "arbitrary",
+ "bytes",
+ "cfg-if 1.0.0",
+ "const-hex",
+ "derive_arbitrary",
+ "derive_more",
+ "ethereum_ssz",
+ "getrandom",
+ "hex-literal",
+ "itoa",
+ "k256",
+ "keccak-asm",
+ "proptest",
+ "proptest-derive",
+ "rand",
+ "ruint",
+ "serde",
+ "tiny-keccak",
+]
+
+[[package]]
+name = "alloy-provider"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad5d89acb7339fad13bc69e7b925232f242835bfd91c82fcb9326b36481bd0f0"
+dependencies = [
+ "alloy-chains",
+ "alloy-consensus",
+ "alloy-eips",
+ "alloy-json-rpc",
+ "alloy-network",
+ "alloy-primitives",
+ "alloy-rpc-client",
+ "alloy-rpc-types-eth",
+ "alloy-transport",
+ "alloy-transport-http",
+ "async-stream",
+ "async-trait",
+ "auto_impl",
+ "dashmap",
+ "futures",
+ "futures-utils-wasm",
+ "lru",
+ "pin-project",
+ "reqwest",
+ "serde",
+ "serde_json",
+ "tokio",
+ "tracing",
+ "url",
+]
+
+[[package]]
+name = "alloy-rlp"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a43b18702501396fa9bcdeecd533bc85fac75150d308fc0f6800a01e6234a003"
+dependencies = [
+ "alloy-rlp-derive",
+ "arrayvec",
+ "bytes",
+]
+
+[[package]]
+name = "alloy-rlp-derive"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d83524c1f6162fcb5b0decf775498a125066c86dda6066ed609531b0e912f85a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "alloy-rpc-client"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "479ce003e8c74bbbc7d4235131c1d6b7eaf14a533ae850295b90d240340989cb"
+dependencies = [
+ "alloy-json-rpc",
+ "alloy-transport",
+ "alloy-transport-http",
+ "futures",
+ "pin-project",
+ "reqwest",
+ "serde",
+ "serde_json",
+ "tokio",
+ "tokio-stream",
+ "tower",
+ "tracing",
+ "url",
+]
+
+[[package]]
+name = "alloy-rpc-types"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0dfa1dd3e0bc3a3d89744fba8d1511216e83257160da2cd028a18b7d9c026030"
+dependencies = [
+ "alloy-rpc-types-eth",
+ "alloy-serde",
+]
+
+[[package]]
+name = "alloy-rpc-types-eth"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13bd7aa9ff9e67f1ba7ee0dd8cebfc95831d1649b0e4eeefae940dc3681079fa"
+dependencies = [
+ "alloy-consensus",
+ "alloy-eips",
+ "alloy-primitives",
+ "alloy-rlp",
+ "alloy-serde",
+ "alloy-sol-types",
+ "itertools 0.13.0",
+ "serde",
+ "serde_json",
+ "thiserror",
+]
+
+[[package]]
+name = "alloy-serde"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8913f9e825068d77c516188c221c44f78fd814fce8effe550a783295a2757d19"
+dependencies = [
+ "alloy-primitives",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "alloy-signer"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f740e13eb4c6a0e4d0e49738f1e86f31ad2d7ef93be499539f492805000f7237"
+dependencies = [
+ "alloy-primitives",
+ "async-trait",
+ "auto_impl",
+ "elliptic-curve",
+ "k256",
+ "thiserror",
+]
+
+[[package]]
+name = "alloy-signer-local"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87db68d926887393a1d0f9c43833b44446ea29d603291e7b20e5d115f31aa4e3"
+dependencies = [
+ "alloy-consensus",
+ "alloy-network",
+ "alloy-primitives",
+ "alloy-signer",
+ "async-trait",
+ "elliptic-curve",
+ "eth-keystore",
+ "k256",
+ "rand",
+ "thiserror",
+]
+
+[[package]]
+name = "alloy-sol-macro"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bad41a7c19498e3f6079f7744656328699f8ea3e783bdd10d85788cd439f572"
+dependencies = [
+ "alloy-sol-macro-expander",
+ "alloy-sol-macro-input",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "alloy-sol-macro-expander"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd9899da7d011b4fe4c406a524ed3e3f963797dbc93b45479d60341d3a27b252"
+dependencies = [
+ "alloy-json-abi",
+ "alloy-sol-macro-input",
+ "const-hex",
+ "heck",
+ "indexmap 2.2.6",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+ "syn-solidity",
+ "tiny-keccak",
+]
+
+[[package]]
+name = "alloy-sol-macro-input"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d32d595768fdc61331a132b6f65db41afae41b9b97d36c21eb1b955c422a7e60"
+dependencies = [
+ "alloy-json-abi",
+ "const-hex",
+ "dunce",
+ "heck",
+ "proc-macro2",
+ "quote",
+ "serde_json",
+ "syn 2.0.68",
+ "syn-solidity",
+]
+
+[[package]]
+name = "alloy-sol-type-parser"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baa2fbd22d353d8685bd9fee11ba2d8b5c3b1d11e56adb3265fcf1f32bfdf404"
+dependencies = [
+ "winnow 0.6.13",
+]
+
+[[package]]
+name = "alloy-sol-types"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a49042c6d3b66a9fe6b2b5a8bf0d39fc2ae1ee0310a2a26ffedd79fb097878dd"
+dependencies = [
+ "alloy-json-abi",
+ "alloy-primitives",
+ "alloy-sol-macro",
+ "const-hex",
+ "serde",
+]
+
+[[package]]
+name = "alloy-transport"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd9773e4ec6832346171605c776315544bd06e40f803e7b5b7824b325d5442ca"
+dependencies = [
+ "alloy-json-rpc",
+ "base64",
+ "futures-util",
+ "futures-utils-wasm",
+ "serde",
+ "serde_json",
+ "thiserror",
+ "tokio",
+ "tower",
+ "url",
+]
+
+[[package]]
+name = "alloy-transport-http"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff8ef947b901c0d4e97370f9fa25844cf8b63b1a58fd4011ee82342dc8a9fc6b"
+dependencies = [
+ "alloy-json-rpc",
+ "alloy-transport",
+ "reqwest",
+ "serde_json",
+ "tower",
+ "tracing",
+ "url",
+]
+
+[[package]]
+name = "anstream"
+version = "0.6.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391"
+dependencies = [
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
+dependencies = [
+ "anstyle",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "arbitrary"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110"
+
+[[package]]
+name = "ark-ff"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6"
+dependencies = [
+ "ark-ff-asm 0.3.0",
+ "ark-ff-macros 0.3.0",
+ "ark-serialize 0.3.0",
+ "ark-std 0.3.0",
+ "derivative",
+ "num-bigint",
+ "num-traits",
+ "paste",
+ "rustc_version 0.3.3",
+ "zeroize",
+]
+
+[[package]]
+name = "ark-ff"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba"
+dependencies = [
+ "ark-ff-asm 0.4.2",
+ "ark-ff-macros 0.4.2",
+ "ark-serialize 0.4.2",
+ "ark-std 0.4.0",
+ "derivative",
+ "digest 0.10.7",
+ "itertools 0.10.5",
+ "num-bigint",
+ "num-traits",
+ "paste",
+ "rustc_version 0.4.0",
+ "zeroize",
+]
+
+[[package]]
+name = "ark-ff-asm"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44"
+dependencies = [
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "ark-ff-asm"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348"
+dependencies = [
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "ark-ff-macros"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20"
+dependencies = [
+ "num-bigint",
+ "num-traits",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "ark-ff-macros"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565"
+dependencies = [
+ "num-bigint",
+ "num-traits",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "ark-serialize"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671"
+dependencies = [
+ "ark-std 0.3.0",
+ "digest 0.9.0",
+]
+
+[[package]]
+name = "ark-serialize"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5"
+dependencies = [
+ "ark-std 0.4.0",
+ "digest 0.10.7",
+ "num-bigint",
+]
+
+[[package]]
+name = "ark-std"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c"
+dependencies = [
+ "num-traits",
+ "rand",
+]
+
+[[package]]
+name = "ark-std"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185"
+dependencies = [
+ "num-traits",
+ "rand",
+]
+
+[[package]]
+name = "arrayvec"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
+
+[[package]]
+name = "async-stream"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51"
+dependencies = [
+ "async-stream-impl",
+ "futures-core",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "async-stream-impl"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "async-trait"
+version = "0.1.81"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "auto_impl"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
+
+[[package]]
+name = "backtrace"
+version = "0.3.73"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
+dependencies = [
+ "addr2line",
+ "cc",
+ "cfg-if 1.0.0",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+]
+
+[[package]]
+name = "base16ct"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
+
+[[package]]
+name = "base64"
+version = "0.22.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+
+[[package]]
+name = "base64ct"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
+
+[[package]]
+name = "benches"
+version = "0.1.0"
+dependencies = [
+ "alloy",
+ "alloy-primitives",
+ "alloy-sol-types",
+ "e2e",
+ "eyre",
+ "futures",
+ "keccak-const",
+ "koba",
+ "pyth-stylus",
+ "serde",
+ "stylus-sdk",
+ "tokio",
+]
+
+[[package]]
+name = "bit-set"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
+dependencies = [
+ "bit-vec",
+]
+
+[[package]]
+name = "bit-vec"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bitflags"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
+
+[[package]]
+name = "bitvec"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
+dependencies = [
+ "funty",
+ "radium",
+ "tap",
+ "wyz",
+]
+
+[[package]]
+name = "block-buffer"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "blst"
+version = "0.3.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62dc83a094a71d43eeadd254b1ec2d24cb6a0bb6cadce00df51f0db594711a32"
+dependencies = [
+ "cc",
+ "glob",
+ "threadpool",
+ "zeroize",
+]
+
+[[package]]
+name = "brotli-sys"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "brotli2"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e"
+dependencies = [
+ "brotli-sys",
+ "libc",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
+
+[[package]]
+name = "byte-slice-cast"
+version = "1.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c"
+
+[[package]]
+name = "bytecheck"
+version = "0.6.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2"
+dependencies = [
+ "bytecheck_derive",
+ "ptr_meta",
+ "simdutf8",
+]
+
+[[package]]
+name = "bytecheck_derive"
+version = "0.6.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "byteorder"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
+
+[[package]]
+name = "bytes"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "bytesize"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc"
+
+[[package]]
+name = "c-kzg"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdf100c4cea8f207e883ff91ca886d621d8a166cb04971dfaa9bb8fd99ed95df"
+dependencies = [
+ "blst",
+ "cc",
+ "glob",
+ "hex",
+ "libc",
+ "serde",
+]
+
+[[package]]
+name = "cc"
+version = "1.0.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490"
+
+[[package]]
+name = "cfg-if"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "cipher"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
+dependencies = [
+ "crypto-common",
+ "inout",
+]
+
+[[package]]
+name = "clap"
+version = "4.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
+
+[[package]]
+name = "const-hex"
+version = "1.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94fb8a24a26d37e1ffd45343323dc9fe6654ceea44c12f2fcb3d7ac29e610bc6"
+dependencies = [
+ "cfg-if 1.0.0",
+ "cpufeatures",
+ "hex",
+ "proptest",
+ "serde",
+]
+
+[[package]]
+name = "const-oid"
+version = "0.9.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
+
+[[package]]
+name = "convert_case"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
+
+[[package]]
+name = "convert_case"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
+name = "core-foundation"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
+
+[[package]]
+name = "corosensei"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "80128832c58ea9cbd041d2a759ec449224487b2c1e400453d99d244eead87a8e"
+dependencies = [
+ "autocfg",
+ "cfg-if 1.0.0",
+ "libc",
+ "scopeguard",
+ "windows-sys 0.33.0",
+]
+
+[[package]]
+name = "cpufeatures"
+version = "0.2.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "cranelift-bforest"
+version = "0.91.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a2ab4512dfd3a6f4be184403a195f76e81a8a9f9e6c898e19d2dc3ce20e0115"
+dependencies = [
+ "cranelift-entity",
+]
+
+[[package]]
+name = "cranelift-codegen"
+version = "0.91.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98b022ed2a5913a38839dfbafe6cf135342661293b08049843362df4301261dc"
+dependencies = [
+ "arrayvec",
+ "bumpalo",
+ "cranelift-bforest",
+ "cranelift-codegen-meta",
+ "cranelift-codegen-shared",
+ "cranelift-egraph",
+ "cranelift-entity",
+ "cranelift-isle",
+ "gimli 0.26.2",
+ "log",
+ "regalloc2",
+ "smallvec",
+ "target-lexicon",
+]
+
+[[package]]
+name = "cranelift-codegen-meta"
+version = "0.91.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "639307b45434ad112a98f8300c0f0ab085cbefcd767efcdef9ef19d4c0756e74"
+dependencies = [
+ "cranelift-codegen-shared",
+]
+
+[[package]]
+name = "cranelift-codegen-shared"
+version = "0.91.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "278e52e29c53fcf32431ef08406c295699a70306d05a0715c5b1bf50e33a9ab7"
+
+[[package]]
+name = "cranelift-egraph"
+version = "0.91.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "624b54323b06e675293939311943ba82d323bb340468ce1889be5da7932c8d73"
+dependencies = [
+ "cranelift-entity",
+ "fxhash",
+ "hashbrown 0.12.3",
+ "indexmap 1.9.3",
+ "log",
+ "smallvec",
+]
+
+[[package]]
+name = "cranelift-entity"
+version = "0.91.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a59bcbca89c3f1b70b93ab3cbba5e5e0cbf3e63dadb23c7525cb142e21a9d4c"
+
+[[package]]
+name = "cranelift-frontend"
+version = "0.91.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d70abacb8cfef3dc8ff7e8836e9c1d70f7967dfdac824a4cd5e30223415aca6"
+dependencies = [
+ "cranelift-codegen",
+ "log",
+ "smallvec",
+ "target-lexicon",
+]
+
+[[package]]
+name = "cranelift-isle"
+version = "0.91.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "393bc73c451830ff8dbb3a07f61843d6cb41a084f9996319917c0b291ed785bb"
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
+dependencies = [
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
+
+[[package]]
+name = "crunchy"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
+
+[[package]]
+name = "crypto-bigint"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
+dependencies = [
+ "generic-array",
+ "rand_core",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "ctr"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
+dependencies = [
+ "cipher",
+]
+
+[[package]]
+name = "darling"
+version = "0.20.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1"
+dependencies = [
+ "darling_core",
+ "darling_macro",
+]
+
+[[package]]
+name = "darling_core"
+version = "0.20.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120"
+dependencies = [
+ "fnv",
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.20.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178"
+dependencies = [
+ "darling_core",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "dashmap"
+version = "5.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
+dependencies = [
+ "cfg-if 1.0.0",
+ "hashbrown 0.14.5",
+ "lock_api",
+ "once_cell",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "der"
+version = "0.7.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0"
+dependencies = [
+ "const-oid",
+ "zeroize",
+]
+
+[[package]]
+name = "derivative"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "derive_arbitrary"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "derive_more"
+version = "0.99.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce"
+dependencies = [
+ "convert_case 0.4.0",
+ "proc-macro2",
+ "quote",
+ "rustc_version 0.4.0",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "digest"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "digest"
+version = "0.10.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
+dependencies = [
+ "block-buffer",
+ "const-oid",
+ "crypto-common",
+ "subtle",
+]
+
+[[package]]
+name = "dunce"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b"
+
+[[package]]
+name = "e2e"
+version = "0.1.0"
+source = "git+https://github.com/Ifechukwudaniel/e2e-stylus#bbcc5885f0b45a53d1f87adcbf31c0b5e7e144d2"
+dependencies = [
+ "alloy",
+ "e2e-proc",
+ "eyre",
+ "koba",
+ "once_cell",
+ "regex",
+ "tokio",
+ "toml",
+]
+
+[[package]]
+name = "e2e-proc"
+version = "0.1.0"
+source = "git+https://github.com/Ifechukwudaniel/e2e-proc-stylus#6894e8b62896ed16fb3128664ec2f390536c27c5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "ecdsa"
+version = "0.16.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca"
+dependencies = [
+ "der",
+ "digest 0.10.7",
+ "elliptic-curve",
+ "rfc6979",
+ "signature",
+ "spki",
+]
+
+[[package]]
+name = "either"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
+
+[[package]]
+name = "elliptic-curve"
+version = "0.13.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
+dependencies = [
+ "base16ct",
+ "crypto-bigint",
+ "digest 0.10.7",
+ "ff",
+ "generic-array",
+ "group",
+ "pkcs8",
+ "rand_core",
+ "sec1",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "enum-iterator"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4eeac5c5edb79e4e39fe8439ef35207780a11f69c52cbe424ce3dfad4cb78de6"
+dependencies = [
+ "enum-iterator-derive",
+]
+
+[[package]]
+name = "enum-iterator-derive"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "enumset"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "226c0da7462c13fb57e5cc9e0dc8f0635e7d27f276a3a7fd30054647f669007d"
+dependencies = [
+ "enumset_derive",
+]
+
+[[package]]
+name = "enumset_derive"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af"
+dependencies = [
+ "darling",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "equivalent"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+
+[[package]]
+name = "errno"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
+dependencies = [
+ "libc",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "eth-keystore"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fda3bf123be441da5260717e0661c25a2fd9cb2b2c1d20bf2e05580047158ab"
+dependencies = [
+ "aes",
+ "ctr",
+ "digest 0.10.7",
+ "hex",
+ "hmac",
+ "pbkdf2",
+ "rand",
+ "scrypt",
+ "serde",
+ "serde_json",
+ "sha2",
+ "sha3",
+ "thiserror",
+ "uuid 0.8.2",
+]
+
+[[package]]
+name = "ethbloom"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60"
+dependencies = [
+ "crunchy",
+ "fixed-hash",
+ "impl-rlp",
+ "impl-serde",
+ "tiny-keccak",
+]
+
+[[package]]
+name = "ethereum-types"
+version = "0.14.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee"
+dependencies = [
+ "ethbloom",
+ "fixed-hash",
+ "impl-rlp",
+ "impl-serde",
+ "primitive-types",
+ "uint",
+]
+
+[[package]]
+name = "ethereum_ssz"
+version = "0.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d3627f83d8b87b432a5fad9934b4565260722a141a2c40f371f8080adec9425"
+dependencies = [
+ "ethereum-types",
+ "itertools 0.10.5",
+ "smallvec",
+]
+
+[[package]]
+name = "extend-pyth-example"
+version = "0.1.0"
+dependencies = [
+ "alloy",
+ "alloy-primitives",
+ "alloy-sol-types",
+ "e2e",
+ "eyre",
+ "keccak-const",
+ "mini-alloc",
+ "pyth-stylus",
+ "stylus-sdk",
+ "tokio",
+]
+
+[[package]]
+name = "eyre"
+version = "0.6.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec"
+dependencies = [
+ "indenter",
+ "once_cell",
+]
+
+[[package]]
+name = "fallible-iterator"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
+
+[[package]]
+name = "fastrand"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
+
+[[package]]
+name = "fastrlp"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418"
+dependencies = [
+ "arrayvec",
+ "auto_impl",
+ "bytes",
+]
+
+[[package]]
+name = "ff"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
+dependencies = [
+ "rand_core",
+ "subtle",
+]
+
+[[package]]
+name = "fixed-hash"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534"
+dependencies = [
+ "arbitrary",
+ "byteorder",
+ "rand",
+ "rustc-hex",
+ "static_assertions",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "foreign-types"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
+dependencies = [
+ "foreign-types-shared",
+]
+
+[[package]]
+name = "foreign-types-shared"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
+
+[[package]]
+name = "form_urlencoded"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "function-example"
+version = "0.1.0"
+dependencies = [
+ "alloy",
+ "alloy-primitives",
+ "alloy-sol-types",
+ "e2e",
+ "eyre",
+ "keccak-const",
+ "mini-alloc",
+ "pyth-stylus",
+ "stylus-sdk",
+ "tokio",
+]
+
+[[package]]
+name = "funty"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
+
+[[package]]
+name = "futures"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-executor",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
+
+[[package]]
+name = "futures-executor"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-io"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
+
+[[package]]
+name = "futures-macro"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "futures-sink"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
+
+[[package]]
+name = "futures-task"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
+
+[[package]]
+name = "futures-util"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-macro",
+ "futures-sink",
+ "futures-task",
+ "memchr",
+ "pin-project-lite",
+ "pin-utils",
+ "slab",
+]
+
+[[package]]
+name = "futures-utils-wasm"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9"
+
+[[package]]
+name = "fxhash"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
+dependencies = [
+ "byteorder",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+ "zeroize",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
+dependencies = [
+ "cfg-if 1.0.0",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "gimli"
+version = "0.26.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
+dependencies = [
+ "fallible-iterator",
+ "indexmap 1.9.3",
+ "stable_deref_trait",
+]
+
+[[package]]
+name = "gimli"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
+
+[[package]]
+name = "glob"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
+
+[[package]]
+name = "group"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
+dependencies = [
+ "ff",
+ "rand_core",
+ "subtle",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+dependencies = [
+ "ahash 0.7.8",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.14.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
+dependencies = [
+ "ahash 0.8.11",
+ "allocator-api2",
+]
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "hermit-abi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
+
+[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "hex-literal"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46"
+
+[[package]]
+name = "hmac"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+dependencies = [
+ "digest 0.10.7",
+]
+
+[[package]]
+name = "http"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "http-body"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
+dependencies = [
+ "bytes",
+ "http",
+]
+
+[[package]]
+name = "http-body-util"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f"
+dependencies = [
+ "bytes",
+ "futures-util",
+ "http",
+ "http-body",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "httparse"
+version = "1.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9"
+
+[[package]]
+name = "hyper"
+version = "1.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-util",
+ "http",
+ "http-body",
+ "httparse",
+ "itoa",
+ "pin-project-lite",
+ "smallvec",
+ "tokio",
+ "want",
+]
+
+[[package]]
+name = "hyper-tls"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
+dependencies = [
+ "bytes",
+ "http-body-util",
+ "hyper",
+ "hyper-util",
+ "native-tls",
+ "tokio",
+ "tokio-native-tls",
+ "tower-service",
+]
+
+[[package]]
+name = "hyper-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-util",
+ "http",
+ "http-body",
+ "hyper",
+ "pin-project-lite",
+ "socket2",
+ "tokio",
+ "tower",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "ident_case"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
+
+[[package]]
+name = "idna"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
+dependencies = [
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "impl-codec"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f"
+dependencies = [
+ "parity-scale-codec",
+]
+
+[[package]]
+name = "impl-rlp"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808"
+dependencies = [
+ "rlp",
+]
+
+[[package]]
+name = "impl-serde"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "impl-trait-for-tuples"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "indenter"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
+
+[[package]]
+name = "indexmap"
+version = "1.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
+dependencies = [
+ "autocfg",
+ "hashbrown 0.12.3",
+]
+
+[[package]]
+name = "indexmap"
+version = "2.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
+dependencies = [
+ "equivalent",
+ "hashbrown 0.14.5",
+]
+
+[[package]]
+name = "inout"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "ipnet"
+version = "2.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
+
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
+
+[[package]]
+name = "itertools"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itertools"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
+
+[[package]]
+name = "js-sys"
+version = "0.3.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "k256"
+version = "0.13.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b"
+dependencies = [
+ "cfg-if 1.0.0",
+ "ecdsa",
+ "elliptic-curve",
+ "once_cell",
+ "sha2",
+]
+
+[[package]]
+name = "keccak"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654"
+dependencies = [
+ "cpufeatures",
+]
+
+[[package]]
+name = "keccak-asm"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47a3633291834c4fbebf8673acbc1b04ec9d151418ff9b8e26dcd79129928758"
+dependencies = [
+ "digest 0.10.7",
+ "sha3-asm",
+]
+
+[[package]]
+name = "keccak-const"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57d8d8ce877200136358e0bbff3a77965875db3af755a11e1fa6b1b3e2df13ea"
+
+[[package]]
+name = "koba"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "80e92e1148d087df999396266311bece9e5311c352821872cccaf5dc67117cfc"
+dependencies = [
+ "alloy",
+ "brotli2",
+ "bytesize",
+ "clap",
+ "eyre",
+ "hex",
+ "once_cell",
+ "owo-colors",
+ "regex",
+ "tempfile",
+ "tokio",
+ "wasmer",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+
+[[package]]
+name = "leb128"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
+
+[[package]]
+name = "libc"
+version = "0.2.155"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
+
+[[package]]
+name = "libm"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
+
+[[package]]
+name = "lock_api"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
+
+[[package]]
+name = "lru"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc"
+dependencies = [
+ "hashbrown 0.14.5",
+]
+
+[[package]]
+name = "mach"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "mach2"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "memchr"
+version = "2.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+
+[[package]]
+name = "memmap2"
+version = "0.5.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "memoffset"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "memory_units"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3"
+
+[[package]]
+name = "mime"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
+
+[[package]]
+name = "mini-alloc"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd9993556d3850cdbd0da06a3dc81297edcfa050048952d84d75e8b944e8f5af"
+dependencies = [
+ "cfg-if 1.0.0",
+ "wee_alloc",
+]
+
+[[package]]
+name = "miniz_oxide"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
+dependencies = [
+ "adler",
+]
+
+[[package]]
+name = "mio"
+version = "0.8.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
+dependencies = [
+ "libc",
+ "wasi",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "more-asserts"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389"
+
+[[package]]
+name = "motsu"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "744174e5011fed86212d90c1120037da87e0c45fee7a5861c2b3105e41283810"
+dependencies = [
+ "const-hex",
+ "motsu-proc",
+ "once_cell",
+ "stylus-sdk",
+ "tiny-keccak",
+]
+
+[[package]]
+name = "motsu-proc"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0785317ee15f9a1bc5d761da9d0d1dadd92225cd5a88eed0ec37c54a277fac44"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "native-tls"
+version = "0.2.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466"
+dependencies = [
+ "libc",
+ "log",
+ "openssl",
+ "openssl-probe",
+ "openssl-sys",
+ "schannel",
+ "security-framework",
+ "security-framework-sys",
+ "tempfile",
+]
+
+[[package]]
+name = "num-bigint"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
+dependencies = [
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.46"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+ "libm",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "num_enum"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845"
+dependencies = [
+ "num_enum_derive",
+]
+
+[[package]]
+name = "num_enum_derive"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "object"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+
+[[package]]
+name = "openssl"
+version = "0.10.64"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f"
+dependencies = [
+ "bitflags 2.6.0",
+ "cfg-if 1.0.0",
+ "foreign-types",
+ "libc",
+ "once_cell",
+ "openssl-macros",
+ "openssl-sys",
+]
+
+[[package]]
+name = "openssl-macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "openssl-probe"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
+
+[[package]]
+name = "openssl-sys"
+version = "0.9.102"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "owo-colors"
+version = "4.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "caff54706df99d2a78a5a4e3455ff45448d81ef1bb63c22cd14052ca0e993a3f"
+
+[[package]]
+name = "parity-scale-codec"
+version = "3.6.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee"
+dependencies = [
+ "arrayvec",
+ "bitvec",
+ "byte-slice-cast",
+ "impl-trait-for-tuples",
+ "parity-scale-codec-derive",
+ "serde",
+]
+
+[[package]]
+name = "parity-scale-codec-derive"
+version = "3.6.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c"
+dependencies = [
+ "proc-macro-crate",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "parking_lot"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
+dependencies = [
+ "cfg-if 1.0.0",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-targets 0.52.5",
+]
+
+[[package]]
+name = "paste"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
+
+[[package]]
+name = "pbkdf2"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917"
+dependencies = [
+ "digest 0.10.7",
+]
+
+[[package]]
+name = "percent-encoding"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
+
+[[package]]
+name = "pest"
+version = "2.7.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8"
+dependencies = [
+ "memchr",
+ "thiserror",
+ "ucd-trie",
+]
+
+[[package]]
+name = "pin-project"
+version = "1.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "pkcs8"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
+dependencies = [
+ "der",
+ "spki",
+]
+
+[[package]]
+name = "pkg-config"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+
+[[package]]
+name = "primitive-types"
+version = "0.12.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2"
+dependencies = [
+ "fixed-hash",
+ "impl-codec",
+ "impl-rlp",
+ "impl-serde",
+ "uint",
+]
+
+[[package]]
+name = "proc-macro-crate"
+version = "3.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284"
+dependencies = [
+ "toml_edit 0.21.1",
+]
+
+[[package]]
+name = "proc-macro-error"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.86"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "proptest"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d"
+dependencies = [
+ "bit-set",
+ "bit-vec",
+ "bitflags 2.6.0",
+ "lazy_static",
+ "num-traits",
+ "rand",
+ "rand_chacha",
+ "rand_xorshift",
+ "regex-syntax",
+ "rusty-fork",
+ "tempfile",
+ "unarray",
+]
+
+[[package]]
+name = "proptest-derive"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9cf16337405ca084e9c78985114633b6827711d22b9e6ef6c6c0d665eb3f0b6e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "ptr_meta"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1"
+dependencies = [
+ "ptr_meta_derive",
+]
+
+[[package]]
+name = "ptr_meta_derive"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "pyth-example"
+version = "0.1.0"
+dependencies = [
+ "alloy",
+ "alloy-primitives",
+ "alloy-sol-types",
+ "e2e",
+ "eyre",
+ "keccak-const",
+ "mini-alloc",
+ "pyth-stylus",
+ "stylus-sdk",
+ "tokio",
+]
+
+[[package]]
+name = "pyth-stylus"
+version = "0.1.0"
+dependencies = [
+ "alloy-primitives",
+ "alloy-sol-macro",
+ "alloy-sol-macro-expander",
+ "alloy-sol-macro-input",
+ "alloy-sol-types",
+ "keccak-const",
+ "mini-alloc",
+ "motsu",
+ "stylus-sdk",
+]
+
+[[package]]
+name = "quick-error"
+version = "1.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
+
+[[package]]
+name = "quote"
+version = "1.0.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "radium"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_xorshift"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "rayon"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
+dependencies = [
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
+dependencies = [
+ "crossbeam-deque",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd"
+dependencies = [
+ "bitflags 2.6.0",
+]
+
+[[package]]
+name = "regalloc2"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "300d4fbfb40c1c66a78ba3ddd41c1110247cf52f97b87d0f2fc9209bd49b030c"
+dependencies = [
+ "fxhash",
+ "log",
+ "slice-group-by",
+ "smallvec",
+]
+
+[[package]]
+name = "regex"
+version = "1.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
+
+[[package]]
+name = "region"
+version = "3.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6b6ebd13bc009aef9cd476c1310d49ac354d36e240cf1bd753290f3dc7199a7"
+dependencies = [
+ "bitflags 1.3.2",
+ "libc",
+ "mach2",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "rend"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c"
+dependencies = [
+ "bytecheck",
+]
+
+[[package]]
+name = "reqwest"
+version = "0.12.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37"
+dependencies = [
+ "base64",
+ "bytes",
+ "futures-core",
+ "futures-util",
+ "http",
+ "http-body",
+ "http-body-util",
+ "hyper",
+ "hyper-tls",
+ "hyper-util",
+ "ipnet",
+ "js-sys",
+ "log",
+ "mime",
+ "native-tls",
+ "once_cell",
+ "percent-encoding",
+ "pin-project-lite",
+ "rustls-pemfile",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+ "sync_wrapper",
+ "tokio",
+ "tokio-native-tls",
+ "tower-service",
+ "url",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "web-sys",
+ "winreg",
+]
+
+[[package]]
+name = "rfc6979"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
+dependencies = [
+ "hmac",
+ "subtle",
+]
+
+[[package]]
+name = "rkyv"
+version = "0.7.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5cba464629b3394fc4dbc6f940ff8f5b4ff5c7aef40f29166fd4ad12acbc99c0"
+dependencies = [
+ "bitvec",
+ "bytecheck",
+ "bytes",
+ "hashbrown 0.12.3",
+ "indexmap 1.9.3",
+ "ptr_meta",
+ "rend",
+ "rkyv_derive",
+ "seahash",
+ "tinyvec",
+ "uuid 1.9.1",
+]
+
+[[package]]
+name = "rkyv_derive"
+version = "0.7.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "rlp"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec"
+dependencies = [
+ "bytes",
+ "rustc-hex",
+]
+
+[[package]]
+name = "ruint"
+version = "1.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c3cc4c2511671f327125da14133d0c5c5d137f006a1017a16f557bc85b16286"
+dependencies = [
+ "alloy-rlp",
+ "arbitrary",
+ "ark-ff 0.3.0",
+ "ark-ff 0.4.2",
+ "bytes",
+ "fastrlp",
+ "num-bigint",
+ "num-traits",
+ "parity-scale-codec",
+ "primitive-types",
+ "proptest",
+ "rand",
+ "rlp",
+ "ruint-macro",
+ "serde",
+ "valuable",
+ "zeroize",
+]
+
+[[package]]
+name = "ruint-macro"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18"
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
+
+[[package]]
+name = "rustc-hex"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6"
+
+[[package]]
+name = "rustc_version"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee"
+dependencies = [
+ "semver 0.11.0",
+]
+
+[[package]]
+name = "rustc_version"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
+dependencies = [
+ "semver 1.0.23",
+]
+
+[[package]]
+name = "rustix"
+version = "0.38.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
+dependencies = [
+ "bitflags 2.6.0",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "rustls-pemfile"
+version = "2.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d"
+dependencies = [
+ "base64",
+ "rustls-pki-types",
+]
+
+[[package]]
+name = "rustls-pki-types"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d"
+
+[[package]]
+name = "rustversion"
+version = "1.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
+
+[[package]]
+name = "rusty-fork"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f"
+dependencies = [
+ "fnv",
+ "quick-error",
+ "tempfile",
+ "wait-timeout",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
+
+[[package]]
+name = "salsa20"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213"
+dependencies = [
+ "cipher",
+]
+
+[[package]]
+name = "schannel"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534"
+dependencies = [
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "scrypt"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f9e24d2b632954ded8ab2ef9fea0a0c769ea56ea98bddbafbad22caeeadf45d"
+dependencies = [
+ "hmac",
+ "pbkdf2",
+ "salsa20",
+ "sha2",
+]
+
+[[package]]
+name = "seahash"
+version = "4.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
+
+[[package]]
+name = "sec1"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
+dependencies = [
+ "base16ct",
+ "der",
+ "generic-array",
+ "pkcs8",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "security-framework"
+version = "2.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0"
+dependencies = [
+ "bitflags 2.6.0",
+ "core-foundation",
+ "core-foundation-sys",
+ "libc",
+ "security-framework-sys",
+]
+
+[[package]]
+name = "security-framework-sys"
+version = "2.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "semver"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
+dependencies = [
+ "semver-parser",
+]
+
+[[package]]
+name = "semver"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
+
+[[package]]
+name = "semver-parser"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
+dependencies = [
+ "pest",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.203"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde-wasm-bindgen"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf"
+dependencies = [
+ "js-sys",
+ "serde",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.203"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.119"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8eddb61f0697cc3989c5d64b452f5488e2b8a60fd7d5076a3045076ffef8cb0"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "serde_spanned"
+version = "0.6.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "serde_urlencoded"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
+dependencies = [
+ "form_urlencoded",
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "sha2"
+version = "0.10.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
+dependencies = [
+ "cfg-if 1.0.0",
+ "cpufeatures",
+ "digest 0.10.7",
+]
+
+[[package]]
+name = "sha3"
+version = "0.10.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60"
+dependencies = [
+ "digest 0.10.7",
+ "keccak",
+]
+
+[[package]]
+name = "sha3-asm"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9b57fd861253bff08bb1919e995f90ba8f4889de2726091c8876f3a4e823b40"
+dependencies = [
+ "cc",
+ "cfg-if 1.0.0",
+]
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "signature"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
+dependencies = [
+ "digest 0.10.7",
+ "rand_core",
+]
+
+[[package]]
+name = "simdutf8"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a"
+
+[[package]]
+name = "slab"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "slice-group-by"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7"
+
+[[package]]
+name = "smallvec"
+version = "1.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
+
+[[package]]
+name = "socket2"
+version = "0.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
+dependencies = [
+ "libc",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "spki"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
+dependencies = [
+ "base64ct",
+ "der",
+]
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
+[[package]]
+name = "strum"
+version = "0.26.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
+dependencies = [
+ "strum_macros",
+]
+
+[[package]]
+name = "strum_macros"
+version = "0.26.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "stylus-proc"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fd02e91dffe7b73df84a861c992494d6b72054bc9a17fe73e147e34e9a64ef3"
+dependencies = [
+ "alloy-primitives",
+ "alloy-sol-types",
+ "cfg-if 1.0.0",
+ "convert_case 0.6.0",
+ "lazy_static",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "sha3",
+ "syn 1.0.109",
+ "syn-solidity",
+]
+
+[[package]]
+name = "stylus-sdk"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26042693706e29fb7e3cf3d71c99534ac97fca98b6f81ba77ab658022ab2e210"
+dependencies = [
+ "alloy-primitives",
+ "alloy-sol-types",
+ "cfg-if 1.0.0",
+ "derivative",
+ "hex",
+ "keccak-const",
+ "lazy_static",
+ "stylus-proc",
+]
+
+[[package]]
+name = "subtle"
+version = "2.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.68"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn-solidity"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d71e19bca02c807c9faa67b5a47673ff231b6e7449b251695188522f1dc44b2"
+dependencies = [
+ "paste",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "sync_wrapper"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
+
+[[package]]
+name = "tap"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
+
+[[package]]
+name = "target-lexicon"
+version = "0.12.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f"
+
+[[package]]
+name = "tempfile"
+version = "3.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
+dependencies = [
+ "cfg-if 1.0.0",
+ "fastrand",
+ "rustix",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.61"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.61"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "threadpool"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
+dependencies = [
+ "num_cpus",
+]
+
+[[package]]
+name = "tiny-keccak"
+version = "2.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
+dependencies = [
+ "crunchy",
+]
+
+[[package]]
+name = "tinyvec"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c55115c6fbe2d2bef26eb09ad74bde02d8255476fc0c7b515ef09fbb35742d82"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
+[[package]]
+name = "tokio"
+version = "1.38.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a"
+dependencies = [
+ "backtrace",
+ "bytes",
+ "libc",
+ "mio",
+ "num_cpus",
+ "parking_lot",
+ "pin-project-lite",
+ "signal-hook-registry",
+ "socket2",
+ "tokio-macros",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "tokio-native-tls"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
+dependencies = [
+ "native-tls",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-stream"
+version = "0.1.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
+ "tokio-util",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.7.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "toml"
+version = "0.8.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit 0.22.14",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.21.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1"
+dependencies = [
+ "indexmap 2.2.6",
+ "toml_datetime",
+ "winnow 0.5.40",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.22.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38"
+dependencies = [
+ "indexmap 2.2.6",
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "winnow 0.6.13",
+]
+
+[[package]]
+name = "tower"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
+dependencies = [
+ "futures-core",
+ "futures-util",
+ "pin-project",
+ "pin-project-lite",
+ "tokio",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "tower-layer"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
+
+[[package]]
+name = "tower-service"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
+
+[[package]]
+name = "tracing"
+version = "0.1.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
+dependencies = [
+ "log",
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "try-lock"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
+
+[[package]]
+name = "typenum"
+version = "1.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
+
+[[package]]
+name = "ucd-trie"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9"
+
+[[package]]
+name = "uint"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52"
+dependencies = [
+ "arbitrary",
+ "byteorder",
+ "crunchy",
+ "hex",
+ "static_assertions",
+]
+
+[[package]]
+name = "unarray"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94"
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
+
+[[package]]
+name = "url"
+version = "2.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "percent-encoding",
+]
+
+[[package]]
+name = "utf8parse"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+
+[[package]]
+name = "uuid"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
+dependencies = [
+ "getrandom",
+ "serde",
+]
+
+[[package]]
+name = "uuid"
+version = "1.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439"
+
+[[package]]
+name = "valuable"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
+
+[[package]]
+name = "vcpkg"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
+[[package]]
+name = "version_check"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+
+[[package]]
+name = "wait-timeout"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "want"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
+dependencies = [
+ "try-lock",
+]
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
+dependencies = [
+ "cfg-if 1.0.0",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-downcast"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5dac026d43bcca6e7ce1c0956ba68f59edf6403e8e930a5d891be72c31a44340"
+dependencies = [
+ "js-sys",
+ "once_cell",
+ "wasm-bindgen",
+ "wasm-bindgen-downcast-macros",
+]
+
+[[package]]
+name = "wasm-bindgen-downcast-macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c5020cfa87c7cecefef118055d44e3c1fc122c7ec25701d528ee458a0b45f38f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "wasm-bindgen-futures"
+version = "0.4.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0"
+dependencies = [
+ "cfg-if 1.0.0",
+ "js-sys",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
+
+[[package]]
+name = "wasm-encoder"
+version = "0.212.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "501940df4418b8929eb6d52f1aade1fdd15a5b86c92453cb696e3c906bd3fc33"
+dependencies = [
+ "leb128",
+]
+
+[[package]]
+name = "wasmer"
+version = "3.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78caedecd8cb71ed47ccca03b68d69414a3d278bb031e6f93f15759344efdd52"
+dependencies = [
+ "bytes",
+ "cfg-if 1.0.0",
+ "derivative",
+ "indexmap 1.9.3",
+ "js-sys",
+ "more-asserts",
+ "rustc-demangle",
+ "serde",
+ "serde-wasm-bindgen",
+ "target-lexicon",
+ "thiserror",
+ "wasm-bindgen",
+ "wasm-bindgen-downcast",
+ "wasmer-compiler",
+ "wasmer-compiler-cranelift",
+ "wasmer-derive",
+ "wasmer-types",
+ "wasmer-vm",
+ "wat",
+ "winapi",
+]
+
+[[package]]
+name = "wasmer-compiler"
+version = "3.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "726a8450541af4a57c34af7b6973fdbfc79f896cc7e733429577dfd1d1687180"
+dependencies = [
+ "backtrace",
+ "cfg-if 1.0.0",
+ "enum-iterator",
+ "enumset",
+ "lazy_static",
+ "leb128",
+ "memmap2",
+ "more-asserts",
+ "region",
+ "smallvec",
+ "thiserror",
+ "wasmer-types",
+ "wasmer-vm",
+ "wasmparser",
+ "winapi",
+]
+
+[[package]]
+name = "wasmer-compiler-cranelift"
+version = "3.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1e5633f90f372563ebbdf3f9799c7b29ba11c90e56cf9b54017112d2e656c95"
+dependencies = [
+ "cranelift-codegen",
+ "cranelift-entity",
+ "cranelift-frontend",
+ "gimli 0.26.2",
+ "more-asserts",
+ "rayon",
+ "smallvec",
+ "target-lexicon",
+ "tracing",
+ "wasmer-compiler",
+ "wasmer-types",
+]
+
+[[package]]
+name = "wasmer-derive"
+version = "3.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97901fdbaae383dbb90ea162cc3a76a9fa58ac39aec7948b4c0b9bbef9307738"
+dependencies = [
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "wasmer-types"
+version = "3.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67f1f2839f4f61509550e4ddcd0e658e19f3af862b51c79fda15549d735d659b"
+dependencies = [
+ "bytecheck",
+ "enum-iterator",
+ "enumset",
+ "indexmap 1.9.3",
+ "more-asserts",
+ "rkyv",
+ "target-lexicon",
+ "thiserror",
+]
+
+[[package]]
+name = "wasmer-vm"
+version = "3.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "043118ec4f16d1714fed3aab758b502b864bd865e1d5188626c9ad290100563f"
+dependencies = [
+ "backtrace",
+ "cc",
+ "cfg-if 1.0.0",
+ "corosensei",
+ "dashmap",
+ "derivative",
+ "enum-iterator",
+ "fnv",
+ "indexmap 1.9.3",
+ "lazy_static",
+ "libc",
+ "mach",
+ "memoffset",
+ "more-asserts",
+ "region",
+ "scopeguard",
+ "thiserror",
+ "wasmer-types",
+ "winapi",
+]
+
+[[package]]
+name = "wasmparser"
+version = "0.95.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2ea896273ea99b15132414be1da01ab0d8836415083298ecaffbe308eaac87a"
+dependencies = [
+ "indexmap 1.9.3",
+ "url",
+]
+
+[[package]]
+name = "wast"
+version = "212.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4606a05fb0aae5d11dd7d8280a640d88a63ee019360ba9be552da3d294b8d1f5"
+dependencies = [
+ "bumpalo",
+ "leb128",
+ "memchr",
+ "unicode-width",
+ "wasm-encoder",
+]
+
+[[package]]
+name = "wat"
+version = "1.212.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c74ca7f93f11a5d6eed8499f2a8daaad6e225cab0151bc25a091fff3b987532f"
+dependencies = [
+ "wast",
+]
+
+[[package]]
+name = "web-sys"
+version = "0.3.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "wee_alloc"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e"
+dependencies = [
+ "cfg-if 0.1.10",
+ "libc",
+ "memory_units",
+ "winapi",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-sys"
+version = "0.33.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43dbb096663629518eb1dfa72d80243ca5a6aca764cae62a2df70af760a9be75"
+dependencies = [
+ "windows_aarch64_msvc 0.33.0",
+ "windows_i686_gnu 0.33.0",
+ "windows_i686_msvc 0.33.0",
+ "windows_x86_64_gnu 0.33.0",
+ "windows_x86_64_msvc 0.33.0",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets 0.48.5",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets 0.52.5",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.5",
+ "windows_aarch64_msvc 0.48.5",
+ "windows_i686_gnu 0.48.5",
+ "windows_i686_msvc 0.48.5",
+ "windows_x86_64_gnu 0.48.5",
+ "windows_x86_64_gnullvm 0.48.5",
+ "windows_x86_64_msvc 0.48.5",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.5",
+ "windows_aarch64_msvc 0.52.5",
+ "windows_i686_gnu 0.52.5",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc 0.52.5",
+ "windows_x86_64_gnu 0.52.5",
+ "windows_x86_64_gnullvm 0.52.5",
+ "windows_x86_64_msvc 0.52.5",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.33.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd761fd3eb9ab8cc1ed81e56e567f02dd82c4c837e48ac3b2181b9ffc5060807"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.33.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cab0cf703a96bab2dc0c02c0fa748491294bf9b7feb27e1f4f96340f208ada0e"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.33.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8cfdbe89cc9ad7ce618ba34abc34bbb6c36d99e96cae2245b7943cd75ee773d0"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.33.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4dd9b0c0e9ece7bb22e84d70d01b71c6d6248b81a3c60d11869451b4cb24784"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.33.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff1e4aa646495048ec7f3ffddc411e1d829c026a2ec62b39da15c1055e406eaa"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
+
+[[package]]
+name = "winnow"
+version = "0.5.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "winnow"
+version = "0.6.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "winreg"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5"
+dependencies = [
+ "cfg-if 1.0.0",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "wyz"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
+dependencies = [
+ "tap",
+]
+
+[[package]]
+name = "zerocopy"
+version = "0.7.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.7.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "zeroize"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
+dependencies = [
+ "zeroize_derive",
+]
+
+[[package]]
+name = "zeroize_derive"
+version = "1.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]

+ 92 - 0
target_chains/ethereum/sdk/stylus/Cargo.toml

@@ -0,0 +1,92 @@
+[workspace]
+members = [
+  "contracts",
+  "examples/pyth-example",
+  "examples/extend-pyth-example",
+  "examples/function-example",
+  "benches"
+]
+default-members = [
+  "contracts",
+  "examples/pyth-example",
+  "examples/extend-pyth-example",
+  "examples/function-example",
+]
+
+# Explicitly set the resolver to version 2, which is the default for packages
+# with edition >= 2021.
+# https://doc.rust-lang.org/edition-guide/rust-2021/default-cargo-resolver.html
+resolver = "2"
+
+[workspace.package]
+authors = ["Ifechukwu Daniel"]
+edition = "2021"
+license = "Apache-2.0"
+repository = "https://github.com/pyth-network/pyth-crosschain"
+version = "0.1.0"
+
+[workspace.lints.rust]
+missing_docs = "warn"
+unreachable_pub = "warn"
+rust_2021_compatibility = { level = "warn", priority = -1 }
+
+
+[workspace.dependencies]
+# stylus-related
+stylus-sdk = { version = "0.6.0", default-features = false }
+mini-alloc = "0.4.2"
+
+alloy = { version = "0.1.4", features = [
+  "contract",
+  "network",
+  "providers",
+  "provider-http",
+  "rpc-client",
+  "rpc-types-eth",
+  "signer-local",
+  "getrandom",
+] }
+# Even though `alloy` includes `alloy-primitives` and `alloy-sol-types` we need
+# to keep both versions for compatibility with the Stylus SDK. Once they start
+# using `alloy` we can remove these.
+alloy-primitives = { version = "0.7.6", default-features = false }
+alloy-sol-types = { version = "0.7.6", default-features = false }
+alloy-sol-macro = { version = "0.7.6", default-features = false }
+alloy-sol-macro-expander = { version = "0.7.6", default-features = false }
+alloy-sol-macro-input = { version = "0.7.6", default-features = false }
+
+dotenv = "0.15.0"
+const-hex = { version = "1.11.1", default-features = false }
+eyre = "0.6.8"
+keccak-const = "0.2.0"
+koba = "0.2.0"
+once_cell = "1.19.0"
+rand = "0.8.5"
+regex = "1.10.4"
+tiny-keccak = { version = "2.0.2", features = ["keccak"] }
+tokio = { version = "1.12.0", features = ["full"] }
+futures = "0.3.30"
+
+# procedural macros
+syn = { version = "2.0.58", features = ["full"] }
+proc-macro2 = "1.0.79"
+quote = "1.0.35"
+
+# members
+motsu = "0.1.0"
+e2e = { git = "https://github.com/Ifechukwudaniel/e2e-stylus"}
+pyth-stylus ={path ="contracts"}
+
+[profile.release]
+codegen-units = 1
+panic = "abort"
+opt-level = "z"
+strip = true
+lto = true
+debug = false
+rpath = false
+debug-assertions = false
+incremental = false
+
+[profile.dev]
+panic = "abort"

+ 5 - 0
target_chains/ethereum/sdk/stylus/GUIDELINES.md

@@ -0,0 +1,5 @@
+# Engineering Guidelines
+
+For best practices, coding standards, and other essential guidelines, please refer to the official [OpenZeppelin Rust Contracts Stylus Engineering Guidelines](https://github.com/OpenZeppelin/rust-contracts-stylus/blob/main/GUIDELINES.md).
+
+This document outlines the principles and practices for ths codebase , maintainable, and secure Rust code within the context of the Rust Contracts Stylus project.

+ 98 - 0
target_chains/ethereum/sdk/stylus/README.md

@@ -0,0 +1,98 @@
+# Pyth Stylus SDK
+
+This package provides utilities for consuming prices from the [Pyth Network](https://pyth.network/) Oracle in Rust with Stylus. It also includes the [Pyth Interface ABI](./abis/IPyth.json), which can be used in your libraries to interact with the Pyth contract.
+
+It is **strongly recommended** to follow the [consumer best practices](https://docs.pyth.network/documentation/pythnet-price-feeds/best-practices) when consuming data from Pyth.
+
+## Features
+
+- Integrates with the [`pyth-solidity-contracts`] library for external calls to Pyth smart contracts.
+- Provides first-class `no_std` support.
+- Includes Solidity constructors powered by [`koba`].
+- Supports both [unit] and [integration] test affordances for thorough testing.
+
+## Installation
+
+To add the Stylus Contracts from crates.io, add the following line to your `Cargo.toml` (pinning to a specific version is recommended):
+
+```toml
+[dependencies]
+pyth-stylus = "0.1.0"
+```
+
+For the latest changes from the `main` branch, you can also specify a git dependency:
+
+```toml
+[dependencies]
+pyth-stylus = { git = "https://github.com/pyth-network/pyth-crosschain.git" }
+```
+
+## Example Usage
+
+To consume prices, use the functions interface. Be sure to read the function documentation to ensure safe use of price data.
+
+For example, to read the latest price, call [`getPriceNoOlderThan`](https://github.com/pyth-network/pyth-crosschain/blob/stylus-sdk/target_chains/ethereum/sdk/stylus/contracts/src/pyth/functions.rs) with the Price ID of the price feed you are interested in:
+
+You can interact directly with the Pyth contract, which implements the IPyth functions, instead of using call functions:
+
+```rust
+#![cfg_attr(not(test), no_std, no_main)]
+extern crate alloc;
+
+use stylus_sdk::prelude::{entrypoint, public, sol_storage};
+use pyth_stylus::pyth::pyth_contract::PythContract;
+
+sol_storage! {
+    #[entrypoint]
+    struct ProxyCallsExample {
+        #[borrow]
+        PythContract pyth;
+    }
+}
+
+#[public]
+#[inherit(PythContract)]
+impl ProxyCallsExample {
+}
+```
+
+## Mocking Pyth
+
+[MockPyth](./mock.rs) is a mock contract that can be deployed locally to simulate Pyth contract behavior. To set and update price feeds, call `updatePriceFeeds` and provide an array of encoded price feeds as the argument. Encoded price feeds can be created using the `create_price_feed_update_data` function in the mock contract, which is also available in the functions module.
+
+## Test Documentation
+
+### Running Unit Tests for `pyth-stylus`
+
+To run all the unit tests for the `pyth-stylus` package with all its features enabled, use the following command:
+
+```bash
+cargo test -p pyth-stylus --all-features
+```
+
+This command will:
+
+- Target the `pyth-stylus` package specifically (`-p pyth-stylus`).
+- Enable **all features** defined in the package during the test run (`--all-features`).
+
+### Running End-to-End Tests
+
+To run the end-to-end tests for `pyth-stylus`, follow these steps:
+
+1. Start the test node:
+
+   ```bash
+   ./scripts/nitro-testnode.sh
+   ```
+
+2. Run the end-to-end tests:
+   ```
+   ./scripts/e2e-tests.sh
+   ```
+
+### Releases
+
+We use [Semantic Versioning](https://semver.org/) for our releases. To release a new version of this package and publish it to npm, follow these steps:
+
+1. Run `npm version <new version number> --no-git-tag-version` to update the package version, then push your changes to GitHub.
+2. Once the change is merged into `main`, create a release with the tag `v<new version number>`, such as `v1.5.2`. A GitHub action will automatically publish the new version of the package to npm.

+ 21 - 0
target_chains/ethereum/sdk/stylus/benches/Cargo.toml

@@ -0,0 +1,21 @@
+[package]
+name = "benches"
+edition.workspace = true
+license.workspace = true
+repository.workspace = true
+publish = false
+version.workspace = true
+
+[dependencies]
+pyth-stylus.workspace = true
+alloy-sol-types.workspace = true
+alloy-primitives = { workspace = true, features = ["tiny-keccak"] }
+alloy.workspace = true
+tokio.workspace = true
+futures.workspace = true
+stylus-sdk.workspace = true
+eyre.workspace = true
+koba.workspace = true
+e2e.workspace = true
+keccak-const.workspace = true
+serde = "1.0.203"

+ 106 - 0
target_chains/ethereum/sdk/stylus/benches/src/extend_pyth_example.rs

@@ -0,0 +1,106 @@
+use std::str::FromStr;
+
+use alloy::{
+    network::{AnyNetwork, EthereumWallet},
+    primitives::{uint, Address, FixedBytes as TypeFixedBytes},
+    providers::ProviderBuilder,
+    sol,
+    sol_types::{SolCall, SolConstructor},
+};
+use e2e::{env, receipt, Account};
+use pyth_stylus::pyth::mock::create_price_feed_update_data_list;
+
+use crate::{
+    report::{ContractReport, FunctionReport},
+    CacheOpt,
+};
+
+sol!(
+    #[sol(rpc)]
+    contract ExtendPyth{
+     function getPriceUnsafe(bytes32 id) external returns (uint8[] price);
+     function getEmaPriceUnsafe(bytes32 id) external returns (uint8[] price);
+     function getPriceNoOlderThan(bytes32 id, uint age) external returns (uint8[] price);
+     function getEmaPriceNoOlderThan(bytes32 id, uint age) external returns (uint8[] price);
+     function getUpdateFee(bytes[] calldata updateData) external returns (uint256 fee);
+     function getValidTimePeriod() external returns (uint256 period);
+     function updatePriceFeeds(bytes[] calldata updateData) external payable;
+     function updatePriceFeedsIfNecessary(bytes[] calldata updateData, bytes32[] calldata priceIds, uint64[] calldata publishTimes) external payable;
+
+      function getData() external returns (uint[] calldata data);
+    }
+);
+
+sol!("../examples/extend-pyth-example/src/constructor.sol");
+
+pub async fn bench() -> eyre::Result<ContractReport> {
+    let reports = run_with(CacheOpt::None).await?;
+    let report = reports
+        .into_iter()
+        .try_fold(ContractReport::new("ExtendPyth"), ContractReport::add)?;
+
+    let cached_reports = run_with(CacheOpt::Bid(0)).await?;
+    let report = cached_reports
+        .into_iter()
+        .try_fold(report, ContractReport::add_cached)?;
+
+    Ok(report)
+}
+
+pub async fn run_with(cache_opt: CacheOpt) -> eyre::Result<Vec<FunctionReport>> {
+    let alice = Account::new().await?;
+    let alice_wallet = ProviderBuilder::new()
+        .network::<AnyNetwork>()
+        .with_recommended_fillers()
+        .wallet(EthereumWallet::from(alice.signer.clone()))
+        .on_http(alice.url().parse()?);
+
+    let contract_addr = deploy(&alice, cache_opt).await?;
+
+    let contract = ExtendPyth::new(contract_addr, &alice_wallet);
+    let id = keccak_const::Keccak256::new()
+        .update(b"ETH")
+        .finalize()
+        .to_vec();
+    let id = TypeFixedBytes::<32>::from_slice(&id);
+    let time_frame = uint!(10000_U256);
+    let age = uint!(10000_U256);
+
+    let (data, _ids) = create_price_feed_update_data_list();
+
+    let _ = receipt!(contract.getPriceUnsafe(id))?;
+    let _ = receipt!(contract.getEmaPriceUnsafe(id))?;
+    let _ = receipt!(contract.getPriceNoOlderThan(id, age))?;
+    let _ = receipt!(contract.getEmaPriceNoOlderThan(id, age))?;
+    let _ = receipt!(contract.getValidTimePeriod())?;
+    let _ = receipt!(contract.getUpdateFee(data.clone()))?;
+    let _ = receipt!(contract.updatePriceFeeds(data.clone()))?;
+
+    // IMPORTANT: Order matters!
+    use ExtendPyth::*;
+    #[rustfmt::skip]
+    let receipts = vec![
+        (getPriceUnsafeCall::SIGNATURE, receipt!(contract.getPriceUnsafe(id))?),
+        (getEmaPriceUnsafeCall::SIGNATURE, receipt!(contract.getEmaPriceUnsafe(id))?),
+        (getPriceNoOlderThanCall::SIGNATURE, receipt!(contract.getPriceNoOlderThan(id, time_frame))?),
+        (getEmaPriceNoOlderThanCall::SIGNATURE, receipt!(contract.getEmaPriceNoOlderThan(id, time_frame))?),
+        (getValidTimePeriodCall::SIGNATURE, receipt!(contract.getValidTimePeriod())?),
+        (getUpdateFeeCall::SIGNATURE, receipt!(contract.getUpdateFee(data.clone()))?),
+    ];
+
+    receipts
+        .into_iter()
+        .map(FunctionReport::new)
+        .collect::<eyre::Result<Vec<_>>>()
+}
+
+async fn deploy(account: &Account, cache_opt: CacheOpt) -> eyre::Result<Address> {
+    let pyth_addr = env("MOCK_PYTH_ADDRESS")?;
+    println!("Pyth address: {}", pyth_addr);
+    let address = Address::from_str(&pyth_addr)?;
+    let args = ExtendPythExample::constructorCall {
+        _pythAddress: address,
+    };
+    let args = alloy::hex::encode(args.abi_encode());
+    crate::deploy(account, "extend-pyth", Some(args), cache_opt).await
+}

+ 106 - 0
target_chains/ethereum/sdk/stylus/benches/src/lib.rs

@@ -0,0 +1,106 @@
+use std::process::Command;
+
+use alloy::{
+    primitives::Address,
+    rpc::types::{serde_helpers::WithOtherFields, AnyReceiptEnvelope, Log, TransactionReceipt},
+};
+use alloy_primitives::U128;
+use e2e::{Account, ReceiptExt};
+use eyre::WrapErr;
+use koba::config::{Deploy, Generate, PrivateKey};
+use serde::Deserialize;
+
+pub mod extend_pyth_example;
+pub mod report;
+
+#[derive(Debug, Deserialize)]
+struct ArbOtherFields {
+    #[serde(rename = "gasUsedForL1")]
+    gas_used_for_l1: U128,
+    #[allow(dead_code)]
+    #[serde(rename = "l1BlockNumber")]
+    l1_block_number: String,
+}
+
+/// Cache options for the contract.
+/// `Bid(0)` will likely cache the contract on the nitro test node.
+pub enum CacheOpt {
+    None,
+    Bid(u32),
+}
+
+type ArbTxReceipt = WithOtherFields<TransactionReceipt<AnyReceiptEnvelope<Log>>>;
+
+async fn deploy(
+    account: &Account,
+    contract_name: &str,
+    args: Option<String>,
+    cache_opt: CacheOpt,
+) -> eyre::Result<Address> {
+    let manifest_dir = std::env::current_dir().context("should get current dir from env")?;
+
+    let wasm_path = manifest_dir
+        .join("target")
+        .join("wasm32-unknown-unknown")
+        .join("release")
+        .join(format!("{}_example.wasm", contract_name.replace('-', "_")));
+    let sol_path = args.as_ref().map(|_| {
+        manifest_dir
+            .join("examples")
+            .join(format!("{}-example", contract_name))
+            .join("src")
+            .join("constructor.sol")
+    });
+    let pk = account.pk();
+    let config = Deploy {
+        generate_config: Generate {
+            wasm: wasm_path.clone(),
+            sol: sol_path,
+            args,
+            legacy: false,
+        },
+        auth: PrivateKey {
+            private_key_path: None,
+            private_key: Some(pk),
+            keystore_path: None,
+            keystore_password_path: None,
+        },
+        endpoint: env("RPC_URL")?,
+        deploy_only: false,
+        quiet: true,
+    };
+
+    let address = koba::deploy(&config)
+        .await
+        .expect("should deploy contract")
+        .address()?;
+
+    if let CacheOpt::Bid(bid) = cache_opt {
+        cache_contract(account, address, bid)?;
+    }
+
+    Ok(address)
+}
+
+/// Try to cache a contract on the stylus network.
+/// Already cached contracts won't be cached, and this function will not return
+/// an error.
+/// Output will be forwarded to the child process.
+fn cache_contract(account: &Account, contract_addr: Address, bid: u32) -> eyre::Result<()> {
+    // We don't need a status code.
+    // Since it is not zero when the contract is already cached.
+    let _ = Command::new("cargo")
+        .args(["stylus", "cache", "bid"])
+        .args(["-e", &env("RPC_URL")?])
+        .args(["--private-key", &format!("0x{}", account.pk())])
+        .arg(contract_addr.to_string())
+        .arg(bid.to_string())
+        .status()
+        .context("failed to execute `cargo stylus cache bid` command")?;
+    Ok(())
+}
+
+/// Load the `name` environment variable.
+fn env(name: &str) -> eyre::Result<String> {
+    std::env::var(name).wrap_err(format!("failed to load {name}"))
+}

+ 15 - 0
target_chains/ethereum/sdk/stylus/benches/src/main.rs

@@ -0,0 +1,15 @@
+use benches::{extend_pyth_example, report::BenchmarkReport};
+use futures::FutureExt;
+
+#[tokio::main]
+async fn main() -> eyre::Result<()> {
+    let report = futures::future::try_join_all([extend_pyth_example::bench().boxed()])
+        .await?
+        .into_iter()
+        .fold(BenchmarkReport::default(), BenchmarkReport::merge_with);
+
+    println!();
+    println!("{report}");
+
+    Ok(())
+}

+ 150 - 0
target_chains/ethereum/sdk/stylus/benches/src/report.rs

@@ -0,0 +1,150 @@
+use std::{collections::HashMap, fmt::Display};
+
+use crate::{ArbOtherFields, ArbTxReceipt};
+
+const SEPARATOR: &str = "::";
+
+#[derive(Debug)]
+pub struct FunctionReport {
+    sig: String,
+    gas: u128,
+}
+
+impl FunctionReport {
+    pub(crate) fn new(receipt: (&str, ArbTxReceipt)) -> eyre::Result<Self> {
+        Ok(FunctionReport {
+            sig: receipt.0.to_owned(),
+            gas: get_l2_gas_used(&receipt.1)?,
+        })
+    }
+}
+
+#[derive(Debug)]
+pub struct ContractReport {
+    contract: String,
+    functions: Vec<FunctionReport>,
+    functions_cached: Vec<FunctionReport>,
+}
+
+impl ContractReport {
+    pub fn new(contract: &str) -> Self {
+        ContractReport {
+            contract: contract.to_owned(),
+            functions: vec![],
+            functions_cached: vec![],
+        }
+    }
+
+    pub fn add(mut self, fn_report: FunctionReport) -> eyre::Result<Self> {
+        self.functions.push(fn_report);
+        Ok(self)
+    }
+
+    pub fn add_cached(mut self, fn_report: FunctionReport) -> eyre::Result<Self> {
+        self.functions_cached.push(fn_report);
+        Ok(self)
+    }
+
+    fn signature_max_len(&self) -> usize {
+        let prefix_len = self.contract.len() + SEPARATOR.len();
+        self.functions
+            .iter()
+            .map(|FunctionReport { sig: name, .. }| prefix_len + name.len())
+            .max()
+            .unwrap_or_default()
+    }
+
+    fn gas_max_len(&self) -> usize {
+        self.functions
+            .iter()
+            .map(|FunctionReport { gas, .. }| gas.to_string().len())
+            .max()
+            .unwrap_or_default()
+    }
+
+    fn gas_cached_max_len(&self) -> usize {
+        self.functions_cached
+            .iter()
+            .map(|FunctionReport { gas, .. }| gas.to_string().len())
+            .max()
+            .unwrap_or_default()
+    }
+}
+
+#[derive(Debug, Default)]
+pub struct BenchmarkReport(Vec<ContractReport>);
+
+impl BenchmarkReport {
+    pub fn merge_with(mut self, report: ContractReport) -> Self {
+        self.0.push(report);
+        self
+    }
+
+    pub fn column_width(
+        &self,
+        column_value: impl FnMut(&ContractReport) -> usize,
+        header: &str,
+    ) -> usize {
+        self.0
+            .iter()
+            .map(column_value)
+            .chain(std::iter::once(header.len()))
+            .max()
+            .unwrap_or_default()
+    }
+}
+
+impl Display for BenchmarkReport {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        const HEADER_SIG: &str = "Contract::function";
+        const HEADER_GAS_CACHED: &str = "Cached";
+        const HEADER_GAS: &str = "Not Cached";
+
+        // Calculating the width of table columns.
+        let width1 = self.column_width(ContractReport::signature_max_len, HEADER_SIG);
+        let width2 = self.column_width(ContractReport::gas_cached_max_len, HEADER_GAS_CACHED);
+        let width3 = self.column_width(ContractReport::gas_max_len, HEADER_GAS);
+
+        // Print headers for the table columns.
+        writeln!(
+            f,
+            "| {HEADER_SIG:<width1$} | {HEADER_GAS_CACHED:>width2$} | {HEADER_GAS:>width3$} |"
+        )?;
+        writeln!(
+            f,
+            "| {:->width1$} | {:->width2$} | {:->width3$} |",
+            "", "", ""
+        )?;
+
+        // Merging a non-cached gas report with a cached one.
+        for report in &self.0 {
+            let prefix = format!("{}{SEPARATOR}", report.contract);
+            let gas: HashMap<_, _> = report
+                .functions
+                .iter()
+                .map(|func| (&*func.sig, func.gas))
+                .collect();
+
+            for report_cached in &report.functions_cached {
+                let sig = &*report_cached.sig;
+                let gas_cached = &report_cached.gas;
+                let gas = gas[sig];
+
+                let full_sig = format!("{prefix}{sig}");
+                writeln!(
+                    f,
+                    "| {full_sig:<width1$} | {gas_cached:>width2$} | {gas:>width3$} |"
+                )?;
+            }
+        }
+
+        Ok(())
+    }
+}
+
+fn get_l2_gas_used(receipt: &ArbTxReceipt) -> eyre::Result<u128> {
+    let l2_gas = receipt.gas_used;
+    let arb_fields: ArbOtherFields = receipt.other.deserialize_as()?;
+    let l1_gas = arb_fields.gas_used_for_l1.to::<u128>();
+    Ok(l2_gas - l1_gas)
+}

+ 33 - 0
target_chains/ethereum/sdk/stylus/contracts/Cargo.toml

@@ -0,0 +1,33 @@
+[package]
+name = "pyth-stylus"
+authors.workspace = true
+license.workspace = true
+repository.workspace = true
+version.workspace = true
+edition.workspace = true
+
+[dependencies]
+alloy-primitives.workspace = true
+alloy-sol-types.workspace = true
+alloy-sol-macro.workspace = true
+alloy-sol-macro-expander.workspace = true
+alloy-sol-macro-input.workspace = true
+stylus-sdk.workspace = true
+mini-alloc.workspace = true
+keccak-const.workspace = true
+
+[dev-dependencies]
+motsu.workspace = true
+alloy-primitives = { workspace = true, features = ["arbitrary"] }
+
+[features]
+# Enables using the standard library. This is not included in the default
+# features, because this crate is meant to be used in a `no_std` environment.
+# Currently, the std feature is only used for testing purposes.
+std = []
+
+[lib]
+crate-type = ["lib", "cdylib"]
+
+[lints]
+workspace = true

+ 23 - 0
target_chains/ethereum/sdk/stylus/contracts/src/lib.rs

@@ -0,0 +1,23 @@
+#![allow(missing_docs)]
+#![allow(clippy::pub_underscore_fields, clippy::module_name_repetitions)]
+#![cfg_attr(not(feature = "std"), no_std, no_main)]
+#![deny(rustdoc::broken_intra_doc_links)]
+#![allow(clippy::let_unit_value)]
+extern crate alloc;
+
+#[global_allocator]
+static ALLOC: mini_alloc::MiniAlloc = mini_alloc::MiniAlloc::INIT;
+
+/// Utility functions for interacting with the Pyth oracle.
+/// This module contains functions for interacting with the Pyth oracle.
+pub mod utils;
+
+/// Pyth contract for interacting with the Pyth oracle.
+/// This module contains the types and functions for interacting with the Pyth oracle.
+pub mod pyth;
+
+#[cfg(target_arch = "wasm32")]
+#[panic_handler]
+fn panic(_info: &core::panic::PanicInfo) -> ! {
+    loop {}
+}

+ 120 - 0
target_chains/ethereum/sdk/stylus/contracts/src/pyth/errors.rs

@@ -0,0 +1,120 @@
+use alloy_sol_types::sol;
+use stylus_sdk::{call::MethodError, prelude::*};
+
+sol! {
+    // Function arguments are invalid (e.g., the arguments lengths mismatch)
+    // Signature: 0xa9cb9e0d
+    #[derive(Debug)]
+    #[allow(missing_docs)]
+    error InvalidArgument();
+
+    // Update data is coming from an invalid data source.
+    // Signature: 0xe60dce71
+    #[derive(Debug)]
+    #[allow(missing_docs)]
+    error InvalidUpdateDataSource();
+
+    // Update data is invalid (e.g., deserialization error)
+    // Signature: 0xe69ffece
+    #[derive(Debug)]
+    #[allow(missing_docs)]
+    error InvalidUpdateData();
+
+    // Insufficient fee is paid to the method.
+    // Signature: 0x025dbdd4
+    #[derive(Debug)]
+    #[allow(missing_docs)]
+    error InsufficientFee();
+
+    // There is no fresh update, whereas expected fresh updates.
+    // Signature: 0xde2c57fa
+    #[derive(Debug)]
+    #[allow(missing_docs)]
+    error NoFreshUpdate();
+
+    // There is no price feed found within the given range or it does not exists.
+    // Signature: 0x45805f5d
+    #[derive(Debug)]
+    #[allow(missing_docs)]
+    error PriceFeedNotFoundWithinRange();
+
+    // Price feed not found or it is not pushed on-chain yet.
+    // Signature: 0x14aebe68
+    #[derive(Debug)]
+    #[allow(missing_docs)]
+    error PriceFeedNotFound();
+
+    // Requested price is stale.
+    // Signature: 0x19abf40e
+    #[derive(Debug)]
+    #[allow(missing_docs)]
+    error StalePrice();
+
+    // Given message is not a valid Wormhole VAA.
+    // Signature: 0x2acbe915
+    #[derive(Debug)]
+    #[allow(missing_docs)]
+    error InvalidWormholeVaa();
+
+    // Governance message is invalid (e.g., deserialization error).
+    // Signature: 0x97363b35
+    #[derive(Debug)]
+    #[allow(missing_docs)]
+    error InvalidGovernanceMessage();
+
+    // Governance message is not for this contract.
+    // Signature: 0x63daeb77
+    #[derive(Debug)]
+    #[allow(missing_docs)]
+    error InvalidGovernanceTarget();
+
+    // Governance message is coming from an invalid data source.
+    // Signature: 0x360f2d87
+    #[derive(Debug)]
+    #[allow(missing_docs)]
+    error InvalidGovernanceDataSource();
+
+    // Governance message is old.
+    // Signature: 0x88d1b847
+    #[derive(Debug)]
+    #[allow(missing_docs)]
+    error OldGovernanceMessage();
+
+    // The wormhole address to set in SetWormholeAddress governance is invalid.
+    // Signature: 0x13d3ed82
+    #[derive(Debug)]
+    #[allow(missing_docs)]
+    error InvalidWormholeAddressToSet();
+
+    #[derive(Debug)]
+    #[allow(missing_docs)]
+    error FalledDecodeData();
+
+
+}
+
+/// A Pausable error.
+#[derive(SolidityError, Debug)]
+pub enum Error {
+    InvalidArgument(InvalidArgument),
+    InvalidUpdateDataSource(InvalidUpdateDataSource),
+    InvalidUpdateData(InvalidUpdateData),
+    InsufficientFee(InsufficientFee),
+    NoFreshUpdate(NoFreshUpdate),
+    PriceFeedNotFoundWithinRange(PriceFeedNotFoundWithinRange),
+    PriceFeedNotFound(PriceFeedNotFound),
+    StalePrice(StalePrice),
+    InvalidWormholeVaa(InvalidWormholeVaa),
+    InvalidGovernanceMessage(InvalidGovernanceMessage),
+    InvalidGovernanceTarget(InvalidGovernanceTarget),
+    InvalidGovernanceDataSource(InvalidGovernanceDataSource),
+    OldGovernanceMessage(OldGovernanceMessage),
+    InvalidWormholeAddressToSet(InvalidWormholeAddressToSet),
+    FalledDecodeData(FalledDecodeData),
+}
+
+impl MethodError for Error {
+    fn encode(self) -> alloc::vec::Vec<u8> {
+        self.into()
+    }
+}

+ 10 - 0
target_chains/ethereum/sdk/stylus/contracts/src/pyth/events.rs

@@ -0,0 +1,10 @@
+use alloy_sol_types::sol;
+
+sol! {
+  event PriceFeedUpdate(
+        bytes32 indexed id,
+        uint64 publishTime,
+        int64 price,
+        uint64 conf
+    );
+}

+ 277 - 0
target_chains/ethereum/sdk/stylus/contracts/src/pyth/functions.rs

@@ -0,0 +1,277 @@
+#![allow(clippy::too_many_arguments)]
+use crate::pyth::mock::DecodeDataType;
+use crate::pyth::types::{
+    getEmaPriceNoOlderThanCall, getEmaPriceUnsafeCall, getPriceNoOlderThanCall, getPriceUnsafeCall,
+    getUpdateFeeCall, getValidTimePeriodCall, parsePriceFeedUpdatesCall,
+    parsePriceFeedUpdatesUniqueCall, updatePriceFeedsCall, updatePriceFeedsIfNecessaryCall, Price,
+    PriceFeed,
+};
+use crate::utils::{call_helper, delegate_call_helper};
+use alloc::vec::Vec;
+use alloy_primitives::{Address, Bytes, B256, U256};
+use alloy_sol_types::SolType;
+use stylus_sdk::storage::TopLevelStorage;
+
+/// Retrieves the price for a given asset ID from the Pyth price feed, ensuring the price is not older than a specified age.
+///
+/// # Parameters
+/// - `storage`: A mutable reference to an implementation of `TopLevelStorage`.
+/// - `pyth_address`: The address of the Pyth price feed contract.
+/// - `id`: The fixed byte identifier for the asset whose price is being retrieved.
+/// - `age`: The maximum allowed age of the price.
+///
+/// # Returns
+/// - `Result<Price, Vec<u8>>`: A `Result` that contains the `Price` struct if successful, or an error message as a byte vector.
+pub fn get_price_no_older_than(
+    storage: &mut impl TopLevelStorage,
+    pyth_address: Address,
+    id: B256,
+    age: U256,
+) -> Result<Price, Vec<u8>> {
+    let price_call = call_helper::<getPriceNoOlderThanCall>(storage, pyth_address, (id, age))?;
+    Ok(price_call.price)
+}
+
+/// Queries the contract for the fee required to update price data, given the update data as input.
+///
+/// # Parameters
+/// - `storage`: A mutable reference to an implementation of `TopLevelStorage`.
+/// - `pyth_address`: The address of the Pyth price feed contract.
+/// - `update_data`: A vector of bytes containing the data required for the update.
+///
+/// # Returns
+/// - `Result<U256, Vec<u8>>`: A `Result` containing the update fee as a `U256` if successful, or an error message as a byte vector.
+pub fn get_update_fee(
+    storage: &mut impl TopLevelStorage,
+    pyth_address: Address,
+    update_data: Vec<Bytes>,
+) -> Result<U256, Vec<u8>> {
+    let update_fee_call = call_helper::<getUpdateFeeCall>(storage, pyth_address, (update_data,))?;
+    Ok(update_fee_call.feeAmount)
+}
+
+/// Retrieves the Exponential Moving Average (EMA) price for a specific asset ID without safety checks.
+///
+/// # Parameters
+/// - `storage`: A mutable reference to an implementation of `TopLevelStorage`.
+/// - `pyth_address`: The address of the Pyth price feed contract.
+/// - `id`: The fixed byte identifier for the asset whose EMA price is being retrieved.
+///
+/// # Returns
+/// - `Result<Price, Vec<u8>>`: A `Result` containing the `Price` struct if successful, or an error message as a byte vector.
+pub fn get_ema_price_unsafe(
+    storage: &mut impl TopLevelStorage,
+    pyth_address: Address,
+    id: B256,
+) -> Result<Price, Vec<u8>> {
+    let ema_price = call_helper::<getEmaPriceUnsafeCall>(storage, pyth_address, (id,))?;
+    Ok(ema_price.price)
+}
+
+/// Similar to `get_ema_price_unsafe`, but ensures the EMA price is not older than a specified age.
+///
+/// # Parameters
+/// - `storage`: A mutable reference to an implementation of `TopLevelStorage`.
+/// - `pyth_address`: The address of the Pyth price feed contract.
+/// - `id`: The fixed byte identifier for the asset whose EMA price is being retrieved.
+/// - `age`: The maximum allowed age of the EMA price.
+///
+/// # Returns
+/// - `Result<Price, Vec<u8>>`: A `Result` containing the `Price` struct if successful, or an error message as a byte vector.
+pub fn get_ema_price_no_older_than(
+    storage: &mut impl TopLevelStorage,
+    pyth_address: Address,
+    id: B256,
+    age: U256,
+) -> Result<Price, Vec<u8>> {
+    let ema_price = call_helper::<getEmaPriceNoOlderThanCall>(storage, pyth_address, (id, age))?;
+    Ok(ema_price.price)
+}
+
+/// Retrieves the current price for a given asset ID without safety checks, constructing a `Price` struct from raw values.
+///
+/// # Parameters
+/// - `storage`: A mutable reference to an implementation of `TopLevelStorage`.
+/// - `pyth_address`: The address of the Pyth price feed contract.
+/// - `id`: The fixed byte identifier for the asset whose price is being retrieved.
+///
+/// # Returns
+/// - `Result<Price, Vec<u8>>`: A `Result` containing the constructed `Price` struct if successful, or an error message as a byte vector.
+pub fn get_price_unsafe(
+    storage: &mut impl TopLevelStorage,
+    pyth_address: Address,
+    id: B256,
+) -> Result<Price, Vec<u8>> {
+    let price = call_helper::<getPriceUnsafeCall>(storage, pyth_address, (id,))?;
+    let price = Price {
+        price: price._0,
+        conf: price._1,
+        expo: price._2,
+        publish_time: price._3,
+    };
+    Ok(price)
+}
+
+/// Queries the Pyth contract to get the valid time period for price feeds.
+///
+/// # Parameters
+/// - `storage`: A mutable reference to an implementation of `TopLevelStorage`.
+/// - `pyth_address`: The address of the Pyth price feed contract.
+///
+/// # Returns
+/// - `Result<U256, Vec<u8>>`: A `Result` containing the valid time period as a `U256` if successful, or an error message as a byte vector.
+pub fn get_valid_time_period(
+    storage: &mut impl TopLevelStorage,
+    pyth_address: Address,
+) -> Result<U256, Vec<u8>> {
+    let valid_time_period = call_helper::<getValidTimePeriodCall>(storage, pyth_address, ())?;
+    Ok(valid_time_period.validTimePeriod)
+}
+
+/// Updates the price feeds in the Pyth contract using the provided update data.
+///
+/// # Parameters
+/// - `storage`: A mutable reference to an implementation of `TopLevelStorage`.
+/// - `pyth_address`: The address of the Pyth price feed contract.
+/// - `update_data`: A vector of bytes containing the data required for the update.
+///
+/// # Returns
+/// - `Result<(), Vec<u8>>`: A `Result` that indicates success or failure, returning an error message as a byte vector if unsuccessful.
+pub fn update_price_feeds(
+    storage: &mut impl TopLevelStorage,
+    pyth_address: Address,
+    update_data: Vec<Bytes>,
+) -> Result<(), Vec<u8>> {
+    delegate_call_helper::<updatePriceFeedsCall>(storage, pyth_address, (update_data,))?;
+    Ok(())
+}
+
+/// Updates price feeds only if necessary, based on provided price IDs and publish times.
+///
+/// # Parameters
+/// - `storage`: A mutable reference to an implementation of `TopLevelStorage`.
+/// - `pyth_address`: The address of the Pyth price feed contract.
+/// - `update_data`: A vector of bytes containing the data required for the update.
+/// - `price_ids`: A vector of fixed byte identifiers for the assets to update.
+/// - `publish_times`: A vector of timestamps indicating when the prices were published.
+///
+/// # Returns
+/// - `Result<(), Vec<u8>>`: A `Result` that indicates success or failure, returning an error message as a byte vector if unsuccessful.
+pub fn update_price_feeds_if_necessary(
+    storage: &mut impl TopLevelStorage,
+    pyth_address: Address,
+    update_data: Vec<Bytes>,
+    price_ids: Vec<B256>,
+    publish_times: Vec<u64>,
+) -> Result<(), Vec<u8>> {
+    delegate_call_helper::<updatePriceFeedsIfNecessaryCall>(
+        storage,
+        pyth_address,
+        (update_data, price_ids, publish_times),
+    )?;
+    Ok(())
+}
+
+/// Parses the updates to price feeds, returning a vector of `PriceFeed` structs based on the provided time range.
+///
+/// # Parameters
+/// - `storage`: A mutable reference to an implementation of `TopLevelStorage`.
+/// - `pyth_address`: The address of the Pyth price feed contract.
+/// - `update_data`: A vector of bytes containing the data required for the updates.
+/// - `price_ids`: A vector of fixed byte identifiers for the assets being updated.
+/// - `min_publish_time`: The minimum publish time to consider for the updates.
+/// - `max_publish_time`: The maximum publish time to consider for the updates.
+///
+/// # Returns
+/// - `Result<Vec<PriceFeed>, Vec<u8>>`: A `Result` containing a vector of `PriceFeed` structs if successful, or an error message as a byte vector.
+pub fn parse_price_feed_updates(
+    storage: &mut impl TopLevelStorage,
+    pyth_address: Address,
+    update_data: Vec<Bytes>,
+    price_ids: Vec<B256>,
+    min_publish_time: u64,
+    max_publish_time: u64,
+) -> Result<Vec<PriceFeed>, Vec<u8>> {
+    let parse_price_feed_updates_call = delegate_call_helper::<parsePriceFeedUpdatesCall>(
+        storage,
+        pyth_address,
+        (update_data, price_ids, min_publish_time, max_publish_time),
+    )?;
+    Ok(parse_price_feed_updates_call.priceFeeds)
+}
+
+/// Similar to `parse_price_feed_updates`, but only returns the latest price feed for each asset if multiple updates are available.
+///
+/// # Parameters
+/// - `storage`: A mutable reference to an implementation of `TopLevelStorage`.
+/// - `pyth_address`: The address of the Pyth price feed contract.
+/// - `update_data`: A vector of bytes containing the data required for the updates.
+/// - `price_ids`: A vector of fixed byte identifiers for the assets being updated.
+/// - `min_publish_time`: The minimum publish time to consider for the updates.
+/// - `max_publish_time`: The maximum publish time to consider for the updates.
+///
+/// # Returns
+/// - `Result<Vec<PriceFeed>, Vec<u8>>`: A `Result` containing a vector of `PriceFeed` structs if successful, or an error message as a byte vector.
+pub fn parse_price_feed_updates_unique(
+    storage: &mut impl TopLevelStorage,
+    pyth_address: Address,
+    update_data: Vec<Bytes>,
+    price_ids: Vec<B256>,
+    min_publish_time: u64,
+    max_publish_time: u64,
+) -> Result<Vec<PriceFeed>, Vec<u8>> {
+    let parse_price_feed_updates_call = delegate_call_helper::<parsePriceFeedUpdatesUniqueCall>(
+        storage,
+        pyth_address,
+        (update_data, price_ids, min_publish_time, max_publish_time),
+    )?;
+    Ok(parse_price_feed_updates_call.priceFeeds)
+}
+
+/// Creates the update data required for a price feed, encapsulating the current price, confidence interval,
+/// exponential moving average (EMA) price, and other relevant details.
+///
+/// # Parameters
+/// - `id`: The fixed byte identifier for the asset being updated.
+/// - `price`: The current price of the asset as a 64-bit signed integer.
+/// - `conf`: The confidence level of the current price as a 64-bit unsigned integer.
+/// - `expo`: The exponent for the price, indicating its precision.
+/// - `ema_price`: The Exponential Moving Average price of the asset as a 64-bit signed integer.
+/// - `ema_conf`: The confidence level of the EMA price as a 64-bit unsigned integer.
+/// - `publish_time`: The time the price was published, represented as a `U256`.
+/// - `prev_publish_time`: The previous publish time of the price, represented as a 64-bit unsigned integer.
+///
+/// # Returns
+/// - `Vec<u8>`: A byte vector containing the encoded update data for the price feed.
+pub fn create_price_feed_update_data(
+    id: B256,
+    price: i64,
+    conf: u64,
+    expo: i32,
+    ema_price: i64,
+    ema_conf: u64,
+    publish_time: U256,
+    prev_publish_time: u64,
+) -> Vec<u8> {
+    let price = Price {
+        price,
+        conf,
+        expo,
+        publish_time,
+    };
+    let ema_price = Price {
+        price: ema_price,
+        conf: ema_conf,
+        expo,
+        publish_time,
+    };
+
+    let price_feed_data = PriceFeed {
+        id,
+        price,
+        ema_price,
+    };
+
+    let price_feed_data_encoding = (price_feed_data, prev_publish_time);
+    DecodeDataType::abi_encode(&price_feed_data_encoding)
+}

+ 383 - 0
target_chains/ethereum/sdk/stylus/contracts/src/pyth/mock.rs

@@ -0,0 +1,383 @@
+#![allow(clippy::clone_on_copy)]
+#![allow(clippy::too_many_arguments)]
+use crate::pyth::errors::{Error, PriceFeedNotFound};
+use crate::pyth::events::PriceFeedUpdate;
+use crate::pyth::functions::create_price_feed_update_data;
+use crate::pyth::types::{Price, PriceFeed, StoragePriceFeed};
+use crate::{
+    pyth::errors::{FalledDecodeData, InsufficientFee, InvalidArgument},
+    utils::CALL_RETDATA_DECODING_ERROR_MESSAGE,
+};
+use alloc::vec::Vec;
+use alloy_primitives::{Bytes, B256, U256};
+use alloy_sol_types::{sol_data::Uint as SolUInt, SolType, SolValue};
+use stylus_sdk::storage::{StorageMap, StorageUint};
+use stylus_sdk::{
+    abi::Bytes as AbiBytes,
+    evm, msg,
+    prelude::{public, storage},
+};
+
+/// Decode data type PriceFeed and uint64
+pub type DecodeDataType = (PriceFeed, SolUInt<64>);
+
+#[storage]
+pub struct MockPythContract {
+    single_update_fee_in_wei: StorageUint<256, 4>,
+    valid_time_period: StorageUint<256, 4>,
+    price_feeds: StorageMap<B256, StoragePriceFeed>,
+}
+
+#[public]
+impl MockPythContract {
+    fn initialize(
+        &mut self,
+        single_update_fee_in_wei: U256,
+        valid_time_period: U256,
+    ) -> Result<(), Vec<u8>> {
+        if single_update_fee_in_wei <= U256::ZERO || valid_time_period <= U256::ZERO {
+            return Err(Error::InvalidArgument(InvalidArgument {}).into());
+        }
+        self.single_update_fee_in_wei.set(single_update_fee_in_wei);
+        self.valid_time_period.set(valid_time_period);
+        Ok(())
+    }
+
+    fn query_price_feed(&self, id: B256) -> Result<Vec<u8>, Vec<u8>> {
+        let price_feed = self.price_feeds.get(id).to_price_feed();
+        if price_feed.id.is_zero() {
+            return Err(Error::PriceFeedNotFound(PriceFeedNotFound {}).into());
+        }
+        Ok(price_feed.abi_encode())
+    }
+
+    fn price_feed_exists(&self, id: B256) -> bool {
+        self.price_feeds.getter(id).id.is_empty()
+    }
+
+    fn get_valid_time_period(&self) -> U256 {
+        self.valid_time_period.get()
+    }
+
+    /// Takes an array of encoded price feeds and stores them.
+    /// You can create this data either by calling createPriceFeedUpdateData or
+    /// by using web3.js or ethers abi utilities.
+    /// @note: The updateData expected here is different from the one used in the main contract.
+    /// In particular, the expected format is:
+    /// [
+    ///     abi.encode(
+    ///         PythStructs.PriceFeed(
+    ///             bytes32 id,
+    ///             PythStructs.Price price,
+    ///             PythStructs.Price emaPrice
+    ///         ),
+    ///         uint64 prevPublishTime
+    ///     )
+    /// ]
+
+    #[payable]
+    fn update_price_feeds(&mut self, update_data: Vec<AbiBytes>) -> Result<(), Vec<u8>> {
+        let required_fee = self.get_update_fee(update_data.clone());
+        if required_fee < msg::value() {
+            return Err(Error::InsufficientFee(InsufficientFee {}).into());
+        }
+
+        for item in update_data.iter() {
+            let price_feed_data = <PriceFeed as SolType>::abi_decode(item, false)
+                .map_err(|_| CALL_RETDATA_DECODING_ERROR_MESSAGE.to_vec())?;
+            let last_publish_time = &self
+                .price_feeds
+                .get(price_feed_data.id)
+                .price
+                .publish_time
+                .get();
+            if last_publish_time < &price_feed_data.price.publish_time {
+                self.price_feeds
+                    .setter(price_feed_data.id)
+                    .set(price_feed_data);
+                evm::log(PriceFeedUpdate {
+                    id: price_feed_data.id,
+                    publishTime: price_feed_data.price.publish_time.to(),
+                    price: price_feed_data.price.price,
+                    conf: price_feed_data.price.conf,
+                });
+            }
+        }
+        Ok(())
+    }
+
+    fn get_update_fee(&self, update_data: Vec<AbiBytes>) -> U256 {
+        self.single_update_fee_in_wei.get() * U256::from(update_data.len())
+    }
+
+    #[payable]
+    fn parse_price_feed_updates(
+        &mut self,
+        update_data: Vec<AbiBytes>,
+        price_ids: Vec<B256>,
+        min_publish_time: u64,
+        max_publish_time: u64,
+    ) -> Result<Vec<u8>, Vec<u8>> {
+        self.parse_price_feed_updates_internal(
+            update_data,
+            price_ids,
+            min_publish_time,
+            max_publish_time,
+            false,
+        )
+    }
+
+    #[payable]
+    fn parse_price_feed_updates_unique(
+        &mut self,
+        update_data: Vec<AbiBytes>,
+        price_ids: Vec<B256>,
+        min_publish_time: u64,
+        max_publish_time: u64,
+    ) -> Result<Vec<u8>, Vec<u8>> {
+        self.parse_price_feed_updates_internal(
+            update_data,
+            price_ids,
+            min_publish_time,
+            max_publish_time,
+            true,
+        )
+    }
+
+    fn create_price_feed_update_data(
+        &self,
+        id: B256,
+        price: i64,
+        conf: u64,
+        expo: i32,
+        ema_price: i64,
+        ema_conf: u64,
+        publish_time: U256,
+        prev_publish_time: u64,
+    ) -> Vec<u8> {
+        let price = Price {
+            price,
+            conf,
+            expo,
+            publish_time,
+        };
+        let ema_price = Price {
+            price: ema_price,
+            conf: ema_conf,
+            expo,
+            publish_time,
+        };
+
+        let price_feed_data = PriceFeed {
+            id,
+            price,
+            ema_price,
+        };
+
+        let price_feed_data_encoding = (price_feed_data, prev_publish_time);
+        DecodeDataType::abi_encode(&price_feed_data_encoding)
+    }
+}
+
+impl MockPythContract {
+    fn parse_price_feed_updates_internal(
+        &mut self,
+        update_data: Vec<AbiBytes>,
+        price_ids: Vec<B256>,
+        min_publish_time: u64,
+        max_publish_time: u64,
+        unique: bool,
+    ) -> Result<Vec<u8>, Vec<u8>> {
+        let required_fee = self.get_update_fee(update_data.clone());
+        if required_fee > msg::value() {
+            return Err(Error::InsufficientFee(InsufficientFee {}).into());
+        }
+
+        let mut result_feeds = Vec::new();
+
+        for price_id in price_ids {
+            let mut matched_feed: Option<PriceFeed> = None;
+
+            for data in &update_data {
+                // Decode the update_data
+                let (price_feed, _prev_publish_time) = match DecodeDataType::abi_decode(data, false)
+                {
+                    Ok(res) => res,
+                    Err(_) => {
+                        return Err(Error::FalledDecodeData(FalledDecodeData {}).into());
+                    }
+                };
+
+                if price_feed.id == price_id {
+                    let publish_time = price_feed.price.publish_time;
+                    let previous_publish_time =
+                        self.price_feeds.get(price_id).price.publish_time.get();
+
+                    // Validate publish time and uniqueness
+                    if publish_time > U256::from(min_publish_time)
+                        && publish_time <= U256::from(max_publish_time)
+                        && (!unique || previous_publish_time < U256::from(min_publish_time))
+                    {
+                        // Store the matched feed
+                        matched_feed = Some(price_feed.clone());
+
+                        // Update storage if the feed is newer
+                        if previous_publish_time < publish_time {
+                            self.price_feeds.setter(price_id).set(price_feed.clone());
+                            evm::log(PriceFeedUpdate {
+                                id: price_feed.id,
+                                publishTime: publish_time.to(),
+                                price: price_feed.price.price,
+                                conf: price_feed.price.conf,
+                            });
+                        }
+                        break;
+                    }
+                }
+            }
+
+            // Check if a matching feed was found for the price_id
+            if let Some(feed) = matched_feed {
+                result_feeds.push(feed);
+            } else {
+                return Err(Error::FalledDecodeData(FalledDecodeData {}).into());
+            }
+        }
+
+        Ok(result_feeds.abi_encode())
+    }
+}
+
+pub fn create_price_feed_update_data_list() -> (Vec<Bytes>, Vec<B256>) {
+    let id = ["ETH", "SOL", "BTC"].map(|x| {
+        let x = keccak_const::Keccak256::new()
+            .update(x.as_bytes())
+            .finalize()
+            .to_vec();
+        B256::from_slice(&x)
+    });
+    let mut price_feed_data_list = Vec::new();
+    for item in &id {
+        let price_feed_data = create_price_feed_update_data(
+            *item,
+            100,
+            100,
+            100,
+            100,
+            100,
+            U256::from(U256::MAX - U256::from(10)),
+            0,
+        );
+        let price_feed_data = Bytes::from(AbiBytes::from(price_feed_data).0);
+        price_feed_data_list.push(price_feed_data);
+    }
+    (price_feed_data_list, id.to_vec())
+}
+
+#[cfg(all(test, feature = "std"))]
+mod tests {
+    use crate::pyth::mock::{DecodeDataType, MockPythContract};
+    use alloc::vec;
+    use alloy_primitives::{B256, U256};
+    use alloy_sol_types::SolType;
+    use stylus_sdk::abi::Bytes;
+
+    /// Updated constants to use uppercase naming convention
+    const PRICE: i64 = 1000;
+    const CONF: u64 = 1000;
+    const EXPO: i32 = 1000;
+    const EMA_PRICE: i64 = 1000;
+    const EMA_CONF: u64 = 1000;
+    const PREV_PUBLISH_TIME: u64 = 1000;
+
+    fn generate_bytes() -> B256 {
+        B256::repeat_byte(30)
+    }
+
+    #[motsu::test]
+    fn can_initialize_mock_contract(contract: MockPythContract) {
+        let _ = contract.initialize(U256::from(1000), U256::from(1000));
+        assert_eq!(contract.single_update_fee_in_wei.get(), U256::from(1000));
+        assert_eq!(contract.valid_time_period.get(), U256::from(1000));
+    }
+
+    #[motsu::test]
+    fn error_initialize_mock_contract(contract: MockPythContract) {
+        let err = contract.initialize(U256::from(0), U256::from(0));
+        assert!(err.is_err())
+    }
+
+    #[motsu::test]
+    fn created_price_feed_data(contract: MockPythContract) {
+        let _ = contract.initialize(U256::from(1000), U256::from(1000));
+        let id = generate_bytes();
+        let publish_time = U256::from(1000);
+        let price_feed_created = contract.create_price_feed_update_data(
+            id,
+            PRICE,
+            CONF,
+            EXPO,
+            EMA_PRICE,
+            EMA_CONF,
+            publish_time,
+            PREV_PUBLISH_TIME,
+        );
+        let price_feed_decoded = DecodeDataType::abi_decode(&price_feed_created, true).unwrap();
+        assert_eq!(price_feed_decoded.0.id, id);
+        assert_eq!(price_feed_decoded.0.price.price, PRICE);
+        assert_eq!(price_feed_decoded.0.price.conf, CONF);
+        assert_eq!(price_feed_decoded.0.price.expo, EXPO);
+        assert_eq!(price_feed_decoded.0.ema_price.price, EMA_PRICE);
+        assert_eq!(price_feed_decoded.0.ema_price.conf, EMA_CONF);
+        assert_eq!(price_feed_decoded.1, PREV_PUBLISH_TIME);
+    }
+
+    #[motsu::test]
+    fn can_get_update_fee(contract: MockPythContract) {
+        let _ = contract.initialize(U256::from(1000), U256::from(1000));
+        let publish_time = U256::from(1000);
+        let mut update_data: Vec<Bytes> = vec![];
+        let mut x = 0;
+        while x < 10 {
+            let id = generate_bytes();
+            let price_feed_created = contract.create_price_feed_update_data(
+                id,
+                PRICE,
+                CONF,
+                EXPO,
+                EMA_PRICE,
+                EMA_CONF,
+                publish_time,
+                PREV_PUBLISH_TIME,
+            );
+            update_data.push(Bytes::from(price_feed_created));
+            x += 1;
+        }
+        let required_fee = contract.get_update_fee(update_data.clone());
+        assert_eq!(required_fee, U256::from(1000 * x));
+    }
+
+    #[motsu::test]
+    fn price_feed_does_not_exist(contract: MockPythContract) {
+        let _ = contract.initialize(U256::from(1000), U256::from(1000));
+        let id = generate_bytes();
+        let price_feed_found = contract.price_feed_exists(id);
+        assert_eq!(price_feed_found, false);
+    }
+
+    #[motsu::test]
+    fn query_price_feed_failed(contract: MockPythContract) {
+        let _ = contract.initialize(U256::from(1000), U256::from(1000));
+        let id = generate_bytes();
+        let _price_feed = contract
+            .query_price_feed(id)
+            .expect_err("should not query if price feed does not exist");
+    }
+
+    #[motsu::test]
+    fn can_get_valid_time_period(contract: MockPythContract) {
+        let _ = contract.initialize(U256::from(1000), U256::from(1000));
+        let valid_time_period = contract.get_valid_time_period();
+        assert_eq!(valid_time_period, U256::from(1000));
+    }
+}

+ 13 - 0
target_chains/ethereum/sdk/stylus/contracts/src/pyth/mod.rs

@@ -0,0 +1,13 @@
+mod errors;
+mod events;
+/// Types and functions for interacting with the Pyth oracle.
+pub mod types;
+
+/// Mock module for testing
+pub mod mock;
+
+/// Functions for interacting with the Pyth oracle.
+pub mod functions;
+
+/// Contract for interacting with the Pyth oracle.
+pub mod pyth_contract;

+ 244 - 0
target_chains/ethereum/sdk/stylus/contracts/src/pyth/pyth_contract.rs

@@ -0,0 +1,244 @@
+pub use crate::pyth::functions::{
+    get_ema_price_no_older_than, get_ema_price_unsafe, get_price_no_older_than, get_price_unsafe,
+    get_update_fee, get_valid_time_period, parse_price_feed_updates,
+    parse_price_feed_updates_unique, update_price_feeds, update_price_feeds_if_necessary,
+};
+use alloc::vec::Vec;
+use alloy_primitives::{Bytes, B256, U256};
+use alloy_sol_types::SolValue;
+use stylus_sdk::{
+    abi::Bytes as AbiBytes,
+    prelude::*,
+    storage::{StorageAddress, TopLevelStorage},
+};
+/// `IPyth` is a trait that defines methods for interacting with the Pyth contract.
+pub trait IPyth {
+    /// The Error Type for the Pyth Contract.
+    /// - `Vec<u8>`: The error message in bytes.
+    type Error: Into<alloc::vec::Vec<u8>>;
+
+    /// Retrieves the latest price feed without any recency checks.
+    ///
+    /// # Parameters
+    /// - `id`: The unique identifier for the price feed.
+    ///
+    /// # Returns
+    /// - `Result<Vec<u8>, Self::Error>`: The price data in bytes, or an error.
+    fn get_price_unsafe(&mut self, id: B256) -> Result<Vec<u8>, Self::Error>;
+
+    /// Retrieves a price that is no older than a specified `age`.
+    ///
+    /// # Parameters
+    /// - `id`: The unique identifier for the price feed.
+    /// - `age`: The maximum acceptable age of the price in seconds.
+    ///
+    /// # Returns
+    /// - `Result<Vec<u8>, Self::Error>`: The price data in bytes, or an error.
+    fn get_price_no_older_than(&mut self, id: B256, age: U256) -> Result<Vec<u8>, Self::Error>;
+
+    /// Retrieves the exponentially-weighted moving average (EMA) price without recency checks.
+    ///
+    /// # Parameters
+    /// - `id`: The unique identifier for the price feed.
+    ///
+    /// # Returns
+    /// - `Result<Vec<u8>, Self::Error>`: The EMA price data in bytes, or an error.
+    fn get_ema_price_unsafe(&mut self, id: B256) -> Result<Vec<u8>, Self::Error>;
+
+    /// Retrieves an EMA price that is no older than the specified `age`.
+    ///
+    /// # Parameters
+    /// - `id`: The unique identifier for the price feed.
+    /// - `age`: The maximum acceptable age of the price in seconds.
+    ///
+    /// # Returns
+    /// - `Result<Vec<u8>, Self::Error>`: The EMA price data in bytes, or an error.
+    fn get_ema_price_no_older_than(&mut self, id: B256, age: U256) -> Result<Vec<u8>, Self::Error>;
+
+    /// Updates price feeds with the given data.
+    ///
+    /// # Parameters
+    /// - `update_data`: Array of price update data.
+    ///
+    /// # Returns
+    /// - `Result<(), Self::Error>`: Success or error.
+    fn update_price_feeds(&mut self, update_data: Vec<AbiBytes>) -> Result<(), Self::Error>;
+
+    /// Updates price feeds if necessary, based on given publish times.
+    ///
+    /// # Parameters
+    /// - `update_data`: Array of price update data.
+    /// - `price_ids`: Array of price IDs.
+    /// - `publish_times`: Array of publish times for the corresponding price IDs.
+    ///
+    /// # Returns
+    /// - `Result<(), Self::Error>`: Success or error.
+    fn update_price_feeds_if_necessary(
+        &mut self,
+        update_data: Vec<AbiBytes>,
+        price_ids: Vec<B256>,
+        publish_times: Vec<u64>,
+    ) -> Result<(), Self::Error>;
+
+    /// Returns the fee required to update the price feeds based on the provided data.
+    ///
+    /// # Parameters
+    /// - `update_data`: Array of price update data.
+    ///
+    /// # Returns
+    /// - `Result<U256, Self::Error>`: The required fee in Wei, or an error.
+    fn get_update_fee(&mut self, update_data: Vec<AbiBytes>) -> Result<U256, Self::Error>;
+
+    /// Returns the fee required to update the price feeds based on the provided data.
+    ///
+    /// # Parameters
+    /// - `update_data`: Array of price update data.
+    ///
+    /// # Returns
+    /// - `Result<U256, Self::Error>`: The required fee in Wei, or an error.
+    fn get_valid_time_period(&mut self) -> Result<U256, Self::Error>;
+
+    /// Parses the price feed updates for specific price IDs within a given time range.
+    ///
+    /// # Parameters
+    /// - `update_data`: Array of price update data.
+    /// - `price_ids`: Array of price IDs to parse.
+    /// - `min_publish_time`: Minimum acceptable publish time for the price IDs.
+    /// - `max_publish_time`: Maximum acceptable publish time for the price IDs.
+    ///
+    /// # Returns
+    /// - `Result<Vec<u8>, Self::Error>`: Parsed price feed data in bytes, or an error.
+    fn parse_price_feed_updates(
+        &mut self,
+        update_data: Vec<AbiBytes>,
+        price_ids: Vec<B256>,
+        min_publish_time: u64,
+        max_publish_time: u64,
+    ) -> Result<Vec<u8>, Self::Error>;
+
+    /// Parses price feed updates for specific price IDs, ensuring only the first updates within a time range are returned.
+    ///
+    /// # Parameters
+    /// - `update_data`: Array of price update data.
+    /// - `price_ids`: Array of price IDs to parse.
+    /// - `min_publish_time`: Minimum acceptable publish time for the price IDs.
+    /// - `max_publish_time`: Maximum acceptable publish time for the price IDs.
+    ///
+    /// # Returns
+    /// - `Result<Vec<u8>, Self::Error>`: Parsed price feed data in bytes, or an error.
+    fn parse_price_feed_updates_unique(
+        &mut self,
+        update_data: Vec<AbiBytes>,
+        price_ids: Vec<B256>,
+        min_publish_time: u64,
+        max_publish_time: u64,
+    ) -> Result<Vec<u8>, Self::Error>;
+}
+
+#[storage]
+pub struct PythContract {
+    pub _ipyth: StorageAddress,
+}
+
+unsafe impl TopLevelStorage for PythContract {}
+
+#[public]
+impl IPyth for PythContract {
+    type Error = Vec<u8>;
+
+    fn get_price_unsafe(&mut self, id: B256) -> Result<Vec<u8>, Self::Error> {
+        let price = get_price_unsafe(self, self._ipyth.get(), id)?;
+        let data = price.abi_encode();
+        Ok(data)
+    }
+
+    fn get_price_no_older_than(&mut self, id: B256, age: U256) -> Result<Vec<u8>, Self::Error> {
+        let price = get_price_no_older_than(self, self._ipyth.get(), id, age)?;
+        let data = price.abi_encode();
+        Ok(data)
+    }
+
+    fn get_ema_price_unsafe(&mut self, id: B256) -> Result<Vec<u8>, Self::Error> {
+        let price = get_ema_price_unsafe(self, self._ipyth.get(), id)?;
+        let data = price.abi_encode();
+        Ok(data)
+    }
+
+    fn get_ema_price_no_older_than(&mut self, id: B256, age: U256) -> Result<Vec<u8>, Self::Error> {
+        let price = get_ema_price_no_older_than(self, self._ipyth.get(), id, age)?;
+        let data = price.abi_encode();
+        Ok(data)
+    }
+
+    fn get_valid_time_period(&mut self) -> Result<U256, Self::Error> {
+        let time = get_valid_time_period(self, self._ipyth.get())?;
+        Ok(time)
+    }
+
+    fn get_update_fee(&mut self, update_data: Vec<AbiBytes>) -> Result<U256, Self::Error> {
+        let data = update_data.into_iter().map(|x| Bytes::from(x.0)).collect();
+        let fee = get_update_fee(self, self._ipyth.get(), data)?;
+        Ok(fee)
+    }
+
+    #[payable]
+    fn update_price_feeds(&mut self, update_data: Vec<AbiBytes>) -> Result<(), Self::Error> {
+        let data = update_data.into_iter().map(|x| Bytes::from(x.0)).collect();
+        update_price_feeds(self, self._ipyth.get(), data)?;
+        Ok(())
+    }
+
+    #[payable]
+    fn update_price_feeds_if_necessary(
+        &mut self,
+        update_data: Vec<AbiBytes>,
+        price_ids: Vec<B256>,
+        publish_times: Vec<u64>,
+    ) -> Result<(), Self::Error> {
+        let data = update_data.into_iter().map(|x| Bytes::from(x.0)).collect();
+        update_price_feeds_if_necessary(self, self._ipyth.get(), data, price_ids, publish_times)?;
+        Ok(())
+    }
+
+    #[payable]
+    fn parse_price_feed_updates(
+        &mut self,
+        update_data: Vec<AbiBytes>,
+        price_ids: Vec<B256>,
+        min_publish_time: u64,
+        max_publish_time: u64,
+    ) -> Result<Vec<u8>, Self::Error> {
+        let data = update_data.into_iter().map(|x| Bytes::from(x.0)).collect();
+        let encode_data = parse_price_feed_updates(
+            self,
+            self._ipyth.get(),
+            data,
+            price_ids,
+            min_publish_time,
+            max_publish_time,
+        )?
+        .abi_encode();
+        Ok(encode_data)
+    }
+
+    #[payable]
+    fn parse_price_feed_updates_unique(
+        &mut self,
+        update_data: Vec<AbiBytes>,
+        price_ids: Vec<B256>,
+        min_publish_time: u64,
+        max_publish_time: u64,
+    ) -> Result<Vec<u8>, Self::Error> {
+        let data = update_data.into_iter().map(|x| Bytes::from(x.0)).collect();
+        let encode_data = parse_price_feed_updates_unique(
+            self,
+            self._ipyth.get(),
+            data,
+            price_ids,
+            min_publish_time,
+            max_publish_time,
+        )?
+        .abi_encode();
+        Ok(encode_data)
+    }
+}

+ 319 - 0
target_chains/ethereum/sdk/stylus/contracts/src/pyth/types.rs

@@ -0,0 +1,319 @@
+#![allow(missing_docs)]
+//! Solidity type definitions used throughout the project
+use alloy_primitives::{I32, I64, U256, U64};
+use stylus_sdk::{alloy_sol_types::sol, prelude::*};
+
+sol_storage! {
+    /// Represents a storage-optimized price structure containing the current price data.
+    pub struct StoragePrice {
+        int64 price;
+        uint64 conf;
+        int32 expo;
+        uint publish_time;
+    }
+
+   /// Represents a storage-optimized price feed structure containing an ID and associated price data.
+    pub struct StoragePriceFeed {
+        bytes32 id;
+        StoragePrice price;
+        StoragePrice ema_price;
+    }
+}
+
+sol! {
+    /// Represents a price structure containing the current price data.
+    ///
+    /// # Fields
+    /// - `price`: The current price value as an `int64`.
+    /// - `conf`: The confidence level of the price as a `uint64`.
+    /// - `expo`: The exponent value indicating the scale of the price as an `int32`.
+    /// - `publish_time`: The timestamp of when the price was published as a `uint`.
+   #[derive(Debug, Copy)]
+   struct Price {
+        int64 price;
+        uint64 conf;
+        int32 expo;
+        uint publish_time;
+    }
+
+    /// Represents a price feed structure containing an ID and associated price data.
+    ///
+    /// This struct is used solely as a return type for function selectors related
+    /// to price feeds in the SDK.
+    ///
+    /// # Fields
+    /// - `id`: The unique identifier for the price feed as a `bytes32`.
+    /// - `price`: The current price information as a `Price`.
+    /// - `ema_price`: The Exponential Moving Average (EMA) price information as a `Price`.
+   #[derive(Debug, Copy)]
+    struct PriceFeed {
+        bytes32 id;
+        Price price;
+        Price ema_price;
+    }
+     /// Function call selector: Fetches the price associated with the given ID without validation.
+        /// Returns the raw `Price` data for the specified `bytes32` ID, acting as a return call selector.
+        function getPriceUnsafe(bytes32 id) external view returns (int64,uint64,int32,uint);
+
+        /// Function call selector: Retrieves the price associated with the given ID
+        /// ensuring that the price is not older than the specified age in seconds.
+        /// Returns the `Price` data for the specified `bytes32` ID.
+        function getPriceNoOlderThan(
+            bytes32 id,
+            uint age
+        ) external view returns (Price memory price);
+
+        /// Function call selector: Fetches the Exponential Moving Average (EMA) price
+        /// associated with the given ID without validation.
+        /// Returns the raw `Price` data for the specified `bytes32` ID, acting as a return call selector.
+        function getEmaPriceUnsafe(
+            bytes32 id
+        ) external view returns (Price memory price);
+
+        /// Function call selector: Retrieves the EMA price associated with the given ID
+        /// ensuring that the price is not older than the specified age in seconds.
+        /// Returns the `Price` data for the specified `bytes32` ID.
+        function getEmaPriceNoOlderThan(
+            bytes32 id,
+            uint age
+        ) external view returns (Price memory price);
+
+        /// Function call selector: Updates multiple price feeds using the provided update data.
+        /// Accepts an array of `bytes` containing update data and processes the updates.
+        function updatePriceFeeds(bytes[] calldata updateData) external payable;
+
+        /// Function call selector: Updates multiple price feeds only if necessary based on the provided conditions.
+        /// Accepts arrays of `bytes`, `bytes32`, and `uint64` to check against existing feeds
+        /// and processes the updates if conditions are met.
+        function updatePriceFeedsIfNecessary(
+            bytes[] calldata updateData,
+            bytes32[] calldata priceIds,
+            uint64[] calldata publishTimes
+        ) external payable;
+
+        /// Function call selector: Calculates the fee amount required to update price feeds
+        /// based on the provided update data.
+        /// Returns the fee amount as a `uint`.
+        function getUpdateFee(
+            bytes[] calldata updateData
+        ) external view returns (uint feeAmount);
+
+        /// Function call selector: Parses updates from the provided data for multiple price feeds.
+        /// Accepts arrays of `bytes` and `bytes32`, along with publish time constraints,
+        /// and returns an array of `PriceFeed` structs containing the parsed updates.
+        function parsePriceFeedUpdates(
+            bytes[] calldata updateData,
+            bytes32[] calldata priceIds,
+            uint64 minPublishTime,
+            uint64 maxPublishTime
+        ) external payable returns (PriceFeed[] memory priceFeeds);
+
+        /// Function call selector: Parses updates from the provided data for unique price feeds.
+        /// Accepts arrays of `bytes` and `bytes32`, along with publish time constraints,
+        /// and returns an array of unique `PriceFeed` structs containing the parsed updates.
+        function parsePriceFeedUpdatesUnique(
+            bytes[] calldata updateData,
+            bytes32[] calldata priceIds,
+            uint64 minPublishTime,
+            uint64 maxPublishTime
+        ) external payable returns (PriceFeed[] memory priceFeeds);
+
+        /// Function call selector: Queries the price feed for a given ID.
+        /// Returns an array of `PriceFeed` structs associated with the specified `bytes32` ID.
+        function queryPriceFeed(
+            bytes32 id
+        ) public view virtual returns (PriceFeed[] memory priceFeeds);
+
+        /// Function call selector: Checks if a price feed exists for the given ID.
+        /// Returns an array of `PriceFeed` structs if it exists for the specified `bytes32` ID.
+        function priceFeedExists(
+        bytes32 id
+        ) public view virtual returns (PriceFeed[] memory priceFeeds);
+
+        /// Function call selector: Retrieves the valid time period for price feeds.
+        /// Returns the valid time period as a `uint`.
+        function getValidTimePeriod()
+            public
+            view
+            virtual
+            returns (uint validTimePeriod);
+}
+
+impl StoragePrice {
+    /// Converts the `StoragePrice` instance into a `Price` struct.
+    ///
+    /// This method retrieves the stored values from the `StoragePrice`
+    /// and creates a `Price` struct, making it suitable for external
+    /// use or return types in function calls.
+    pub fn to_price(&self) -> Price {
+        Price {
+            price: self.price.get().as_i64(),
+            conf: self.conf.get().to(),
+            expo: self.expo.get().as_i32(),
+            publish_time: self.publish_time.get(),
+        }
+    }
+
+    /// Sets the values of the `StoragePrice` instance from a given `Price` struct.
+    /// This method updates the stored values in the `StoragePrice` with
+    /// the corresponding values from the provided `Price` struct, ensuring
+    /// that the internal state is accurately reflected.
+    pub fn set(&mut self, price: Price) {
+        self.price.set(I64::try_from(price.price).unwrap());
+        self.conf.set(U64::try_from(price.conf).unwrap());
+        self.expo.set(I32::try_from(price.expo).unwrap());
+        self.publish_time.set(price.publish_time);
+    }
+
+    /// This function is for just for testing
+    pub fn test_from_price(price: Price) -> Self {
+        let mut storage_price = unsafe { StoragePrice::new(U256::from(100), 0) };
+        storage_price.set(price);
+        storage_price
+    }
+}
+
+impl StoragePriceFeed {
+    /// Converts the `StoragePriceFeed` instance into a `PriceFeed` struct.
+    ///
+    /// This method retrieves the stored price feed values and creates
+    /// a `PriceFeed` struct, which includes the unique identifier and
+    /// associated price data, making it suitable for external use or
+    /// return types in function calls.
+    pub fn to_price_feed(&self) -> PriceFeed {
+        PriceFeed {
+            id: self.id.get(),
+            price: self.price.to_price(),
+            ema_price: self.ema_price.to_price(),
+        }
+    }
+
+    /// Sets the values of the `StoragePriceFeed` instance from a given `PriceFeed` struct.
+    ///
+    /// This method updates the stored values in the `StoragePriceFeed`
+    /// with the corresponding values from the provided `PriceFeed` struct,
+    /// ensuring that the internal state is accurately reflected.
+    pub fn set(&mut self, price_feed: PriceFeed) {
+        self.id.set(price_feed.id);
+        self.price.set(price_feed.price);
+        self.ema_price.set(price_feed.ema_price);
+    }
+
+    /// This function is for just for testing
+    #[cfg(test)]
+    pub fn test_from_price_feed(price_feed: PriceFeed) -> Self {
+        let mut storage_price_feed = unsafe { StoragePriceFeed::new(U256::from(100), 0) };
+        storage_price_feed.set(price_feed);
+        storage_price_feed
+    }
+}
+
+#[cfg(all(test, feature = "std"))]
+mod tests {
+    use crate::pyth::types::{Price, PriceFeed, StoragePrice, StoragePriceFeed};
+    use alloy_primitives::{B256, U256};
+
+    // Updated constants to use uppercase naming convention
+    const PRICE: i64 = 1000;
+    const CONF: u64 = 1000;
+    const EXPO: i32 = 1000;
+
+    /// Generates a 256-bit hash filled with the byte value 30.
+    ///
+    /// # Returns
+    /// - `B256`: A 256-bit hash where each byte is set to 30.
+    fn generate_bytes() -> B256 {
+        B256::repeat_byte(30)
+    }
+
+    #[motsu::test]
+    fn can_create_type_price() {
+        let price_result = Price {
+            price: PRICE,
+            conf: CONF,
+            expo: EXPO,
+            publish_time: U256::from(1000),
+        };
+        assert_eq!(price_result.price, PRICE);
+        assert_eq!(price_result.conf, CONF);
+        assert_eq!(price_result.expo, EXPO);
+        assert_eq!(price_result.publish_time, U256::from(1000));
+    }
+
+    #[motsu::test]
+    fn can_create_type_price_feed() {
+        let id = generate_bytes();
+        let price_result = Price {
+            price: PRICE,
+            conf: CONF,
+            expo: EXPO,
+            publish_time: U256::from(1000),
+        };
+        let price_result_ema = Price {
+            price: PRICE,
+            conf: CONF,
+            expo: EXPO,
+            publish_time: U256::from(1000),
+        };
+        let price_feed_result = PriceFeed {
+            id,
+            price: price_result,
+            ema_price: price_result_ema,
+        };
+        assert_eq!(price_feed_result.price.price, PRICE);
+        assert_eq!(price_feed_result.price.conf, CONF);
+        assert_eq!(price_feed_result.price.expo, EXPO);
+        assert_eq!(price_feed_result.price.publish_time, U256::from(1000));
+        assert_eq!(price_feed_result.ema_price.price, PRICE);
+        assert_eq!(price_feed_result.ema_price.conf, CONF);
+        assert_eq!(price_feed_result.ema_price.expo, EXPO);
+        assert_eq!(price_feed_result.ema_price.publish_time, U256::from(1000));
+    }
+
+    #[motsu::test]
+    fn can_create_type_storage_price() {
+        let price_result = Price {
+            price: PRICE,
+            conf: CONF,
+            expo: EXPO,
+            publish_time: U256::from(1000),
+        };
+        let storage_price_result = StoragePrice::test_from_price(price_result);
+        let price_result = storage_price_result.to_price();
+        assert_eq!(price_result.price, PRICE);
+        assert_eq!(price_result.conf, CONF);
+        assert_eq!(price_result.expo, EXPO);
+        assert_eq!(price_result.publish_time, U256::from(1000));
+    }
+
+    #[motsu::test]
+    fn can_create_type_storage_price_feed() {
+        let price_result = Price {
+            price: PRICE,
+            conf: CONF,
+            expo: EXPO,
+            publish_time: U256::from(1000),
+        };
+        let price_result_ema = Price {
+            price: PRICE,
+            conf: CONF,
+            expo: EXPO,
+            publish_time: U256::from(1000),
+        };
+        let price_feed_result = PriceFeed {
+            id: generate_bytes(),
+            price: price_result,
+            ema_price: price_result_ema,
+        };
+        let storage_price_feed_result = StoragePriceFeed::test_from_price_feed(price_feed_result);
+        let price_feed_result = storage_price_feed_result.to_price_feed();
+        assert_eq!(price_feed_result.price.price, PRICE);
+        assert_eq!(price_feed_result.price.conf, CONF);
+        assert_eq!(price_feed_result.price.expo, EXPO);
+        assert_eq!(price_feed_result.price.publish_time, U256::from(1000));
+        assert_eq!(price_feed_result.ema_price.price, PRICE);
+        assert_eq!(price_feed_result.ema_price.conf, CONF);
+        assert_eq!(price_feed_result.ema_price.expo, EXPO);
+        assert_eq!(price_feed_result.ema_price.publish_time, U256::from(1000));
+    }
+}

+ 65 - 0
target_chains/ethereum/sdk/stylus/contracts/src/utils/mod.rs

@@ -0,0 +1,65 @@
+use {
+    alloc::vec::Vec,
+    alloy_primitives::U256,
+    alloy_sol_types::{SolCall, SolType},
+    stylus_sdk::{
+        alloy_primitives::Address,
+        call::{call, delegate_call, Call},
+        storage::TopLevelStorage,
+    },
+};
+
+/// The revert message when failing to decode the data
+/// returned by an external contract call
+pub const CALL_RETDATA_DECODING_ERROR_MESSAGE: &[u8] = b"error decoding retdata";
+
+/// Maps an error returned from an external contract call to a `Vec<u8>`,
+/// which is the expected return type of external contract methods.
+pub fn map_call_error(e: stylus_sdk::call::Error) -> Vec<u8> {
+    match e {
+        stylus_sdk::call::Error::Revert(msg) => msg,
+        stylus_sdk::call::Error::AbiDecodingFailed(_) => {
+            CALL_RETDATA_DECODING_ERROR_MESSAGE.to_vec()
+        }
+    }
+}
+
+/// Performs a `delegate call` to the given address, calling the function
+/// defined as a `SolCall` with the given arguments.
+
+pub fn delegate_call_helper<C: SolCall>(
+    storage: &mut impl TopLevelStorage,
+    address: Address,
+    args: <C::Parameters<'_> as SolType>::RustType,
+) -> Result<C::Return, Vec<u8>> {
+    let calldata = C::new(args).abi_encode();
+    let res = unsafe { delegate_call(storage, address, &calldata).map_err(map_call_error)? };
+    C::abi_decode_returns(&res, false /* validate */)
+        .map_err(|_| CALL_RETDATA_DECODING_ERROR_MESSAGE.to_vec())
+}
+
+/// Performs a `call` to the given address, calling the function
+/// defined as a `SolCall` with the given arguments.
+pub fn call_helper<C: SolCall>(
+    storage: &mut impl TopLevelStorage,
+    address: Address,
+    args: <C::Parameters<'_> as SolType>::RustType,
+) -> Result<C::Return, Vec<u8>> {
+    let calldata = C::new(args).abi_encode();
+    let res = call(storage, address, &calldata).map_err(map_call_error)?;
+    C::abi_decode_returns(&res, false /* validate */)
+        .map_err(|_| CALL_RETDATA_DECODING_ERROR_MESSAGE.to_vec())
+}
+
+pub fn call_helper_value<C: SolCall>(
+    storage: &mut impl TopLevelStorage,
+    address: Address,
+    args: <C::Parameters<'_> as SolType>::RustType,
+    value: U256,
+) -> Result<C::Return, Vec<u8>> {
+    let calldata = C::new(args).abi_encode();
+    let res =
+        call(Call::new_in(storage).value(value), address, &calldata).map_err(map_call_error)?;
+    C::abi_decode_returns(&res, false /* validate */)
+        .map_err(|_| CALL_RETDATA_DECODING_ERROR_MESSAGE.to_vec())
+}

+ 28 - 0
target_chains/ethereum/sdk/stylus/examples/extend-pyth-example/Cargo.toml

@@ -0,0 +1,28 @@
+[package]
+name = "extend-pyth-example"
+edition.workspace = true
+license.workspace = true
+repository.workspace = true
+publish = false
+version.workspace = true
+
+[dependencies]
+pyth-stylus.workspace = true
+alloy-primitives = { workspace = true, features = ["tiny-keccak"] }
+alloy-sol-types.workspace = true
+stylus-sdk.workspace = true
+mini-alloc.workspace = true
+keccak-const.workspace = true
+
+[dev-dependencies]
+alloy.workspace = true
+eyre.workspace = true
+tokio.workspace = true
+e2e.workspace = true
+
+[lib]
+crate-type = ["lib", "cdylib"]
+
+[features]
+e2e = []
+export-abi = []

+ 1 - 0
target_chains/ethereum/sdk/stylus/examples/extend-pyth-example/README.MD

@@ -0,0 +1 @@
+# This is an example using the sdk and extending it to use other funtions

+ 10 - 0
target_chains/ethereum/sdk/stylus/examples/extend-pyth-example/src/constructor.sol

@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+contract ExtendPythExample {
+    address private pythAddress;
+
+    constructor(address _pythAddress) {
+        pythAddress = _pythAddress;
+    }
+}

+ 24 - 0
target_chains/ethereum/sdk/stylus/examples/extend-pyth-example/src/lib.rs

@@ -0,0 +1,24 @@
+#![cfg_attr(not(test), no_std, no_main)]
+extern crate alloc;
+
+use alloc::vec;
+use alloc::vec::Vec;
+use pyth_stylus::pyth::pyth_contract::PythContract;
+use stylus_sdk::prelude::{entrypoint, public, storage};
+
+#[entrypoint]
+#[storage]
+struct ExtendPythExample {
+    #[borrow]
+    pyth: PythContract,
+}
+
+#[public]
+#[inherit(PythContract)]
+impl ExtendPythExample {
+    /// Returns a vector of bytes containing the data.
+    fn get_data(&self) -> Vec<u8> {
+        // just reteun data
+        vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
+    }
+}

+ 18 - 0
target_chains/ethereum/sdk/stylus/examples/extend-pyth-example/tests/abi/mod.rs

@@ -0,0 +1,18 @@
+#![allow(dead_code)]
+use alloy::sol;
+
+sol!(
+    #[sol(rpc)]
+   contract ExtendPyth {
+     function getPriceUnsafe(bytes32 id) external returns (uint8[] price);
+     function getEmaPriceUnsafe(bytes32 id) external returns (uint8[] price);
+     function getPriceNoOlderThan(bytes32 id, uint age) external returns (uint8[] price);
+     function getEmaPriceNoOlderThan(bytes32 id, uint age) external returns (uint8[] price);
+     function getUpdateFee(bytes[] calldata updateData) external returns (uint256 fee);
+     function getValidTimePeriod() external returns (uint256 period);
+     function updatePriceFeeds(bytes[] calldata updateData) external payable;
+     function updatePriceFeedsIfNecessary(bytes[] calldata updateData, bytes32[] calldata priceIds, uint64[] calldata publishTimes) external payable;
+
+     function getData() external returns (uint[] calldata data);
+   }
+);

+ 230 - 0
target_chains/ethereum/sdk/stylus/examples/extend-pyth-example/tests/extend-pyth.rs

@@ -0,0 +1,230 @@
+#![cfg(feature = "e2e")]
+
+use std::assert_eq;
+
+use abi::ExtendPyth;
+use alloy::{primitives::U256, sol};
+use alloy_sol_types::SolValue;
+use e2e::{env, Account, ReceiptExt};
+use stylus_sdk::alloy_primitives::{Address, FixedBytes};
+
+use crate::ExtendPythExample::constructorCall;
+use eyre::Result;
+use pyth_stylus::pyth::{mock::create_price_feed_update_data_list, types::Price};
+
+mod abi;
+
+sol!("src/constructor.sol");
+// // ============================================================================
+// // Integration Tests: Proxy Calls
+// // ============================================================================
+
+impl Default for constructorCall {
+    fn default() -> Self {
+        ctr(false)
+    }
+}
+
+fn generate_pyth_id_from_str(key_id: &str) -> FixedBytes<32> {
+    let id = keccak_const::Keccak256::new()
+        .update(key_id.as_bytes())
+        .finalize()
+        .to_vec();
+    let price_id = FixedBytes::<32>::from_slice(&id);
+    price_id
+}
+
+fn ctr(invaid_pyth_address: bool) -> constructorCall {
+    let pyth_addr = if invaid_pyth_address {
+        "0xdC79c650B6560cBF15391C3F90A833a349735676".to_string()
+    } else {
+        env("MOCK_PYTH_ADDRESS").unwrap()
+    };
+    let address_addr = Address::parse_checksummed(&pyth_addr, None).unwrap();
+    constructorCall {
+        _pythAddress: address_addr,
+    }
+}
+
+#[e2e::test]
+async fn constructs(alice: Account) -> Result<()> {
+    let contract_addr = alice
+        .as_deployer()
+        .with_default_constructor::<constructorCall>()
+        .deploy()
+        .await?
+        .address()?;
+
+    let contract = ExtendPyth::new(contract_addr, &alice.wallet);
+    let id = generate_pyth_id_from_str("ETH");
+    contract.getPriceUnsafe(id).call().await?;
+    Ok(())
+}
+
+#[e2e::test]
+async fn can_get_price_unsafe(alice: Account) -> Result<()> {
+    let contract_addr = alice
+        .as_deployer()
+        .with_default_constructor::<constructorCall>()
+        .deploy()
+        .await?
+        .address()?;
+    let contract = ExtendPyth::new(contract_addr, &alice.wallet);
+    let id = generate_pyth_id_from_str("ETH");
+    let ExtendPyth::getPriceUnsafeReturn { price } = contract.getPriceUnsafe(id).call().await?;
+    let decoded_price = Price::abi_decode(&price, false).expect("Failed to decode price");
+    assert!(decoded_price.price > 0_i64);
+    assert!(decoded_price.conf > 0_u64);
+    assert!(decoded_price.expo > 0_i32);
+    assert!(decoded_price.publish_time > U256::from(0));
+    Ok(())
+}
+
+#[e2e::test]
+async fn error_provided_invaild_id_get_price_unsafe(alice: Account) -> Result<()> {
+    let contract_addr = alice
+        .as_deployer()
+        .with_default_constructor::<constructorCall>()
+        .deploy()
+        .await?
+        .address()?;
+    let contract = ExtendPyth::new(contract_addr, &alice.wallet);
+    let id = generate_pyth_id_from_str("BALLON");
+    let price_result = contract.getPriceUnsafe(id).call().await;
+    assert!(price_result.is_err());
+    Ok(())
+}
+
+#[e2e::test]
+async fn can_get_ema_price_unsafe(alice: Account) -> Result<()> {
+    let contract_addr = alice
+        .as_deployer()
+        .with_default_constructor::<constructorCall>()
+        .deploy()
+        .await?
+        .address()?;
+    let contract = ExtendPyth::new(contract_addr, &alice.wallet);
+    let id = generate_pyth_id_from_str("ETH");
+    let ExtendPyth::getEmaPriceUnsafeReturn { price } =
+        contract.getEmaPriceUnsafe(id).call().await?;
+    let decoded_price = Price::abi_decode(&price, false).expect("Failed to decode price");
+    assert!(decoded_price.price > 0_i64);
+    assert!(decoded_price.conf > 0_u64);
+    assert!(decoded_price.expo > 0_i32);
+    assert!(decoded_price.publish_time > U256::from(0));
+    Ok(())
+}
+
+#[e2e::test]
+async fn error_provided_invaild_id_get_ema_price_unsafe(alice: Account) -> Result<()> {
+    let contract_addr = alice
+        .as_deployer()
+        .with_default_constructor::<constructorCall>()
+        .deploy()
+        .await?
+        .address()?;
+    let contract = ExtendPyth::new(contract_addr, &alice.wallet);
+    let id = generate_pyth_id_from_str("BALLON");
+    let price_result = contract.getEmaPriceUnsafe(id).call().await;
+    assert!(price_result.is_err());
+    Ok(())
+}
+
+#[e2e::test]
+async fn can_get_price_no_older_than(alice: Account) -> Result<()> {
+    let contract_addr = alice
+        .as_deployer()
+        .with_default_constructor::<constructorCall>()
+        .deploy()
+        .await?
+        .address()?;
+    let contract = ExtendPyth::new(contract_addr, &alice.wallet);
+    let id = generate_pyth_id_from_str("ETH");
+    let ExtendPyth::getPriceNoOlderThanReturn { price } = contract
+        .getPriceNoOlderThan(id, U256::from(1000))
+        .call()
+        .await?;
+    let decoded_price = Price::abi_decode(&price, false).expect("Failed to decode price");
+    assert!(decoded_price.price > 0_i64);
+    assert!(decoded_price.conf > 0_u64);
+    assert!(decoded_price.expo > 0_i32);
+    assert!(decoded_price.publish_time > U256::from(0));
+    Ok(())
+}
+
+#[e2e::test]
+async fn error_provided_invaild_id_get_price_no_older_than(alice: Account) -> Result<()> {
+    let contract_addr = alice
+        .as_deployer()
+        .with_default_constructor::<constructorCall>()
+        .deploy()
+        .await?
+        .address()?;
+    let contract = ExtendPyth::new(contract_addr, &alice.wallet);
+    let id = generate_pyth_id_from_str("BALLON");
+    let price_result = contract
+        .getPriceNoOlderThan(id, U256::from(1000))
+        .call()
+        .await;
+    assert!(price_result.is_err());
+    Ok(())
+}
+
+#[e2e::test]
+async fn error_provided_invaild_period_get_price_no_older_than(alice: Account) -> Result<()> {
+    let contract_addr = alice
+        .as_deployer()
+        .with_default_constructor::<constructorCall>()
+        .deploy()
+        .await?
+        .address()?;
+    let contract = ExtendPyth::new(contract_addr, &alice.wallet);
+    let id = generate_pyth_id_from_str("SOL");
+    let price_result = contract.getPriceNoOlderThan(id, U256::from(1)).call().await;
+    assert!(price_result.is_err());
+    Ok(())
+}
+
+#[e2e::test]
+async fn can_get_fee(alice: Account) -> Result<()> {
+    let contract_addr = alice
+        .as_deployer()
+        .with_default_constructor::<constructorCall>()
+        .deploy()
+        .await?
+        .address()?;
+    let contract = ExtendPyth::new(contract_addr, &alice.wallet);
+    let (data, _id) = create_price_feed_update_data_list();
+    let ExtendPyth::getUpdateFeeReturn { fee } = contract.getUpdateFee(data).call().await?;
+    assert_eq!(fee, U256::from(300));
+    Ok(())
+}
+
+#[e2e::test]
+async fn can_get_valid_time_peroid(alice: Account) -> Result<()> {
+    let contract_addr = alice
+        .as_deployer()
+        .with_default_constructor::<constructorCall>()
+        .deploy()
+        .await?
+        .address()?;
+    let contract = ExtendPyth::new(contract_addr, &alice.wallet);
+    let ExtendPyth::getValidTimePeriodReturn { period } =
+        contract.getValidTimePeriod().call().await?;
+    assert_eq!(period, U256::from(100000));
+    Ok(())
+}
+
+#[e2e::test]
+async fn can_get_data(alice: Account) -> Result<()> {
+    let contract_addr = alice
+        .as_deployer()
+        .with_default_constructor::<constructorCall>()
+        .deploy()
+        .await?
+        .address()?;
+    let contract = ExtendPyth::new(contract_addr, &alice.wallet);
+    let ExtendPyth::getDataReturn { data } = contract.getData().call().await?;
+    assert!(data.len() > 0);
+    Ok(())
+}

+ 28 - 0
target_chains/ethereum/sdk/stylus/examples/function-example/Cargo.toml

@@ -0,0 +1,28 @@
+[package]
+name = "function-example"
+edition.workspace = true
+license.workspace = true
+repository.workspace = true
+publish = false
+version.workspace = true
+
+[dependencies]
+pyth-stylus.workspace = true
+alloy-primitives = { workspace = true, features = ["tiny-keccak"] }
+alloy-sol-types.workspace = true
+stylus-sdk.workspace = true
+mini-alloc.workspace = true
+keccak-const.workspace = true
+
+[dev-dependencies]
+alloy.workspace = true
+eyre.workspace = true
+tokio.workspace = true
+e2e.workspace = true
+
+[lib]
+crate-type = ["lib", "cdylib"]
+
+[features]
+e2e = []
+export-abi = []

+ 1 - 0
target_chains/ethereum/sdk/stylus/examples/function-example/README.MD

@@ -0,0 +1 @@
+# This is an example using function call as defined in the sdk

+ 35 - 0
target_chains/ethereum/sdk/stylus/examples/function-example/src/constructor.sol

@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+contract FunctionCallsExample {
+    address private pythAddress;
+    bytes32 private priceId;
+
+    struct Price {
+        int64 price;
+        uint64 conf;
+        int32 expo;
+        uint256 publishTime; // Using uint256 as Solidity does not have a native uint type
+    }
+
+    struct PriceFeed {
+        bytes32 id;
+        Price price;
+        Price emaPrice;
+    }
+
+    // Storage variables for the Price and PriceFeed data
+    Price private price;
+    PriceFeed private priceFeed;
+    Price private ema_price;
+    PriceFeed private ema_priceFeed;
+
+    constructor(address _pythAddress, bytes32 _priceId) {
+        pythAddress = _pythAddress;
+        priceId = _priceId;
+        price = Price(0, 0, 0, 0);
+        ema_price = Price(0, 0, 0, 0);
+        priceFeed = PriceFeed(_priceId, price, ema_price);
+        ema_priceFeed = PriceFeed(_priceId, ema_price, ema_price);
+    }
+}

+ 93 - 0
target_chains/ethereum/sdk/stylus/examples/function-example/src/lib.rs

@@ -0,0 +1,93 @@
+#![cfg_attr(not(test), no_std, no_main)]
+#![allow(clippy::let_unit_value)]
+extern crate alloc;
+
+use alloc::vec;
+use alloc::vec::Vec;
+use alloy_primitives::U256;
+use alloy_sol_types::sol;
+use pyth_stylus::pyth::{
+    functions::{
+        get_ema_price_no_older_than, get_ema_price_unsafe, get_price_no_older_than,
+        get_price_unsafe, get_update_fee, get_valid_time_period, update_price_feeds,
+    },
+    mock::create_price_feed_update_data_list,
+    types::StoragePrice,
+};
+use stylus_sdk::{
+    prelude::{entrypoint, public, storage},
+    storage::{StorageAddress, StorageB256},
+    stylus_proc::SolidityError,
+};
+
+#[entrypoint]
+#[storage]
+struct FunctionCallsExample {
+    pyth_address: StorageAddress,
+    price_id: StorageB256,
+    price: StoragePrice,
+}
+
+sol! {
+    error ArraySizeNotMatch();
+    error CallFailed();
+}
+
+#[derive(SolidityError)]
+pub enum MultiCallErrors {
+    ArraySizeNotMatch(ArraySizeNotMatch),
+
+    CallFailed(CallFailed),
+}
+
+#[public]
+impl FunctionCallsExample {
+    pub fn get_price_unsafe(&mut self) -> Result<i64, Vec<u8>> {
+        let price_result = get_price_unsafe(self, self.pyth_address.get(), self.price_id.get())?;
+        self.price.set(price_result);
+        Ok(price_result.price)
+    }
+
+    pub fn get_ema_price_unsafe(&mut self) -> Result<i64, Vec<u8>> {
+        let price_result =
+            get_ema_price_unsafe(self, self.pyth_address.get(), self.price_id.get())?;
+        Ok(price_result.price)
+    }
+    pub fn get_price_no_older_than(&mut self) -> Result<i64, Vec<u8>> {
+        let price_result = get_price_no_older_than(
+            self,
+            self.pyth_address.get(),
+            self.price_id.get(),
+            U256::from(1000),
+        )?;
+        Ok(price_result.price)
+    }
+
+    pub fn get_ema_price_no_older_than(&mut self) -> Result<i64, Vec<u8>> {
+        let price_result = get_ema_price_no_older_than(
+            self,
+            self.pyth_address.get(),
+            self.price_id.get(),
+            U256::from(1000),
+        )?;
+        Ok(price_result.price)
+    }
+
+    pub fn get_update_fee(&mut self) -> Result<U256, Vec<u8>> {
+        let (data, _) = create_price_feed_update_data_list();
+        let fee = get_update_fee(self, self.pyth_address.get(), data)?;
+        Ok(fee)
+    }
+
+    pub fn get_valid_time_period(&mut self) -> Result<U256, Vec<u8>> {
+        let time = get_valid_time_period(self, self.pyth_address.get())?;
+        Ok(time)
+    }
+
+    #[payable]
+    pub fn update_price_feeds(&mut self) -> Result<(), Vec<u8>> {
+        let (data_bytes, _) = create_price_feed_update_data_list();
+        let _ = update_price_feeds(self, self.pyth_address.get(), data_bytes)?;
+        Ok(())
+    }
+}

+ 28 - 0
target_chains/ethereum/sdk/stylus/examples/pyth-example/Cargo.toml

@@ -0,0 +1,28 @@
+[package]
+name = "pyth-example"
+edition.workspace = true
+license.workspace = true
+repository.workspace = true
+publish = false
+version.workspace = true
+
+[dependencies]
+pyth-stylus.workspace = true
+alloy-primitives = { workspace = true, features = ["tiny-keccak"] }
+alloy-sol-types.workspace = true
+stylus-sdk.workspace = true
+mini-alloc.workspace = true
+keccak-const.workspace = true
+
+[dev-dependencies]
+alloy.workspace = true
+eyre.workspace = true
+tokio.workspace = true
+e2e.workspace = true
+
+[lib]
+crate-type = ["lib", "cdylib"]
+
+[features]
+e2e = []
+export-abi = []

+ 1 - 0
target_chains/ethereum/sdk/stylus/examples/pyth-example/README.MD

@@ -0,0 +1 @@
+# This is an example using sdk with an example contract

+ 10 - 0
target_chains/ethereum/sdk/stylus/examples/pyth-example/src/constructor.sol

@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+contract PythExample {
+    address private pythAddress;
+
+    constructor(address _pythAddress) {
+        pythAddress = _pythAddress;
+    }
+}

+ 76 - 0
target_chains/ethereum/sdk/stylus/examples/pyth-example/src/lib.rs

@@ -0,0 +1,76 @@
+#![cfg_attr(not(test), no_std, no_main)]
+extern crate alloc;
+
+use alloc::vec::Vec;
+use alloy_sol_types::SolValue;
+use pyth_stylus::pyth::{
+    pyth_contract::{IPyth, PythContract},
+    types::Price,
+};
+use stylus_sdk::{
+    abi::Bytes,
+    alloy_primitives::U256,
+    msg,
+    prelude::{entrypoint, public, storage},
+    storage::StorageB256,
+    stylus_proc::SolidityError,
+};
+
+pub use sol::*;
+
+mod sol {
+    use alloy_sol_types::sol;
+
+    sol! {
+        /// Indicates an error related to the issue about mismatched signature.
+        #[derive(Debug)]
+        #[allow(missing_docs)]
+        error InsufficientFee();
+    }
+}
+
+#[derive(SolidityError, Debug)]
+pub enum Error {
+    InsufficientFee(InsufficientFee),
+}
+
+#[entrypoint]
+#[storage]
+struct PythExample {
+    #[borrow]
+    pyth: PythContract,
+    eth_usd_price_id: StorageB256,
+}
+
+#[public]
+impl PythExample {
+    fn mint(&mut self) -> Result<(), Vec<u8>> {
+        // Get the price if it is not older than 60 seconds.
+        let price = self
+            .pyth
+            .get_ema_price_no_older_than(self.eth_usd_price_id.get(), U256::from(60))?;
+        let decode_price = Price::abi_decode(&price, false).expect("Failed to decode price");
+
+        let eth_price_18_decimals = U256::from(decode_price.price) / U256::from(decode_price.expo);
+
+        let one_dollar_in_wei = U256::MAX / eth_price_18_decimals;
+
+        if msg::value() >= one_dollar_in_wei {
+            // User paid enough money.
+            // TODO: mint the NFT here
+        } else {
+            return Err(Error::InsufficientFee(InsufficientFee {}).into());
+        }
+        Ok(())
+    }
+
+    fn update_and_mint(&mut self, pyth_price_update: Vec<Bytes>) -> Result<(), Vec<u8>> {
+        let update_fee = self.pyth.get_update_fee(pyth_price_update.clone())?;
+        if update_fee < msg::value() {
+            return Err(Error::InsufficientFee(InsufficientFee {}).into());
+        }
+        self.pyth.update_price_feeds(pyth_price_update)?;
+        self.mint()?;
+        Ok(())
+    }
+}

+ 15 - 0
target_chains/ethereum/sdk/stylus/pyth-mock-solidity/.gitignore

@@ -0,0 +1,15 @@
+# Compiler files
+cache/
+out/
+
+# Ignores development broadcast logs
+!/broadcast
+/broadcast/*
+/broadcast/*/31337/
+/broadcast/**/dry-run/
+
+# Docs
+docs/
+
+# Dotenv file
+.env

+ 66 - 0
target_chains/ethereum/sdk/stylus/pyth-mock-solidity/README.md

@@ -0,0 +1,66 @@
+## Foundry
+
+**The goal of the folder is to deploy a mock solidity pyth contract using the pyth sdk**
+
+Foundry consists of:
+
+- **Forge**: Ethereum testing framework (like Truffle, Hardhat, and DappTools).
+- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions, and getting chain data.
+- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network.
+- **Chisel**: Fast, utilitarian, and verbose solidity REPL.
+
+## Documentation
+
+https://book.getfoundry.sh/
+
+## Usage
+
+### Build
+
+```shell
+$ forge build
+```
+
+### Test
+
+```shell
+$ forge test
+```
+
+### Format
+
+```shell
+$ forge fmt
+```
+
+### Gas Snapshots
+
+```shell
+$ forge snapshot
+```
+
+### Anvil
+
+```shell
+$ anvil
+```
+
+### Deploy
+
+```shell
+$ forge script script/Counter.s.sol:CounterScript --rpc-url <your_rpc_url> --private-key <your_private_key>
+```
+
+### Cast
+
+```shell
+$ cast <subcommand>
+```
+
+### Help
+
+```shell
+$ forge --help
+$ anvil --help
+$ cast --help
+```

+ 4 - 0
target_chains/ethereum/sdk/stylus/pyth-mock-solidity/foundry.toml

@@ -0,0 +1,4 @@
+[profile.default]
+src = "src"
+out = "out"
+libs = ["lib"]

+ 1 - 0
target_chains/ethereum/sdk/stylus/pyth-mock-solidity/lib/forge-std

@@ -0,0 +1 @@
+Subproject commit 1eea5bae12ae557d589f9f0f0edae2faa47cb262

+ 1 - 0
target_chains/ethereum/sdk/stylus/pyth-mock-solidity/lib/openzeppelin-contracts-upgradeable

@@ -0,0 +1 @@
+Subproject commit fa525310e45f91eb20a6d3baa2644be8e0adba31

+ 1 - 0
target_chains/ethereum/sdk/stylus/pyth-mock-solidity/lib/openzeppelin-foundry-upgrades

@@ -0,0 +1 @@
+Subproject commit 16e0ae21e0e39049f619f2396fa28c57fad07368

+ 15 - 0
target_chains/ethereum/sdk/stylus/pyth-mock-solidity/package.json

@@ -0,0 +1,15 @@
+{
+  "name": "pyth-mock-solidity",
+  "version": "1.0.0",
+  "description": "** Deploy mock solidity pyth contract using the pyth solidity sdk **",
+  "directories": {
+    "lib": "lib",
+    "test": "test"
+  },
+  "keywords": [],
+  "author": "",
+  "license": "ISC",
+  "dependencies": {
+    "@pythnetwork/pyth-sdk-solidity": "^4.0.0"
+  }
+}

+ 1 - 0
target_chains/ethereum/sdk/stylus/pyth-mock-solidity/remappings.txt

@@ -0,0 +1 @@
+@pythnetwork/pyth-sdk-solidity/=node_modules/@pythnetwork/pyth-sdk-solidity

+ 96 - 0
target_chains/ethereum/sdk/stylus/pyth-mock-solidity/script/MockPyth.s.sol

@@ -0,0 +1,96 @@
+/// SPDX-License-Identifier: Apache 2
+pragma solidity ^0.8.13;
+
+import {Script, console} from "forge-std/Script.sol";
+import {MockPythSample} from "../src/MockPyth.sol";
+
+contract MockPythScript is Script {
+    uint randNonce = 0;
+    string[] tickers = [
+        "ETH",
+        "BTC",
+        "USDT",
+        "BNB",
+        "SOL",
+        "MATIC",
+        "ADA",
+        "DOT",
+        "DOGE",
+        "SHIB"
+    ];
+    bytes[] priceData = new bytes[](tickers.length);
+    bytes32[] priceIds = new bytes32[](tickers.length);
+    MockPythSample pyth_contract;
+
+    function setUp() public {}
+
+    function run() public {
+        vm.startBroadcast();
+        deploy(100000, 100);
+        _generateInitialData();
+        console.log("Pyth contract address:", address(pyth_contract));
+        uint update_cost = pyth_contract.getUpdateFee(priceData);
+        pyth_contract.updatePriceFeeds{value: update_cost}(priceData);
+        vm.stopBroadcast();
+    }
+
+    function deploy(uint validTimePeriod, uint singleUpdateFeeInWei) internal {
+        pyth_contract = new MockPythSample(
+            validTimePeriod,
+            singleUpdateFeeInWei
+        );
+    }
+
+    function _generateInitialData() internal {
+        for (uint i = 0; i < tickers.length; i++) {
+            priceIds[i] = keccak256(abi.encodePacked(tickers[i]));
+
+            uint randomBase = uint(
+                keccak256(
+                    abi.encodePacked(block.timestamp, priceIds[i], msg.sender)
+                )
+            );
+
+            int64 price = int64(uint64(_deriveRandom(randomBase, 1) % 10));
+            uint64 conf = uint64(_deriveRandom(randomBase, 2) % 10);
+            int32 expo = int32(uint32(_deriveRandom(randomBase, 3) % 40));
+            int64 emaPrice = int64(uint64(_deriveRandom(randomBase, 4) % 10));
+            uint64 emaConf = uint64(_deriveRandom(randomBase, 5) % 10);
+            priceData[i] = pyth_contract.createPriceFeedUpdateData(
+                priceIds[i],
+                price,
+                conf,
+                expo,
+                emaPrice,
+                emaConf,
+                uint64(block.timestamp),
+                0
+            );
+        }
+    }
+
+    // Internal function to generate deterministic random numbers from a base seed
+    function _deriveRandom(uint base, uint salt) internal pure returns (uint) {
+        return uint(keccak256(abi.encodePacked(base, salt))) + 1;
+    }
+
+    function uint2str(uint256 _i) internal pure returns (string memory str) {
+        if (_i == 0) {
+            return "0";
+        }
+        uint256 j = _i;
+        uint256 length;
+        while (j != 0) {
+            length++;
+            j /= 10;
+        }
+        bytes memory bstr = new bytes(length);
+        uint256 k = length;
+        j = _i;
+        while (j != 0) {
+            bstr[--k] = bytes1(uint8(48 + (j % 10)));
+            j /= 10;
+        }
+        str = string(bstr);
+    }
+}

+ 12 - 0
target_chains/ethereum/sdk/stylus/pyth-mock-solidity/src/MockPyth.sol

@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: Apache 2
+pragma solidity ^0.8.13;
+
+import "@pythnetwork/pyth-sdk-solidity/MockPyth.sol";
+import {console} from "forge-std/console.sol";
+
+contract MockPythSample is MockPyth {
+    constructor(
+        uint validTimePeriod,
+        uint singleUpdateFeeInWei
+    ) MockPyth(validTimePeriod, singleUpdateFeeInWei) {}
+}

+ 8 - 0
target_chains/ethereum/sdk/stylus/pyth-mock-solidity/test/MockPyth.t.sol

@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: Apache 2
+pragma solidity ^0.8.13;
+
+import {Test, console} from "forge-std/Test.sol";
+
+contract MockPythTest is Test {
+    function setUp() public {}
+}

+ 4 - 0
target_chains/ethereum/sdk/stylus/rust-toolchain.toml

@@ -0,0 +1,4 @@
+[toolchain]
+channel = "nightly-2024-09-05"
+components = ["rust-src"]
+targets = ["wasm32-unknown-unknown"]

+ 73 - 0
target_chains/ethereum/sdk/stylus/scripts/bench.sh

@@ -0,0 +1,73 @@
+#!/bin/bash
+set -e
+
+if [ -z "$CI" ]; then
+
+MYDIR=$(realpath "$(dirname "$0")")
+cd "$MYDIR"
+cd ..
+
+export RPC_URL=http://localhost:8547
+export PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
+export WALLER_ADDRESS=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
+ls
+cd "nitro-testnode"
+./test-node.bash script send-l2 --to address_$WALLER_ADDRESS --ethamount 0.1
+
+cd ..
+cd "pyth-mock-solidity"
+deployed_to=$(
+  forge script ./script/MockPyth.s.sol:MockPythScript \
+  --rpc-url "$RPC_URL" \
+  --private-key "$PRIVATE_KEY" \
+  --broadcast \ | grep -oP '(?<=Pyth contract address: )0x[a-fA-F0-9]{40}' | tail -n 1
+)
+
+export MOCK_PYTH_ADDRESS=$deployed_to
+cd ..
+else
+  echo "Skipping MockPyth deployment in CI"
+fi
+
+
+MYDIR=$(realpath "$(dirname "$0")")
+cd "$MYDIR"
+cd ..
+
+# Optimize contract's wasm binary by crate name.
+opt_wasm () {
+  local CONTRACT_CRATE_NAME=$1
+  local CONTRACT_BIN_NAME="${CONTRACT_CRATE_NAME//-/_}.wasm"
+  local CONTRACT_OPT_BIN_NAME="${CONTRACT_CRATE_NAME//-/_}_opt.wasm"
+
+  echo
+  echo "Optimizing $CONTRACT_CRATE_NAME WASM binary"
+  # https://rustwasm.github.io/book/reference/code-size.html#use-the-wasm-opt-tool
+  wasm-opt -O3 -o ./target/wasm32-unknown-unknown/release/"$CONTRACT_OPT_BIN_NAME" ./target/wasm32-unknown-unknown/release/"$CONTRACT_BIN_NAME"
+}
+
+# Retrieve all alphanumeric contract's crate names in `./examples` directory.
+get_example_crate_names () {
+  # shellcheck disable=SC2038
+  # NOTE: optimistically relying on the 'name = ' string at Cargo.toml file
+  find ./examples -maxdepth 2 -type f -name "Cargo.toml" | xargs grep 'name = ' | grep -oE '".*"' | tr -d "'\""
+}
+
+cargo build --release --target wasm32-unknown-unknown -Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort
+
+# Optimize contract's wasm for gas usage.
+for CRATE_NAME in $(get_example_crate_names)
+do
+  opt_wasm "$CRATE_NAME"
+done
+
+export RPC_URL=http://localhost:8547
+
+# No need to compile benchmarks with `--release`
+# since this only runs the benchmarking code and the contracts have already been compiled with `--release`.
+cargo run -p benches
+
+echo "NOTE: To measure non cached contract's gas usage correctly,
+ benchmarks should run on a clean instance of the nitro test node."
+echo
+echo "Finished running benches!"

+ 30 - 0
target_chains/ethereum/sdk/stylus/scripts/check-wasm.sh

@@ -0,0 +1,30 @@
+#!/bin/bash
+set -e
+
+mydir=$(dirname "$0")
+cd "$mydir" || exit
+cd ..
+
+# Check contract wasm binary by crate name
+check_wasm () {
+  local CONTRACT_CRATE_NAME=$1
+  local CONTRACT_BIN_NAME="${CONTRACT_CRATE_NAME//-/_}.wasm"
+
+  echo
+  echo "Checking contract $CONTRACT_CRATE_NAME"
+  cargo stylus check -e https://sepolia-rollup.arbitrum.io/rpc --wasm-file ./target/wasm32-unknown-unknown/release/"$CONTRACT_BIN_NAME"
+}
+
+# Retrieve all alphanumeric contract's crate names in `./examples` directory.
+get_example_crate_names () {
+  # shellcheck disable=SC2038
+  # NOTE: optimistically relying on the 'name = ' string at Cargo.toml file
+  find ./examples -maxdepth 2 -type f -name "Cargo.toml" | xargs grep 'name = ' | grep -oE '".*"' | tr -d "'\""
+}
+
+cargo build --release --target wasm32-unknown-unknown -Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort
+
+for CRATE_NAME in $(get_example_crate_names)
+do
+  check_wasm "$CRATE_NAME"
+done

+ 46 - 0
target_chains/ethereum/sdk/stylus/scripts/deploy.sh

@@ -0,0 +1,46 @@
+#!/bin/bash
+# This script compiles Rust contracts to WebAssembly and deploys the .wasm binaries to a blockchain using `cargo stylus deploy`.
+# It retrieves crate names from Cargo.toml files in the examples directory and automates the deployment process for each contract.
+
+set -e
+
+mydir=$(dirname "$0")
+cd "$mydir" || exit
+cd ..
+
+export RPC_URL=http://localhost:8547
+export PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
+export WALLER_ADDRESS=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
+
+cd "nitro-testnode"
+./test-node.bash script send-l2 --to address_$WALLER_ADDRESS --ethamount 0.1
+
+
+cd ..
+# Check contract wasm binary by crate name
+deploy_wasm () {
+  local CONTRACT_CRATE_NAME=$1
+  local CONTRACT_BIN_NAME="${CONTRACT_CRATE_NAME//-/_}.wasm"
+
+  echo "deploy contract $CONTRACT_CRATE_NAME"
+  cargo stylus deploy --wasm-file ./target/wasm32-unknown-unknown/release/"$CONTRACT_BIN_NAME" \
+  --endpoint $RPC_URL \
+  --private-key $PRIVATE_KEY \
+  --no-verify
+  }
+
+# Retrieve all alphanumeric contract's crate names in `./examples` directory.
+get_example_crate_names () {
+  # shellcheck disable=SC2038
+  # NOTE: optimistically relying on the 'name = ' string at Cargo.toml file
+  find ./examples -maxdepth 2 -type f -name "Cargo.toml" | xargs grep 'name = ' | grep -oE '".*"' | tr -d "'\""
+}
+
+NIGHTLY_TOOLCHAIN=${NIGHTLY_TOOLCHAIN:-nightly-2024-09-05}
+
+cargo +"$NIGHTLY_TOOLCHAIN" build --release --target wasm32-unknown-unknown -Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort
+
+for CRATE_NAME in $(get_example_crate_names)
+do
+  deploy_wasm "$CRATE_NAME"
+done

+ 45 - 0
target_chains/ethereum/sdk/stylus/scripts/e2e-tests.sh

@@ -0,0 +1,45 @@
+#!/bin/bash
+set -e
+
+if [ -z "$CI" ]; then
+
+MYDIR=$(realpath "$(dirname "$0")")
+cd "$MYDIR"
+
+export RPC_URL=http://localhost:8547
+export PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
+export WALLET_ADDRESS=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
+
+cd ..
+cd "nitro-testnode"
+./test-node.bash script send-l2 --to address_$WALLET_ADDRESS --ethamount 0.1
+
+cd ..
+cd "pyth-mock-solidity"
+deployed_to=$(
+  forge script ./script/MockPyth.s.sol:MockPythScript \
+  --rpc-url "$RPC_URL" \
+  --private-key "$PRIVATE_KEY" \
+  --broadcast \
+  | grep -oP '(?<=Pyth contract address: )0x[a-fA-F0-9]{40}' | tail -n 1
+)
+export MOCK_PYTH_ADDRESS=$deployed_to
+cd ..
+else
+  echo "Skipping MockPyth deployment in CI"
+fi
+
+env
+# Navigate to project root
+cd "$(dirname "$(realpath "$0")")/.."
+
+cargo build --release --target wasm32-unknown-unknown -Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort
+
+export RPC_URL=http://localhost:8547
+
+# If any arguments are set, just pass them as-is to the cargo test command
+if [[ $# -eq 0 ]]; then
+    cargo test --features e2e --test "*"
+else
+    cargo test --features e2e "$@"
+fi

+ 66 - 0
target_chains/ethereum/sdk/stylus/scripts/nitro-testnode.sh

@@ -0,0 +1,66 @@
+#!/bin/bash
+
+MYDIR=$(realpath "$(dirname "$0")")
+cd "$MYDIR" || exit
+
+HAS_INIT=false
+HAS_DETACH=false
+
+while [[ $# -gt 0 ]]
+do
+  case "$1" in
+    -i|--init)
+      HAS_INIT=true
+      shift
+      ;;
+    -d|--detach)
+      HAS_DETACH=true
+      shift
+      ;;
+    -q|--quit)
+      NITRO_CONTAINERS=$(docker container ls -q --filter name=nitro-testnode)
+
+      if [ -z "$NITRO_CONTAINERS" ]; then
+          echo "No nitro-testnode containers running"
+      else
+          docker container stop $NITRO_CONTAINERS || exit
+      fi
+
+      exit 0
+      ;;
+    *)
+      echo "OPTIONS:"
+      echo "-i|--init:         clone repo and init nitro test node"
+      echo "-d|--detach:       setup nitro test node in detached mode"
+      echo "-q|--quit:         shutdown nitro test node docker containers"
+      exit 0
+      ;;
+  esac
+done
+
+TEST_NODE_DIR="$MYDIR/../nitro-testnode"
+if [ ! -d "$TEST_NODE_DIR" ]; then
+  HAS_INIT=true
+fi
+
+if $HAS_INIT
+then
+  cd "$MYDIR" || exit
+  cd ..
+
+  git clone --recurse-submodules https://github.com/OffchainLabs/nitro-testnode.git
+  cd ./nitro-testnode || exit
+  git pull origin release --recurse-submodules
+  git checkout af851769d52cab38bc3733dbd0a4db6120fa7864 || exit
+
+  ./test-node.bash --no-run --init || exit
+fi
+
+
+cd "$TEST_NODE_DIR" || exit
+if $HAS_DETACH
+then
+  ./test-node.bash --detach
+else
+  ./test-node.bash
+fi