1

I am trying to put together an archive that will store contract address, metadata and abi etc. in a db for use by Dapps outside of hardhat. (This archiver is written inside hardhat but read outside of it)

In particular I'd like to store the abi, in json format, so that I can access and run the contract in a non-hardhat environment using ethers.js

This works well enough when the contract doesn't require libraries, but:

I have a "prototype" contract (BKProto) which includes two functions common to every smart contract I write: BKContractName and BKContractVersion. I use the abi of BKProto to get the name and version of the contracts I'm storing.

I pass each contract I create to the archiver in the form of ethers.js Contract object. I cast each contract in the BKProto class created by the Hardhat typechain so I can read the name and version of the contract. Then I try to get the contractFactory object for each contract so I can retrieve the abi json and store it in the archive.

The code below (starting let factory) works just fine for contracts which don't depend on libraries. But if they do, I can't get the factory this way -- I get the error: NomicLabsHardhatPluginError: The contract MyContract is missing links for the following libraries: contracts/MyLibrary.sol:MyLibrary

So . . . I am wondering if, within the hardhat environment, is there an easy way to retrieve the abi of a deployed contract, using the name of the contract? Or just using a contract instance provided as a param to this function?

The reason is that I use ethers, but not hardhat in some DApps which create the Contract object using the new syntax to call its various functions. let myContract = new Contract(address, abi, signer);

Suggestions appreciated.

 private async extractRecordFromContract(projectName: string, contract: Contract) : ArchiveRecord {
       let deployer = await contract.signer.getAddress();
       let con = contract as BKProto
       let name = await con.BKContractName();
       let version = await con.BKVersion();
       let factory = await ethers.getContractFactory(await con.BKContractName())
       let abi = factory.interface.format(ethers.utils.FormatTypes.json)
       //now store this data in the db.




2 Answers 2

1

The ABI is automatically saved to artifacts/contracts during compilation, e.g. if your contract is stored in MyNFT.sol its ABI will be saved in artifacts/contracts/MyNFT.sol/MyNFT.json

0

Make a folder called contractsData in your hardhat root directory and then past the following code in the scripts section:

async function main() {

  const Marketplace = await ethers.getContractFactory("Marketplace");
  const marketplace = await Marketplace.deploy();
  
  saveFrontendFiles(marketplace , "Marketplace");
  
  console.log('Marketplace deployed at: ', marketplace.address);
  
}

function saveFrontendFiles(contract, name) {
  const fs = require("fs");
  const contractsDir = __dirname + "/../contractsData";

  if (!fs.existsSync(contractsDir)) {
    fs.mkdirSync(contractsDir);
  }

  fs.writeFileSync(
    contractsDir + `/${name}-address.json`,
    JSON.stringify({ address: contract.address }, undefined, 2)
  );

  const contractArtifact = artifacts.readArtifactSync(name);

  fs.writeFileSync(
    contractsDir + `/${name}.json`,
    JSON.stringify(contractArtifact, null, 2)
  );
}

main()
  .then(() => process.exit(0))
  .catch(error => {
    console.error(error);
    process.exit(1);
  });

Replace marketplace with your contract information and then run the script. The abi will be saved in the contractsData directory.

1
  • You need to init artifacts variable in saveFrontendFiles function. Mar 6 at 10:50

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.