eth 0.5.14 → 0.5.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.github/workflows/codeql.yml +4 -4
 - data/.github/workflows/docs.yml +1 -1
 - data/.github/workflows/spec.yml +31 -13
 - data/CHANGELOG.md +53 -0
 - data/CODE_OF_CONDUCT.md +3 -5
 - data/Gemfile +3 -3
 - data/README.md +8 -6
 - data/SECURITY.md +2 -2
 - data/eth.gemspec +10 -1
 - data/lib/eth/abi/decoder.rb +94 -39
 - data/lib/eth/abi/encoder.rb +85 -58
 - data/lib/eth/abi/function.rb +124 -0
 - data/lib/eth/abi/type.rb +69 -5
 - data/lib/eth/abi.rb +2 -0
 - data/lib/eth/bls.rb +68 -0
 - data/lib/eth/chain.rb +3 -0
 - data/lib/eth/client/http.rb +5 -8
 - data/lib/eth/client/ws.rb +323 -0
 - data/lib/eth/client.rb +44 -40
 - data/lib/eth/contract/error.rb +62 -0
 - data/lib/eth/contract/function.rb +21 -0
 - data/lib/eth/contract/function_output.rb +11 -3
 - data/lib/eth/contract.rb +55 -4
 - data/lib/eth/eip712.rb +48 -13
 - data/lib/eth/key.rb +1 -1
 - data/lib/eth/tx/eip1559.rb +32 -7
 - data/lib/eth/tx/eip2930.rb +31 -6
 - data/lib/eth/tx/eip4844.rb +401 -0
 - data/lib/eth/tx/eip7702.rb +34 -9
 - data/lib/eth/tx/legacy.rb +30 -6
 - data/lib/eth/tx.rb +45 -4
 - data/lib/eth/util.rb +19 -7
 - data/lib/eth/version.rb +1 -1
 - data/lib/eth.rb +1 -0
 - metadata +53 -15
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: ad70051a0aa71d2f7ed5a4acea236b677c9d1f4eb3467f8194de19a8de9f8714
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 5558228d301116bd2be49ac184c01f3c2d1cb0e725deb9ab3f070021927b63cf
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: acf9b6267efa46befed740d7d00c5938ed8d384b3297c57953f71c2ae5ebac31bd279a44694dd3675f77648f66e381dccacb70f533896600b3fd1bdc15a04a3b
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: dbb137aa5449234ba86f64951740d0f985693f37d1da329a70b7efdfb44b17a8bb2511a74560ac07a8d116aba100894e584c55fc3cc367c5c91e48fed456593a
         
     | 
| 
         @@ -24,15 +24,15 @@ jobs: 
     | 
|
| 
       24 
24 
     | 
    
         
             
                      - ruby
         
     | 
| 
       25 
25 
     | 
    
         
             
                steps:
         
     | 
| 
       26 
26 
     | 
    
         
             
                  - name: "Checkout repository"
         
     | 
| 
       27 
     | 
    
         
            -
                    uses: actions/checkout@ 
     | 
| 
      
 27 
     | 
    
         
            +
                    uses: actions/checkout@v5
         
     | 
| 
       28 
28 
     | 
    
         
             
                  - name: "Initialize CodeQL"
         
     | 
| 
       29 
     | 
    
         
            -
                    uses: github/codeql-action/init@ 
     | 
| 
      
 29 
     | 
    
         
            +
                    uses: github/codeql-action/init@v4
         
     | 
| 
       30 
30 
     | 
    
         
             
                    with:
         
     | 
| 
       31 
31 
     | 
    
         
             
                      languages: "${{ matrix.language }}"
         
     | 
| 
       32 
32 
     | 
    
         
             
                  - name: Autobuild
         
     | 
| 
       33 
     | 
    
         
            -
                    uses: github/codeql-action/autobuild@ 
     | 
| 
      
 33 
     | 
    
         
            +
                    uses: github/codeql-action/autobuild@v4
         
     | 
| 
       34 
34 
     | 
    
         
             
                  - name: "Perform CodeQL Analysis"
         
     | 
| 
       35 
     | 
    
         
            -
                    uses: github/codeql-action/analyze@ 
     | 
| 
      
 35 
     | 
    
         
            +
                    uses: github/codeql-action/analyze@v4
         
     | 
| 
       36 
36 
     | 
    
         
             
                  - uses: ruby/setup-ruby@v1
         
     | 
| 
       37 
37 
     | 
    
         
             
                    with:
         
     | 
| 
       38 
38 
     | 
    
         
             
                      ruby-version: '3.4'
         
     | 
    
        data/.github/workflows/docs.yml
    CHANGED
    
    
    
        data/.github/workflows/spec.yml
    CHANGED
    
    | 
         @@ -21,33 +21,51 @@ jobs: 
     | 
|
| 
       21 
21 
     | 
    
         
             
                    os: [ubuntu-latest, macos-latest]
         
     | 
| 
       22 
22 
     | 
    
         
             
                    ruby: ['3.3', '3.4']
         
     | 
| 
       23 
23 
     | 
    
         
             
                steps:
         
     | 
| 
       24 
     | 
    
         
            -
                - uses: actions/checkout@ 
     | 
| 
       25 
     | 
    
         
            -
                - uses: ruby/setup-ruby@v1
         
     | 
| 
       26 
     | 
    
         
            -
                  with:
         
     | 
| 
       27 
     | 
    
         
            -
                    ruby-version: ${{ matrix.ruby }}
         
     | 
| 
       28 
     | 
    
         
            -
                    bundler-cache: false
         
     | 
| 
      
 24 
     | 
    
         
            +
                - uses: actions/checkout@v5
         
     | 
| 
       29 
25 
     | 
    
         
             
                - name: MacOs Dependencies
         
     | 
