simolus3 / web3dart

Ethereum library, written in Dart.
MIT License
441 stars 270 forks source link

Bug: Zero address returned from contract call causes exception #226

Open cryptobys-rami opened 2 years ago

cryptobys-rami commented 2 years ago

I found this bug in the library where a zero address returned from a contract results in an exception (because zero address is '0x0'). I suggest manipulating return data from contracts to check for zero address. It is quite typical for contracts to search an internal map for an address, returning zero address if it cannot find it. BAF41D45-AD45-494E-8338-BDC3B8CA8235_4_5005_c

Solido commented 2 years ago

I think this is related to #239

0x is linked to UintType(length 256) then final result = type.decode(buffer, offset + headersLength); and fail on _decode32Bytes

cryptobys-rami commented 2 years ago

BTW - this happens any time any function returns the default variable. Not just for addresses, also other value types... maybe this is a hint?

Solido commented 2 years ago

Trying to debug the cause. Effect is a problem with Buffer decoding but even the 0x response is incorrect. But I'm just starting using the API so it is a lot of research. Let's discuss here about details to solve this.

cryptobys-rami commented 2 years ago

Sure im happy to help. I ve worked around it by using a different library for reading from functions. Very annoying!

Solido commented 2 years ago

That was my question! This is the basic call of a function so not sure how the tests passes. Which lib are you using? can we provide a PR to this lib?

cryptobys-rami commented 2 years ago

I used this: https://github.com/y-pakorn/flutter_web3

the problem with flutter_web3 library is that its not native dart, so impossible to debug anything. Also smaller community/less testing? plus side of flutter_web3 is that it uses ethers js library which is the gold standard.

Happy to help make web3dart better

Solido commented 2 years ago

Oh I see it is a wrapper around .js so it also mean limitation in going mobile or desktop. Like you said less community and commits.

I'd rather help build a standard around web3dart if possible for multi platforms.

Digging now. Keep you updated in the coming hours.

cryptobys-rami commented 2 years ago

Im very keen on the mobile part.

basically at the moment its impossible to use web3dart with metamask on mobile platform its also impossible to use it on mobile web unless it is run in metamask browser

would love to cooperate to make this possible.

Solido commented 2 years ago

It is possible you need to use wallet connect You can reach me here https://twitter.com/BlueAquilae

Solido commented 2 years ago

Hi @simolus3 would you accept a bounty to resolve this case? 40euros to help support this project and help us with timing resolution. Thank you for your consideration on the matter.

cryptobys-rami commented 2 years ago

happy to contribute (to the bounty) as well!

simolus3 commented 2 years ago

Sorry for the delay on this issue. I'm not too involved in the Ethereum ecosystem anymore, but I'll try to maintain this package as best as I can.

I tried to reproduce this issue with the following contract:

pragma solidity >=0.7.0 <0.9.0;

contract ReturnDefaults {
    function zero_int() public pure returns (int) {
        return 0;
    }

    function zero_address() public pure returns (address) {
        return address(0);
    }
}

I've deployed this to a local Ganache instance and then ran this script:

import 'package:http/http.dart';
import 'package:web3dart/web3dart.dart';

import 'test.g.dart';

Future<void> main() async {
  final client = Web3Client('http://localhost:7545', Client());
  final contract = Test(
      address:
          EthereumAddress.fromHex('0x4BBA8dcCAff0Dd855e6EC6400cc8494Bfa904c57'),
      client: client);

  print(await contract.zero_address());
  print(await contract.zero_int());
}

This prints zero for me, I don't get the range error here. If you have clear instructions on how to reproduce this (ideally, some simple contract source code + the local chain software) I'm happy to take another look. I don't need a bounty for this, just happy to help.

Solido commented 2 years ago

Thx for the quick reply. The easiest way is to use hardhat https://hardhat.org/getting-started/#installation

It will create a default local chain and contract

pragma solidity ^0.8.0;

import "hardhat/console.sol";

contract Greeter {
    string private greeting;

    constructor(string memory _greeting) {
        console.log("Deploying a Greeter with greeting:", _greeting);
        greeting = _greeting;
    }

    function greet() public view returns (string memory) {
        return greeting;
    }

    function setGreeting(string memory _greeting) public {
        console.log("Changing greeting from '%s' to '%s'", greeting, _greeting);
        greeting = _greeting;
    }
}

