Documentation Index
Fetch the complete documentation index at: https://policykit.xyz/llms.txt
Use this file to discover all available pages before exploring further.
Rule Evaluators
Each on-chain rule type is implemented as a separate evaluator contract. The PolicyEngine dispatches to these contracts during evaluation.
Tier 1: Stateless Rules
AllowTargetsRule
Checks if the transaction target is in a whitelist of allowed addresses.
contract AllowTargetsRule {
function evaluate(
address target,
bytes calldata ruleData
) external pure returns (bool);
}
Rule Data Format:
[addressCount: uint8][addr1: address][addr2: address]...
Gas Cost: ~2,500 + 200 per address in the list
DenyTargetsRule
Checks if the transaction target is NOT in a blacklist of denied addresses.
contract DenyTargetsRule {
function evaluate(
address target,
bytes calldata ruleData
) external pure returns (bool);
}
Rule Data Format: Same as AllowTargetsRule
AllowSelectorsRule
Checks if the function selector (first 4 bytes of calldata) is in a whitelist.
contract AllowSelectorsRule {
function evaluate(
bytes calldata data,
bytes calldata ruleData
) external pure returns (bool);
}
Rule Data Format:
[selectorCount: uint8][selector1: bytes4][selector2: bytes4]...
DenySelectorsRule
Checks if the function selector is NOT in a blacklist.
contract DenySelectorsRule {
function evaluate(
bytes calldata data,
bytes calldata ruleData
) external pure returns (bool);
}
MaxValueRule
Checks if the ETH value is within the allowed maximum.
contract MaxValueRule {
function evaluate(
uint256 value,
bytes calldata ruleData
) external pure returns (bool);
}
Rule Data Format:
Gas Cost: ~800
Tier 2: Stateful Rules
SpendLimitRule
Tracks cumulative token spending within a rolling time window.
contract SpendLimitRule {
// Track spending per account per token
mapping(address => mapping(address => SpendWindow)) public windows;
struct SpendWindow {
uint256 spent; // Amount spent in current window
uint256 windowStart; // Start timestamp of current window
}
function evaluate(
address account,
address target,
bytes calldata data,
bytes calldata ruleData
) external returns (bool);
}
Rule Data Format:
[token: address][limit: uint256][windowSeconds: uint256]
Behavior:
- Decode the ERC-20
transfer or transferFrom amount from calldata
- Check if the current window has expired; if so, reset
- Add the transfer amount to cumulative spending
- Return
true if cumulative spend is within the limit
Gas Cost: ~25,000 (SLOAD + SSTORE)
CooldownRule
Enforces a minimum time between transactions.
contract CooldownRule {
// Track last transaction timestamp per account
mapping(address => uint256) public lastTxTimestamp;
function evaluate(
address account,
bytes calldata ruleData
) external returns (bool);
}
Rule Data Format:
[cooldownSeconds: uint256]
Behavior:
- Check if
block.timestamp - lastTxTimestamp >= cooldownSeconds
- Update
lastTxTimestamp to block.timestamp
- Return
true if enough time has passed
Gas Cost: ~22,000 (SLOAD + SSTORE)
AttestationVerifier
Verifies EIP-712 signed attestations from Lit Protocol PKPs.
contract AttestationVerifier {
function verify(
address account,
address target,
uint256 value,
bytes calldata data,
bytes32 policyCID,
address pkpAddress,
bytes calldata attestation
) external view returns (bool);
}
Verification steps:
- Decode the attestation as
(uint256 deadline, uint256 nonce, bytes signature)
- Check that
block.timestamp <= deadline (not expired)
- Reconstruct the EIP-712 typed data hash
- Recover the signer from the signature
- Check that the signer matches
pkpAddress
- Return
true if all checks pass
Gas Cost: ~30,000 (ecrecover + hash computations)
Adding Custom On-Chain Rules
To create a custom Tier 1 or Tier 2 rule evaluator:
- Implement the evaluator interface:
interface IRuleEvaluator {
function evaluate(
address account,
address target,
uint256 value,
bytes calldata data,
bytes calldata ruleData
) external returns (bool);
}
- Deploy the evaluator contract
- Register it with the
PolicyEngine (requires governance/admin)
- Use the custom rule type in your policy