Truffle: Issue with same event name from two contracts

Created on 20 Feb 2019  路  15Comments  路  Source: trufflesuite/truffle

  • [X] I've asked for help in the Truffle Gitter before filing this issue.

Issue

When two different contracts have the same event name but different signature, Truffle-contract does not decodeLogs correctly.

Steps to Reproduce

simple contract code:

pragma solidity ^0.5.0;

contract ContractA  {

   event Approval(
    address indexed _owner,
    address indexed _approved,
    uint256 indexed _tokenId
  );
    function testA() public {

         emit Approval(address(this), address(0), 1);
    }
}
contract ContractB  {

   event Approval(
     address indexed owner,
    address indexed spender,
    uint256  value
  );

    function TestFunctionNotOK(address contractA_Address) public{       
        ContractA(contractA_Address).testA();     
    }
}

using this code for Truffle-Test:

var ContractB = artifacts.require("ContractB");
var ContractA = artifacts.require("ContractA");

contract('ContractB',  function(accounts) {

  it("test EventB",  function() {
    return ContractB.deployed().then(async function(contractBInstance) {
        const constractAInstance = await ContractA.deployed();

        await contractBInstance.TestFunctionNotOK(constractAInstance.address);     
    })
  });
});

Expected Behavior

Expect it to pass the test

Actual Results

You will see this error:

Error: TypeError: Cannot read property 'toString' of null Given value: "null"
at Object.toBN (C:\Users\chris\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\web3-utils\src\utils.js:64:1)
at _convertNumber (C:\Users\chris\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\truffle-contract\lib\reformat.js:20:1)
at abiSegment.forEach (C:\Users\chris\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\truffle-contract\lib\reformat.js:76:1)
at Array.forEach ()
at Function.numbers (C:\Users\chris\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\truffle-contract\lib\reformat.js:51:1)
at C:\Users\chris\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\truffle-contract\lib\utils.js:61:1
at Array.map ()
at Function.decodeLogs (C:\Users\chris\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\truffle-contract\lib\utils.js:44:1)
at Promise.receipt (C:\Users\chris\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\truffle-contract\lib\handlers.js:98:1)
at Promise.emit (C:\Users\chris\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\eventemitter3index.js:89:1)
at C:\Users\chris\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\web3-eth\~\web3-core-method\srcindex.js:353:1
at process._tickCallback (internal/process/next_tick.js:68:7)

Environment

  • Operating System: win10
  • Ethereum client: ganache-cli
  • Truffle version (truffle version):
    Truffle v5.0.4 (core: 5.0.4)
    Solidity v0.5.0 (solc-js)
    Node v10.1.0
  • node version (node --version): v10.1.0
  • npm version (npm --version): 6.0.1
Contract bug

Most helpful comment

We just hit the same. Because we interface with ERC20 and ERC721, we cannot rename the "Transfer" and "Approval" events as @chrischip pointed out.

Is the work-around to migrate tests to not use Truffle anymore, e.g. making calls with web3 instead? Anything else I could try?

All 15 comments

Please note that this is not an uncommon scenario and might affect a lot of Dapp implementations. Both ERC20 and ERC721 have the events "Transfer" and "Approval", both have a slightly signature (one parameter is indexed vs the other one is not). If a contract tries to invoke a function which utilize both ERC20 and ERC721 at the same time, truffle-contract will appears to fail (while the blockchain could successfully processed the transaction).

We just hit the same. Because we interface with ERC20 and ERC721, we cannot rename the "Transfer" and "Approval" events as @chrischip pointed out.

Is the work-around to migrate tests to not use Truffle anymore, e.g. making calls with web3 instead? Anything else I could try?

I created another example of this issue:
https://github.com/hardlydifficult/SolidityBugInvestigation_EventsWithTheSameName
Let me know if there are any questions on this

It seems switching to the web3 API is not a viable workaround here (the request hangs instead of throws as error).

