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

Type: 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)) }
            }
        }
    }
}
ESC
Type to search