Skip to main content
What you’ll be able to do
  • Create a MIP20 token on Metal Testnet.
  • Verify its address, owner, initial supply, and the initial holder’s balance.
MIP20Factory.deployMIP20 creates a token with the name, symbol, decimals, initial supply and initial holder you choose. The account that calls it is the MIP20 deployer. It becomes the token owner and can create additional supply through the token’s mint function. This guide creates 100 units of a test token with six decimals, then verifies the token configuration and delivery to its initial holder.

Prepare the creation request

The factory address is 0x0000000000000000000000000000000000000f4c, and the *USDZ address is 0x000000000000000000000000000000000000b5d5. Both are listed in Contract Addresses. Install the public packages in the application directory. For a new project, run pnpm init first:
The build allowance enables the esbuild dependency used by tsx.

Define the creation inputs

Set the initial supply and define the factory interface and arguments. The code uses client from Connect to Metal and account and wallet from Estimate and record fees:
With six decimals, the initial supply of 100 tokens is 100000000 base units. The mint credits the initial holder if its receive policy accepts the tokens. If the policy refuses them, the entire initial supply goes to quarantine, including when the refusal mode is REVERT. See ReceivePolicy for recipient rules and recovery.

Call the factory

Follow Estimate and record fees to estimate deployMIP20 with the arguments above. Omit fee fields during estimation and check that the signing account’s balance in the gas token covers the maximum gas cost. Sign the factory call with the resulting gasLimit and maxFeePerGas:
Save signed.txHash, signed.raw, and the requested configuration before broadcasting with await signed.send(). If the submission result is uncertain, investigate that saved transaction before signing again. A new factory call would create another token.

Extract the created address

Read the transaction receipt by the saved hash and check that execution succeeded. Extract the token address from MIP20Deployed, checking that the factory emitted it and that its deployer matches the signing account:

Verify and save the configuration

Confirm finality and the canonical receipt block. Read the token state at receipt.blockNumber to check the configuration at the finalized creation block. Start with the initial supply:
Before saving the token as verified, check every field: Add owner() to the standard ERC-20 ABI:
Check the table’s remaining getters with the same readContract pattern. For isMIP20, call the factory with args: [token]. For balanceOf, call the token with args: [initialHolder]. Read the bytecode with publicClient.getCode({ address: token, blockNumber: receipt.blockNumber }). Stop if the metadata, owner, MIP20 status or supply differs from the request. Verify delivery by matching the token’s Transfer(zeroAddress, initialHolder, initialSupply) event and the initial holder’s balance. If the mint went to quarantine, require a matching quarantine receipt for this token, the zero-address originator, intended initial holder and full supply. Save the complete receipt, including its recovery authority, and recover that supply through ReceivePolicy. Save the chain ID, token address, decimals, owner, initial holder, requested configuration, deployment transaction hash and delivery or quarantine status in the deployment record. Retain the created address as soon as the deployment event is verified, so an interrupted delivery check can resume from that address and hash.

Recover a pending creation

If submission or receipt polling times out, look up the saved transaction with publicClient.waitForTransactionReceipt({ hash: savedHash }). Once its receipt is available, repeat address extraction and verification against the original signing account, initial holder, and token configuration. Check the endpoint and saved transaction’s status before rebroadcasting. To submit the same signed transaction again, use publicClient.sendRawTransaction({ serializedTransaction: savedRaw }). The TypeScript SDK describes this signing and submission procedure. If estimation fails, check the signing account’s balance in the gas token and the requested arguments. If execution reverts, creation rolls back and a transaction fee can still be charged.

Mint additional supply

The factory-deployed token exposes mint(address to, uint256 amount). Its current owner can call this function on the token address to increase the supply. Convert the amount using the token’s decimals, estimate and pay gas, then verify the receipt, finality and resulting supply increase. Match either the destination credit or its quarantine receipt. If the mint was quarantined, recover the existing supply through ReceivePolicy using that receipt. The owner can transfer ownership using transferOwnership(address newOwner). The new owner then controls minting. Verify the resulting owner() value before updating the application’s authority records.