Giter Site home page Giter Site logo

exw3's People

Contributors

aguxez avatar ayrat555 avatar dependabot[bot] avatar dsummers91 avatar hswick avatar kianmeng avatar mjia-catalx avatar mosic avatar pik694 avatar rupurt avatar timjp87 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

exw3's Issues

Problem with ABI.TypeDecoder

Hi!

I have a problem with ExW3.Contract.call method and ABI.TypeDecoder.decode_type.

Solidity function:
function get_DFA(uint dfaID) public returns (DFA memory) { DFA storage dfa = dfa_pool[dfaID]; return dfa; }

Elixir function:

def sc_call(sc_abi_path, sc_address, sc_name, sc_method, sc_method_args \\ []) do
    ExW3.Contract.start_link()
    sc_abi = ExW3.Abi.load_abi(sc_abi_path)
    ExW3.Contract.register(String.to_atom(sc_name), abi: sc_abi)
    ExW3.Contract.at(String.to_atom(sc_name), sc_address)
    ExW3.Contract.call(String.to_atom(sc_name), String.to_atom(sc_method), sc_method_args)
end

When I call this method from ElixirApp, I get a error

ElixirApp.Utils.Ethereum.sc_call("data/DFAPool.abi", "0x39Df1178CCBeC6d48A81969b6f67f13F3B4CC6E3", "DFAPool", "get_DFA", [1])

