PCL ReasonCode

mechanism compliance

PCL이 트랜잭션을 거절할 때 발행하는 타입화된 오류의 전체 집합입니다. 지갑과 SDK는 이 코드를 기준으로 UX를 분기합니다.

모든 PCL 거절은 IPcl에 정의된 타입화된 Solidity 오류 중 하나를 동반합니다. 지갑과 dApp 코드는 IPcl ABI에 대해 revert 페이로드를 디코드하고 오류 이름과 인자를 기준으로 UX를 분기해야 하며, 자유 텍스트에 의존해서는 안 됩니다. 코드는 세 그룹으로 나뉩니다. 정책 위반 코드는 사용자 트랜잭션이 컴플라이언스 검사를 통과하지 못한 경우에 발행되며 일부는 사용자 액션으로 해소할 수 있습니다. 템플릿 관리 코드register…set… 호출에서 발생하는 admin 도구 오류로, 규제 경로에서 최종 사용자가 보는 일은 없습니다. 내부 코드는 체인 설정 오류이며 운영자에게만 surface됩니다.

정책 위반 코드

트랜잭션이 PCL 평가에 도달했고 등록된 정책을 통과하지 못할 때 발생합니다. 일부는 사용자 액션(KYC 완료, 더 작게 보내기, 윈도우 리셋 대기)으로 해소할 수 있으므로, 지갑은 코드를 감지하고 적절한 해결책을 제시해야 합니다.

ReasonCode트리거지갑 UX
InDenylist(address sender)DENYLIST_POLICY — 발신자/수신자가 목록에 있음종결 — "이 주소는 거래 불가". 재시도하지 않습니다.
VolumeBelowMinLimit(uint256 minLimit, uint256 value)VOLUME_POLICY — denom의 value < minLimit더 큰 금액을 제안합니다.
VolumeAboveMaxLimit(uint256 maxLimit, uint256 value)VOLUME_POLICYvalue > maxLimit분할 전송을 제안합니다.
ExceededPeriodicVolume(uint256 maxLimit, uint256 value, uint256 resetAt)PERIODIC_VOLUME_POLICY 또는 OKRW_EAS_PERIODIC_VOLUME_LIMIT_POLICY 윈도우 소진"한도 도달; \<resetAt\>에 초기화"를 표시합니다.
EasAttestationRequired(address sender)EAS_POLICY — 일반 "발신자 attestation 필요"KYC 온보딩을 트리거합니다.
EasNoAttestationReceived(address sender)그 스키마로 attestation 받은 적 없음동일하게 온보딩 흐름으로 이어집니다.
EasAttestationRevoked(address sender)받았었지만 폐기됨재온보딩 또는 에스컬레이션 흐름으로 이어집니다(폐기는 의도된 동작입니다).
EasAttestationExpired(address sender)만료됨재attest 흐름으로 이어집니다.
EasAttestationLookupFailed(address sender)평가 도중 attestation 읽기 실패일시적 오류로 처리하고, 일반 오류 표시 후 재시도합니다.
ExceededAgentTransferLimit(uint256 maxLimit, uint256 value)OKRW_EAS_TRANSFER_LIMIT_POLICY (미인증 상한) 또는 AGENT_OKRW_TRANSFER_LIMIT_POLICY (에이전트별 상한)금액을 줄이거나 KYC 완료를 제안합니다.
ReachedLimitOfNonEAS(uint256 maxLimit, uint256 value)비 EAS 한도용 예약된 과거 명칭; 이전 정책 변형에서 등장 가능volume 코드와 동일하게 처리합니다.

템플릿 관리 코드

정책 그래프를 변경하는 admin 호출(registerPolicyTemplate, setGlobalPolicies, registerContractPolicies 등)에서 발생합니다. 규제 경로의 최종 사용자는 이 코드를 트리거하지 않으며, admin UI와 CI 스크립트가 raw 오류로 노출합니다.

