IPcl.registerPolicyTemplate / removePolicyTemplate
registerPolicyTemplate(
string calldata templateId
) external
removePolicyTemplate(string calldata templateId) external Chain-wide policy admin operations that add or remove one of the built-in PCL policy templates from the active registry. registerPolicyTemplate makes a template ID available for instantiation inside a PolicySet; removePolicyTemplate withdraws it. Only the address returned by IPcl.policyAdmin() may call these — other callers revert with Unauthorized(). Both calls, when made by the admin against the PCL precompile, bypass PCL policy evaluation via the admin recovery path, so they cannot be blocked by a misconfigured global policy that would otherwise reject the admin's own address.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
templateId | string | ✓ | The template identifier — one of the built-in IDs shipped with the chain (for example 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). Registering an unknown ID reverts with InvalidPolicyTemplate(input); registering an already-registered ID reverts with DuplicatedPolicyTemplate(templateId); removing an unregistered ID reverts with PolicyTemplateNotFound(templateId). |
Returns
void No return value. Success emits PolicyTemplateRegistered(templateId) or PolicyTemplateRemoved(templateId).
Errors
| Code | Name | Description |
|---|---|---|
Unauthorized | Unauthorized | Reverts when the caller is not the address returned by IPcl.policyAdmin(). |
InvalidPolicyTemplate | InvalidPolicyTemplate | Reverts when templateId does not match any built-in template shipped with the chain. Encoded as InvalidPolicyTemplate(bytes input). |
DuplicatedPolicyTemplate | DuplicatedPolicyTemplate | Reverts on registerPolicyTemplate when the template is already in the active registry. Encoded as DuplicatedPolicyTemplate(string templateId). |
PolicyTemplateNotFound | PolicyTemplateNotFound | Reverts on removePolicyTemplate when the template is not currently registered. Encoded as PolicyTemplateNotFound(string templateId). This same error surfaces at policy evaluation time if an existing PolicySet references a template that was subsequently removed — the removal itself is no longer blocked by outstanding consumers, so stale references are surfaced lazily against the offending transaction rather than eagerly against the admin. |
Examples
Register a template as the policy admin
The call must originate from the current policyAdmin() address. Because the admin is calling one of the four PCL control-plane selectors on the PCL precompile, the transaction bypasses PCL policy evaluation and cannot be blocked by a global policy that would otherwise reject the admin's address.
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
const PCL = "0x1000000000000000000000000000000000000005" as const;
const pclAbi = [
{ type: "function", name: "registerPolicyTemplate", stateMutability: "nonpayable",
inputs: [{ name: "templateId", type: "string" }], outputs: [] },
{ type: "function", name: "removePolicyTemplate", stateMutability: "nonpayable",
inputs: [{ name: "templateId", type: "string" }], outputs: [] },
] as const;
const admin = createWalletClient({
account: privateKeyToAccount(process.env.POLICY_ADMIN_KEY as `0x${string}`),
transport: http("https://rpc-testnet.maroo.io"),
});
await admin.writeContract({
address: PCL,
abi: pclAbi,
functionName: "registerPolicyTemplate",
args: ["EAS_POLICY"],
}); Removing a template no longer checks for consumers
Removing a template is now a pure registry operation: it does not scan for contracts or global policies that reference the template. Any PolicySet left pointing at a removed template will fail at evaluation time with PolicyTemplateNotFound against the caller whose transaction triggered the check, not against the admin who performed the removal.
// Previously this could revert with `PolicyTemplateInUse` when a contract
// policy or the global config still referenced the template. That check has
// been removed; the call succeeds as long as the template is currently
// registered and the caller is the policy admin.
await admin.writeContract({
address: PCL,
abi: pclAbi,
functionName: "removePolicyTemplate",
args: ["VOLUME_POLICY"],
});
// Outstanding `PolicySet` entries that still reference "VOLUME_POLICY" will
// now cause the *user transaction* they gate to revert with
// `PolicyTemplateNotFound("VOLUME_POLICY")` when PCL evaluates it. The admin
// is expected to clean up (or re-register) the template before it removes it.