| 
      
 26 
     | 
    
         
            +
                  if: matrix.os == 'macos-latest'
         
     | 
| 
       30 
27 
     | 
    
         
             
                  run: |
         
     | 
| 
      
 28 
     | 
    
         
            +
                    brew update
         
     | 
| 
       31 
29 
     | 
    
         
             
                    brew tap ethereum/ethereum
         
     | 
| 
       32 
     | 
    
         
            -
                    brew install --verbose pkg-config  
     | 
| 
       33 
     | 
    
         
            -
                  if: startsWith(matrix.os, 'macOS')
         
     | 
| 
      
 30 
     | 
    
         
            +
                    brew install --verbose autoconf automake libtool pkg-config autogen geth solidity
         
     | 
| 
       34 
31 
     | 
    
         
             
                - name: Ubuntu Dependencies
         
     | 
| 
      
 32 
     | 
    
         
            +
                  if: matrix.os == 'ubuntu-latest'
         
     | 
| 
       35 
33 
     | 
    
         
             
                  run: |
         
     | 
| 
       36 
34 
     | 
    
         
             
                    sudo add-apt-repository -y ppa:ethereum/ethereum
         
     | 
| 
       37 
35 
     | 
    
         
             
                    sudo apt-get update
         
     | 
| 
       38 
     | 
    
         
            -
                    sudo apt-get install geth solc
         
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
      
 36 
     | 
    
         
            +
                    sudo apt-get install -y autoconf automake libtool pkg-config geth solc
         
     | 
| 
      
 37 
     | 
    
         
            +
                - uses: ruby/setup-ruby@v1
         
     | 
| 
      
 38 
     | 
    
         
            +
                  with:
         
     | 
| 
      
 39 
     | 
    
         
            +
                    ruby-version: ${{ matrix.ruby }}
         
     | 
| 
      
 40 
     | 
    
         
            +
                    bundler-cache: true
         
     | 
| 
       40 
41 
     | 
    
         
             
                - name: Run Geth
         
     | 
| 
       41 
42 
     | 
    
         
             
                  run: |
         
     | 
| 
       42 
     | 
    
         
            -
                    geth --dev  
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
      
 43 
     | 
    
         
            +
                    geth --dev \
         
     | 
| 
      
 44 
     | 
    
         
            +
                         --http \
         
     | 
| 
      
 45 
     | 
    
         
            +
                         --ws \
         
     | 
| 
      
 46 
     | 
    
         
            +
                         --ipcpath /tmp/geth.ipc \
         
     | 
| 
      
 47 
     | 
    
         
            +
                         >/tmp/geth.log 2>&1 &
         
     | 
| 
      
 48 
     | 
    
         
            +
                    echo $! > /tmp/geth.pid
         
     | 
| 
      
 49 
     | 
    
         
            +
                    sleep 10
         
     | 
| 
       44 
50 
     | 
    
         
             
                - name: Gem Dependencies
         
     | 
| 
       45 
51 
     | 
    
         
             
                  run: |
         
     | 
| 
       46 
     | 
    
         
            -
                    git submodule update --init
         
     | 
| 
       47 
     | 
    
         
            -
                    bundle install
         
     | 
| 
      
 52 
     | 
    
         
            +
                    git submodule update --init --recursive
         
     | 
| 
       48 
53 
     | 
    
         
             
                - name: Run Tests
         
     | 
| 
       49 
54 
     | 
    
         
             
                  run: |
         
     | 
| 
       50 
55 
     | 
    
         
             
                    bundle exec rspec
         
     | 
| 
      
 56 
     | 
    
         
            +
                - name: Stop Geth
         
     | 
| 
      
 57 
     | 
    
         
            +
                  if: always()
         
     | 
| 
      
 58 
     | 
    
         
            +
                  run: |
         
     | 
| 
      
 59 
     | 
    
         
            +
                    if [ -f /tmp/geth.pid ]; then
         
     | 
| 
      
 60 
     | 
    
         
            +
                      kill "$(cat /tmp/geth.pid)" 2>/dev/null || true
         
     | 
| 
      
 61 
     | 
    
         
            +
                    fi
         
     | 
| 
      
 62 
     | 
    
         
            +
                - name: Geth Logs (on failure)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  if: failure()
         
     | 
| 
      
 64 
     | 
    
         
            +
                  run: |
         
     | 
| 
      
 65 
     | 
    
         
            +
                    if [ -f /tmp/geth.log ]; then
         
     | 
| 
      
 66 
     | 
    
         
            +
                      echo "===== geth log ====="
         
     | 
| 
      
 67 
     | 
    
         
            +
                      tail -n 200 /tmp/geth.log
         
     | 
| 
      
 68 
     | 
    
         
            +
                    fi
         
     | 
| 
       51 
69 
     | 
    
         
             
                - name: Upload coverage to Codecov
         
     | 
| 
       52 
70 
     | 
    
         
             
                  uses: codecov/codecov-action@v5
         
     | 
| 
       53 
71 
     | 
    
         
             
                  with:
         
     | 
    
        data/CHANGELOG.md
    CHANGED
    
    | 
         @@ -1,6 +1,59 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # Change Log
         
     | 
| 
       2 
2 
     | 
    
         
             
            All notable changes to this project will be documented in this file.
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
      
 4 
     | 
    
         
            +
            ## [0.5.15]
         
     | 
| 
      
 5 
     | 
    
         
            +
            ### Added
         
     | 
