IPcl.registerPolicyTemplate / removePolicyTemplate

registerPolicyTemplate(
  string calldata templateId
) external
removePolicyTemplate(string calldata templateId) external

체인 단위 정책 관리자가 내장 PCL 정책 템플릿을 활성 레지스트리에 추가하거나 제거하는 작업입니다. registerPolicyTemplate은 템플릿 ID를 PolicySet으로 인스턴스화할 수 있게 만들며, removePolicyTemplate은 이를 회수합니다. IPcl.policyAdmin()이 반환하는 주소만 호출할 수 있으며, 다른 호출자는 Unauthorized()로 revert됩니다. 관리자가 PCL 프리컴파일에 대해 두 호출을 수행하면 관리자 복구 경로에 의해 PCL 정책 평가가 우회되므로, 관리자 자신의 주소를 거절할 수 있는 잘못 구성된 전역 정책이 있어도 차단되지 않습니다.

파라미터

이름 타입 필수 설명
templateId string ✓ 템플릿 식별자입니다. 체인에 내장된 ID 중 하나여야 합니다: EAS_POLICY, DENYLIST_POLICY, VOLUME_POLICY, PERIODIC_VOLUME_POLICY, AGENT_OKRW_TRANSFER_LIMIT_POLICY, LOGICAL_POLICY, FOR_EACH_POLICY. 그 밖의 ID를 등록하면 InvalidPolicyTemplate(input)으로, 이미 등록된 ID를 다시 등록하면 DuplicatedPolicyTemplate(templateId)로 revert됩니다. 다만 maroo-testnet-1의 레지스트리에는 제거된 OKRW_EAS_TRANSFER_LIMIT_POLICY와 OKRW_EAS_PERIODIC_VOLUME_LIMIT_POLICY가 아직 남아 있어, 이 둘을 등록하면 InvalidPolicyTemplate이 아니라 DuplicatedPolicyTemplate으로 revert되고, 이 둘을 지정한 PolicySet은 UnknownPolicyType으로 거부됩니다. 등록되지 않은 ID를 제거해도 revert되지 않습니다.

반환값

타입: void

반환 값이 없습니다. 성공 시 PolicyTemplateRegistered(templateId) 또는 PolicyTemplateRemoved(templateId) 이벤트가 발행됩니다.

에러

코드 이름 설명
Unauthorized Unauthorized 호출자가 IPcl.policyAdmin()이 반환하는 주소가 아닐 때 revert됩니다.
InvalidPolicyTemplate InvalidPolicyTemplate templateId가 체인에 내장된 어떤 템플릿과도 일치하지 않을 때 revert됩니다. InvalidPolicyTemplate(string input) 형태로 인코딩됩니다.
DuplicatedPolicyTemplate DuplicatedPolicyTemplate registerPolicyTemplate 호출 시 템플릿이 이미 활성 레지스트리에 있으면 revert됩니다. DuplicatedPolicyTemplate(string templateId) 형태로 인코딩됩니다.

예제

정책 관리자가 템플릿 등록

호출은 현재 policyAdmin() 주소에서 출발해야 합니다. 관리자가 PCL 프리컴파일의 네 개 제어 평면 selector 중 하나를 호출하므로 이 트랜잭션은 PCL 정책 평가를 우회하며, 관리자 주소를 거절할 수 있는 전역 정책이 있어도 차단되지 않습니다.

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"],
});

템플릿 제거 시 사용처를 더 이상 확인하지 않음

이제 템플릿 제거는 순수 레지스트리 작업입니다. 해당 템플릿을 참조하는 컨트랙트 정책이나 전역 정책을 스캔하지 않습니다. 제거된 템플릿을 가리키는 PolicySet은 이후 평가 시점에 PolicyNotRegistered로 실패하며, 실패는 제거를 수행한 관리자가 아니라 해당 검사를 유발한 호출자의 트랜잭션에 대해 발생합니다.

// 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 whenever the caller is the policy admin
// (even for an ID that is not registered).
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
// `PolicyNotRegistered("VOLUME_POLICY")` when PCL evaluates it. The admin
// is expected to clean up (or re-register) the template before it removes it.
ESC
검색어를 입력하세요