NomicFoundation / hardhat-ignition

Hardhat Ignition is a declarative deployment system that enables you to deploy your smart contracts without navigating the mechanics of the deployment process.
https://hardhat.org
MIT License
100 stars 19 forks source link

Log to console the value of a `readEventArgument` function result #666

Closed wyze closed 7 months ago

wyze commented 7 months ago

I have a factory pattern where the create function supports an array of tokens to create, which in turn, emits event per token created. I am trying to read the token name and address from the event emitted and log out the address during deployment. I see the value is in the journal file but not sure how to get it to display in the terminal somewhere.

Here is my module:

import { buildModule } from "@nomicfoundation/ignition-core";

export default buildModule("wToken", (module) => {
  const factory = module.contract("WrappedFactory", []);

  const token = { /* .. */  };

  const create = module.call(factory, "create", [[token]]);

  const address = module.readEventArgument(
    create,
    "WrappedToken",
    "wrappedToken",
  );
  const name = module.readEventArgument(create, "WrappedToken", "name");

  return { factory, name, address };
});

I am trying to read the name and address values here.

Factory contract here:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";
import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol";
import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import {Wrapped} from "./Wrapped.sol";

contract WrappedFactory is AccessControl, Pausable {
    event WrappedToken(
        address indexed wrappedToken,
        string name,
        string symbol
    );

    Wrapped[] public _wrapped;

    bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");

    /**
     * @dev Create the contract
     */
    constructor() {
        _grantRole(DEFAULT_ADMIN_ROLE, _msgSender());
        _grantRole(ADMIN_ROLE, _msgSender());
    }

    function create(Token[] calldata tokens_) external onlyRole(ADMIN_ROLE) {
        for (uint256 index; index < tokens_.length; index++) {
            Token memory token = tokens_[index];
            Wrapped wrapped = new Wrapped(
                token.name,
                token.symbol
            );

            emit WrappedToken(
                address(wrapped),
                token.name,
                token.symbol,
            );

            _wrapped.push(wrapped);
        }
    }
}

struct Token {
    string name;
    string symbol;
    /* .. */
}
kanej commented 7 months ago

Hey, @wyze. You can pass a readEventArgument future into contractAt:

const address = module.readEventArgument(
  create,
  "WrappedToken",
  "wrappedToken",
);

const newToken = m.contract("name", address);

return { newToken }

It will show up in the list of deployed contracts under "name" or an id you specify (e.g. m.contract("name", address, { id: "MyToken" }).

You can't currently pass a readEventArgument future in as the name of a contract though.