OKRW Precompile
OKRW exposes two stable EVM surfaces — the IOkrw precompile at 0x1000…0001 for Maroo-specific operations (mint, getParams), and the native ERC20 representation at 0xEeeE…EEeE for standard ERC20 calls (transfer, approve, balanceOf).
OKRW is Maroo's KRW-pegged stablecoin and the chain's native gas token. From a Solidity caller's perspective it shows up at two fixed addresses on every network: the IOkrw precompile (0x1000000000000000000000000000000000000001) exposes Maroo-specific operations like mint and getParams, while the native ERC20 representation (0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) is the canonical ERC20 surface registered at genesis as the default token pair for the aokrw base denom. Use the ERC20 address for any standard wallet / DEX / vault integration; use the IOkrw precompile only for Maroo-extension operations.
Architecture
flowchart LR
SC["Your Solidity Contract"] -->|"IOkrw.mint(recipient, amount)"| OKRW["OKRW Precompile<br/>0x...001"]
OKRW --> XOK["x/okrw module<br/>(checks minter authorization)"]
XOK -->|"on success"| XBK["x/bank module<br/>(credits recipient with aokrw)"]
XOK -->|"emit event"| EV["Mint event<br/>(EVM log)"]
XOK -.->|"on failure"| Err["Revert: UnauthorizedMinter"]
classDef evm fill:#0096AA,stroke:#0096AA,color:#fff;
classDef precompile fill:#FF8C50,stroke:#FF8C50,color:#fff;
classDef module fill:#8CC3C3,stroke:#8CC3C3,color:#fff;
classDef bad fill:#AA0019,stroke:#AA0019,color:#fff;
class SC,EV evm;
class OKRW precompile;
class XOK,XBK module;
class Err bad; Calling IOkrw.mint: precompile bridges to x/okrw for authorization, then x/bank for the actual aokrw credit. Mint event emitted on success.
Two addresses, one token
@maroo-chain/contracts.| Surface | Address | Use for |
|---|---|---|
| IOkrw precompile | 0x1000000000000000000000000000000000000001 | mint, getParams, Maroo-specific extensions |
| Native ERC20 representation | 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE | Standard transfer, approve, transferFrom, balanceOf, totalSupply, Approval / Transfer events |
The ERC20 representation is registered at genesis as a token pair mapping
aokrw (the 18-decimal base denom) to its ERC20 contract address, with OWNER_MODULE as the contract owner. Standard ERC20 ABIs work against it unchanged.// Standard ERC20 path — wallets, DEXs, vaults
IERC20 okrw = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
okrw.transfer(recipient, 10_000_000 ether); // 10,000,000 OKRW
okrw.approve(spender, 10_000_000 ether);
// Maroo-extension path — minter operations
import "@maroo-chain/contracts/precompiles/okrw/IOkrw.sol";
IOkrw extn = IOkrw(0x1000000000000000000000000000000000000001);
extn.mint(recipient, 10_000_000 ether); // authorized minter only Denominations and unit conversion
aokrw (1 OKRW = 10^18 aokrw); the display denom is okrw. Note that aokrw is the gas / fee denom, while staking uses a separate denom (amaroo). Solidity literals that read as 1_000_000 ether mean 1,000,000 OKRW.// 10,000,000 OKRW — a realistic transfer-cap example amount
uint256 amount = 10_000_000 ether; // 10_000_000 * 10**18 aokrw
okrw.transfer(recipient, amount); Why both surfaces exist
Transfer events. The IOkrw precompile carries Maroo-specific operations that don't fit the ERC20 interface (controlled minting by the authorized minter, parameter discovery via getParams). Both ultimately move the same underlying aokrw balances; choosing the right address is just a matter of which API surface the call needs.Controlled minting authority
IOkrw.mint. Any other caller reverts with UnauthorizedMinter(caller, authorizedMinter). Rotating the minter is a consortium-governance action and not something an external dApp performs. Read the current minter via IOkrw.getParams() and treat the answer as authoritative for routing mint requests through the right operator.import "@maroo-chain/contracts/precompiles/okrw/IOkrw.sol";
IOkrw okrw = IOkrw(0x1000000000000000000000000000000000000001);
address minter = okrw.getParams().minter;
require(msg.sender == minter, "not authorized to mint"); Reading balances from off-chain code
https://explorer-testnet.maroo.io as an ERC20-style account.import { createPublicClient, http, parseAbi } from "viem";
const OKRW_ERC20 = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
const erc20Abi = parseAbi([
"function balanceOf(address) view returns (uint256)",
"function totalSupply() view returns (uint256)",
]);
const client = createPublicClient({ transport: http("https://rpc-testnet.maroo.io") });
const balance = await client.readContract({
address: OKRW_ERC20,
abi: erc20Abi,
functionName: "balanceOf",
args: ["0xUserAddress..."], // replace before production
});