00:35:02.056 [error] GenServer ContractManager terminating
** (FunctionClauseError) no function clause matching in ABI.TypeDecoder.decode_type/2
(ex_abi 0.5.3) lib/abi/type_decoder.ex:244: ABI.TypeDecoder.decode_type(:tuple, <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...>>)
(ex_abi 0.5.3) lib/abi/type_decoder.ex:270: anonymous fn/3 in ABI.TypeDecoder.decode_type/2
(elixir 1.11.4) lib/enum.ex:2193: Enum."-reduce/3-lists^foldl/2-0-"/3
(ex_abi 0.5.3) lib/abi/type_decoder.ex:265: ABI.TypeDecoder.decode_type/2
(ex_abi 0.5.3) lib/abi/type_decoder.ex:189: anonymous fn/3 in ABI.TypeDecoder.do_decode_raw/2
(elixir 1.11.4) lib/enum.ex:2193: Enum."-reduce/3-lists^foldl/2-0-"/3
(ex_abi 0.5.3) lib/abi/type_decoder.ex:184: ABI.TypeDecoder.do_decode_raw/2
(ex_abi 0.5.3) lib/abi/type_decoder.ex:178: ABI.TypeDecoder.decode_raw/2
Last message (from #PID<0.255.0>): {:call, {:DFAPool, :get_DFA, [1]}}

I don't understand what's happened.

Add watcher to auto-compile Solidity Files

Hello guys!

First off I wanna thank you for the awesome, although concise library!

But this section/feature on Readme, got me thinking, maybe could we automate this?

To compile the test solidity contracts after making a change run this command:

$ solc --abi --bin --overwrite -o test/examples/build test/examples/contracts/*.sol

And such, I did as a MVP, a simple implementation, that you can check out here. I did some changes, implemented better automations, and error treatments. But unfortunately I couldn't create a branch here ๐Ÿ˜ข .

So Here's my request, can we got my PR here, and such we can get this working? I already integrated with the library, and tested in a sample Phoenix Framework Project:

image

Eth unit converters

Would be nice to have unit converters. This is a handy web3 util, that should be included here as well

Can't compile ex_keccak

This is the the error I am getting when trying to compile. I'm using a Mac Air with an M1 processor. Any ideas how to fix this?

$ mix compile
==> ex_keccak
Compiling 1 file (.ex)

== Compilation error in file lib/ex_keccak.ex ==
** (ErlangError) Erlang error: :enoent
    (elixir 1.13.2) lib/system.ex:1044: System.cmd("cargo", ["metadata", "--format-version=1"], [cd: "native/exkeccak"])
    (rustler 0.22.2) lib/rustler/compiler/config.ex:81: Rustler.Compiler.Config.external_resources/2
    (rustler 0.22.2) lib/rustler/compiler/config.ex:69: Rustler.Compiler.Config.build/1
    (rustler 0.22.2) lib/rustler/compiler.ex:9: Rustler.Compiler.compile_crate/2
    lib/ex_keccak.ex:2: (module)
could not compile dependency :ex_keccak, "mix compile" failed. Errors may have been logged above. You can recompile this dependency with "mix deps.compile ex_keccak", update it with "mix deps.update ex_keccak" or clean it with "mix deps.clean ex_keccak"

Passing string as parameter throws error

I create 2 diff contracts, one with set function receiving integer as parameter, the other receiving string.

First works fine and the second one fails with this message:

{:error,
 %{
   "code" => -32000,
   "data" => %{
     "0xe20bb21666d462cfec33dad694cae424fadd38cdc4820970c8769f2e7690f149" => %{
       "error" => "revert",
       "program_counter" => 5281,
       "return" => "0x"
     },
     "name" => "RuntimeError",
     "stack" => "RuntimeError: VM Exception while processing transaction: revert\n    at Function.RuntimeError.fromResults (/tmp/.mount_ganachjrwblU/resources/static/node/node_modules/ganache-core/lib/utils/runtimeerror.js:94:13)\n    at BlockchainDouble.processBlock (/tmp/.mount_ganachjrwblU/resources/static/node/node_modules/ganache-core/lib/blockchain_double.js:627:24)\n    at runMicrotasks (<anonymous>)\n    at processTicksAndRejections (internal/process/task_queues.js:93:5)"
   },
   "message" => "VM Exception while processing transaction: revert"
 }}

I've tried converting string to hex and didn't work either.

Please add an example on readme on how to format string before passing it to contract function.

Provide timeout as a config value

In the following function

@spec call(atom(), atom(), list()) :: {:ok, any()}
@doc "Use a Contract's method with an eth_call"
def call(contract_name, method_name, args \\ []) do
  GenServer.call(ContractManager, {:call, {contract_name, method_name, args}})
end

the GenServer request times out quite a few times while accessing data on the mainnet (because the default timeout is 5 seconds).

The timeout of Ethereumex.HttpClient can be set to :infinity, but the request times out at exw3.

Will it be helpful in allowing setting the GenServer timeout as a config value?

EventListener should use the GenServer abstraction

Right now EventListener module uses the loop receive pattern. However, I'm learning that this is an antipattern, in that using basic processes is like using assembly language.

I also have a suspicion that EventPoller's behavior could be rolled into the EventListener GenServer which might decrease the amount of code.

Provide a nonblocking send using cast instead of call

For the most part any time someone interacts with the blockchain they want some feedback. However, there are cases of fire and forget and the easiest way to implement this would be to provide a send method that uses GenServer cast instead of call.

Leaving this issue open for others to comment on.

How to send ERC20 tokens using ExW3?

Could you please provide an example of sending ERC20 tokens using ExW3? I have the following ABI:

// transfer
  {
    "constant": false,
    "inputs": [
      {
        "name": "_to",
        "type": "address"
      },
      {
        "name": "_value",
        "type": "uint256"
      }
    ],
    "name": "transfer",
    "outputs": [
      {
        "name": "",
        "type": "bool"
      }
    ],
    "type": "function"
  }

and would like to send USDT from one ethereum address to another.

get_filter_changes_batch

Would be useful (possibly more performant) to grab a batch of changes for a list of filters.

This would mean less trips over the wire to the Ethereum node.

Error when decoding array of uint256

I'm getting a MatchError raised by ex_abi when I use this library to call a contract's method that returns an array of uint256. Initially I thought it was a bug in ex_abi but based on the evidence provided in poanetwork/ex_abi#98 it seems that there might something wrong on how this library is handling the response from the RPC call and passing that to ex_abi for decoding.

The issue I reference in ex_abi has all the required information to reproduce the bug

Single Contract process

One suggestion I've received is to have a single process that handles all the requests for every contract. This seems to be a more idiomatic style for Elixir apps, where this process is in charge of any Contract related service. One benefit would be that this single process would be easier to pass around different modules, and you would only have to start it in the Application supervisor.

I was going to implement this and realized it is a very involved change because it completely changes the way state is handled starting from init to every single call. This would also be a very breaking change, so I think it is best to sit on it, and see what others think.

Experimental ABI features crash.

For contracts that have been compiled with pragma experimental ABIEncoderV2;, and return an array for example:

  function actors() external view returns (address[] memory) {
    return actorList.values;
  }

ExW3 doesn't return, hogs the CPU and the memory.

Issue with calling smart contract

ExW3.Contract.start_link()
ExW3.Contract.register(:Contract, abi: ExW3.Abi.load_abi("path/to/abis/erc721.json"))
ExW3.Contract.at(:Contract, "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d")
url = Spool.Chain.Helpers.get_endpoint_for_network(1)
Application.put_env(:ethereumex, :url, url)
ExW3.Contract.call(:Contract, :symbol)
[error] GenServer ContractManager terminating
** (MatchError) no match of right hand side value: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>
    (ex_abi 0.5.16) lib/abi/type_decoder.ex:238: ABI.TypeDecoder.decode_bytes/4
    (ex_abi 0.5.16) lib/abi/type_decoder.ex:327: anonymous fn/3 in ABI.TypeDecoder.decode_type/3
    (elixir 1.14.1) lib/enum.ex:2468: Enum."-reduce/3-lists^foldl/2-0-"/3
    (ex_abi 0.5.16) lib/abi/type_decoder.ex:325: ABI.TypeDecoder.decode_type/3
    (ex_abi 0.5.16) lib/abi/type_decoder.ex:188: anonymous fn/3 in ABI.TypeDecoder.do_decode_raw/2
    (elixir 1.14.1) lib/enum.ex:2468: Enum."-reduce/3-lists^foldl/2-0-"/3
    (ex_abi 0.5.16) lib/abi/type_decoder.ex:185: ABI.TypeDecoder.do_decode_raw/2
    (ex_abi 0.5.16) lib/abi/type_decoder.ex:179: ABI.TypeDecoder.decode_raw/2
    (exw3 0.6.1) lib/exw3/abi.ex:52: ExW3.Abi.decode_output/3
    (exw3 0.6.1) lib/exw3/contract.ex:214: ExW3.Contract.eth_call_helper/4
    (exw3 0.6.1) lib/exw3/contract.ex:480: ExW3.Contract.handle_call/3
    (stdlib 4.1.1) gen_server.erl:1149: :gen_server.try_handle_call/4
    (stdlib 4.1.1) gen_server.erl:1178: :gen_server.handle_msg/6
    (stdlib 4.1.1) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Last message (from #PID<0.840.0>): {:call, {:Contract, :symbol, []}}

#153

Here is a quick fix

Signing Transactions

ethereumex explains a way to do this, but it requires the Blockchain hex package. Considering, that the entire Blockchain project probably isnt necessary for this feature, it may make sense to extract those parts out.

The thinking would be something like this (taken from etheremex README):

eth_send_raw_transaction example - Payable smart contract call

Calling a smart contract method that requires computation will cost you gas or ether (if that method requires payment also). This means you will have to sign your transactions using the private key that owns some ethereum. In order to send signed transactions you will need both ABI and Blockchain hex packages.

abi_encoded_data = ABI.encode("transferFrom(address,address,uint)", [from_address, to_address, token_id])
contract_address = "0x123" |> String.slice(2..-1) |> Base.decode16(case: :mixed)

transaction_data = %Blockchain.Transaction{
    data: abi_encoded_data,
    gas_limit: 100_000,
    gas_price: 16_000_000_000,
    init: <<>>,
    nonce: 5,
    to: contract_address,
    value: 0
}
|> Blockchain.Transaction.Signature.sign_transaction(private_key)
|> Blockchain.Transaction.serialize()
|> ExRLP.encode()
|> Base.encode16(case: :lower)

Ethereumex.HttpClient.eth_send_raw_transaction("0x" <> transaction_data)

Permissioned DLTs - Quorum

Hi,

I am using permissioned DLT -> Quorum from Consensys (previously JPMorgan). This is basically "enterprise functionaliy" rich version of Ethereum. Most important one are private contracts and private transactions.

For instance:
https://docs.goquorum.consensys.net/en/stable/HowTo/Use/DevelopingSmartContracts/#creating-private-transactionscontracts

Can I handle this with exw3? Deployment of such contract, calling it later?
Can't really see from the documentation.

Thanks

Issues With Memory String Consumption In Smart Contracts

When attempting to consume a String in a contract function, ExW3 seems to handle encoding improperly, causing variables to mix and or set improperly in the contracts state.

Smart Contract Example:

pragma solidity >=0.4.22 <0.9.0;

contract Tester {
  address public currentAddr;
  uint256 public currentInt;
  string public sym;

  function setOnlyStringBefore(string memory _sym, address new_addr, uint256 new_int) public {
    currentAddr = new_addr;
    currentInt = new_int;
    sym = _sym;
  }

  function setOnlyStringAfter(address new_addr, uint256 new_int, string memory _sym) public {
    currentAddr = new_addr;
    currentInt = new_int;
    sym = _sym;
  }

  function setOnlyAddrAndInt(address new_addr, uint256 new_int) public {
    currentAddr = new_addr;
    currentInt = new_int;
  }
}

Scenario 1

(Function setOnlyStringBefore) - string is set before address and uint256 in smart contract function parameters

Using ExW3 ->
ExW3.Contract.send(:Tester, :setOnlyStringBefore, ["name", "0x0255bff90b8787f06cf13ab325997cbf3b139c1d", 10], %{from: @contracts_owner, gas: 6000000})

{:ok, "0x1c6ac0864e8e6418cfc743200ee74ad06bb2442bd5842fd73c2d12bb835db0dc"}

In Truffle ->

truffle(k8s)> let test = await Tester.deployed()

truffle(k8s)> test.sym()

Thrown:
{ Error: invalid codepoint at offset 14; unexpected continuation byte (argument="bytes", value={"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":2,"13":85,"14":191,"15":249,"16":11,"17":135,"18":135,"19":240,"20":108,"21":241,"22":58,"23":179,"24":37,"25":153,"26":124,"27":191,"28":59,"29":19,"30":156,"31":29,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":10,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0,"92":0,"93":0,"94":0,"95":4}, code=INVALID_ARGUMENT, version=strings/5.0.5)
    at evalmachine.<anonymous>:0:6
    at sigintHandlersWrap (vm.js:288:15)
    at Script.runInContext (vm.js:130:14)
    at runScript (/usr/local/lib/node_modules/truffle/build/webpack:/packages/core/lib/console.js:251:1)
    at Console.interpret (/usr/local/lib/node_modules/truffle/build/webpack:/packages/core/lib/console.js:266:1)
    at bound (domain.js:402:14)
    at REPLServer.runBound [as eval] (domain.js:415:12)
    at REPLServer.onLine (repl.js:642:10)
    at REPLServer.emit (events.js:198:13)
    at REPLServer.EventEmitter.emit (domain.js:448:20)
    at REPLServer.Interface._onLine (readline.js:308:10)
    at REPLServer.Interface._line (readline.js:656:8)
    at REPLServer.Interface._ttyWrite (readline.js:937:14)
    at REPLServer.self._ttyWrite (repl.js:715:7)
    at ReadStream.onkeypress (readline.js:184:10)
    at ReadStream.emit (events.js:198:13)
    at ReadStream.EventEmitter.emit (domain.js:448:20)
    at emitKeys (internal/readline.js:424:14)
    at emitKeys.next (<anonymous>)
    at ReadStream.onData (readline.js:1073:36)
    at ReadStream.emit (events.js:198:13)
    at ReadStream.EventEmitter.emit (domain.js:448:20)
    at addChunk (_stream_readable.js:288:12)
    at readableAddChunk (_stream_readable.js:269:11)
    at ReadStream.Readable.push (_stream_readable.js:224:10)
    at TTY.onStreamRead [as onread] (internal/stream_base_commons.js:94:17)
  reason:
   'invalid codepoint at offset 14; unexpected continuation byte',
  code: 'INVALID_ARGUMENT',
  argument: 'bytes',
  value:
   Uint8Array [
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     2,
     85,
     191,
     249,
     11,
     135,
     135,
     240,
     108,
     241,
     58,
     179,
     37,
     153,
     124,
     191,
     59,
     19,
     156,
     29,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     10,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     0,
     4 ],
  baseType: 'string',
  name: null,
  type: 'string',
  hijackedStack:
   'Error: invalid codepoint at offset 14; unexpected continuation byte (argument="bytes", value={"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":2,"13":

truffle(k8s)> test.currentAddr()
'0x0000000000000000000000000000000000000060'

truffle(k8s)> test.currentInt()
<BN: 255bff90b8787f06cf13ab325997cbf3b139c1d>

Note: The transaction is successful but the sym is set as a byte array and the address and uint256 values are swapped. They are passed in as

[name, new_addr, new_int]

and the function consumes them as

(string memory _sym, address new_addr, uint256 new_int)

however you can see in the above .currentAddr() and .currentInt() that the addr is set as a hex encoded value of 10 and the int is set as a BigNumber conversion of the address.

Note: This function is successful when called directly from truffle

truffle(k8s)> test.setOnlyStringBefore("Name", "0xfe5e669eD4C62A7D4621A604BcC1029171814046", 10)
{ tx:
   '0x1e7f54778810d2ea33b604dc2e1791b05b69540cd77a2357e8572f3f3f580588',
  receipt:
   { blockHash:
      '0x28a3a821daf8b6d8844b330f355ac74e46ee46c900f1be5b748c166357b044c2',
     blockNumber: 878,
     contractAddress: null,
     cumulativeGasUsed: 85007,
     from: '0xfe5e669ed4c62a7d4621a604bcc1029171814046',
     gasUsed: 85007,
     logs: [],
     logsBloom:
      '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
     status: true,
     to: '0x3c7d058ccb934c732674e28b4c45bcc722fb0004',
     transactionHash:
      '0x1e7f54778810d2ea33b604dc2e1791b05b69540cd77a2357e8572f3f3f580588',
     transactionIndex: 0,
     rawLogs: [] },
  logs: [] }

truffle(k8s)> test.sym()

'Name'

truffle(k8s)> test.currentAddr()

'0xfe5e669eD4C62A7D4621A604BcC1029171814046'

truffle(k8s)> test.currentInt()

<BN: a>


Scenerio 2

### (Function setOnlyStringAfter) - string is set after address and uint256 in smart contract function parameters

ExW3.Contract.send(:Tester, :setOnlyStringAfter, [10, "0x0255bff90b8787f06cf13ab325997cbf3b139c1d", "name"], %{from: @contracts_owner, gas: 6000000})

{:ok, "0xcb1e0f29d7a0fa5bc7822c2d9302b12cc5a22b02a52323d3ac3bad1a01b64634"}

In Truffle ->

truffle(k8s)> let test = await Tester.deployed()

truffle(k8s)> test.sym()

'' //// <--- Value never got set

truffle(k8s)> web3.eth.getTransactionReceipt("0xcb1e0f29d7a0fa5bc7822c2d9302b12cc5a22b02a52323d3ac3bad1a01b64634")
{ blockHash:
   '0x146459c31989cc9cfe8ae9025c31701566b5a3da14b74f8e69b97bfe4290d983',
  blockNumber: 877,
  contractAddress: null,
  cumulativeGasUsed: 24203,
  from: '0xfe5e669ed4c62a7d4621a604bcc1029171814046',
  gasUsed: '0x5e8b',
  logs: [],
  logsBloom:
   '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
  status: false,
  to: '0x3c7d058ccb934c732674e28b4c45bcc722fb0004',
  transactionHash:
   '0xcb1e0f29d7a0fa5bc7822c2d9302b12cc5a22b02a52323d3ac3bad1a01b64634',
  transactionIndex: 0 }

Note: The transaction status is 'false', meaning that the transaction has failed for some reason.

Note: The function call is successful when called from Truffle

ABI function calls with output type "string" Decode (MatchError)

I'm trying to call an abi's :symbol method in an erc721 smartcontract but get an error whenever I call a method that returns and abi function output with "string" type. Methods that return address or uint256 work fine... Is this an issue with exw3 or ex_abi? I noticed that this repo doesn't test for smart-contracts calls that have return outputs of "string"

GenServer ContractManager terminating
** (MatchError) no match of right hand side value: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>
    (ex_abi 0.5.5) lib/abi/type_decoder.ex:238: ABI.TypeDecoder.decode_bytes/4
    (ex_abi 0.5.5) lib/abi/type_decoder.ex:333: anonymous fn/3 in ABI.TypeDecoder.decode_type/3
    (elixir 1.11.4) lib/enum.ex:2193: Enum."-reduce/3-lists^foldl/2-0-"/3
    (ex_abi 0.5.5) lib/abi/type_decoder.ex:331: ABI.TypeDecoder.decode_type/3
    (ex_abi 0.5.5) lib/abi/type_decoder.ex:188: anonymous fn/3 in ABI.TypeDecoder.do_decode_raw/2
    (elixir 1.11.4) lib/enum.ex:2193: Enum."-reduce/3-lists^foldl/2-0-"/3
    (ex_abi 0.5.5) lib/abi/type_decoder.ex:185: ABI.TypeDecoder.do_decode_raw/2
    (ex_abi 0.5.5) lib/abi/type_decoder.ex:179: ABI.TypeDecoder.decode_raw/2
    (exw3 0.6.0) lib/exw3/abi.ex:52: ExW3.Abi.decode_output/3
    (exw3 0.6.0) lib/exw3/contract.ex:214: ExW3.Contract.eth_call_helper/4
    (exw3 0.6.0) lib/exw3/contract.ex:480: ExW3.Contract.handle_call/3
    (stdlib 3.14.2.1) gen_server.erl:715: :gen_server.try_handle_call/4
    (stdlib 3.14.2.1) gen_server.erl:744: :gen_server.handle_msg/6
    (stdlib 3.14.2.1) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Last message (from #PID<0.639.0>): {:call, {:"0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D", :symbol, []}}

This issues is occurring on this line when the output decoded type is "string" https://github.com/hswick/exw3/blob/master/lib/exw3/abi.ex#L49

Implement send_async and call_async using Task

A nice enhancement would be to make it easy to interact with the client asynchronously. What I'm thinking is that the Contract process acts as a Supervision tree for Tasks to be created for interacting with the blockchain.

The idea is that send_async and call_async return tasks that have to be awaited on using Task.await. Also these tasks would be managed with the Supervision tree.

Reasoning behind this is that it will probably be a common pattern when people need this functionality to asynchronously so this library can make it very easy.

Fix CI server

Travis is now using old Elixir and OTP, which causes mix test command to fail, but Travis still thinks that it has not failed, because it checks status of the last command and the command is the whole script, which last line simply kills parity so it is always successful.

The command "bash travis_test.sh" exited with 0.

Singing with PK

Does this library support signing transactions with a given PK? I can't seem to find any details in the documentation.
I don't want to use accounts since I'll be using Alchemy RPC.

Assertion error sending to contract...

    accounts = ExW3.accounts()
    simple_storage_abi = ExW3.Abi.load_abi("abi/MyContract.abi")

    ExW3.Contract.start_link
    ExW3.Contract.register(:MyContract, abi: simple_storage_abi)
    ExW3.Contract.at(:MyContract, Application.get_env(:ethereumex, :contract_address) |> Base.encode16(case: :lower) )

    ExW3.Contract.send(:MyContract, :MyFunction, [1, "Foo"], %{from: Enum.at(accounts, 0), gas: 50_000})

"AssertionError [ERR_ASSERTION]: The field to must have byte length of 20\n at Transaction.setter [as to] (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/node_modules/ethereumjs-util/src/object.ts:57:9)\n at /tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/lib/utils/transaction.js:116:23\n at Array.forEach ()\n at initData (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/lib/utils/transaction.js:110:18)\n at new Transaction (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/lib/utils/transaction.js:168:5)\n at Function.fromJSON (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/lib/utils/transaction.js:228:16)\n at StateManager.queueTransaction (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/lib/statemanager.js:371:22)\n at GethApiDouble.eth_sendTransaction (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/lib/subproviders/geth_api_double.js:325:14)\n at GethApiDouble.handleRequest (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/lib/subproviders/geth_api_double.js:109:10)\n at next (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/node_modules/web3-provider-engine/index.js:136:18)\n at GethDefaults.handleRequest (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/lib/subproviders/gethdefaults.js:15:12)\n at next (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/node_modules/web3-provider-engine/index.js:136:18)\n at SubscriptionSubprovider.FilterSubprovider.handleRequest (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/node_modules/web3-provider-engine/subproviders/filters.js:89:7)\n at SubscriptionSubprovider.handleRequest (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/node_modules/web3-provider-engine/subproviders/subscriptions.js:137:49)\n at next (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/node_modules/web3-provider-engine/index.js:136:18)\n at DelayedBlockFilter.handleRequest (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/lib/subproviders/delayedblockfilter.js:31:3)"

Better error messages for missing options

Thanks @pik694 exw3 will throw an error message if you don't include gas, from, or contract address in a transaction. Which helps with debugging.

Right now the error messages look like this:

** (MatchError) no match of right hand side value: {:error, :missing_gas}

Which is useful, and does tell what is going wrong. But I think it would be better if we could have a more readable and clear error message like

(MissingOptionsError) transaction request is missing the :gas field

Encode bytes32 error

I am trying to call a function with the following function signature:

get(bytes32)

I tried the following:

ExW3.Contract.call(:my_contract, :get, ["63cb2f697029ee491b58939796e9013087104b816ce0f51e731e9b03cc50c3b9"])

I get the following error:

[error] GenServer ContractManager terminating
** (RuntimeError) size mismatch for bytes32: "63cb2f697029ee491b58939796e9013087104b816ce0f51e731e9b03cc50c3b9"
    lib/abi/type_encoder.ex:178: ABI.TypeEncoder.encode_type/2
    lib/abi/type_encoder.ex:199: anonymous fn/2 in ABI.TypeEncoder.encode_type/2
    (elixir) lib/enum.ex:1940: Enum."-reduce/3-lists^foldl/2-0-"/3
    lib/abi/type_encoder.ex:191: ABI.TypeEncoder.encode_type/2
    lib/abi/type_encoder.ex:141: ABI.TypeEncoder.do_encode/3
    (exw3) lib/exw3.ex:442: ExW3.encode_method_call/3
    (exw3) lib/exw3.ex:697: ExW3.Contract.eth_call_helper/4
    (exw3) lib/exw3.ex:959: ExW3.Contract.handle_call/3

Is the hex string supposed to be encoded in a different format before providing in the arguments?

Allow a way to parse get_logs the same way the Contract.get_filter_changes works

Right now get_filter_changes can return a feed of logs parsed to the contract's events. Would be great to open up the capability to do this for get_logs so you can use the same parsing for both current and historical blocks. Easiest way may be to open up two methods. 1 that would take an ABI, convert it and return the event_attributes and then either open up format_log_data or refactor the format logs code in the Genserver call for :get_filter_changes and make that public. get_logs probably should not be a genserver call as someone may make tons of calls going through 10k's of blocks historically.

Happy to submit this or open to another alternatives!

Contract Manager can't access ExthCrypto library

Hi,

I'm using exw3 to deploy a ETH 2 Validator Deposit Contract via a Mix Task:
https://github.com/timjp87/panacea/blob/master/apps/beaconchain/lib/mix/tasks/deploy.ex

However, when I run "mix deploy" it can't access ExthCrypto.Hash.Keccak.kec/1 which should be available through the ethereumex dependency, right?

16:56:05.451 [info]  Deploying validator deposit contract.
16:56:05.493 [info]  Started Ethereumex Application.
16:56:05.595 [info]  Got list of accounts from RPC.
16:56:05.596 [info]  Started contract manager.
16:56:05.597 [info]  Loaded contract ABI.
16:56:05.597 [info]  Contract registered.

16:56:05.614 [error] GenServer ContractManager terminating
** (UndefinedFunctionError) function ExthCrypto.Hash.Keccak.kec/1 is undefined (module ExthCrypto.Hash.Keccak is not available)
    ExthCrypto.Hash.Keccak.kec("Deposit(bytes,bytes)")
    lib/exw3.ex:293: ExW3.encode_event/1
    lib/exw3.ex:587: anonymous fn/1 in ExW3.Contract.init_events/1
    (elixir) lib/enum.ex:1327: Enum."-map/2-lists^map/1-0-"/2
    lib/exw3.ex:583: ExW3.Contract.init_events/1
    lib/exw3.ex:720: ExW3.Contract.register_helper/1
    lib/exw3.ex:742: ExW3.Contract.handle_cast/2
    (stdlib) gen_server.erl:637: :gen_server.try_dispatch/4```

Test arg count error

There should be a throw triggered if the args count given is not the same as the input types of the abi. But I need to test this more.

As well, need to ensure the error message is good.

Calling function that requires bytes argument fails

I have been running into a case where if I use ExW3 with a solidity smart contract that needs a bytes function argument it will fail. I think this might be related to how the encoding works within ExW3, however when I bypass ExW3 and use ABI directly it works:

ABI.encode("setTest(bytes)", [encoded_data])

From what I can tell, there seems to be an extra 64 bytes of data being included in the ExW3 version that I am not sure where it is coming from.

Example:

# Fails when submitted as part of the transaction

# the variable `abi` was parsed from the contract abi file using ExW3
ExW3.Abi.encode_method_call(abi, "setTest", [<<1,2,3,4>>])
"0af724830000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000040102030400000000000000000000000000000000000000000000000000000000"

# Works when submitted as part of the transaction

ABI.encode("setTest(bytes)", [<<1,2,3,4>>]) |> Base.encode16(case: :lower)
"0af72483000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000040102030400000000000000000000000000000000000000000000000000000000"

Looking at the output it seems to be include a second "0x2" block of 64 bytes so I think something is getting wrapped twice.

Returning error instead of raising when a transaction is not mined.

At the moment when you try to check the receipt of a transaction tx_receipt/1 with a hash of a transaction which has not been mined yet, the function will raise a BadMapError I think it should be better to return an error ({:error, :not_mined} in this case) so we don't cut operations of related functions outside of the library,

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.