Minting OKRW from a Smart Contract
A step-by-step tutorial on how to create, deploy, and interact with a smart contract that mints OKRW tokens using the precompile.
What You Will Learn
- ✓How to interface with a Maroo precompile in Solidity.
- ✓How to write a contract that can mint OKRW.
- ✓How to configure your local testnet to authorize your contract as a minter.
- ✓How to use Hardhat scripts to deploy and call your contract.
- ✓How to verify the minting event and balance changes.
Prerequisites
- A running Maroo local testnet (`marood testnet`).
- Basic understanding of Solidity and Hardhat.
Tools Needed
Node.js 18+Hardhatmarood CLI
In this tutorial, you will build a simple 'Faucet' contract. This contract will be authorized to mint a fixed amount of OKRW to any address that requests it, demonstrating the full lifecycle of programmatic minting on Maroo.
1
1. Project Setup
First, let's set up a new Hardhat project. Open your terminal and run the following commands:
terminal bash
mkdir maroo-faucet && cd maroo-faucet
npm init -y
npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox @openzeppelin/contracts
npx hardhat init # Choose 'Create a TypeScript project' 2
2. Create the Smart Contracts
We need the
IOkrw.sol interface to interact with the precompile. Create this file in your contracts directory. Then, we'll write the OkrwFaucet.sol contract that uses this interface. contracts/IOkrw.sol solidity
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;
interface IOkrw {
error UnauthorizedMinter(address caller, address authorizedMinter);
error InvalidAddress(address addr);
error InvalidAmount(uint256 amount);
function mint(address recipient, uint256 amount) external returns (bool);
event Mint(address indexed minter, address indexed recipient, uint256 amount);
} contracts/OkrwFaucet.sol solidity
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;
import "./IOkrw.sol";
contract OkrwFaucet {
IOkrw constant okrw = IOkrw(0x1000000000000000000000000000000000000001);
uint256 public immutable dripAmount = 100 * 10**18; // 100 OKRW
event Dispensed(address indexed recipient, uint256 amount);
function requestTokens() external {
// This call will only succeed if this contract's address
// is the authorized minter on the Maroo network.
bool success = okrw.mint(msg.sender, dripAmount);
require(success, "Faucet: OKRW minting failed");
emit Dispensed(msg.sender, dripAmount);
}
} 3
3. Deploy the Faucet
Now, let's write a Hardhat script to deploy our faucet. This will give us the contract address we need for the next step.
scripts/deploy.ts typescript
import { ethers } from "hardhat";
async function main() {
const Faucet = await ethers.getContractFactory("OkrwFaucet");
const faucet = await Faucet.deploy();
await faucet.waitForDeployment();
const faucetAddress = await faucet.getAddress();
console.log(`OkrwFaucet deployed to: ${faucetAddress}`);
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
}); Tip: You'll need to configure your `hardhat.config.ts` to connect to your local Maroo node. The default RPC URL is `http://127.0.0.1:8545` and the chain ID is `9000`.
4
4. Authorize the Faucet as Minter
The OKRW precompile only allows a specific address to mint. We must now authorize our newly deployed
OkrwFaucet contract. Run the deploy script, copy the contract address, and then use the marood CLI to update the x/okrw module parameters. terminal bash
npx hardhat run scripts/deploy.ts --network localhost
# Copy the output address, e.g., 0x5FbDB2315678afecb367f032d93F642f64180aa3 terminal bash
# Replace with your validator key name from the local testnet setup
VALIDATOR_KEY_NAME="validator"
# Paste the deployed contract address here
CONTRACT_ADDR_HEX="0x5FbDB2315678afecb367f032d93F642f64180aa3"
# Convert hex address to bech32 format for the transaction
CONTRACT_ADDR_BECH32=$(marood debug addr $CONTRACT_ADDR_HEX | grep "Bech32 Acc" | awk '{print $3}')
# Send the transaction to update the minter address
marood tx okrw update-params --minter-address $CONTRACT_ADDR_BECH32 --from $VALIDATOR_KEY_NAME --chain-id maroo_9000-1 --keyring-backend test -y --broadcast-mode=block 5
5. Interact and Verify
With the faucet deployed and authorized, anyone can now call
requestTokens() to receive 100 OKRW. Let's create a script to do this and then verify the balance change. scripts/request.ts typescript
import { ethers } from "hardhat";
async function main() {
const faucetAddress = "0x5FbDB2315678afecb367f032d93F642f64180aa3"; // Paste your deployed address
const faucet = await ethers.getContractAt("OkrwFaucet", faucetAddress);
const [signer] = await ethers.getSigners();
console.log(`Requesting 100 OKRW for ${signer.address}...`);
const tx = await faucet.requestTokens();
const receipt = await tx.wait();
console.log("Tokens requested! Tx hash:", receipt.hash);
}
main().catch(console.error); terminal bash
# Run the request script
npx hardhat run scripts/request.ts --network localhost
# Verify the balance of the Hardhat default account (0xf39...2266)
marood query bank balances 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266
# You should see a balance of 100000000000000000000aokrw Conclusion
Congratulations! You have successfully created a smart contract that can mint OKRW, configured the Maroo chain to authorize it, and used it to receive tokens. This pattern is fundamental for building applications that manage OKRW liquidity on Maroo.