Called greet() will fail as a default example.

Solido commented 2 years ago

@simolus3 Who is taking care of this repo now?

simolus3 commented 2 years ago

That also works for me? I ran npx hardhat node followed by npx hardhat run scripts/sample-script.js --network localhost.

import 'package:http/http.dart';
import 'package:web3dart/web3dart.dart';

import 'test.g.dart';

Future<void> main() async {
  final client = Web3Client('http://localhost:8545', Client());
  final contract = Test(
      address:
          EthereumAddress.fromHex('0x5FbDB2315678afecb367f032d93F642f64180aa3'),
      client: client);

  print(await contract.greet()); // Hello, Hardhat!
}

I get the "Value not in range: 32" error only if I pick the wrong contract address. The error message sure could be better here, but I assume that's not the actual cause for you?

Who is taking care of this repo now?

I still am. If anyone wants to help, I'm happy to add new maintainers or transfer the repo, but I need to make sure it's not going into the wrong hands since this package may manage private keys for users.

Solido commented 2 years ago

That is a good news!

Just need to find where the diff is. I tried the generator, building from Abi or even manual function setup for the same result.

Also I test in a Flutter app. Need to try a direct call like you. Edit: idem in dart

Contract address are always the same in hardhat EthereumAddress.fromHex('0x5FbDB2315678afecb367f032d93F642f64180aa3') too.

And this is my Greeter.abi.json