| 
      
 6 
     | 
    
         
            +
            * Implement EIP712 array encoding [#361](https://github.com/q9f/eth.rb/pull/361)
         
     | 
| 
      
 7 
     | 
    
         
            +
            * Support nested dynamic arrays in ABI [#356](https://github.com/q9f/eth.rb/pull/356)
         
     | 
| 
      
 8 
     | 
    
         
            +
            * Allow signing transactions with external signatures [#349](https://github.com/q9f/eth.rb/pull/349)
         
     | 
| 
      
 9 
     | 
    
         
            +
            * Feat: add eip-4844 transactions [#345](https://github.com/q9f/eth.rb/pull/345)
         
     | 
| 
      
 10 
     | 
    
         
            +
            * Support Solidity custom errors per ERC-6093 [#344](https://github.com/q9f/eth.rb/pull/344)
         
     | 
| 
      
 11 
     | 
    
         
            +
            * Allow to use chains with id > 4294967295 [#337](https://github.com/q9f/eth.rb/pull/337)
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            ### Changed
         
     | 
| 
      
 14 
     | 
    
         
            +
            * Harden ABI type parsing [#358](https://github.com/q9f/eth.rb/pull/358)
         
     | 
| 
      
 15 
     | 
    
         
            +
            * Ensure ABI decoder rejects ZST offsets [#359](https://github.com/q9f/eth.rb/pull/359)
         
     | 
| 
      
 16 
     | 
    
         
            +
            * Test: decode eip4844 blobs [#360](https://github.com/q9f/eth.rb/pull/360)
         
     | 
| 
      
 17 
     | 
    
         
            +
            * Abi: decode transaction input [#354](https://github.com/q9f/eth.rb/pull/354)
         
     | 
| 
      
 18 
     | 
    
         
            +
            * Fix tuple output decoding for contract calls [#353](https://github.com/q9f/eth.rb/pull/353)
         
     | 
| 
      
 19 
     | 
    
         
            +
            * Add comprehensive Tx module tests [#352](https://github.com/q9f/eth.rb/pull/352)
         
     | 
| 
      
 20 
     | 
    
         
            +
            * Move error decoding to contract module [#350](https://github.com/q9f/eth.rb/pull/350)
         
     | 
| 
      
 21 
     | 
    
         
            +
            * Enforce minimal RLP integer decoding [#351](https://github.com/q9f/eth.rb/pull/351)
         
     | 
| 
      
 22 
     | 
    
         
            +
            * Fix tuple size calculation without components [#348](https://github.com/q9f/eth.rb/pull/348)
         
     | 
| 
      
 23 
     | 
    
         
            +
            * Docs: update readme [#347](https://github.com/q9f/eth.rb/pull/347)
         
     | 
| 
      
 24 
     | 
    
         
            +
            * Chore: update development dependencies [#346](https://github.com/q9f/eth.rb/pull/346)
         
     | 
| 
      
 25 
     | 
    
         
            +
            * Handle hex string inputs in big-endian conversion [#343](https://github.com/q9f/eth.rb/pull/343)
         
     | 
| 
      
 26 
     | 
    
         
            +
            * Handle uppercase hex prefixes [#339](https://github.com/q9f/eth.rb/pull/339)
         
     | 
| 
      
 27 
     | 
    
         
            +
            * Add methods to encode function call and decode its result [#334](https://github.com/q9f/eth.rb/pull/334)
         
     | 
| 
      
 28 
     | 
    
         
            +
            * Docs(util): fix hex? return type [#342](https://github.com/q9f/eth.rb/pull/342)
         
     | 
| 
      
 29 
     | 
    
         
            +
            * Handle hex input consistently in int_to_big_endian [#341](https://github.com/q9f/eth.rb/pull/341)
         
     | 
| 
      
 30 
     | 
    
         
            +
            * Fix receiver option spelling [#340](https://github.com/q9f/eth.rb/pull/340)
         
     | 
| 
      
 31 
     | 
    
         
            +
            * Chore: bump version to 0.5.15 [#333](https://github.com/q9f/eth.rb/pull/333)
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            ## [0.5.14]
         
     | 
| 
      
 34 
     | 
    
         
            +
            ### Added
         
     | 
| 
      
 35 
     | 
    
         
            +
            * Add ability to decode event parameters using ABI reference. [#328](https://github.com/q9f/eth.rb/pull/328)
         
     | 
| 
      
 36 
     | 
    
         
            +
            * Add support for EIP-7702 transactions  [#320](https://github.com/q9f/eth.rb/pull/320)
         
     | 
| 
      
 37 
     | 
    
         
            +
            * Eth/abi: implement packed encoder [#310](https://github.com/q9f/eth.rb/pull/310)
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            ### Changed
         
     | 
| 
      
 40 
     | 
    
         
            +
            * Chore: run rufo, add docs [#332](https://github.com/q9f/eth.rb/pull/332)
         
     | 
| 
      
 41 
     | 
    
         
            +
            * Spec/client: fix nonce too low error handling in spec [#331](https://github.com/q9f/eth.rb/pull/331)
         
     | 
| 
      
 42 
     | 
    
         
            +
            * Move the tests that are failing due to a geth upgrade to pending  [#330](https://github.com/q9f/eth.rb/pull/330)
         
     | 
| 
      
 43 
     | 
    
         
            +
            * Spec/client: don't require any rpc api token for tests [#326](https://github.com/q9f/eth.rb/pull/326)
         
     | 
| 
      
 44 
     | 
    
         
            +
            * Build(deps): bump JamesIves/github-pages-deploy-action from 4.7.2 to 4.7.3 [#327](https://github.com/q9f/eth.rb/pull/327)
         
     | 
| 
      
 45 
     | 
    
         
            +
            * Eth/eip712: prepare tests for packed encoding [#216](https://github.com/q9f/eth.rb/pull/216)
         
     | 
| 
      
 46 
     | 
    
         
            +
            * Spec/solidity: mute system call output [#319](https://github.com/q9f/eth.rb/pull/319)
         
     | 
| 
      
 47 
     | 
    
         
            +
            * Updated nesting of describe blocks in the EIP-1559 spec. [#318](https://github.com/q9f/eth.rb/pull/318)
         
     | 
| 
      
 48 
     | 
    
         
            +
            * Update README.md [#317](https://github.com/q9f/eth.rb/pull/317)
         
     | 
| 
      
 49 
     | 
    
         
            +
            * Docs: update README.md [#314](https://github.com/q9f/eth.rb/pull/314)
         
     | 
| 
      
 50 
     | 
    
         
            +
            * Gem: update copyright headers [#312](https://github.com/q9f/eth.rb/pull/312)
         
     | 
| 
      
 51 
     | 
    
         
            +
            * Build(deps): bump JamesIves/github-pages-deploy-action from 4.7.1 to 4.7.2 [#309](https://github.com/q9f/eth.rb/pull/309)
         
     | 
| 
      
 52 
     | 
    
         
            +
            * Spec: switch from infura to drpc [#308](https://github.com/q9f/eth.rb/pull/308)
         
     | 
| 
      
 53 
     | 
    
         
            +
            * Ci: update ruby version [#307](https://github.com/q9f/eth.rb/pull/307)
         
     | 
| 
      
 54 
     | 
    
         
            +
            * Gem: bump version to 0.5.14 [#305](https://github.com/q9f/eth.rb/pull/305)
         
     | 
| 
      
 55 
     | 
    
         
            +
            * Docs: update changelog [#304](https://github.com/q9f/eth.rb/pull/304)
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
       4 
57 
     | 
    
         
             
            ## [0.5.13]
         
     | 
| 
       5 
58 
     | 
    
         
             
            ### Changed
         
     | 
| 
       6 
59 
     | 
    
         
             
            * Eth/api: update to latest available go-ethereum apis [#301](https://github.com/q9f/eth.rb/pull/301)
         
     | 
    
        data/CODE_OF_CONDUCT.md
    CHANGED
    
    | 
         @@ -115,8 +115,6 @@ community. 
     | 
|
| 
       115 
115 
     | 
    
         | 
| 
       116 
116 
     | 
    
         
             
            ## Attribution
         
     | 
| 
       117 
117 
     | 
    
         | 
| 
       118 
     | 
    
         
            -
            This Code of Conduct is adapted from the [Contributor Covenant] 
     | 
| 
       119 
     | 
    
         
            -
            version 2.1, available at
         
     | 
| 
       120 
     | 
    
         
            -
             
     | 
| 
       121 
     | 
    
         
            -
            Community Impact Guidelines were inspired by
         
     | 
| 
       122 
     | 
    
         
            -
            [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
         
     | 
| 
      
 118 
     | 
    
         
            +
            This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org),
         
     | 
| 
      
 119 
     | 
    
         
            +
            version 2.1, available at [v2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct.html).
         
     | 
| 
      
 120 
     | 
    
         
            +
            Community Impact Guidelines were inspired by Mozilla's code of conduct enforcement ladder.
         
     | 
    
        data/Gemfile
    CHANGED
    
    | 
         @@ -3,14 +3,14 @@ 
     | 
|
| 
       3 
3 
     | 
    
         
             
            source "https://rubygems.org"
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
            group :test, :development do
         
     | 
| 
       6 
     | 
    
         
            -
              gem "bundler", "~> 2. 
     | 
| 
      
 6 
     | 
    
         
            +
              gem "bundler", "~> 2.5"
         
     | 
| 
       7 
7 
     | 
    
         
             
              gem "pry", "~> 0.15"
         
     | 
| 
       8 
8 
     | 
    
         
             
              gem "rake", "~> 13.2"
         
     | 
| 
       9 
     | 
    
         
            -
              gem "rdoc", "~> 6. 
     | 
| 
      
 9 
     | 
    
         
            +
              gem "rdoc", "~> 6.13"
         
     | 
| 
       10 
10 
     | 
    
         
             
              gem "rspec", "~> 3.13"
         
     | 
| 
       11 
11 
     | 
    
         
             
              gem "rufo", "~> 0.18"
         
     | 
| 
       12 
12 
     | 
    
         
             
              gem "simplecov", "~> 0.22"
         
     | 
| 
       13 
     | 
    
         
            -
              gem "simplecov-cobertura", "~>  
     | 
| 
      
 13 
     | 
    
         
            +
              gem "simplecov-cobertura", "~> 3.0"
         
     | 
| 
       14 
14 
     | 
    
         
             
              gem "yard", "~> 0.9"
         
     | 
| 
       15 
15 
     | 
    
         
             
            end
         
     | 
| 
       16 
16 
     | 
    
         | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -10,9 +10,7 @@ 
     | 
|
| 
       10 
10 
     | 
    
         
             
            [](https://github.com/q9f/eth.rb/releases)
         
     | 
| 
       11 
11 
     | 
    
         
             
            [](https://rubygems.org/gems/eth)
         
     | 
| 
       12 
12 
     | 
    
         
             
            [](https://rubygems.org/gems/eth)
         
     | 
| 
       13 
     | 
    
         
            -
            [](https://hits.seeyoufarm.com)
         
     | 
| 
       14 
13 
     | 
    
         
             
            [](https://codecov.io/gh/q9f/eth.rb)
         
     | 
| 
       15 
     | 
    
         
            -
            [](https://codeclimate.com/github/q9f/eth.rb/maintainability)
         
     | 
| 
       16 
14 
     | 
    
         
             
            [](https://github.com/q9f/eth.rb/pulse)
         
     | 
| 
       17 
15 
     | 
    
         
             
            [](https://q9f.github.io/eth.rb)
         
     | 
| 
       18 
16 
     | 
    
         
             
            [](https://github.com/q9f/eth.rb/wiki)
         
     | 
| 
         @@ -34,11 +32,15 @@ What you get: 
     | 
|
| 
       34 
32 
     | 
    
         
             
            - [x] EIP-2028 Call-data intrinsic gas cost estimates (plus access lists)
         
     | 
| 
       35 
33 
     | 
    
         
             
            - [x] EIP-2718 Ethereum Transaction Envelopes (and types)
         
     | 
| 
       36 
34 
     | 
    
         
             
            - [x] EIP-2930 Ethereum Type-1 Transactions (with access lists)
         
     | 
| 
      
 35 
     | 
    
         
            +
            - [x] EIP-4844 Ethereum Type-3 Transactions (with shard blobs, up to 9 blobs per block)
         
     | 
| 
      
 36 
     | 
    
         
            +
            - [x] EIP-7702 Ethereum Type-4 Transactions (with authorization lists)
         
     | 
| 
       37 
37 
     | 
    
         
             
            - [x] ABI-Encoder and Decoder (including type parser)
         
     | 
| 
      
 38 
     | 
    
         
            +
            - [x] Packed ABI-Encoder for Solidity smart contracts
         
     | 
| 
       38 
39 
     | 
    
         
             
            - [x] RLP-Encoder and Decoder (including sedes)
         
     | 
| 
       39 
     | 
    
         
            -
            - [x] RPC-Client (IPC/HTTP) for Execution-Layer APIs
         
     | 
| 
      
 40 
     | 
    
         
            +
            - [x] RPC-Client (IPC/HTTP/WS) for Execution-Layer APIs
         
     | 
| 
       40 
41 
     | 
    
         
             
            - [x] Solidity bindings (compile contracts from Ruby)
         
     | 
| 
       41 
42 
     | 
    
         
             
            - [x] Full smart-contract support (deploy, transact, and call)
         
     | 
| 
      
 43 
     | 
    
         
            +
            - [x] ERC-6093 custom Solidity errors
         
     | 
| 
       42 
44 
     | 
    
         | 
| 
       43 
45 
     | 
    
         
             
            ## Installation
         
     | 
| 
       44 
46 
     | 
    
         
             
            Add this line to your application's Gemfile:
         
     | 
| 
         @@ -74,10 +76,10 @@ yard doc 
     | 
|
| 
       74 
76 
     | 
    
         
             
            The goal is to have 100% API documentation available.
         
     | 
| 
       75 
77 
     | 
    
         | 
| 
       76 
78 
     | 
    
         
             
            ## Testing
         
     | 
| 
       77 
     | 
    
         
            -
            The test suite expects working local HTTP and IPC endpoints with a prefunded developer account, e.g.:
         
     | 
| 
      
 79 
     | 
    
         
            +
            The test suite expects working local HTTP, WS, and IPC endpoints with a prefunded developer account, e.g.:
         
     | 
| 
       78 
80 
     | 
    
         | 
| 
       79 
81 
     | 
    
         
             
            ```shell
         
     | 
| 
       80 
     | 
    
         
            -
            geth --dev --http --ipcpath /tmp/geth.ipc &
         
     | 
| 
      
 82 
     | 
    
         
            +
            geth --dev --http --ws --ipcpath /tmp/geth.ipc &
         
     | 
| 
       81 
83 
     | 
    
         
             
            ```
         
     | 
| 
       82 
84 
     | 
    
         | 
| 
       83 
85 
     | 
    
         
             
            To run tests, simply use `rspec`. Note, that the Ethereum test fixtures are also required.
         
     | 
| 
         @@ -88,7 +90,7 @@ bundle install 
     | 
|
| 
       88 
90 
     | 
    
         
             
            rspec
         
     | 
| 
       89 
91 
     | 
    
         
             
            ```
         
     | 
| 
       90 
92 
     | 
    
         | 
| 
       91 
     | 
    
         
            -
            The goal is to have 100%  
     | 
| 
      
 93 
     | 
    
         
            +
            The goal is to have 100% unit-test coverage for all code inside this gem.
         
     | 
| 
       92 
94 
     | 
    
         | 
| 
       93 
95 
     | 
    
         
             
            ## Contributing
         
     | 
| 
       94 
96 
     | 
    
         
             
            Pull requests are welcome! To contribute, please consider the following:
         
     | 
    
        data/SECURITY.md
    CHANGED
    
    | 
         @@ -10,8 +10,8 @@ later. 
     | 
|
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         
             
            | Gem            | Version | Supported          |
         
     | 
| 
       12 
12 
     | 
    
         
             
            | -------------- | ------- | ------------------ |
         
     | 
| 
       13 
     | 
    
         
            -
            | `eth`          | 0.5 
     | 
| 
       14 
     | 
    
         
            -
            | `eth`          | < 
     | 
| 
      
 13 
     | 
    
         
            +
            | `eth`          | >= 0.5  | :white_check_mark: |
         
     | 
| 
      
 14 
     | 
    
         
            +
            | `eth`          | <  0.5  | :x:                |
         
     | 
| 
       15 
15 
     | 
    
         
             
            | `ethereum`     | _any_   | :x:                |
         
     | 
| 
       16 
16 
     | 
    
         
             
            | `ethereum-abi` | _any_   | :x:                |
         
     | 
| 
       17 
17 
     | 
    
         
             
            | `rlp`          | _any_   | :x:                |
         
     | 
    
        data/eth.gemspec
    CHANGED
    
    | 
         @@ -50,8 +50,17 @@ Gem::Specification.new do |spec| 
     | 
|
| 
       50 
50 
     | 
    
         
             
              spec.add_dependency "rbsecp256k1", "~> 6.0"
         
     | 
| 
       51 
51 
     | 
    
         | 
| 
       52 
52 
     | 
    
         
             
              # openssl for encrypted key derivation
         
     | 
| 
       53 
     | 
    
         
            -
              spec.add_dependency "openssl", " 
     | 
| 
      
 53 
     | 
    
         
            +
              spec.add_dependency "openssl", "~> 3.3"
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
              # base64 is required explicitly in Ruby >= 3.4
         
     | 
| 
      
 56 
     | 
    
         
            +
              spec.add_dependency "base64", "~> 0.1"
         
     | 
| 
       54 
57 
     | 
    
         | 
| 
       55 
58 
     | 
    
         
             
              # scrypt for encrypted key derivation
         
     | 
| 
       56 
59 
     | 
    
         
             
              spec.add_dependency "scrypt", "~> 3.0"
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
              # bls12-381 for BLS signatures and pairings
         
     | 
| 
      
 62 
     | 
    
         
            +
              spec.add_dependency "bls12-381", "~> 0.3"
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
              # httpx for HTTP/2 and persistent connections
         
     | 
| 
      
 65 
     | 
    
         
            +
              spec.add_dependency "httpx", "~> 1.6"
         
     | 
| 
       57 
66 
     | 
    
         
             
            end
         
     | 
    
        data/lib/eth/abi/decoder.rb
    CHANGED
    
    | 
         @@ -31,59 +31,91 @@ module Eth 
     | 
|
| 
       31 
31 
     | 
    
         
             
                  # @return [String] the decoded data for the type.
         
     | 
| 
       32 
32 
     | 
    
         
             
                  # @raise [DecodingError] if decoding fails for type.
         
     | 
| 
       33 
33 
     | 
    
         
             
                  def type(type, arg)
         
     | 
| 
       34 
     | 
    
         
            -
                    if %w(string bytes).include?(type.base_type) and type.sub_type.empty?
         
     | 
| 
       35 
     | 
    
         
            -
                       
     | 
| 
       36 
     | 
    
         
            -
                       
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
                        data = arg[32..-1]
         
     | 
| 
       39 
     | 
    
         
            -
                        raise DecodingError, "Wrong data size for string/bytes object" unless data.size == Util.ceil32(l)
         
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
                        # decoded strings and bytes
         
     | 
| 
       42 
     | 
    
         
            -
                        data[0, l]
         
     | 
| 
       43 
     | 
    
         
            -
                        # Case: decoding array of string/bytes
         
     | 
| 
       44 
     | 
    
         
            -
                      else
         
     | 
| 
       45 
     | 
    
         
            -
                        l = Util.deserialize_big_endian_to_int arg[0, 32]
         
     | 
| 
      
 34 
     | 
    
         
            +
                    if %w(string bytes).include?(type.base_type) and type.sub_type.empty? and type.dimensions.empty?
         
     | 
| 
      
 35 
     | 
    
         
            +
                      l = Util.deserialize_big_endian_to_int arg[0, 32]
         
     | 
| 
      
 36 
     | 
    
         
            +
                      data = arg[32..-1]
         
     | 
| 
      
 37 
     | 
    
         
            +
                      raise DecodingError, "Wrong data size for string/bytes object" unless data.size == Util.ceil32(l)
         
     | 
| 
       46 
38 
     | 
    
         | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
                          data_l = Util.deserialize_big_endian_to_int arg[32 + pointer, 32] # length of the element
         
     | 
| 
       51 
     | 
    
         
            -
                          type(Type.parse(type.base_type), arg[pointer + 32, Util.ceil32(data_l) + 32])
         
     | 
| 
       52 
     | 
    
         
            -
                        end
         
     | 
| 
       53 
     | 
    
         
            -
                      end
         
     | 
| 
       54 
     | 
    
         
            -
                    elsif type.base_type == "tuple"
         
     | 
| 
      
 39 
     | 
    
         
            +
                      # decoded strings and bytes
         
     | 
| 
      
 40 
     | 
    
         
            +
                      data[0, l]
         
     | 
| 
      
 41 
     | 
    
         
            +
                    elsif type.base_type == "tuple" && type.dimensions.empty?
         
     | 
| 
       55 
42 
     | 
    
         
             
                      offset = 0
         
     | 
| 
       56 
     | 
    
         
            -
                       
     | 
| 
      
 43 
     | 
    
         
            +
                      result = []
         
     | 
| 
       57 
44 
     | 
    
         
             
                      raise DecodingError, "Cannot decode tuples without known components" if type.components.nil?
         
     | 
| 
       58 
     | 
    
         
            -
                      type.components.each do |c|
         
     | 
| 
       59 
     | 
    
         
            -
                        if c.dynamic?
         
     | 
| 
       60 
     | 
    
         
            -
                          pointer = Util.deserialize_big_endian_to_int arg[offset, 32] # Pointer to the size of the array's element
         
     | 
| 
       61 
     | 
    
         
            -
                          data_len = Util.deserialize_big_endian_to_int arg[pointer, 32] # length of the element
         
     | 
| 
       62 
45 
     | 
    
         | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
      
 46 
     | 
    
         
            +
                      head_offset = 0
         
     | 
| 
      
 47 
     | 
    
         
            +
                      dynamic_offsets = []
         
     | 
| 
      
 48 
     | 
    
         
            +
                      type.components.each_with_index do |component, index|
         
     | 
| 
      
 49 
     | 
    
         
            +
                        if component.dynamic?
         
     | 
| 
      
 50 
     | 
    
         
            +
                          raise DecodingError, "Offset out of bounds" if head_offset + 32 > arg.size
         
     | 
| 
      
 51 
     | 
    
         
            +
                          pointer = Util.deserialize_big_endian_to_int arg[head_offset, 32]
         
     | 
| 
      
 52 
     | 
    
         
            +
                          dynamic_offsets << [index, pointer]
         
     | 
| 
      
 53 
     | 
    
         
            +
                          head_offset += 32
         
     | 
| 
      
 54 
     | 
    
         
            +
                        else
         
     | 
| 
      
 55 
     | 
    
         
            +
                          size = component.size
         
     | 
| 
      
 56 
     | 
    
         
            +
                          raise DecodingError, "Offset out of bounds" if head_offset + size > arg.size
         
     | 
| 
      
 57 
     | 
    
         
            +
                          head_offset += size
         
     | 
| 
      
 58 
     | 
    
         
            +
                        end
         
     | 
| 
      
 59 
     | 
    
         
            +
                      end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                      dynamic_ranges = tuple_dynamic_ranges(dynamic_offsets, arg.size, head_offset)
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                      type.components.each_with_index do |component, index|
         
     | 
| 
      
 64 
     | 
    
         
            +
                        if component.dynamic?
         
     | 
| 
      
 65 
     | 
    
         
            +
                          pointer, next_offset = dynamic_ranges[index]
         
     | 
| 
      
 66 
     | 
    
         
            +
                          raise DecodingError, "Offset out of bounds" if pointer > arg.size || next_offset > arg.size
         
     | 
| 
      
 67 
     | 
    
         
            +
                          raise DecodingError, "Offset out of bounds" if next_offset < pointer
         
     | 
| 
      
 68 
     | 
    
         
            +
                          result << type(component, arg[pointer, next_offset - pointer])
         
     | 
| 
       64 
69 
     | 
    
         
             
                          offset += 32
         
     | 
| 
       65 
70 
     | 
    
         
             
                        else
         
     | 
| 
       66 
     | 
    
         
            -
                          size =  
     | 
| 
       67 
     | 
    
         
            -
                           
     | 
| 
      
 71 
     | 
    
         
            +
                          size = component.size
         
     | 
| 
      
 72 
     | 
    
         
            +
                          raise DecodingError, "Offset out of bounds" if offset + size > arg.size
         
     | 
| 
      
 73 
     | 
    
         
            +
                          result << type(component, arg[offset, size])
         
     | 
| 
       68 
74 
     | 
    
         
             
                          offset += size
         
     | 
| 
       69 
75 
     | 
    
         
             
                        end
         
     | 
| 
       70 
76 
     | 
    
         
             
                      end
         
     | 
| 
       71 
     | 
    
         
            -
                       
     | 
| 
       72 
     | 
    
         
            -
                    elsif type.dynamic?
         
     | 
| 
      
 77 
     | 
    
         
            +
                      result
         
     | 
| 
      
 78 
     | 
    
         
            +
                    elsif type.dynamic? && !type.dimensions.empty? && type.dimensions.last == 0
         
     | 
| 
       73 
79 
     | 
    
         
             
                      l = Util.deserialize_big_endian_to_int arg[0, 32]
         
     | 
| 
       74 
80 
     | 
    
         
             
                      nested_sub = type.nested_sub
         
     | 
| 
       75 
81 
     | 
    
         | 
| 
       76 
     | 
    
         
            -
                       
     | 
| 
       77 
     | 
    
         
            -
             
     | 
| 
       78 
     | 
    
         
            -
             
     | 
| 
       79 
     | 
    
         
            -
             
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
      
 82 
     | 
    
         
            +
                      if nested_sub.dynamic?
         
     | 
| 
      
 83 
     | 
    
         
            +
                        raise DecodingError, "Wrong data size for dynamic array" unless arg.size >= 32 + 32 * l
         
     | 
| 
      
 84 
     | 
    
         
            +
                        offsets = (0...l).map do |i|
         
     | 
| 
      
 85 
     | 
    
         
            +
                          off = Util.deserialize_big_endian_to_int arg[32 + 32 * i, 32]
         
     | 
| 
      
 86 
     | 
    
         
            +
                          raise DecodingError, "Offset out of bounds" if off < 32 * l || off > arg.size - 64
         
     | 
| 
      
 87 
     | 
    
         
            +
                          off
         
     | 
| 
      
 88 
     | 
    
         
            +
                        end
         
     | 
| 
      
 89 
     | 
    
         
            +
                        offsets.each_with_index.map do |off, index|
         
     | 
| 
      
 90 
     | 
    
         
            +
                          start = 32 + off
         
     | 
| 
      
 91 
     | 
    
         
            +
                          stop = index + 1 < offsets.length ? 32 + offsets[index + 1] : arg.size
         
     | 
| 
      
 92 
     | 
    
         
            +
                          raise DecodingError, "Offset out of bounds" if stop > arg.size || stop < start
         
     | 
| 
      
 93 
     | 
    
         
            +
                          type(nested_sub, arg[start, stop - start])
         
     | 
| 
      
 94 
     | 
    
         
            +
                        end
         
     | 
| 
      
 95 
     | 
    
         
            +
                      else
         
     | 
| 
      
 96 
     | 
    
         
            +
                        raise DecodingError, "Wrong data size for dynamic array" unless arg.size >= 32 + nested_sub.size * l
         
     | 
| 
      
 97 
     | 
    
         
            +
                        # decoded dynamic-sized arrays with static sub-types
         
     | 
| 
      
 98 
     | 
    
         
            +
                        (0...l).map { |i| type(nested_sub, arg[32 + nested_sub.size * i, nested_sub.size]) }
         
     | 
| 
      
 99 
     | 
    
         
            +
                      end
         
     | 
| 
       81 
100 
     | 
    
         
             
                    elsif !type.dimensions.empty?
         
     | 
| 
       82 
     | 
    
         
            -
                      l = type.dimensions. 
     | 
| 
      
 101 
     | 
    
         
            +
                      l = type.dimensions.last
         
     | 
| 
       83 
102 
     | 
    
         
             
                      nested_sub = type.nested_sub
         
     | 
| 
       84 
103 
     | 
    
         | 
| 
       85 
     | 
    
         
            -
                       
     | 
| 
       86 
     | 
    
         
            -
             
     | 
| 
      
 104 
     | 
    
         
            +
                      if nested_sub.dynamic?
         
     | 
| 
      
 105 
     | 
    
         
            +
                        raise DecodingError, "Wrong data size for static array" unless arg.size >= 32 * l
         
     | 
| 
      
 106 
     | 
    
         
            +
                        offsets = (0...l).map do |i|
         
     | 
| 
      
 107 
     | 
    
         
            +
                          off = Util.deserialize_big_endian_to_int arg[32 * i, 32]
         
     | 
| 
      
 108 
     | 
    
         
            +
                          raise DecodingError, "Offset out of bounds" if off < 32 * l || off > arg.size - 32
         
     | 
| 
      
 109 
     | 
    
         
            +
                          off
         
     | 
| 
      
 110 
     | 
    
         
            +
                        end
         
     | 
| 
      
 111 
     | 
    
         
            +
                        offsets.each_with_index.map do |off, i|
         
     | 
| 
      
 112 
     | 
    
         
            +
                          size = (i + 1 < offsets.length ? offsets[i + 1] : arg.size) - off
         
     | 
| 
      
 113 
     | 
    
         
            +
                          type(nested_sub, arg[off, size])
         
     | 
| 
      
 114 
     | 
    
         
            +
                        end
         
     | 
| 
      
 115 
     | 
    
         
            +
                      else
         
     | 
| 
      
 116 
     | 
    
         
            +
                        # decoded static-size arrays with static sub-types
         
     | 
| 
      
 117 
     | 
    
         
            +
                        (0...l).map { |i| type(nested_sub, arg[nested_sub.size * i, nested_sub.size]) }
         
     | 
| 
      
 118 
     | 
    
         
            +
                      end
         
     | 
| 
       87 
119 
     | 
    
         
             
                    else
         
     | 
| 
       88 
120 
     | 
    
         | 
| 
       89 
121 
     | 
    
         
             
                      # decoded primitive types
         
     | 
| 
         @@ -108,7 +140,9 @@ module Eth 
     | 
|
| 
       108 
140 
     | 
    
         
             
                        size = Util.deserialize_big_endian_to_int data[0, 32]
         
     | 
| 
       109 
141 
     | 
    
         | 
| 
       110 
142 
     | 
    
         
             
                        # decoded dynamic-sized array
         
     | 
| 
       111 
     | 
    
         
            -
                        data[32..-1][0, size]
         
     | 
| 
      
 143 
     | 
    
         
            +
                        decoded = data[32..-1][0, size]
         
     | 
| 
      
 144 
     | 
    
         
            +
                        decoded.force_encoding(Encoding::UTF_8)
         
     | 
| 
      
 145 
     | 
    
         
            +
                        decoded
         
     | 
| 
       112 
146 
     | 
    
         
             
                      else
         
     | 
| 
       113 
147 
     | 
    
         | 
| 
       114 
148 
     | 
    
         
             
                        # decoded static-sized array
         
     | 
| 
         @@ -148,6 +182,27 @@ module Eth 
     | 
|
| 
       148 
182 
     | 
    
         
             
                      raise DecodingError, "Unknown primitive type: #{type.base_type}"
         
     | 
| 
       149 
183 
     | 
    
         
             
                    end
         
     | 
| 
       150 
184 
     | 
    
         
             
                  end
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
                  private
         
     | 
| 
      
 187 
     | 
    
         
            +
             
     | 
| 
      
 188 
     | 
    
         
            +
                  # Computes the byte ranges for dynamic tuple components.
         
     | 
| 
      
 189 
     | 
    
         
            +
                  #
         
     | 
| 
      
 190 
     | 
    
         
            +
                  # @param offsets [Array<Array(Integer, Integer)>] list of tuples containing the component index and pointer.
         
     | 
| 
      
 191 
     | 
    
         
            +
                  # @param total_size [Integer] total number of bytes available for the tuple.
         
     | 
| 
      
 192 
     | 
    
         
            +
                  # @param head_size [Integer] size in bytes of the tuple head.
         
     | 
| 
      
 193 
     | 
    
         
            +
                  # @return [Hash{Integer=>Array(Integer, Integer)}] mapping component index to a [start, stop) range.
         
     | 
| 
      
 194 
     | 
    
         
            +
                  # @raise [DecodingError] if the encoded offsets overlap or leave the tuple head.
         
     | 
| 
      
 195 
     | 
    
         
            +
                  def tuple_dynamic_ranges(offsets, total_size, head_size)
         
     | 
| 
      
 196 
     | 
    
         
            +
                    ranges = {}
         
     | 
| 
      
 197 
     | 
    
         
            +
                    sorted = offsets.sort_by { |(_, pointer)| pointer }
         
     | 
| 
      
 198 
     | 
    
         
            +
                    sorted.each_with_index do |(index, pointer), idx|
         
     | 
| 
      
 199 
     | 
    
         
            +
                      raise DecodingError, "Offset out of bounds" if pointer < head_size || pointer > total_size
         
     | 
| 
      
 200 
     | 
    
         
            +
                      next_pointer = idx + 1 < sorted.length ? sorted[idx + 1][1] : total_size
         
     | 
| 
      
 201 
     | 
    
         
            +
                      raise DecodingError, "Offset out of bounds" if next_pointer < pointer || next_pointer > total_size
         
     | 
| 
      
 202 
     | 
    
         
            +
                      ranges[index] = [pointer, next_pointer]
         
     | 
| 
      
 203 
     | 
    
         
            +
                    end
         
     | 
| 
      
 204 
     | 
    
         
            +
                    ranges
         
     | 
| 
      
 205 
     | 
    
         
            +
                  end
         
     | 
| 
       151 
206 
     | 
    
         
             
                end
         
     | 
| 
       152 
207 
     | 
    
         
             
              end
         
     | 
| 
       153 
208 
     | 
    
         
             
            end
         
     |