q9f / eth.rb

a straightforward library to build, sign, and broadcast ethereum transactions anywhere you can run ruby.
https://q9f.github.io/eth.rb
Apache License 2.0
204 stars 88 forks source link

Possible problem in translating call() params into camelCase requirement #141

Closed a-moreira closed 1 year ago

a-moreira commented 2 years ago

version: 0.5.6

I haven't been able to send a call transaction to a custom Substrate-based chain with EVM compatibility. I get IOErrors related to the name of the tx params.

Example:

Traceback (most recent call last):
        .
        .
        .
        3: from /home/arthurmoreira-t14/Code/eth.rb/lib/eth/client.rb:440:in `call_raw'
        2: from /home/arthurmoreira-t14/Code/eth.rb/lib/eth/client.rb:400:in `block (2 levels) in <class:Client>'
        1: from /home/arthurmoreira-t14/Code/eth.rb/lib/eth/client.rb:475:in `send_command'
IOError (unknown field `gas_limit`, expected one of `from`, `to`, `gasPrice`, `maxFeePerGas`, `maxPriorityFeePerGas`, `gas`, `value`, `data`, `nonce`, `accessList`, `type` at line 1 column 12)

Investigating further, I noticed that the JSON fields in the payload look like this:

{:jsonrpc=>"2.0", :method=>"eth_call", :params=>[{:gas_limit=>"0xcf08", :chain_id=>"0x7d8", :data=><sensitive>, :to=>"0xB7d2fFd908ef6B69dA0749600F553923C465c811", :priority_fee=>"0x0", :max_gas_fee=>"0x4a817c800"}, "latest"], :id=>9}

And the response is:

"{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32602,\"message\":\"unknown field `gas_price`, expected one of `from`, `to`, `gasPrice`, `maxFeePerGas`, `maxPriorityFeePerGas`, `gas`, `value`, `data`, `nonce`, `accessList`, `type` at line 1 column 25\"},\"id\":9}\n"

I was able to make it work by adding a byebug just before sending the request and manually renaming the JSON fields to camelCase, and removing chain_id, adding transaction type: then I can get the correct response:

irb(main):011:0> request.body = "{\"jsonrpc\":\"2.0\",\"method\":\"eth_call\",\"params\":[{\"gas\":\"0xcf08\",\"data\":\"0x\",\"to\":\"0xC6d1eFd908ef6B69dA0749600F553923C465c812\",\"gasPrice\":\"0x0\",\"type\":\"0x00\"},\"latest\"],\"id\":9}"
irb(main):011:0> response = http.request(body)
#<Net::HTTPOK 200 OK readbody=true>
irb(main):011:0> response.body
"{\"jsonrpc\":\"2.0\",\"result\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"id\":9}\n"
a-moreira commented 2 years ago

Previously, I had been using the 0.4.12 version for more than a year :thinking:

gith-u-b commented 2 years ago

I have the same problem.

gith-u-b commented 2 years ago

version: 0.5.6

I haven't been able to send a read-only call transaction, only getting IOErrors related to the name of the tx params. btw I'm trying to connect to a custom Substrate-based chain with EVM compatibility Example:

Traceback (most recent call last):
        .
        .
        .
        3: from /home/arthurmoreira-t14/Code/eth.rb/lib/eth/client.rb:440:in `call_raw'
        2: from /home/arthurmoreira-t14/Code/eth.rb/lib/eth/client.rb:400:in `block (2 levels) in <class:Client>'
        1: from /home/arthurmoreira-t14/Code/eth.rb/lib/eth/client.rb:475:in `send_command'
IOError (unknown field `gas_limit`, expected one of `from`, `to`, `gasPrice`, `maxFeePerGas`, `maxPriorityFeePerGas`, `gas`, `value`, `data`, `nonce`, `accessList`, `type` at line 1 column 12)

Investigating further, I noticed that the JSON fields in the payload look like this:

{:jsonrpc=>"2.0", :method=>"eth_call", :params=>[{:gas_limit=>"0xcf08", :chain_id=>"0x7d8", :data=><sensitive>, :to=>"0xB7d2fFd908ef6B69dA0749600F553923C465c811", :priority_fee=>"0x0", :max_gas_fee=>"0x4a817c800"}, "latest"], :id=>9}

And the response is:

"{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32602,\"message\":\"unknown field `gas_price`, expected one of `from`, `to`, `gasPrice`, `maxFeePerGas`, `maxPriorityFeePerGas`, `gas`, `value`, `data`, `nonce`, `accessList`, `type` at line 1 column 25\"},\"id\":9}\n"