{
  "_format": "hh-sol-artifact-1",
  "contractName": "Greeter",
  "sourceName": "contracts/Greeter.sol",
  "abi": [
    {
      "inputs": [
        {
          "internalType": "string",
          "name": "_greeting",
          "type": "string"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "constructor"
    },
    {
      "inputs": [],
      "name": "greet",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "string",
          "name": "_greeting",
          "type": "string"
        }
      ],
      "name": "setGreeting",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    }
  ],
  "bytecode": "0x60806040523480156200001157600080fd5b5060405162000c3238038062000c32833981810160405281019062000037919062000278565b6200006760405180606001604052806022815260200162000c1060229139826200008760201b620001ce1760201c565b80600090805190602001906200007f92919062000156565b5050620004c5565b620001298282604051602401620000a0929190620002fe565b6040516020818303038152906040527f4b5c4277000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506200012d60201b60201c565b5050565b60008151905060006a636f6e736f6c652e6c6f679050602083016000808483855afa5050505050565b8280546200016490620003ea565b90600052602060002090601f016020900481019282620001885760008555620001d4565b82601f10620001a357805160ff1916838001178555620001d4565b82800160010185558215620001d4579182015b82811115620001d3578251825591602001919060010190620001b6565b5b509050620001e39190620001e7565b5090565b5b8082111562000202576000816000905550600101620001e8565b5090565b60006200021d620002178462000362565b62000339565b9050828152602081018484840111156200023657600080fd5b62000243848285620003b4565b509392505050565b600082601f8301126200025d57600080fd5b81516200026f84826020860162000206565b91505092915050565b6000602082840312156200028b57600080fd5b600082015167ffffffffffffffff811115620002a657600080fd5b620002b4848285016200024b565b91505092915050565b6000620002ca8262000398565b620002d68185620003a3565b9350620002e8818560208601620003b4565b620002f381620004b4565b840191505092915050565b600060408201905081810360008301526200031a8185620002bd565b90508181036020830152620003308184620002bd565b90509392505050565b60006200034562000358565b905062000353828262000420565b919050565b6000604051905090565b600067ffffffffffffffff82111562000380576200037f62000485565b5b6200038b82620004b4565b9050602081019050919050565b600081519050919050565b600082825260208201905092915050565b60005b83811015620003d4578082015181840152602081019050620003b7565b83811115620003e4576000848401525b50505050565b600060028204905060018216806200040357607f821691505b602082108114156200041a576200041962000456565b5b50919050565b6200042b82620004b4565b810181811067ffffffffffffffff821117156200044d576200044c62000485565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b61073b80620004d56000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063a41368621461003b578063cfae321714610057575b600080fd5b6100556004803603810190610050919061043d565b610075565b005b61005f61013c565b60405161006c91906104b7565b60405180910390f35b6101226040518060600160405280602381526020016106e3602391396000805461009e90610610565b80601f01602080910402602001604051908101604052809291908181526020018280546100ca90610610565b80156101175780601f106100ec57610100808354040283529160200191610117565b820191906000526020600020905b8154815290600101906020018083116100fa57829003601f168201915b50505050508361026a565b8060009080519060200190610138929190610332565b5050565b60606000805461014b90610610565b80601f016020809104026020016040519081016040528092919081815260200182805461017790610610565b80156101c45780601f10610199576101008083540402835291602001916101c4565b820191906000526020600020905b8154815290600101906020018083116101a757829003601f168201915b5050505050905090565b61026682826040516024016101e49291906104d9565b6040516020818303038152906040527f4b5c4277000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610309565b5050565b61030483838360405160240161028293929190610510565b6040516020818303038152906040527f2ced7cef000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610309565b505050565b60008151905060006a636f6e736f6c652e6c6f679050602083016000808483855afa5050505050565b82805461033e90610610565b90600052602060002090601f01602090048101928261036057600085556103a7565b82601f1061037957805160ff19168380011785556103a7565b828001600101855582156103a7579182015b828111156103a657825182559160200191906001019061038b565b5b5090506103b491906103b8565b5090565b5b808211156103d15760008160009055506001016103b9565b5090565b60006103e86103e384610581565b61055c565b90508281526020810184848401111561040057600080fd5b61040b8482856105ce565b509392505050565b600082601f83011261042457600080fd5b81356104348482602086016103d5565b91505092915050565b60006020828403121561044f57600080fd5b600082013567ffffffffffffffff81111561046957600080fd5b61047584828501610413565b91505092915050565b6000610489826105b2565b61049381856105bd565b93506104a38185602086016105dd565b6104ac816106d1565b840191505092915050565b600060208201905081810360008301526104d1818461047e565b905092915050565b600060408201905081810360008301526104f3818561047e565b90508181036020830152610507818461047e565b90509392505050565b6000606082019050818103600083015261052a818661047e565b9050818103602083015261053e818561047e565b90508181036040830152610552818461047e565b9050949350505050565b6000610566610577565b90506105728282610642565b919050565b6000604051905090565b600067ffffffffffffffff82111561059c5761059b6106a2565b5b6105a5826106d1565b9050602081019050919050565b600081519050919050565b600082825260208201905092915050565b82818337600083830152505050565b60005b838110156105fb5780820151818401526020810190506105e0565b8381111561060a576000848401525b50505050565b6000600282049050600182168061062857607f821691505b6020821081141561063c5761063b610673565b5b50919050565b61064b826106d1565b810181811067ffffffffffffffff8211171561066a576106696106a2565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f830116905091905056fe4368616e67696e67206772656574696e672066726f6d202725732720746f2027257327a264697066735822122062b06e5bdee39e73f7ae7ef8606fe9f23da851629e4e297316ce7747f5074b1964736f6c634300080400334465706c6f79696e67206120477265657465722077697468206772656574696e673a",
  "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063a41368621461003b578063cfae321714610057575b600080fd5b6100556004803603810190610050919061043d565b610075565b005b61005f61013c565b60405161006c91906104b7565b60405180910390f35b6101226040518060600160405280602381526020016106e3602391396000805461009e90610610565b80601f01602080910402602001604051908101604052809291908181526020018280546100ca90610610565b80156101175780601f106100ec57610100808354040283529160200191610117565b820191906000526020600020905b8154815290600101906020018083116100fa57829003601f168201915b50505050508361026a565b8060009080519060200190610138929190610332565b5050565b60606000805461014b90610610565b80601f016020809104026020016040519081016040528092919081815260200182805461017790610610565b80156101c45780601f10610199576101008083540402835291602001916101c4565b820191906000526020600020905b8154815290600101906020018083116101a757829003601f168201915b5050505050905090565b61026682826040516024016101e49291906104d9565b6040516020818303038152906040527f4b5c4277000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610309565b5050565b61030483838360405160240161028293929190610510565b6040516020818303038152906040527f2ced7cef000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610309565b505050565b60008151905060006a636f6e736f6c652e6c6f679050602083016000808483855afa5050505050565b82805461033e90610610565b90600052602060002090601f01602090048101928261036057600085556103a7565b82601f1061037957805160ff19168380011785556103a7565b828001600101855582156103a7579182015b828111156103a657825182559160200191906001019061038b565b5b5090506103b491906103b8565b5090565b5b808211156103d15760008160009055506001016103b9565b5090565b60006103e86103e384610581565b61055c565b90508281526020810184848401111561040057600080fd5b61040b8482856105ce565b509392505050565b600082601f83011261042457600080fd5b81356104348482602086016103d5565b91505092915050565b60006020828403121561044f57600080fd5b600082013567ffffffffffffffff81111561046957600080fd5b61047584828501610413565b91505092915050565b6000610489826105b2565b61049381856105bd565b93506104a38185602086016105dd565b6104ac816106d1565b840191505092915050565b600060208201905081810360008301526104d1818461047e565b905092915050565b600060408201905081810360008301526104f3818561047e565b90508181036020830152610507818461047e565b90509392505050565b6000606082019050818103600083015261052a818661047e565b9050818103602083015261053e818561047e565b90508181036040830152610552818461047e565b9050949350505050565b6000610566610577565b90506105728282610642565b919050565b6000604051905090565b600067ffffffffffffffff82111561059c5761059b6106a2565b5b6105a5826106d1565b9050602081019050919050565b600081519050919050565b600082825260208201905092915050565b82818337600083830152505050565b60005b838110156105fb5780820151818401526020810190506105e0565b8381111561060a576000848401525b50505050565b6000600282049050600182168061062857607f821691505b6020821081141561063c5761063b610673565b5b50919050565b61064b826106d1565b810181811067ffffffffffffffff8211171561066a576106696106a2565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f830116905091905056fe4368616e67696e67206772656574696e672066726f6d202725732720746f2027257327a264697066735822122062b06e5bdee39e73f7ae7ef8606fe9f23da851629e4e297316ce7747f5074b1964736f6c63430008040033",
  "linkReferences": {},
  "deployedLinkReferences": {}
}
Solido commented 2 years ago

