IPcl.runOnPcl
runOnPcl(address contractAddress, bytes calldata data, uint256 value) external returns (bytes memory) PCL의 규제된 컨텍스트 내에서 대상 컨트랙트에 대한 호출을 실행합니다. 이 함수는 '규제 트랙'의 진입점입니다. 먼저 발신자, 대상 컨트랙트 및 호출 데이터를 기반으로 적용 가능한 모든 전역 및 컨트랙트별 정책 검사를 트리거합니다. 모든 검사가 통과하면 저수준 call을 사용하여 대상 컨트랙트에서 제공된 호출 데이터를 실행합니다. 검사 중 하나라도 실패하면 트랜잭션은 특정 오류와 함께 되돌려집니다.
파라미터
| 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
contractAddress | address | ✓ | PCL 검사가 통과한 후 호출할 대상 컨트랙트의 주소입니다. |
data | bytes | ✓ | 대상 컨트랙트에서 실행될 함수에 대한 ABI 인코딩된 콜데이터입니다. |
value | uint256 | ✓ | 호출과 함께 보낼 OKRW의 양 (msg.value) 입니다. |
반환값
타입:
bytes memory 대상 컨트랙트 호출의 성공적인 실행으로부터의 반환 데이터입니다.
에러
| 코드 | 이름 | 설명 |
|---|---|---|
InDenylist | InDenylist | 발신자의 주소가 활성 거부 목록 정책에서 발견되면 되돌립니다. |
EasAttestationRequired | EasAttestationRequired | 발신자가 필요한 EAS 증명(예: KYC)이 없는 경우 되돌립니다. |
VolumeAboveMaxLimit | VolumeAboveMaxLimit | 트랜잭션 금액이 구성된 거래량 한도를 초과하면 되돌립니다. |
예제
ERC20 전송 래핑
이 예제는 공개 `transfer` 함수를 재정의하는 토큰 컨트랙트를 보여줍니다. 로직을 직접 실행하는 대신, 자신(`address(this)`)을 대상으로 하고 자신의 `internal` 전송 로직에 대한 인코딩된 콜데이터를 제공하여 `runOnPcl`을 호출합니다. 이를 통해 이 토큰에 등록된 PCL 검사를 통과하지 않고는 어떠한 전송도 발생할 수 없도록 보장합니다.
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IPcl, PCL_CONTRACT } from "./IPcl.sol";
contract CompliantToken is IERC20 {
// ... other ERC20 implementation ...
function _transfer(address from, address to, uint256 amount) internal {
// ... core transfer logic ...
}
// Public transfer function enforces PCL checks
function transfer(address to, uint256 amount) public override returns (bool) {
// Encode the call to the internal transfer function
bytes memory data = abi.encodeWithSelector(
this._transfer.selector,
msg.sender,
to,
amount
);
// Execute via PCL. This contract calls itself through the PCL gate.
PCL_CONTRACT.runOnPcl(address(this), data, 0);
return true;
}
} 에러 처리를 포함한 다른 컨트랙트 호출
이 예제는 `try/catch` 블록을 사용하여 `runOnPcl`에서 발생할 수 있는 되돌림을 처리하는 방법을 보여줍니다. 특히 `InDenylist` 커스텀 에러를 확인하고 더 사용자 친화적인 메시지를 제공합니다.
import { IPcl, PCL_CONTRACT } from "./IPcl.sol";
contract PclCaller {
function callCompliantService(address service, uint256 value) external {
bytes memory data = abi.encodeWithSignature("deposit(uint256)", value);
try PCL_CONTRACT.runOnPcl(service, data, 0) {
// Success
} catch (bytes memory reason) {
// Attempt to decode a PCL custom error
if (reason.length == 36) { // selector + 1 argument (e.g., address)
bytes4 selector = bytes4(reason[:4]);
if (selector == IPcl.InDenylist.selector) {
address sender = abi.decode(reason[4:], (address));
// Handle denylist error specifically
revert("Caller is on the denylist");
}
}
// Revert with the original reason if it's not a known PCL error
revert(string(reason));
}
}
}