Contract Factories

About

Some contracts, like the DataContract require a few more steps to be set up during their creation. These steps may depend on each other, so a user creating these contracts would have to wait for the single steps to be completed before being able to work with the contract.

These contracts are usually created by using contract factories, which offers a few enhancements to the process:

  • it is faster - instead of n single transactions only one transaction is performed
  • creating contracts becomes cheaper - overhead is reduced when performed in a single transaction
  • it can become safer - if one of the setup steps that follow the contract creation fails, the entire creation process is rolled back and if executed via the evan API, this transaction will not be started (if executed with the Blockchain Core API, gas is estimated before each transaction and a failing transaction would be detected and prevented)
  • factories are deployed to ENS addresses and can be updated without delivering code to each client application

Usage

ENS Address

Contract factories that belong to a Business Center are usually deployed at ${FACTORY_NAME}.factory.${BUSINESS_CENTER_ADDRESS}, so a factory for tasks in the business center “sample.evan” would be deployed at “tasks.factory.sample.evan”.

Factories and BusinessCenters

If a factory creates contracts for a Business Center, it has to be registered as a valid factory in that Business Center. Factories register all new contracts they create in the Business Center they belong to, and to be able to do so, they need to be registered at the Business Center as a valid factory.

For this purpose the owner of a business center can call the function registerFactory at a BusinessCenter, e.g. with:

await runtime.executor.executeContractTransaction(
  businessCenter,
  'registerFactory',
  { from: executingAccount },
  factory.options.address,
);

This will allow the given factory to call the function registerContract at the BusinessCenter and therefore allow it to automatically add new contracts, the factory created, to the business center.

Getting Addresses of new Contracts

When creating a contract via factory the address is returned via the ContractCreated event from the factory, so an event listener, that watches for those events has to be created beforehand.

When using the Blockchain Core API, the events for retrieving the contract address can be given to a contract function execution as well, as used in base-contract.ts for example:

const contractId = await this.options.executor.executeContractTransaction(
  factory,
  'createContract', {
    from: accountId,
    autoGas: 1.1,
    event: { target: 'BaseContractFactoryInterface', eventName: 'ContractCreated', },
    getEventResult: (event, args) => args.newAddress,
  },
  businessCenterAddress,
  accountId,
  descriptionDfsHash,
  this.options.nameResolver.config.ensAddress,
);