Contract API
Solidity-callable precompile interfaces covering OKRW (stablecoin), PCL (compliance), EAS (attestation), and Agent (ERC-8004 indexing).
IPcl · Policy management
Register, query, and change policy templates and per-contract policy configurations.
IPcl.registerPolicyTemplate Registers a built-in policy template into the active PCL template registry by templateId. The seven V1 templates (DENYLIST_POLICY, VOLUME_POLICY, PERIODIC_VOLUME_POLICY, EAS_POLICY, OKRW_EAS_TRANSFER_LIMIT_POLICY, OKRW_EAS_PERIODIC_VOLUME_LIMIT_POLICY, AGENT_OKRW_TRANSFER_LIMIT_POLICY) are shipped with the chain; this call makes one of them available for use in PolicyConfigs. Admin-only: the caller must be the PolicyAdmin (set via consortium governance). External dApp builders do not call this directly — surfaced here for protocol auditability and to clarify how a PolicySet's templateId refers back to a registered template.
IPcl.contractPolicies View call. Returns the contract-scoped ContractPolicyConfig currently active for contractAddress — its admin and the full PolicySet[]. When no contract-scoped config has been registered for the address, the call returns a zero-valued struct (_contract = address(0), admin = address(0), empty policies array) rather than reverting; the chain-wide GlobalPolicyConfig still applies to that contract regardless. Use this to inspect the exact rules a target contract enforces via the regulated EVM path (runOnPcl / PCL proxy hook).
IPcl.policyTemplate View call. Returns the registration record for one of the seven built-in PCL templates by templateId. Reverts if templateId is unknown. The parameter shape for each template is fixed in IPcl.sol (e.g. DenylistPolicy { address[] addresses; }) — policyTemplate returns the registry metadata only, not a JSON-schema; readers should consult the corresponding template's Solidity struct directly for the parameter layout.
IPcl.registerContractPolicies Legacy first-time registration of a ContractPolicyConfig. Binds policy.admin as the PCL admin of policy._contract and stores the initial policy set. This entrypoint is deprecated: when the admin slot is already bound, only the currently bound admin may call it — and the call then performs a full re-registration (the policy sets are replaced and the slot is set to policy.admin, which also lets the current admin hand the slot over). A caller who is not the bound admin reverts with PolicyAlreadyRegistered. Prefer changeContractPolicies for all new code.
IPcl.changeContractPolicies Replaces the entire policy configuration for a contract, and — in the same call — optionally hands over admin authority. The caller must be the currently registered admin for policy._contract. On success the stored PolicySet[] is replaced wholesale by policy.policies, and the admin binding is set to policy.admin. To keep the current admin, pass the same address in policy.admin; to hand over, pass the new admin's address. This is the only supported admin-handover path — there is no separate transfer method.
IPcl · Regulated execution
The Regulated Track execution surface: runOnPcl (runs policy checks, then executes the call on the target — a state-changing entry point, not a dry run; use eth_call for pre-flight), PCL proxies, and the pre/post hooks.
IPcl.deployPclProxy Deploys a PCL-wrapped proxy using the canonical proxy bytecode embedded in the chain binary, registers it in the PCL proxy registry, and binds the deploy caller (msg.sender) as the initial PCL contract admin for the resulting proxy address — all before the call returns. Because the initial admin is bound to msg.sender, deploying via a factory contract makes the factory the admin, not the end user. For PclProxyKind.Transparent, initData is abi.encode(logic, initialOwner, initializer).
IPcl.postCall Closes the PCL session opened by a matching preCall after the proxy's delegatecall to its implementation returns. postCall inspects the transfer log delta that occurred inside the implementation, records periodic-volume accumulation, and evaluates any post-call policy checks (e.g. AGENT_OKRW_TRANSFER_LIMIT_POLICY, OKRW_EAS_TRANSFER_LIMIT_POLICY). If workable is false (the implementation already reverted), post-call policy evaluation, volume recording, log marking, and event emission are all skipped.
IPcl.preCall Opens a PCL policy-evaluation session for a proxied call. Invoked by the PCL-wrapped proxy hook before the proxy delegatecalls its implementation. preCall evaluates both the contract-scoped ContractPolicyConfig (if one exists for contractAddress) and the chain-wide GlobalPolicyConfig against the supplied principal / data / value, snapshots the pre-call state needed for accumulation-style policies (e.g. periodic volume), and returns a sessionId that the matching postCall must present. If any policy rejects, the call reverts with the corresponding PCL ReasonCode.
IPcl.pclProxy Returns the registry entry for a proxy that was deployed via deployPclProxy on the PCL precompile. The entry currently carries a single kind field identifying the proxy variant (V1 only registers PclProxyKind.Transparent). If the queried address is not a registered PCL-wrapped proxy, every field of the returned struct is zero — kind decodes to PclProxyKind.Unspecified (enum value 0).
IPcl.runOnPcl Executes a call to a target contract within the PCL's regulated context. This function is the entry point to the 'Regulated Track'. It first triggers all applicable global and contract-specific policy checks based on the sender, target contract, and call data. If all checks pass, it then executes the provided call data on the target contract using a low-level call. If any check fails, the transaction reverts with a specific error.
IPcl · Periodic volume queries
Read the rolling-window volume counters behind periodic volume limit policies.
IPcl.contractPeriodicList Lists every PERIODIC_VOLUME_POLICY running counter attached to contractAddress that applies to user. Filter by asset and optionally by function selector — pass empty bytes ("0x") to match PolicySets registered without a selector. One entry per distinct reset-period bucket configured on the contract.
IPcl.contractPeriodicVolume Reads the running periodic-volume counter for user under a PERIODIC_VOLUME_POLICY attached to the specific contractAddress. The lookup is narrowed by asset and resetPeriodSeconds, and optionally by function selector — pass empty bytes ("0x") to match PolicySets registered without a selector (i.e. those that apply to any call on the contract).
IPcl.globalPeriodicList Lists every PERIODIC_VOLUME_POLICY running counter for user under the global policy config, one entry per distinct reset-period bucket. Use this when the user is subject to multiple global periodic caps at different window lengths (for example a 24-hour cap and a 30-day cap on the same asset) and you want to render or check all of them at once.
IPcl.globalPeriodicVolume Reads the running periodic-volume counter for user under any PERIODIC_VOLUME_POLICY in the global config that matches the given asset and resetPeriodSeconds. Returns the currently accumulated amount, the configured max, the period length, and the unix timestamp at which the current window ends. Use this to preview whether an upcoming transfer would trip a global periodic cap before submitting the transaction.
IPcl · Params
Read PCL module parameters.
OKRW
The OKRW stablecoin precompile — params, minting, and mint events.
IOkrw.getParams Returns the OKRW module parameters — the authorized minter address and the mint denom. The return struct is named OkrwParams (the un-namespaced Params name was renamed so multiple precompile interfaces can be imported together without struct-name collisions). The minter address rotation is a consortium-governance action; clients should treat this as a read-only discovery endpoint.
IOkrw.mint Mints a specified amount of OKRW tokens and credits them to the recipient address. This function can only be successfully called by the authorized Minter address, which is configured at the chain level in the x/okrw module parameters. Calls from any other address will revert with a custom error.
OKRW.Mint (event) Emitted by the OKRW precompile upon a successful call to the mint function. This event provides a verifiable, on-chain record of all OKRW minting activity originating from the EVM. Indexers and client applications can subscribe to this event to track the OKRW supply and distribution.
EAS
Attestation queries against the EAS precompile.
IEas.getParams Returns the canonical addresses of the Ethereum Attestation Service deployment on this Maroo network — the SchemaRegistry, the EAS contract, and the Indexer. Call this once at app startup so your code resolves the right addresses on testnet and mainnet without hard-coding. The return struct is named EasParams (the un-namespaced Params name was renamed to avoid collisions when multiple precompile interfaces are imported together).
EAS.getAttestation Returns the full Attestation struct for a given UID, or an Attestation with uid == 0x00.. if the UID is unknown. This is the canonical read on the EAS contract preinstall — every other surface (@ethereum-attestation-service/eas-sdk, the Indexer, PCL's EAS_POLICY evaluator) ultimately calls this. dApp code should validate revocationTime == 0 and (expirationTime == 0 || expirationTime > now) before treating an attestation as valid.
Indexer.getReceivedAttestationUIDCount Returns the number of attestations issued to recipient under schemaUid. A cheap existence check — call this before paginating with getReceivedAttestationUIDs. The count tracks issuance only; revoked or expired attestations still increment it, so use the count as a search bound rather than a validity gate.
Indexer.getReceivedAttestationUIDs Paginated reverse-lookup: returns up to length attestation UIDs issued to recipient under schemaUid. Use reverseOrder = true to start from the most recent. Each returned UID feeds EAS.getAttestation(uid) to fetch the actual struct and check revocation/expiration.
Agent
ERC-8004 agent registry queries.
IAgent.getAgentIds Paginated reverse lookup: returns the agent IDs registered to wallet. Maroo's Agent precompile exposes this method because walking IdentityRegistry storage from inside a contract is too expensive — the precompile reads from an x/agent chain-side index that's kept in sync. For everything else (register, attest, metadata), call IdentityRegistry directly.
IAgent.getParams Returns the addresses of the ERC-8004 IdentityRegistry and ReputationRegistry preinstalls on this Maroo network. Discovery helper — call this once at app startup so your code resolves the right registries on testnet vs mainnet without hard-coding.