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 중 하나여야 합니다(예: 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). 알 수 없는 ID를 등록하면 InvalidPolicyTemplate(input)으로, 이미 등록된 ID를 다시 등록하면 DuplicatedPolicyTemplate(templateId)로, 등록되지 않은 ID를 제거하면 PolicyTemplateNotFound(templateId)로 revert됩니다. |
반환값
void 반환 값이 없습니다. 성공 시 PolicyTemplateRegistered(templateId) 또는 PolicyTemplateRemoved(templateId) 이벤트가 발행됩니다.
에러
| 코드 | 이름 | 설명 |
|---|---|---|
Unauthorized | Unauthorized | 호출자가 IPcl.policyAdmin()이 반환하는 주소가 아닐 때 revert됩니다. |
InvalidPolicyTemplate | InvalidPolicyTemplate | templateId가 체인에 내장된 어떤 템플릿과도 일치하지 않을 때 revert됩니다. InvalidPolicyTemplate(bytes input) 형태로 인코딩됩니다. |
DuplicatedPolicyTemplate | DuplicatedPolicyTemplate | registerPolicyTemplate 호출 시 템플릿이 이미 활성 레지스트리에 있으면 revert됩니다. DuplicatedPolicyTemplate(string templateId) 형태로 인코딩됩니다. |
PolicyTemplateNotFound | PolicyTemplateNotFound | removePolicyTemplate 호출 시 템플릿이 현재 등록되어 있지 않으면 revert됩니다. PolicyTemplateNotFound(string templateId) 형태로 인코딩됩니다. 기존 PolicySet이 이후 제거된 템플릿을 참조하는 경우 정책 평가 시점에 같은 오류가 발생합니다. 제거 자체는 더 이상 남아 있는 사용처에 의해 차단되지 않으며, 참조 불일치는 관리자에게 즉시 알리지 않고 해당 트랜잭션에 대해 지연 발생합니다. |
예제
정책 관리자가 템플릿 등록
호출은 현재 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은 이후 평가 시점에 PolicyTemplateNotFound로 실패하며, 실패는 제거를 수행한 관리자가 아니라 해당 검사를 유발한 호출자의 트랜잭션에 대해 발생합니다.
// 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.