IPcl.contractPolicies
contractPolicies(address contractAddress) external view returns (ContractPolicyConfig memory) View call. Returns the contract-scoped ContractPolicyConfig currently active for contractAddress — its admin and the full PolicySet[]. When no contract-scoped config has been registered for the address, the call returns a zero-valued struct (_contract = address(0), admin = address(0), empty policies array) rather than reverting; the chain-wide GlobalPolicyConfig still applies to that contract regardless. Use this to inspect the exact rules a target contract enforces via the regulated EVM path (runOnPcl / PCL proxy hook).
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
contractAddress | address | ✓ | The EVM address of the contract whose policy configuration you want to read. |
Returns
ContractPolicyConfig The ContractPolicyConfig struct with fields _contract (address), admin (address), and policies (PolicySet[]). When the target has no registered config, all fields are zero: _contract = address(0), admin = address(0), and policies.length == 0.
Examples
Read a contract's policy config with viem
The call returns a zero-valued struct for unregistered contracts, so branch on admin == address(0) and policies.length == 0 rather than wrapping the read in try/catch.
import { createPublicClient, http } from "viem";
import { pclAbi } from "@maroo-chain/contracts/abis";
const PCL = "0x1000000000000000000000000000000000000005";
const client = createPublicClient({
transport: http("https://rpc-testnet.maroo.io"),
});
// Replace before production — this is a testnet example target.
const target = "0x1111111111111111111111111111111111111111";
const cfg = await client.readContract({
address: PCL,
abi: pclAbi,
functionName: "contractPolicies",
args: [target],
});
if (cfg.admin === "0x0000000000000000000000000000000000000000" && cfg.policies.length === 0) {
console.log("No contract-scoped policies registered — only global policies apply.");
} else {
console.log("Admin:", cfg.admin);
console.log("Policy count:", cfg.policies.length);
for (const p of cfg.policies) {
console.log(" -", p.templateId, "selector=", p.selector);
}
} Read from Solidity
The precompile never reverts on an unregistered target, so a simple field check is enough to distinguish "no contract-scoped config" from a real registration.
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.22;
import { IPcl, ContractPolicyConfig, PCL_CONTRACT } from "@maroo-chain/contracts/precompiles/pcl/IPcl.sol";
contract PolicyInspector {
function hasContractPolicies(address target) external view returns (bool) {
ContractPolicyConfig memory cfg = PCL_CONTRACT.contractPolicies(target);
// Zero-valued struct signals "no config registered"; only global policies apply.
return cfg.admin != address(0) || cfg.policies.length > 0;
}
} Read from the shell with cast
For an unregistered target, the returned tuple is (0x0…0, 0x0…0, []) rather than a revert.
# Replace before production — testnet target address.
TARGET=0x1111111111111111111111111111111111111111
cast call 0x1000000000000000000000000000000000000005 \
"contractPolicies(address)((address,address,(string,bytes,bytes)[]))" \
$TARGET \
--rpc-url https://rpc-testnet.maroo.io