PCL 프리컴파일

component compliance

0x1000…0005에서 온체인 컴플라이언스를 강제하는 표면입니다. 이제 getParams()policyAdmin과 신뢰 ERC-4337 entrypoints 목록을 함께 반환합니다.

프로그래머블 컴플라이언스 레이어(PCL) 프리컴파일은 고정 주소 0x1000000000000000000000000000000000000005에 위치하며, 컴플라이언스 관련 모든 작업의 정식 표면입니다. 정책 템플릿 등록, 컨트랙트별 PolicySet 등록, 현재 규칙 조회, runOnPcl을 통한 규제 경로 실행을 담당합니다. 이제 모듈 파라미터를 단일 getParams() view 한 번으로 얻을 수 있으며, 반환되는 PclParams struct는 policyAdmin(템플릿과 전역 정책 등록 권한을 가진 체인 전역 admin)과 entrypoints(계정 추상화 호출에서 실제 principal을 복원할 때 PCL이 신뢰하는 ERC-4337 EntryPoint 주소 배열)를 포함합니다.

아키텍처

graph TD
    A[dApp / User] -- EVM call --> B{Your Smart Contract};
    B -- "runOnPcl(target, data, value)" --> C[PCL Precompile @ 0x10...05];
    C -- all policies pass --> D[Precompile executes the target call];
    D -- result bytes --> B;
    C -. any policy rejects .-> E[Revert with a typed ReasonCode];
    E -.-> B;
    B -- returns --> A;

    classDef evm fill:#0096AA,stroke:#0096AA,color:#fff;
    classDef precompile fill:#FF8C50,stroke:#FF8C50,color:#fff;
    class A,B,E evm;
    class C,D precompile;

컨트랙트가 `runOnPcl`로 호출을 PCL 프리컴파일에 넘깁니다. 프리컴파일은 적용 대상 전역·컨트랙트 정책을 평가하고, 모두 통과하면 대상 호출을 직접 실행한 뒤 결과 바이트를 그대로 돌려줍니다. 정책이 하나라도 거절하면 호출 전체가 타입이 있는 ReasonCode로 revert됩니다.

표면 구성

IPcl.solPCL_CONTRACT 상수를 export하므로 호출자가 주소를 하드코딩할 필요가 없습니다. 관련 타입은 다음과 같습니다.
import { IPcl, PclParams, PCL_CONTRACT } from "@maroo-chain/contracts/precompiles/pcl/IPcl.sol";

struct PclParams {
    address   policyAdmin;
    address[] entrypoints;
}

// 디스커버리
function getParams() external view returns (PclParams memory);
function policyAdmin() external view returns (address);

// 템플릿
function policyTemplate(string calldata templateId) external view returns (PolicyTemplate memory);
function registerPolicyTemplate(string calldata templateId) external;

// 컨트랙트 정책
function registerContractPolicies(ContractPolicyConfig calldata cfg) external;
function changeContractPolicies(ContractPolicyConfig calldata cfg) external;
function removeContractPolicies(address _contract) external;
function contractPolicies(address _contract) external view returns (ContractPolicyConfig memory);

// 규제 실행
function runOnPcl(address contractAddress, bytes calldata data, uint256 value) external returns (bytes memory);

// 프록시 수명주기 (상시 규제 컨트랙트)
function deployPclProxy(PclProxyKind kind, uint256 value, bytes calldata initData) external returns (address proxy);
function pclProxy(address proxy) external view returns (PclProxyEntry memory);

// 주기 거래량 조회
function globalPeriodicVolume(address user, string calldata asset, uint64 resetPeriodSeconds, bool resolveAgentOwners) external view returns (PeriodicVolume memory);
function contractPeriodicVolume(address contractAddress, address user, bytes calldata selector, string calldata asset, uint64 resetPeriodSeconds, bool resolveAgentOwners) external view returns (PeriodicVolume memory);

`getParams`와 `policyAdmin`의 차이

getParams()와 기존 policyAdmin()은 동일한 admin 주소를 반환합니다. 새 코드에서는 getParams()를 선호합니다. 한 번의 호출로 entrypoints 배열까지 받을 수 있고, AA 통합자가 신뢰 ERC-4337 EntryPoint 목록을 확인하려면 이 정보가 필요하기 때문입니다. policyAdmin()은 간결한 접근자로 남아 있습니다.
PclParams memory p = PCL_CONTRACT.getParams();
address admin            = p.policyAdmin;
address[] memory routes  = p.entrypoints;

`entrypoints`의 역할

entrypoints 배열은 PCL이 신뢰하는 ERC-4337 EntryPoint 컨트랙트 목록입니다. 계정 추상화(AA) 경로로 호출이 들어오면 PCL은 이 목록을 근거로 userOp을 풀어 행위를 번들러가 아닌 실제 principal(EntryPoint 뒤의 스마트 계정)에게 귀속시킵니다. 그래서 denylist·거래량 정책이 실제 행위자에게 적용됩니다. 이 목록은 컨트랙트 정책의 실행 여부를 결정하지 않습니다. 컨트랙트 정책은 이 목록과 무관하게 runOnPcl 또는 PCL로 래핑된 프록시를 거치는 실행에서 평가됩니다(pcl-dual-track-model 참고).
import { createPublicClient, http } from "viem";

const pcl = await client.readContract({
  address: "0x1000000000000000000000000000000000000005",
  abi: pclAbi,
  functionName: "getParams",
});

// PCL이 principal 귀속에 신뢰하는 ERC-4337 EntryPoint 목록입니다.
// AA 지갑/번들러는 자신의 EntryPoint가 여기 포함되는지 확인해야 합니다.
console.log("신뢰 4337 EntryPoint:", pcl.entrypoints);

누가 무엇을 호출하는지

registerPolicyTemplate과 전역 정책 변경자는 policyAdmin만 호출할 수 있습니다. 컨트랙트별 정책 변경자(registerContractPolicies, changeContractPolicies, removeContractPolicies)는 각 ContractPolicyConfigadmin 필드로 게이트됩니다. 이 키는 등록 시점에 컨트랙트 owner가 직접 지정하며 체인 전역 admin과 독립적입니다. 외부 dApp은 이 두 번째 경로로 자기 컨트랙트 정책을 등록합니다.

조회는 오프체인에서 무료입니다

getParams, policyAdmin, policyTemplate, contractPolicies는 모두 순수 view 메서드로 상태를 변경하지 않습니다. 오프체인에서 eth_call로 호출하면 비용이 들지 않지만, 컨트랙트 안에서 온체인으로 호출하면 다른 호출처럼 gas를 소모합니다. 특정 인코딩된 호출을 규제 경로에서 실제로 실행하려면 runOnPcl을 사용합니다.
소스: maroo
ESC
검색어를 입력하세요