ReasonCode트리거
Unauthorized()호출자가 그 작업의 PolicyAdmin (글로벌) 또는 설정별 admin (컨트랙트)이 아닐 때
InvalidPolicyTemplate(string input)템플릿 ID가 인식되는 내장 템플릿이 아닐 때
DuplicatedPolicyTemplate(string templateId)이미 등록된 templateId에 registerPolicyTemplate을 호출했을 때
PolicyTemplateInUse()활성 PolicySet이 여전히 참조하는 템플릿에 removePolicyTemplate을 호출했을 때
UnknownPolicyType(string templateId)PolicySet.templateId가 이 네트워크에 등록되지 않은 값을 참조할 때
UnknownPolicyConfigType()디코드된 설정 struct가 GlobalPolicyConfig / ContractPolicyConfig 형태와 일치하지 않을 때
PolicyAlreadyRegistered(string policy)이미 설정이 있는 컨트랙트에 registerContractPolicies를 호출했을 때 (대신 change…를 사용)
PolicyNotRegistered(string policy)기존 설정 없는 컨트랙트에 change… / remove…를 호출했을 때
InvalidParameter(bytes input)policy 바이트가 템플릿의 파라미터 struct로 깔끔하게 abi.decode되지 않을 때
InvalidSelector(bytes input)PolicySet.selector가 빈 바이트도 4바이트 selector도 아닐 때
InvalidStructType(string got)ABI 디코딩이 예상치 못한 최상위 struct를 만났을 때
AbiDecodeFailed(string reason)일반 abi.decode 실패 (예: 잘린 calldata)
InvalidAddress(string input)address 인자가 0 주소이거나 형식이 불량할 때
InvalidCall()잘못된 인자 형태로 public 메서드를 호출했을 때
CannotEmpty(string field)설정 struct의 필수 필드가 비어있을 때
JSONMarshal() / JSONUnmarshal()내부 직렬화 실패 (대부분 legacy 경로)

내부 / 체인 설정 코드

체인 자체에 잘못 연결된 무언가가 있을 때 발생하며, 사용자 입력 문제는 아닙니다. 버그로 처리하고 운영자에게 보고합니다.

ReasonCode트리거
AgentKeeperRequired()에이전트 keeper 없이 PCL이 호출된 경우(체인 설정 오류).
AgentTransferLimitMetadataInvalid(string reason)에이전트의 TransferLimit 메타데이터는 존재하나 파싱 가능한 32바이트 uint256이 아닙니다. 거의 항상 admin 버그이며 사용자 버그가 아닙니다.

지갑 / SDK 처리 방법

IPcl ABI에 대해 revert 페이로드를 디코드하고 오류 이름으로 분기합니다. 사용자에게 보여줄 카피는 타입화된 인자(maxLimit, value, resetAt, sender)에서 가져오며, 문자열을 재포맷하지 않습니다.
import { decodeErrorResult } from "viem";
import { iPclAbi } from "@maroo-chain/contracts/abi/precompiles/pcl/IPcl";

try {
  await walletClient.writeContract({ /* ... */ });
} catch (err: any) {
  const decoded = decodeErrorResult({ abi: iPclAbi, data: err.data });
  switch (decoded.errorName) {
    case "EasNoAttestationReceived":
    case "EasAttestationRequired":
    case "EasAttestationExpired":
      // KYC 온보딩으로 라우팅
      break;
    case "EasAttestationRevoked":
      // 에스컬레이션 흐름 surface
      break;
    case "InDenylist":
      // 종결 — 재시도 없음
      break;
    case "VolumeAboveMaxLimit":
    case "ExceededAgentTransferLimit":
      // 더 작은 금액 제안
      break;
    case "ExceededPeriodicVolume": {
      const [maxLimit, value, resetAt] = decoded.args;
      // resetAt (unix 초)으로 윈도우 리셋 카운트다운 표시
      break;
    }
    default:
      // 템플릿 관리 또는 내부 — 운영자 UI에만 raw 오류 표시
      break;
  }
}

안정성 보장

코드 식별자는 안정적입니다. 새 정책 템플릿이 출시될 때 새 코드가 추가되며, 기존 코드는 기반 템플릿이 폐기되어도 이름 변경이나 재용도화가 일어나지 않으므로 과거 트랜잭션 실패도 그대로 해석 가능합니다. 정식 전체 목록은 IPcl.sol(error … 선언)에 있습니다.
소스: maroo
ESC
검색어를 입력하세요