Deployed Contracts (Testnet)

resources

Canonical contract addresses on Maroo Testnet — utilities, AA, EAS, ERC-8004, inherited EVM precompiles, and Maroo precompiles.

Stable addresses for the contracts and precompiles available on Maroo Testnet. The Maroo precompile interfaces and ABIs ship in the npm package @maroo-chain/contracts; the ERC-8004 IdentityRegistry and ReputationRegistry ABIs ship as identityRegistryAbi and reputationRegistryAbi in @maroo-chain/viem. Mainnet addresses for Maroo precompiles match these (the Maroo precompiles use 0x10.. prefixes and stay constant across networks). In the contract tables, the Explorer-verified column shows whether the testnet explorer (https://explorer-testnet.maroo.io) has verified source code for that address: ✓ if it does, — if it does not.

OKRW — the native coin

On Maroo Testnet, OKRW is the chain's native coin and gas token. Move it the way you move ETH — as a transaction's value / msg.value — and read balances with eth_getBalance / address.balance. It has no ERC20 representation on the testnet: x/erc20 registers no token pair, and 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE — the native-ERC20 address in maroo's source-default genesis — has no code there. An ERC20 call to that address returns empty data, and a transaction to it succeeds without moving anything, so a DEX router, vault or wallet flow built on approve / transferFrom needs a native (payable) path instead.

The one OKRW contract surface is the IOkrw precompile:

SurfaceAddressUse for
IOkrw precompile0x1000000000000000000000000000000000000001getParams; mint (authorized minter only — a valid call from any other address reverts with UnauthorizedMinter)
import {IOkrw, OkrwParams} from "@maroo-chain/contracts/precompiles/okrw/IOkrw.sol";

// OKRW moves as the native coin — no token contract is involved.
function pay(address payable to) external payable {
    (bool ok, ) = to.call{value: msg.value}("");
    require(ok, "OKRW transfer failed");
}

// The precompile's read surface: who may mint, and the native denom string.
function okrwParams() external view returns (address minter, string memory mintDenom) {
    OkrwParams memory p = IOkrw(0x1000000000000000000000000000000000000001).getParams();
    return (p.minter, p.mintDenom);
}
Note: Need the native denom string — for a Cosmos coin, a denom-keyed PCL policy, or a privacy amount? Read it at runtime: getParams().mintDenom from the precompile above, or evm_denom from https://api-testnet.maroo.io/cosmos/evm/vm/v1/params. On the testnet it is atokrw (display tokrw); maroo's source default aokrw is not in use there.

Maroo precompiles

These precompile addresses are stable across testnet and mainnet. Use the interfaces from @maroo-chain/contracts/precompiles/... to call them. A precompile has no EVM bytecode (eth_getCode returns 0x), so from Solidity call a function that returns nothing with a low-level call — see maroo-architecture.

PrecompileAddressPurpose
IOkrw0x1000000000000000000000000000000000000001OKRW mint / params
IPcl0x1000000000000000000000000000000000000005Programmable Compliance Layer
IEas0x1000000000000000000000000000000000000009EAS discovery (getParams)
IAgent0x100000000000000000000000000000000000000AAgent discovery + reverse lookup
IPrivacy0x100000000000000000000000000000000000000bShielded OKRW (deposit / transfer / withdraw)

Each precompile's interface and call examples are on its overview page: okrw-precompile-overview, pcl-precompile-overview, eas-precompile-overview, agent-precompile-overview and privacy-precompile-overview.
export const ADDR = {
  OKRW_PRECOMPILE: "0x1000000000000000000000000000000000000001",
  PCL:             "0x1000000000000000000000000000000000000005",
  EAS_PRECOMPILE:  "0x1000000000000000000000000000000000000009",
  AGENT:           "0x100000000000000000000000000000000000000A",
  PRIVACY:         "0x100000000000000000000000000000000000000b",
  // ERC-8004 IdentityRegistry preinstall
  ERC8004_IDENTITY:"0x8004000000000000000000000000000000000001",
} as const;

EAS and ERC-8004 preinstalls

The actual EAS attestation contract, SchemaRegistry, and Indexer are deployed as preinstalls — resolve their canonical addresses via IEas.getParams() rather than hard-coding.

ContractAddressExplorer-verified
SchemaRegistry0x1000000000000000000000000000000000000006✓
EAS0x1000000000000000000000000000000000000007✓
Indexer0x1000000000000000000000000000000000000008✓

KYC / KYB attestations are issued and stored on the EAS contract (the standard EAS interface), and the Indexer keeps per-recipient and per-schema lookups. PCL's attestation check, EAS_POLICY, reads these two through the addresses carried in the policy's own parameters (easContract, indexContract), so set them to the eas and indexer addresses that IEas.getParams() returns. The EAS precompile at 0x…09 only returns these three addresses.

ContractAddressExplorer-verified
ERC-8004 IdentityRegistry0x8004000000000000000000000000000000000001✓
ERC-8004 ReputationRegistry0x8004000000000000000000000000000000000002✓

Both registries are preinstalls at fixed addresses, not per-dApp deployments; on Maroo Testnet they arrived with the v0.4.0 upgrade (block 6,372,905), and IAgent.getParams() returns both addresses. There is no Validation registry.
import { createPublicClient, http } from "viem";

const EAS_PRECOMPILE = "0x1000000000000000000000000000000000000009";
const easAbi = [{
  name: "getParams", type: "function", stateMutability: "view",
  inputs: [],
  outputs: [{ type: "tuple", components: [
    { name: "schemaRegistry", type: "address" },
    { name: "eas",            type: "address" },
    { name: "indexer",        type: "address" },
  ]}],
}] as const;

const client = createPublicClient({ transport: http("https://rpc-testnet.maroo.io") });
const { eas, indexer, schemaRegistry } = await client.readContract({
  address: EAS_PRECOMPILE,
  abi: easAbi,
  functionName: "getParams",
});

Importing the ABIs

@maroo-chain/contracts ships every Maroo precompile interface — IOkrw, IPcl, IEas, IAgent, IPrivacy — as Solidity sources and typed ABIs (version 0.0.9 at the time of writing). There is no root import; use the full paths:

  • Solidity: @maroo-chain/contracts/precompiles/<name>/I<Name>.sol
  • TypeScript: @maroo-chain/contracts/abi/precompiles/<name>/I<Name> (needs moduleResolution node16, nodenext or bundler)


iAgentAbi lists the 33 errors every precompile shares before its two functions, getParams and getAgentIds — the functions are there, at the end. The ERC-8004 registry ABIs are not in this package: use identityRegistryAbi and reputationRegistryAbi from @maroo-chain/viem.
// npm install @maroo-chain/contracts viem
import { createPublicClient, getContract, http } from "viem";
import { iPclAbi } from "@maroo-chain/contracts/abi/precompiles/pcl/IPcl";

const client = createPublicClient({ transport: http("https://rpc-testnet.maroo.io") });
const pcl = getContract({ address: "0x1000000000000000000000000000000000000005", abi: iPclAbi, client });
const admin = await pcl.read.policyAdmin();

Foundry remappings

The Solidity sources import cosmos-evm-contracts, which the package does not declare as a dependency. Install it too (npm install @maroo-chain/contracts cosmos-evm-contracts) and add both remappings to remappings.txt:
@maroo-chain/contracts/=node_modules/@maroo-chain/contracts/
cosmos-evm-contracts/=node_modules/cosmos-evm-contracts/

General-purpose utilities

ContractAddressExplorer-verified
Multicall30xcA11bde05977b3631167028862bE2a173976CA11✓
Create2 deployer0x4e59b44847b379578588920ca78fbf26c0b4956c—
Safe singleton factory0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7—
EIP-2935 history0x0000F90827F1C53a10cb7A02335B175320002935—

Multicall3, the Create2 deployer and the Safe singleton factory are the standard deployments at their canonical Ethereum addresses, so cross-chain tooling finds them without configuration. The EIP-2935 history contract sits at its canonical address too, but on Maroo Testnet its get(blockNumber) does not return that block's hash — read block hashes with eth_getBlockByNumber, or blockhash() for the last 256 blocks.

Account abstraction (ERC-4337, EIP-7702)

ContractAddressExplorer-verified
EntryPoint v0.90x433709009B8330FDa32311DF1C2AFA402eD8D009—
EntryPoint v0.80x4337084d9e255ff0702461cf8895ce9e3b5ff108✓
SimpleAccountFactory0x13E9ed32155810FDbd067D4522C492D6f68E5944✓
Simple7702Account0x4Cd241E8d1510e30b2076397afc7508Ae59C66c9✓

To create new smart accounts, use EntryPoint v0.9, deployed at the canonical v0.9 address. Its SenderCreator (0x0A630a99Df908A81115A3022927Be82f9299987e) has code, and accounts have been deployed through it on Maroo Testnet from a factory named in the UserOperation's initCode. Use a factory built for v0.9; the SimpleAccountFactory listed here cannot create accounts.

The v0.8 set does not create accounts on Maroo Testnet. EntryPoint v0.8 has code, but the SenderCreator it points to (0x449ed7c3e6fee6a97311d4b55475df59c44add33) has none, so a UserOperation whose initCode names a factory reverts in EntryPoint v0.8 without a reason. SimpleAccountFactory's accountImplementation() and senderCreator() both return the zero address, so its createAccount reverts with only callable from SenderCreator for every caller and no account can be created through this factory. EntryPoint v0.8 still executes UserOperations that carry no initCode, for example from an EIP-7702-delegated EOA. Simple7702Account has code (an EIP-7702 delegate account implementation).

PCL lists EntryPoint v0.8 and v0.9 as trusted (IPcl.getParams().entrypoints; the list also holds the EntryPoint v0.6 address, 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789, which has no code on Maroo Testnet), so it evaluates each UserOperation against its sender, the smart account, rather than the bundler that submits the batch. The bundler is still checked as the sender of the outer batch transaction.

Inherited EVM precompiles

PrecompileAddress
P256 (signature verification)0x0000000000000000000000000000000000000100
Bech32 (bech32 ↔ hex)0x0000000000000000000000000000000000000400
Staking0x0000000000000000000000000000000000000800
Distribution0x0000000000000000000000000000000000000801
Bank0x0000000000000000000000000000000000000804
Gov0x0000000000000000000000000000000000000805
Slashing0x0000000000000000000000000000000000000806

These come from the chain's EVM runtime unchanged and are active on Maroo Testnet. Like the Maroo precompiles, they have no EVM bytecode. The Gov precompile is the entry point for taking part in governance from Solidity, for example voting on a proposal with vote.

Conclusion

Pin these addresses in a single module of your codebase (the snippet above is a good template). The Maroo precompile addresses are stable across networks; resolve the EAS preinstall addresses at runtime with IEas.getParams(), and the ERC-8004 registry addresses with IAgent.getParams().
ESC
Type to search