runOnPcl로 컴플라이언스 검사를 시뮬레이션하는 방법
PCL의 runOnPcl 함수를 사용하여 사전 트랜잭션 검사를 수행하고, dApp 사용자 경험을 개선하며, 가스 낭비를 방지하는 방법에 대한 집중 가이드입니다.
사전 요구사항
- 함수 콜데이터 인코딩 방법에 대한 이해.
- Ethers.js 또는 유사 라이브러리를 사용한 클라이언트 측 설정.
1. 목표: 사전 검사
사용자가 규제된 토큰을 대량으로 전송하고 싶다고 상상해 보십시오. 만약 그들이 트랜잭션을 제출하고 PCL 정책(예: 전송 한도)으로 인해 실패하면, 그들은 여전히 가스를 지불합니다. 이것은 좋지 않은 사용자 경험입니다. 우리의 목표는
runOnPcl을 사용하여 먼저 트랜잭션을 확인하고 사용자에게 즉각적인 피드백을 제공하여, 자금을 낭비하지 않고 금액을 조정하거나 작업을 중단할 수 있도록 하는 것입니다.2. 계약 설정
클라이언트 측 코드에는 두 개의 계약 인스턴스가 필요합니다: PCL 사전 컴파일용 하나와 상호 작용하려는 대상 계약(예: ERC20 토큰)용 하나입니다.
import { ethers } from 'ethers';
import PCL_ABI from './PclAbi.json';
import TOKEN_ABI from './TokenAbi.json';
const PCL_ADDRESS = '0x1000000000000000000000000000000000000005';
const TOKEN_ADDRESS = '0x...'; // 정책이 적용된 토큰의 주소
// 'provider'가 ethers Provider 인스턴스라고 가정
const pclContract = new ethers.Contract(PCL_ADDRESS, PCL_ABI, provider);
const tokenContract = new ethers.Contract(TOKEN_ADDRESS, TOKEN_ABI, provider); 3. 트랜잭션 콜데이터 인코딩
runOnPcl의 두 번째 인수는 시뮬레이션하려는 함수에 대한 인코딩된 data입니다. 이것은 계약의 인터페이스 객체에서 얻을 수 있습니다.const recipient = '0x...';
const amount = ethers.utils.parseEther('50000'); // 실패할 수 있는 금액
const calldata = tokenContract.interface.encodeFunctionData('transfer', [
recipient,
amount
]);
// calldata는 '0xa9059cbb0000...'과 같은 16진수 문자열이 됩니다. 4. 정적 호출 수행
트랜잭션을 시뮬레이션하기 위해
정적 호출을 사용합니다. 이것은 트랜잭션을 생성하거나 상태를 변경하지 않고 노드에서 함수를 실행합니다. 결정적으로, PCL 정책은 보낸 사람에 대해 평가되므로 호출 옵션에 from 주소를 제공해야 합니다.async function isTransferAllowed(userAddress, tokenAddress, calldata) {
try {
await pclContract.callStatic.runOnPcl(
tokenAddress,
calldata,
0, // 호출에 대한 'value', ERC20 전송의 경우 0
{ from: userAddress } // 이 부분이 가장 중요합니다!
);
console.log('✅ 시뮬레이션 통과. 트랜잭션이 허용됩니다.');
return true;
} catch (error) {
console.error('❌ 시뮬레이션 실패. 트랜잭션이 차단됩니다.');
// 오류를 검사하여 특정 PCL 되돌림 사유를 찾을 수 있습니다.
if (error.data) {
// PCL 사전 컴파일은 사용자 정의 오류를 반환합니다. 디코딩하려면 헬퍼가 필요할 수 있습니다.
console.error('되돌림 사유:', error.data);
}
return false;
}
}
// 사용법:
isTransferAllowed(user.address, TOKEN_ADDRESS, calldata); 참고: `callStatic`(또는 JSON-RPC를 통한 `eth_call`)을 사용하는 것이 핵심입니다. 일반 호출은 상태 변경 트랜잭션을 생성하려고 시도하며, 이는 시뮬레이션에서 원하는 것이 아닙니다.