• Flutter version 2.8.1 at .../flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision 77d935af4d (il y a 4 semaines), 2021-12-16 08:37:33 -0800 • Engine revision 890a5fca2e • Dart version 2.15.1

simolus3 commented 2 years ago

I'm on Dart 2.15.1 as well, I'll try to reproduce this with Flutter as well.

Either way, it might be easier to find differences by adding a logging layer for RPC requests to the Ethereum node:

class LoggingRpc extends RpcService {
  final RpcService inner;

  LoggingRpc(this.inner);

  factory LoggingRpc.defaults() {
    return LoggingRpc(JsonRPC('http://localhost:8545', Client()));
  }

  @override
  Future<RPCResponse> call(String function, [List? params]) async {
    print('REQ: Call $function with $params');
    final response = await inner(function, params);
    print('RES: ${response.id} = ${response.result}');
    return response;
  }
}

void main() {
  final client = Web3Client.custom(LoggingRpc.defaults());
  // ...
}

The request should be Call eth_call with [{to: 0x5fbdb2315678afecb367f032d93f642f64180aa3, data: 0xcfae3217}, latest], does that match what you're seeing?

Solido commented 2 years ago

Interesting points in this code

final  tx1 = await contract.setGreeting('Hello', credentials: privateKey);
final  tx2 = await contract.greet();

The first line will complete and I get an explorable Transaction. The second call fail with RangeError: Value not in range: 32

With log REQ: Call eth_call with [{to: 0x5fbdb2315678afecb367f032d93f642f64180aa3, data: 0xcfae3217}, latest] RES: 1 = 0x

Solido commented 2 years ago

Also logged what the node is seeing and I get

  WARNING: Calling an account which is not a contract
  From:        0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266
  To:          0x5fbdb2315678afecb367f032d93f642f64180aa3

So something fishy here no doubt