Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

assertEventEmitted from new contract construction call. #1196

Closed
1 task done
michaeljohnbennett opened this issue Aug 18, 2018 · 8 comments
Closed
1 task done

assertEventEmitted from new contract construction call. #1196

michaeljohnbennett opened this issue Aug 18, 2018 · 8 comments

Comments

@michaeljohnbennett
Copy link
Contributor


Issue

Upon contract consutruction I would like to be able to read the event logs to ensure an Event was emitted during.

Steps to Reproduce

At present there is no way I can see or is documented to be able to easily use something like this:

c = await MyContract.new();
// this wont work...
truffleAssert.eventEmitted(c, "ContractCreated", (ev) => {
        return ev.param === myInputParam;
});

My contract constructor will emit a ContractCreated event. I want to assert that this happened and the values are as expected. The event itself and its content is irrelevant. Its more the process of asserting events were emitted and contract construction time is important.

Expected Behavior

I would expect or want to know how I can do this assertion and use the assertEventEmitted function above.

Currently the only way I can see to accomplish this is so:

        let event = c.allEvents({fromBlock: 0, toBlock: 'latest'});
        event.watch(function (error, result) {
            if (!error){
                console.log("Result: ", result);
                // or some assertions similar to assertEventEmitted(...)
            }
        });

Actual Results

As above, I can't find an elegant way to read the event logs emitted during contract construction using the truffle toolset.

When you send a transaction in you get the result object you can assert, upon contract creation the object returned is different and as such the logs are not available to check for event emission.

Environment

  • Operating System: Mac OSX
  • Ethereum client: none at present, only inside ganache-cli: 6.1.8
  • Truffle version (truffle version): 4.1.11
  • node version (node --version): 9.2.1
  • npm version (npm --version): 6.4.0
@cgewecke
Copy link
Contributor

@michaeljohnbennett The new contract instance has a transactionHash property which should allow you to fetch the receipt (which has a logs property). Truffle does some post-processing of the transaction return value (see here ) so you might have to extract the logs from the receipt yourself for the truffleAssert library, not sure.

c = await MyContract.new();
const receipt = web3.eth.getTransactionReceipt(c.transactionHash);

Another thing you might be interested in is Truffle V5 (which is available in pre-release form from npm as truffle@next). It uses Web3 1.0 and lets you listen for transactionHash and receipt events per transaction. You could do something like:

MyContract
  .new()
  .onReceipt( receipt => {
     truffleAssert(..etc..)
     done(); // Tell mocha you finished
  });

There are draft release notes for V5 at #1129 with more detail about the new TruffleContract features and info about breaking changes.

@michaeljohnbennett
Copy link
Contributor Author

Thanks for this @cgewecke thats helpful. the new V5 syntax looks like it might solve my problems as this event catching chain methods would make it very easy to test with, rather than the 2 stage, go and check the blockchain route.

I'll use the solve for the current version right now and take it from there and look forward to seeing the new release.

As an aside, would it be worthwhile putting a solution to this problem in the docs or FAQ's as its not very apparent how to solve something like this that is perhaps an edge case but took me hours this morning trying to find some kind of solution between a bunch on semi-relevant SO posts and on here.

@michaeljohnbennett
Copy link
Contributor Author

michaeljohnbennett commented Aug 18, 2018

I tried this:

c = await MyContract.new();
const receipt = web3.eth.getTransactionReceipt(c.transactionHash);

But I can't see how to access the decode logs call from Contract easily enough. do I need to get it from the contract class MyContract or the instance c?

Also the signature needs

decodeLogs: function(C, instance, logs) {
    // code in here
};
// and its called like so:
return accept({
    tx: tx,
    receipt: receipt,
    logs: Utils.decodeLogs(C, instance, receipt.logs)
});

Thanks for all your help, if this is non trivial to resolve I'll just fall back to searching for the events from the blocks.

@cgewecke
Copy link
Contributor

@michaeljohnbennett Thanks for opening and apologies - after looking into this a bit I see it's not the easiest thing to do and the decoding utility isn't well exposed.

The following worked for me: Install web3-eth-abi.

npm install --save-dev web3-eth-abi

Then:

const abi = require('web3-eth-abi');
....
c = await MyContract.new();
const receipt = web3.eth.getTransactionReceipt(c.transactionHash);

// Decode
const inputs = MyContract.abi.find(item => item.name === 'ContractCreated').inputs;
const log = receipt.logs[0]; // Assuming you have a single constructor event
const data = log.data; // Non-indexed event data
const topics = (log.topics.length > 1) ? log.topics.slice(1) : []; // Indexed event data
const decodedLog = abi.decodeLog(inputs, data, topics); 

// Test
assert(decodedLog.param === myInputParam)

TLDR; watching seems simpler? In Web3 1.0 all of this decoding happens automatically for the receipt and you can just access the returnValues field of a log item.

Also agree this subject is not documented well enough although we're also the cusp of using better implementation so .... hopefully people will be able to find a solution to this more easily now that you've raised it.

@michaeljohnbennett
Copy link
Contributor Author

yes I can see its a not trivial fix with the current versions. Super explanation, I'll try it out and also look at using the latest releases of truffle as well.

What's the ETA for the V5 release? I might just push up to using that if we are close to release?

@cgewecke
Copy link
Contributor

@michaeljohnbennett The formal release will probably be in September. We're releasing as a beta next week and the prerelease is available right now.

I don't think there will be substantial changes to the API for truffle-contract between now and formal release, so the only downside to upgrading is that there might be bugs :)

We've done quite a bit of testing to try to make sure V5 works and we have a couple large projects already running it in their suites but there will likely still be a handful of issues to sort out.

Going to close this for house-keeping but thanks so much for opening.

@michaeljohnbennett
Copy link
Contributor Author

michaeljohnbennett commented Aug 19, 2018

Thanks @cgewecke super helpful feedback on this issue, I'm using this framework a lot for projects, looking forward to the next gen release. I'll take it onboard for the next iteration of our current project. I need to get this out the door for a MVP so jumping to Alpha release is just a bit too risky right now.

I also linked this ticket to a stack overflow ethereum question I raised as well to hopefully give some breadcrumbs to people searching for an answer.

I do a lot of TDD/BDD testing so this kind of stuff is always on my mind on how best to test and break stuff, handy in solidity I think.

@marc0olo
Copy link

I am using truffle 5 now and am still very confused about that topic. Haven't found anything about the new TruffleContract features regarding testing of events.

Happy to have found this issue finally 😄

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants