Skip to content

Commit

Permalink
eth/client: raise an error if a contract interaction reverts (#186)
Browse files Browse the repository at this point in the history
  • Loading branch information
q9f authored Dec 21, 2022
1 parent 490f28d commit f878ece
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 2 deletions.
11 changes: 10 additions & 1 deletion lib/eth/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ class Client
# The default gas limit for the transaction, defaults to {Tx::DEFAULT_GAS_LIMIT}.
attr_accessor :gas_limit

# A custom error type if a contract interaction fails.
class ContractExecutionError < StandardError; end

# Creates a new RPC-Client, either by providing an HTTP/S host or
# an IPC path. Supports basic authentication with username and password.
#
Expand Down Expand Up @@ -345,9 +348,15 @@ def transact(contract, function, *args, **kwargs)
#
# See {#transact} for params and overloads.
#
# @raise [Client::ContractExecutionError] if the execution fails.
# @return [Object] returns the result of the transaction.
def transact_and_wait(contract, function, *args, **kwargs)
wait_for_tx(transact(contract, function, *args, **kwargs))
begin
hash = wait_for_tx(transact(contract, function, *args, **kwargs))
return hash if tx_succeeded? hash
rescue IOError => e
raise ContractExecutionError, e
end
end

# Provides an interface to call `isValidSignature` as per EIP-1271 on a given
Expand Down
10 changes: 10 additions & 0 deletions spec/eth/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,16 @@
expect(geth_dev_http.tx_succeeded? hash).to be_truthy
end

it "raises if a transaction fails" do
addr = geth_dev_http.deploy_and_wait(contract)
hash = geth_dev_http.transact_and_wait(contract, "set", 42, address: addr)
expect(geth_dev_http.tx_mined? hash).to be_truthy
expect(geth_dev_http.tx_succeeded? hash).to be_truthy
expect {
hash = geth_dev_http.transact_and_wait(contract, "set", 138, address: addr)
}.to raise_error(Client::ContractExecutionError, "execution reverted")
end

context "when nonce manually set" do
let(:contract_address) { geth_dev_http.deploy_and_wait(contract) }

Expand Down
2 changes: 1 addition & 1 deletion spec/eth/solidity_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
result = solc.compile contract
expect(result.keys).to eq ["Dummy"]
expect(result["Dummy"]["abi"]).to eq JSON.parse '[{"inputs":[],"name":"get","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"}],"name":"set","outputs":[],"stateMutability":"nonpayable","type":"function"}]'
expect(result["Dummy"]["bin"]).to start_with "6080604052348015600f57600080fd5b5060"
expect(result["Dummy"]["bin"]).to start_with "608060405234801561001057600080fd5b50"
end

it "compiles the greeter contract" do
Expand Down
1 change: 1 addition & 0 deletions spec/fixtures/contracts/dummy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pragma solidity ^0.8;
contract Dummy {
uint number;
function set(uint x) public {
require(x < 137);
number = x;
}

Expand Down

0 comments on commit f878ece

Please sign in to comment.