EAS_POLICY

component compliance

Require the transaction sender to hold a valid EAS attestation under a specified schema. The KYC/KYB enforcement gate.

Gates a transaction on whether the sender holds a valid (non-expired, non-revoked) attestation issued under a specific EAS schema. The canonical primitive for KYC, KYB, accreditation, and any credential-based gate. Resolves attestations through the chain's x/eas module, which reads the EAS and Indexer contracts with view calls wherever PCL evaluates the policy — before execution, during execution (in the PCL preCall / postCall hooks or the policy-aware Privacy precompile), or after execution.

Solidity struct + ABI

From IPcl.sol:
struct EasPolicy {
    address easContract;     // EAS deployment to query
    address indexContract;   // EAS Indexer (powers O(1) reverse lookups)
    bytes32 schemaUid;       // schema the sender must have an attestation under
}
ABI tuple shorthand: (address easContract, address indexContract, bytes32 schemaUid).

Encode for PolicySet.policy:
import {
    EasPolicy, PolicySet, LogicalPolicy, ForEachPolicy, LogicalQuantifier, ForEachQuantifier,
    ForEachSubject, VolumePolicy, VolumeUnitPolicy, PeriodicVolumePolicy, UnitPeriodicVolumePolicy,
    ContractPolicyConfig, GlobalPolicyConfig, DenylistPolicy
} from "@maroo-chain/contracts/precompiles/pcl/IPcl.sol";

EasPolicy memory ep = EasPolicy({
    easContract:   0x1000000000000000000000000000000000000007, // EAS preinstall
    indexContract: 0x1000000000000000000000000000000000000008, // EAS Indexer preinstall
    schemaUid:     0x5f3a2b0e1d5c9a7f6e3b4a1d2c8f7b6a5e4d3c2b1a0f9e8d7c6b5a4938271605 // your KYC schema UID
});
bytes memory policyBytes = abi.encode(ep);
// PolicySet.templateId = "EAS_POLICY"
The easContract and indexContract addresses are typically the canonical Maroo preinstalls — you can resolve them at deploy time via the EAS precompile's getParams() instead of hard-coding.

Evaluation

For each transaction it evaluates, PCL checks the sender:

1. Asks the EAS Indexer (indexContract) for the most recently indexed attestation the sender has received under schemaUid. Only indexed attestations count: a plain EAS attest does not index itself, so after attesting, call the Indexer's indexAttestation(uid) (open to any caller; isAttestationIndexed(uid) confirms it), unless the schema's resolver indexes attestations as they are made.
2. Rejects if the Indexer lists none: EasNoAttestationReceived(sender).
3. Fetches that attestation from the EAS contract and validates it:
- lookup fails? → EasAttestationLookupFailed(sender)
- revoked? → EasAttestationRevoked(sender)
- expired (expirationTime != 0 && expirationTime <= now)? → EasAttestationExpired(sender)
4. Otherwise → admit. Only that most recently indexed attestation is checked: if it is revoked or expired, an older valid one does not admit the sender — issue and index a new one.

ReasonCodes on rejection

  • EasNoAttestationReceived(address sender) — the EAS Indexer lists no attestation the sender received under this schema: none was issued, or it was issued but never indexed.
  • EasAttestationRevoked(address sender) — they had one, but it was revoked.
  • EasAttestationExpired(address sender) — they had one, but it has expired.
  • EasAttestationLookupFailed(address sender) — the attestation the Indexer listed could not be read from easContract; check that the policy names the right EAS contract.


EasAttestationRequired(address sender) is declared in the same error set, but EAS_POLICY does not raise it.

Wallet UX: route the user to the appropriate KYC/KYB onboarding partner. Once a fresh attestation is issued and indexed in the EAS Indexer, the same transaction succeeds.

Typical usage

  • KYC gate at the global level (GlobalPolicyConfig): "only KYC-attested accounts may use the regulated path".
  • Higher-tier features: a ContractPolicyConfig requiring an institutional KYB schema for DeFi pool access.
  • Tiered models: put EAS_POLICY and a VOLUME_POLICY cap under one LOGICAL_POLICY with the Or quantifier, so attested senders pass and un-attested ones are held to the cap — typically more useful than a hard yes/no gate. The testnet's own global policy works this way: without an attestation, a transaction is capped at 2,000,000 OKRW.
ESC
Type to search