0

I'm trying to test a factory contract using hardhat and waffle. I have a contract called Domain:

//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

import "hardhat/console.sol";

contract Domain {

    string private publicKey;

    address[] public children;

    constructor(string memory _publicKey) {
        console.log("Deploying a domain using public key: ", _publicKey);
        publicKey = _publicKey;
    }

    function getChildren() public view returns (address[] memory){
        return children;
    }
}

And a factory for deploying this contract:

//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
import "./Domain.sol";
import "hardhat/console.sol";


contract DomainFactory {
    Domain[] private _domains;
    function createDomain(
                          string memory _publicKey
                          ) public returns (address){
        Domain domain = new Domain(
                                   _publicKey
                                   );
        _domains.push(domain);
        return address(domain);
    }
    function allDomains(uint256 limit, uint256 offset)
        public
        view
        returns (Domain[] memory coll)
    {
        return coll;
    }
}

I have the following tests defined, where this refers to a context object defined in a "world" file (using cucumber.js.

When('the holder of this public key creates a domain', async function () {
    this.domain = await this.factory.createDomain('<public_key>');
});

Then('a child of this domain has the name name', async function () {
    const children = this.domain.getChildren();
    const childrenWithName = children.find((child:any) => {
        return child.getNames().some((childName:any) => {
            return childName === 'name';
        })
    })

    expect(childrenWithName).to.be.an('array').that.is.not.empty;
});

Ideally in the when step, I could define this.domain as the result of deploying a contract, and thereafter test the methods of the contract I deploy:

// world.ts

import { setWorldConstructor, setDefaultTimeout } from '@cucumber/cucumber'
import {deployContract, MockProvider, solidity} from 'ethereum-waffle';
import {use} from "chai";
import DomainContract from "../../../artifacts/contracts/Domain.sol/Domain.json";
import DomainFactoryContract from "../../../artifacts/contracts/DomainFactory.sol/DomainFactory.json";
import { Domain, DomainFactory } from "../../../typechain-types";
import {Wallet} from "ethers";



use(solidity);

setDefaultTimeout(20 * 1000);

class DomainWorld {
  public owner: string
  public wallets: Wallet[]
    public factory: DomainFactory | undefined
    public domain: Domain | undefined
    public ready: boolean = false
    private _initialized: Promise<boolean>
 

    async deployContractByAddress(address, ...args){
        return await deployContract(this.wallets[0], address, ...args);
    }
  constructor() {
    this.wallets = new MockProvider().getWallets();
    this.owner = this.wallets[0].address

    const that = this
    this._initialized = new Promise(async (resolve, reject) => {
        try {
            that.factory = (await deployContract(that.wallets[0], DomainFactoryContract, [])) as DomainFactory;
            that.ready = true
            resolve(true)
        }catch (err) {
            reject(err)
        }
    })
  }
}


setWorldConstructor(DomainWorld);

My problem is, hardhat's deployContract function isn't expecting a contract address, which is what is returned by my DomainFactory's create method. How can I test contracts deployed via my factory if the return value is an address?

1

1 Answer 1

0

Use "contract.attach( addressOrName ) ⇒ Contract"

https://docs.ethers.io/v5/api/contract/contract/

Your Answer

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

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