> ## Documentation Index
> Fetch the complete documentation index at: https://docs.initia.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Creating Custom ERC20s

[Tutorial GitHub Repository](https://github.com/initia-labs/examples/tree/main/evm/initia-custom-erc20)

## Prerequisites

### Foundry

For this tutorial, you will be using the
[Foundry](https://github.com/foundry-rs/foundry) toolkit to develop, compile,
and deploy your contracts. If you do not have Foundry installed, follow the
[Foundry installation instructions](https://getfoundry.sh/).

## Setup

First, create a new directory for your project.

```sh theme={null}
mkdir initia-erc20
cd initia-erc20
```

Next, initialize a new Foundry project inside that directory.

```sh theme={null}
forge init
```

Once the project is initialized, you can proceed to installing the required
dependencies needed for this tutorial. In this case, you only need Initia's
[EVM contracts](https://github.com/initia-labs/initia-evm-contracts).

```sh theme={null}
forge install initia-labs/initia-evm-contracts
```

## Implementing the Contract

Before writing the contract, first rename the template contract to
`NewInitiaERC20.sol`.

```sh theme={null}
mv src/Counter.sol src/NewInitiaERC20.sol
```

Then update the contract from the template to be your custom ERC20 contract.
Start by importing the `InitiaCustomERC20` contract from the
`@initia/initia-evm-contracts` package.

```solidity src/NewInitiaERC20.sol theme={null}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "initia-evm-contracts/src/InitiaCustomERC20.sol";
```

Next, extend the `InitiaCustomERC20` contract and add the constructor to
initialize the contract with the name, symbol, and decimals of your custom
ERC20. For this tutorial, you will simply customize the base contract by adding
a logic to mint tokens to the contract deployer during deployment.

```solidity src/NewInitiaERC20.sol theme={null}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "initia-evm-contracts/src/InitiaCustomERC20.sol";

/**
 * @title NewInitiaERC20
 * @dev Demo extension of InitiaERC20 token contract with initial minting functionality
 */
contract NewInitiaERC20 is InitiaERC20 {
    /**
     * @dev Constructor for creating a new InitiaERC20 token with initial minted supply
     * @param name_ The name of the token
     * @param symbol_ The symbol of the token
     * @param decimals_ The number of decimal places for token precision
     * @param mintedTokens_ The initial amount of tokens to mint to the contract deployer
     */
    constructor(string memory name_, string memory symbol_, uint8 decimals_, uint256 mintedTokens_) InitiaERC20(name_, symbol_, decimals_) {
        _mint(msg.sender, mintedTokens_);
    }
}
```

The contract implementation is now ready. However, if you try to compile the
contract using `forge compile`, you will get an error.

This is because the default `Counter.t.sol` and `Counter.s.sol` expect the
original `Counter.sol` contract to be available. To fix this, rename
`Counter.t.sol` to `NewInitiaERC20.t.sol` and `Counter.s.sol` to
`NewInitiaERC20.s.sol`.

```sh theme={null}
mv test/Counter.t.sol test/NewInitiaERC20.t.sol
mv script/Counter.s.sol script/NewInitiaERC20.s.sol
```

Now replace the contents of the `NewInitiaERC20.t.sol` file with the following
placeholder content.

```solidity test/NewInitiaERC20.t.sol theme={null}
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Test, console} from "forge-std/Test.sol";
import {NewInitiaERC20} from "../src/NewInitiaERC20.sol";

contract NewInitiaERC20Test is Test {

}
```

And replace the contents of the `NewInitiaERC20.s.sol` file with following
placeholder content.

```solidity script/NewInitiaERC20.s.sol theme={null}
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Script} from "forge-std/Script.sol";
import {NewInitiaERC20} from "../src/NewInitiaERC20.sol";

contract NewInitiaERC20Script is Script {
    NewInitiaERC20 public erc20;

    function setUp() public {}

    function run() public {
        vm.startBroadcast();

        erc20 = new NewInitiaERC20("New Initia ERC20", "NIERC20", 18, 1000000 * 10 ** 18);

        vm.stopBroadcast();
    }
}
```

Now running `forge compile` should work without any errors.

```sh theme={null}
forge compile
```

### Expected Output:

```sh theme={null}
[⠢] Compiling...
[⠰] Compiling 27 files with 0.8.21
[⠃] Solc 0.8.21 finished in 6.25s
Compiler run successful!
```

## Deploying the Contract

Now that the contract is compiled and ready, you can deploy it to the MiniEVM.
To accomplish this, use Foundry's `forge create` command

<Warning>
  **Security Note:** In this tutorial, a private key is exported directly in the
  terminal for simplicity. This is fine for *testnet* or *throwaway* accounts.
  Do **not** use this method for accounts holding real funds. For production
  usage, place sensitive keys in a `.env` file (ignored by git) or use a secure
  key manager.
</Warning>

```sh theme={null}
export PRIVATE_KEY=0x...
export RPC_URL='https://jsonrpc-evm-1.anvil.asia-southeast.initia.xyz'
forge create src/NewInitiaERC20.sol:NewInitiaERC20 \
  --rpc-url $RPC_URL \
  --private-key $PRIVATE_KEY \
  --legacy \
  --broadcast \
  --constructor-args "MyToken" "MTK" 18 100
```

### Expected Output:

```sh theme={null}
[⠊] Compiling...
No files changed, compilation skipped
Deployer: 0xc5D26D0281e28599c7790aacc810226BBDf0E431
Deployed to: 0x3cc54047D191eeeBDcde081D8708490F6df49Be8
Transaction hash: 0xed1d23b69014ee066be9b761df3c1fb28bedc46cc1c3f2188960550dbf7862a1
```

To confirm that the contract was deployed successfully, you can try querying the
balance of your deployer account using Foundry's `cast call` command.

```sh theme={null}
cast call 0x3cc54047D191eeeBDcde081D8708490F6df49Be8 \
"balanceOf(address)(uint256)" 0xc5D26D0281e28599c7790aacc810226BBDf0E431 \
--rpc-url "https://jsonrpc-evm-1.anvil.asia-southeast.initia.xyz"
```

### \[Expected Output]:

```sh theme={null}
100
```