This example is very close to what we are trying to achieve, our contract implements the ERC721 standard (including the Transfer event) and is attempting to transfer a ERC20 token (which emits a different Transfer event).

Please let me know if you have any suggestions, not sure how we should proceed here.

I dive deep into the code and it seems the problem lies in the Web3 version provided. In my unit test I think web3 is instantiated by Truffle test, and in PRD it is instantiated by Drizzle. I compared the Web3 version they (Truffle and Drizzle) used to the very current version of Web3, it seems that the issue were addressed in the latest Web3 (I didn't actually test it but the decodeLogs part of the code seems to be very different). I think once Truffle move to the new Web3 version, this will probably be resolved. Please correct me if I am wrong.

Currently that is nothing I could do more. I just catch that specific error, simply ignore it and assume that the transaction has been executed successfully.

I struggle so much on the different versions of Web3, and also the providers, especially with subscriptions as HTTP polling seems to be taken out of Web3 1.0. Really hope there is a solution for this Web3 version hell.

Good insight, thanks for sharing. I believe Truffle is using Web3 beta 37... and the versions which came after included breaking changes that seem to be causing others issues. It seems the general recommendation at the moment is to stay on beta 37 until the latest version stabilizes again. I wonder what the latest is on that and if Truffle is considering an upgrade soon.

It seems the only path forward is to catch and ignore the error. But I'm concerned that if the issue is Web3 specifically we may encounter problems in our dapp as well (vs just Truffle tests).

My client side from MetaMask + Drizzle definitely still having the same problem. I can only catch it and ignore it. Otherwise than the annoying error it doesn't seem to have any other side effect so far.....

I believe we found a workaround which will avoid the error completely, make the call using web3's encodeFunctionCall followed by sendTransaction (example below).

I'm guessing this works since when making the call this way, web3 does not know the ABI for the rest of the contract and therefore cannot attempt to decode logs (which is where the failure occurs).

const call = web3.eth.abi.encodeFunctionCall(
  testContract.options.jsonInterface.find(
    e => e.name == 'sendToken'
  ),
  [token.address, toAccount]
)
await web3.eth.sendTransaction({
  to: testContract.options.address,
  data: call,
  from: tokenOwner 
})

I tested and this seems to still be an issue with Web3 beta 50. So I opened a bug over there for investigation: https://github.com/ethereum/web3.js/issues/2542

What an issue to find!

We'll have to look into this. Hopefully some investigation will identify next steps / workarounds / other remediations.

Thanks for raising this!

I can confirm this issue on [email protected].

My smart contract has a public method that, upon being called, issues Transfer/Approve events of both ERC20 and ERC721 implementations within the same transaction.

The only difference is that in my case it was an "Out of gas" error instead of the "Cannot read property 'toString' of null" error mentioned by the OP...

After I renamed ERC721 events to Transfer721/Approve721, the error disappeared.

However, using an external Web3 instance of v1.0.0-beta.55 hasn't helped a lot -- instead of getting an error as before, the transaction just stucks. So it looks like a Web3 issue, not a Truffle issue.

You can try this

This should be resolved on the latest Truffle (currently 5.1.0). We are still left with a problem decoding both of the events but it will no longer error.

In the future at some point we are going to work on correctly decoding both events from the logs.

Truffle 5.1.3 issue is still there.

event Transfer(address indexed _from, address indexed _to, uint256 _tokenId); and
event Transfer(address indexed from, address indexed to, uint256 value);

will not be parsed in the same transaction and will throw Error: Returned values aren't valid, did it run Out of Gas?

@knightlands Do you have a project and steps that I could use to reproduce this error?

@chrischip I think this problem may be fixed on the most recent Truffle (version 5.1.16). Let me know if you are still having this problem and I'll be happy to re-open this issue and try to help!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

TOMOAKI12345 picture TOMOAKI12345  路  3Comments

ripper234 picture ripper234  路  4Comments

ysfAskri picture ysfAskri  路  4Comments

jleeh picture jleeh  路  3Comments

maximilianh picture maximilianh  路  3Comments