IPcl.runOnPcl

runOnPcl(address contractAddress, bytes calldata data, uint256 value) external returns (bytes memory)

PCL의 규제 컨텍스트 안에서 대상 컨트랙트에 대한 호출을 실행합니다. 이 함수는 '규제 트랙'의 진입점입니다. 먼저 발신자, 대상 컨트랙트, 호출 데이터를 기준으로 적용 대상이 되는 전역 및 컨트랙트별 정책 검사를 모두 실행합니다. 모든 검사가 통과하면 저수준 call을 사용하여 대상 컨트랙트에서 제공된 호출 데이터를 실행합니다. 검사 중 하나라도 실패하면 트랜잭션이 해당 오류로 revert됩니다.

파라미터

이름 타입 필수 설명
contractAddress address PCL 검사가 통과한 후 호출할 대상 컨트랙트의 주소입니다.
data bytes 대상 컨트랙트에서 실행할 함수의 ABI 인코딩 콜데이터입니다.
value uint256 호출과 함께 전달할 aokrw(기본 단위, 소수점 18자리) 금액입니다. 대상 컨트랙트에서 msg.value로 전달됩니다.

반환값

타입: bytes memory

대상 컨트랙트 호출이 성공적으로 실행되어 돌려준 반환 데이터입니다.

에러

코드 이름 설명
InDenylist InDenylist 발신자 주소가 활성 거부 목록 정책에 포함되어 있으면 revert됩니다.
EasAttestationRequired EasAttestationRequired 발신자가 필요한 EAS 증명(예: KYC)이 없는 경우 revert됩니다.
VolumeAboveMaxLimit VolumeAboveMaxLimit 트랜잭션 금액이 구성된 거래량 한도를 초과하면 revert됩니다.

예제

ERC20 전송 래핑

이 예제는 public transfer 함수를 재정의하는 토큰 컨트랙트를 보여줍니다. 로직을 직접 실행하지 않고, address(this)(자기 자신)를 대상으로 자신의 internal 전송 로직을 인코딩한 콜데이터를 넘겨 runOnPcl을 호출합니다. 이렇게 하면 이 토큰에 등록된 PCL 검사를 통과해야만 전송이 일어나도록 강제할 수 있습니다.

// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IPcl } from "@maroo-chain/contracts/IPcl.sol";

contract CompliantToken is IERC20 {
    IPcl constant PCL = IPcl(0x1000000000000000000000000000000000000005);
    // ... 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) {
        bytes memory data = abi.encodeWithSelector(
            this._transfer.selector,
            msg.sender,
            to,
            amount
        );

        // Execute via PCL — this contract calls itself through the PCL gate.
        PCL.runOnPcl(address(this), data, 0);
        return true;
    }
}

에러 처리를 포함한 다른 컨트랙트 호출

이 예제는 try/catch 블록으로 runOnPcl에서 발생할 수 있는 revert를 처리하는 방법을 보여줍니다. 특히 InDenylist 커스텀 에러를 식별해 더 사용자 친화적인 메시지를 보여줍니다.

// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;

import { IPcl } from "@maroo-chain/contracts/IPcl.sol";

contract PclCaller {
    IPcl constant PCL = IPcl(0x1000000000000000000000000000000000000005);

    function callCompliantService(address service, uint256 value) external {
        bytes memory data = abi.encodeWithSignature("deposit(uint256)", value);

        try PCL.runOnPcl(service, data, 0) returns (bytes memory) {
            // Success path
        } catch (bytes memory reason) {
            // bytes memory slicing isn't supported in Solidity — read the
            // 4-byte error selector via assembly.
            bytes4 selector;
            assembly { selector := mload(add(reason, 32)) }

            if (selector == IPcl.InDenylist.selector) {
                // Strip the selector and decode the arg.
                bytes memory args = new bytes(reason.length - 4);
                for (uint i = 0; i < args.length; i++) args[i] = reason[i + 4];
                address sender = abi.decode(args, (address));
                revert("Caller is on the denylist");
            }
            // Bubble up unknown reverts.
            revert(string(reason));
        }
    }
}
ESC
검색어를 입력하세요