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
        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
async function bytesTest(byt){
        let c = await bytesContract.takeByt(byt, {gasLimit: 100000});
        let r = await bytesContract.on("bytDone", (res1, res2) => {

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!


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.

  • 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 at 15:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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