IOkrw.mint
mint(address recipient, uint256 amount) external returns (bool) Mints amount of OKRW (in aokrw, the 18-decimal base denom) and credits it to recipient. Only the authorized minter address configured in the x/okrw module parameters can call this successfully; any other caller reverts with the module-owned UnauthorizedMinter(address caller, address authorizedMinter) custom error. Zero-address recipients and zero amounts revert with the shared IPrecompile.InvalidAddress(string bad) and IPrecompile.InvalidAmount(string amount) typed errors respectively (note: both carry a string payload — the offending address or amount rendered as text — not the raw address/uint256). Nil or negative amount inputs (only reachable through low-level ABI abuse) surface as plain string reverts, "amount must not be nil" and "amount must not be negative"; these are not decodable typed errors.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
recipient | address | ✓ | The address to receive the newly minted OKRW. Must not be the zero address — passing 0x0 reverts with IPrecompile.InvalidAddress(bad) where bad is the string form of the zero address. |
amount | uint256 | ✓ | Amount to mint, denominated in aokrw (18 decimals; 1 OKRW = 10^18 aokrw — see okrw-precompile-overview). Must be strictly greater than zero. A zero amount reverts with IPrecompile.InvalidAmount(amount) where the payload is the decimal string of the amount. Nil or negative big.Int inputs (only reachable through low-level ABI abuse) revert with plain string reasons — "amount must not be nil" or "amount must not be negative" — rather than a decodable typed error. |
Returns
bool Returns true on success. Failures revert with a typed custom error (or a plain string reason for the unreachable-from-Solidity nil/negative cases) rather than returning false.
Errors
| Code | Name | Description |
|---|---|---|
UnauthorizedMinter | UnauthorizedMinter | Reverts when msg.sender is not the configured minter address. Encoded as UnauthorizedMinter(address caller, address authorizedMinter) so clients can display both the offending caller and the currently-authorized minter. Owned by IOkrw. |
InvalidAddress | InvalidAddress | Reverts when recipient is the zero address (or when the sender's address cannot be encoded). Inherited from IPrecompile and encoded as InvalidAddress(string bad) — the payload is the address rendered as a hex string, not the raw address type. Clients previously decoded this as InvalidAddress(address); update ABI fragments to the new string shape. |
InvalidAmount | InvalidAmount | Reverts when amount is exactly zero. Inherited from IPrecompile and encoded as InvalidAmount(string amount) — the payload is the amount rendered as a decimal string, not the raw uint256. Nil or negative big.Int inputs (only reachable via low-level ABI abuse) revert with plain string reasons ("amount must not be nil" / "amount must not be negative") instead. |
UnknownMethod | UnknownMethod | Reverts when the ABI-encoded method selector does not match any function on the precompile. Inherited from IPrecompile as UnknownMethod(string methodName). Rarely surfaces from Solidity — usually indicates a mismatched or stale ABI. |
InvalidNumberOfArgs | InvalidNumberOfArgs | Reverts when the precompile receives an argument count that does not match the method signature. Inherited from IPrecompile as InvalidNumberOfArgs(uint256 expected, uint256 got). |
SDKUnauthorized | SDKUnauthorized | Inherited from IPrecompile. Surfaces when the underlying chain-layer authorization check rejects the call for a reason other than the minter mismatch (which is reported as UnauthorizedMinter). |
Examples
Basic minting from an authorized minter contract
The precompile-side authorization check compares msg.sender to the configured minter, so Treasury's own address must be set as the minter for this call to succeed.
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.28;
import "@maroo-chain/contracts/precompiles/okrw/IOkrw.sol";
import {IPrecompile} from "@maroo-chain/contracts/precompiles/common/interfaces/IPrecompile.sol";
contract Treasury {
address constant OKRW_PRECOMPILE = 0x1000000000000000000000000000000000000001;
IOkrw okrw = IOkrw(OKRW_PRECOMPILE);
/// @notice Mint OKRW to `to`. This contract's address must be the
/// authorized minter in the x/okrw module parameters.
function mintTo(address to, uint256 amount) external {
// 10_000_000 OKRW == 10_000_000 * 10**18 aokrw when caller passes ether units.
bool ok = okrw.mint(to, amount);
require(ok, "OKRW mint returned false");
}
} Catching typed errors on the client with viem (updated error shapes)
After the shared-error refactor InvalidAddress and InvalidAmount are inherited from IPrecompile and carry a single string argument. Update any ABI fragments that previously declared them as InvalidAddress(address) / InvalidAmount(uint256); otherwise decodeErrorResult cannot match the 4-byte selector and the revert surfaces as an unrecognised error.
import { createWalletClient, http, parseEther, decodeErrorResult } from "viem";
import { privateKeyToAccount } from "viem/accounts";
const OKRW = "0x1000000000000000000000000000000000000001" as const;
// NOTE: InvalidAddress / InvalidAmount now carry a `string` payload, not
// the old `address` / `uint256` — they come from IPrecompile after the
// shared-error refactor. UnauthorizedMinter is still owned by IOkrw.
const okrwAbi = [
{ type: "function", name: "mint", stateMutability: "nonpayable",
inputs: [{ name: "recipient", type: "address" }, { name: "amount", type: "uint256" }],
outputs: [{ type: "bool" }] },
{ type: "error", name: "UnauthorizedMinter",
inputs: [{ name: "caller", type: "address" }, { name: "authorizedMinter", type: "address" }] },
{ type: "error", name: "InvalidAddress", inputs: [{ name: "bad", type: "string" }] },
{ type: "error", name: "InvalidAmount", inputs: [{ name: "amount", type: "string" }] },
] as const;
const wallet = createWalletClient({
account: privateKeyToAccount(process.env.MINTER_KEY as `0x${string}`),
transport: http("https://rpc-testnet.maroo.io"),
});
try {
await wallet.writeContract({
address: OKRW,
abi: okrwAbi,
functionName: "mint",
// TODO: replace with the real treasury recipient before production.
args: ["0x8F3ac2B1d9E74c05A6B18FE27Dc4913e5A0F7b62", parseEther("10000000")],
});
} catch (err: any) {
if (err?.data) {
const decoded = decodeErrorResult({ abi: okrwAbi, data: err.data });
// decoded.errorName is one of UnauthorizedMinter | InvalidAddress | InvalidAmount
// (plus any inherited IPrecompile error like UnknownMethod / InvalidNumberOfArgs).
console.error(`OKRW.mint reverted: ${decoded.errorName}`, decoded.args);
} else {
// Plain string reverts (nil/negative amount) land here.
throw err;
}
} Handling typed errors inside Solidity via try/catch
The 4-byte selector is what drives dispatch, and each of these three selectors is stable. What changed is the ARGUMENT type of InvalidAddress / InvalidAmount — they now decode as string, so any off-chain consumer that ABI-decodes the tail must be updated even though the on-chain selector dispatch keeps working.
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.28;
import "@maroo-chain/contracts/precompiles/okrw/IOkrw.sol";
import {IPrecompile} from "@maroo-chain/contracts/precompiles/common/interfaces/IPrecompile.sol";
// InvalidAddress / InvalidAmount are INHERITED from IPrecompile, so they are
// referenced through IPrecompile — IOkrw.InvalidAddress does not compile.
contract SafeMinter {
IOkrw constant okrw = IOkrw(0x1000000000000000000000000000000000000001);
event MintFailed(bytes4 selector);
function safeMint(address to, uint256 amount) external {
try okrw.mint(to, amount) returns (bool ok) {
require(ok, "mint returned false");
} catch (bytes memory raw) {
bytes4 sel;
assembly { sel := mload(add(raw, 32)) }
if (sel == IOkrw.UnauthorizedMinter.selector) {
emit MintFailed(sel);
} else if (sel == IPrecompile.InvalidAddress.selector) {
// Now InvalidAddress(string bad) — inherited from IPrecompile.
emit MintFailed(sel);
} else if (sel == IPrecompile.InvalidAmount.selector) {
// Now InvalidAmount(string amount) — inherited from IPrecompile.
emit MintFailed(sel);
} else {
// Unknown revert (e.g. plain-string revert on nil amount) — bubble up.
assembly { revert(add(raw, 32), mload(raw)) }
}
}
}
}