3

I'm trying to get a better understanding of arbitrary bytes parameters, so I wrote a one-function smart contract that accepts a bytes argument, decodes it, and returns the response. I am having trouble calling the contract from a script using ethers.js - I get the correct response, but the script never ends. I have to add process.exit() - I'd like to know why the script isn't ending even though the promise is resolved, and how I should appropriately be handling events;

Here's my Solidity code:

pragma solidity ^0.5.0;
contract Byt {
  event bytDone (uint256 a, uint256 b);
  function takeByt(bytes memory byt) public returns (uint256, uint256) {
    (uint256 a, uint256 b) = abi.decode (
      byt,
      (uint256, uint256));
    emit bytDone(a, b);
    return (a, b);
  }
}

and here's where I'm trying to call the function from javascript with test values of 10 and 15:

let num1 = 10;
let num2 = 15;
let byt = ethers.utils.defaultAbiCoder.encode(
  ['uint256', 'uint256'],
  [num1, num2]
);
bytesTest(byt);
async function bytesTest(byt){
  try{
    let c = await bytesContract.takeByt(byt, {gasLimit: 100000});
    let r = await bytesContract.on("bytDone", (res1, res2) => {
      console.log(res1);
      console.log(res2);
    });
  }catch(err){
    console.log(err);
  }
}

The output is:

BigNumber { _hex: '0x0a' }
BigNumber { _hex: '0x0f' }

These are the appropriate hex encodings of 10 and 15 respectively, meaning I've picked up the event after correctly calling the solidity function. This is supposed to be the "await" part of my javascript code. The problem is, the script doesn't end - after console.logging res1 and res2 - it seems to just be waiting for something else. If anyone could explain why the script isn't ending, and what I should do to appropriately handle the emitted event from my solidity contract, I'd be forever grateful. Thanks in advance for your help!

1
  • Ethers.js, v. 4.0.39, I have exactly the same issue. Have you managed to resolve it?
    – Evgeniy
    Nov 5, 2019 at 15:16

2 Answers 2

3

I had the same issue and using once for events filtering also didn't work. I had to stop provider from polling events.

You can do it like this:

bytesContract.provider.polling = false

This is what ethers documentation says about it

prototype.polling mutable

If the provider is currently polling because it is actively watching for events. This may be set to enable/disable polling temporarily or disabled permanently to allow a node process to exit.

Ethers Provider Polling Documentation

Worked for me. New provider has polling set to false and only when you filter for events or call transactions it will start polling.

0

You established subscription for bytDone events and didn't terminate it, that's why your script is waitng for more such events to come. You need to use bytesContract.once("bytDone", ... if you need to capture only the first instance of event and then unsubscribe automatically. See Web3 API documentation for more details.

1
  • 1
    ah, I see this referenced in ethers github issues as well: (github.com/ethers-io/ethers.js/issues/37#issuecomment-337653030) unfortunately, even when I replaced let r = await bytesContract.on("bytDone", (res1, res2) => { with let r = await bytesContract.once("bytDone", (res1, res2) => { it runs, but I have the same output and it still does not terminate. I was able to get it to terminate by adding process.exit(); after the console.logs, but I don't think this is the appropriate solution since it's just a force-terminate.
    – a94
    Mar 26, 2019 at 15:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.