I was able to make it work by adding a byebug just before sending the request and manually renaming the JSON fields to camelCase, and removing chain_id, adding transaction type: then I can get the correct response:

irb(main):011:0> request.body = "{\"jsonrpc\":\"2.0\",\"method\":\"eth_call\",\"params\":[{\"gas\":\"0xcf08\",\"data\":\"0xfe575a87000000000000000000000000f26d1059a3941766772c8e1e1ae15e141c1af65d\",\"to\":\"0xC6d1eFd908ef6B69dA0749600F553923C465c812\",\"gasPrice\":\"0x0\",\"type\":\"0x00\"},\"latest\"],\"id\":9}"
irb(main):011:0> response = http.request(body)
#<Net::HTTPOK 200 OK readbody=true>
irb(main):011:0> response.body
"{\"jsonrpc\":\"2.0\",\"result\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"id\":9}\n"

this reason is like Substrate-based chain or moonbase chain rpc only accepts different parameters: from, to, gasPrice, maxFeePerGas, maxPriorityFeePerGas, gas, value, data, nonce, accessList, type, can solve this problem by modifying the source code

q9f commented 2 years ago

That's interesting. I only tested against local Geth nodes and remote Infura endpoints which definitely accept the snake_case_parameters. However, I'm more than happy to accept such a change.

Maybe we can add a Moonbeam compatibility feature or rewrite all parameters to camel case. (Does Geth accept camel case?)

a-moreira commented 2 years ago

hey @q9f thanks! How do you see the Moonbeam compatibility feature implemented? It's not clear to me. Regarding Geth accepting camel case, I can't confirm because I haven't tried, but looking at Ethereum docs here I would say it does.

q9f commented 2 years ago

Having camel case compatibility and also adding moonbeam, moonriver, (etc) chain IDs. I'd be happy to onboard new ecosystems!

a-moreira commented 2 years ago

@q9f OK. I can open a PR for that. Should I move everything to CamelCase by default and remove snake_case then?

q9f commented 2 years ago

Yes, a default camel case would work for me! Sorry for the late response! :)

a-moreira commented 2 years ago

OK, I'm working on it here: https://github.com/a-moreira/eth.rb/pull/1 I will open the PR here as soon as I fix all the test errors.

a-moreira commented 2 years ago

hey @q9f I opened the PR to check the CI workflow, since I'm getting a weird error on tests that I couldn't debug. Can please you approve the workflows? :-)

I still need to fix some comments and other details.

q9f commented 2 years ago

Done :)

a-moreira commented 1 year ago

hey @q9f, I'm sorry to bother, but is there any chance you could take a quick look at the PR? For some reason only some of the tests break with a insufficient gas error, I may be getting crazy but could not pin it. The errors I get are the same as the CI shows.

I used byebug to check the transactions in my branch in the main branch just before sending to the node and they are identical, except for the name of the params :thinking:

edit: add more context

q9f commented 1 year ago

I started debugging a bit, something is fishy. I have not too much time to dive deeply into it but I would suggest you starting with the test in client spec on line 128.

rspec spec/eth/client_spec.rb:128

And then try to find out why it needs funds for a call and why the address is 0x0

Run options: include {:locations=>{"./spec/eth/client_spec.rb"=>[128]}}

Eth::Client
  .deploy .deploy_and_wait
    can deploy and call an ens registry (FAILED - 1)

Failures:

  1) Eth::Client.deploy .deploy_and_wait can deploy and call an ens registry
     Failure/Error: raise IOError, output["error"]["message"] unless output["error"].nil?

     IOError:
       err: insufficient funds for gas * price + value: address 0x0000000000000000000000000000000000000000 have 0 want 5993676000000000 (supplied gas 140400)
     # ./lib/eth/client.rb:471:in `send_command'
     # ./lib/eth/client.rb:402:in `block (2 levels) in <class:Client>'
     # ./lib/eth/client.rb:442:in `call_raw'
     # ./lib/eth/client.rb:262:in `call'
     # ./spec/eth/client_spec.rb:133:in `block (3 levels) in <top (required)>'

Finished in 0.11423 seconds (files took 0.13432 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/eth/client_spec.rb:128 # Eth::Client.deploy .deploy_and_wait can deploy and call an ens registry
a-moreira commented 1 year ago

Hey @q9f I was able to fix the problems. I created another branch that delivers the same result, but simpler

in any case, I think we should hold this for a moment, I want to do some more tests with a Moonbeam node and other Frontier-based chains

q9f commented 1 year ago

Looks good to me, can you update the branches to the latest head on main? That should make the entire CI green now.