PCL Policy Admin

term compliance

The single privileged address that holds write authority over global PCL state — only it can change chain-wide PCL rules.

The Policy Admin is one address (visible to callers via IPcl.policyAdmin()) authorized to register/remove built-in PolicyTemplates and to set/remove the chain-wide GlobalPolicyConfig. Anything that affects every transaction on the network goes through this role. The admin slot is a chain parameter — a single keyholder can't claim or transfer it on their own.

What the admin can do (calls on IPcl)

Only the admin can invoke the following on the PCL precompile (0x1000…0005):

  • registerPolicyTemplate(string templateId) — register a built-in template after the chain ships it.
  • removePolicyTemplate(string templateId) — remove an unused template.
  • setGlobalPolicies(GlobalPolicyConfig newConfig) — install or replace the chain-wide PolicySet array.
  • removeGlobalPolicies() — wipe the global config (back to no chain-wide rules).


Note that contract-scoped policies (registerContractPolicies / changeContractPolicies / removeContractPolicies) are not the policy admin's role — those are gated by the per-config admin field that each ContractPolicyConfig carries.

The admin can rotate — don't hard-code it

The admin slot is a chain parameter, not something a single key can claim or transfer on its own. From a dApp builder's perspective the practical consequence is simple: don't hard-code the admin address. Read it on-chain via IPcl.policyAdmin() whenever you need it. Code that caches a hard-coded value will silently break after a rotation.

Reading the current admin

Any caller can verify the active admin without a transaction:
address admin = IPcl(0x1000000000000000000000000000000000000005).policyAdmin();
Wallets and dashboards should rely on this rather than caching a hard-coded address — admin rotations don't break correctly written code.

Blast radius

A compromised admin key could install a denylist that blocks every transaction or a permissive config that disables KYC enforcement chain-wide — so the blast radius is large. The chain-parameter design constrains that risk: a single key can't seize the slot, and any reassignment is visible on-chain. For your own code, the practical mitigation is to watch setGlobalPolicies / removeGlobalPolicies events on the PCL precompile address if your dapp's behavior depends on a specific chain-wide rule being active.

PolicyAdmin vs ContractPolicyConfig.admin

These are different roles. PolicyAdmin governs the global rules (one slot per chain). The admin field on a ContractPolicyConfig governs the rules attached to one specific contract address and is held by whoever the contract owner chose at registration time. Rotating one does not affect the other.
Source: maroo
ESC
Type to search