> ## Documentation Index
> Fetch the complete documentation index at: https://docs.x402r.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom Conditions

> Build your own condition contracts for specialized authorization logic

## Overview

You can create custom conditions for specialized logic beyond what the built-in conditions provide. Build against the `ICondition` interface and follow the security rules below.

## ICondition Rules

From the `ICondition.sol` NatSpec:

1. **MUST NOT revert**: return `false` to deny, never `revert`
2. **Return `true` to allow, `false` to deny**

The operator converts a `false` return into a `PreActionConditionNotMet` revert. Prefer `view` or `pure` implementations to keep call sites cheap and gas predictable.

## Example: TimeOfDayCondition

A condition that only allows actions during specific hours (UTC):

```solidity theme={null}
contract TimeOfDayCondition is ICondition {
    uint256 public immutable startHour;  // e.g., 9 (9 AM)
    uint256 public immutable endHour;    // e.g., 17 (5 PM)

    constructor(uint256 _startHour, uint256 _endHour) {
        startHour = _startHour;
        endHour = _endHour;
    }

    function check(
        PaymentInfo calldata payment,
        uint256,
        address caller,
        bytes calldata
    ) external view returns (bool) {
        uint256 hour = (block.timestamp / 3600) % 24;
        return hour >= startHour && hour < endHour;
    }
}
```

Usage, deploy via a factory and use in operator config:

```typescript theme={null}
// Deploy via your custom factory
const businessHours = await timeOfDayConditionFactory.write.deploy([9, 17]);

// Use in operator config
config.capturePreActionCondition = businessHours;
```

## Security Checklist

Before deploying a custom condition:

* [ ] Returns `false` instead of reverting on denial
* [ ] Declared as `view` or `pure`
* [ ] No external calls to untrusted contracts
* [ ] No state modifications
* [ ] Handles edge cases (zero address, zero amount, uninitialized payments)
* [ ] Full test coverage with Forge tests

<Warning>
  Custom conditions with bugs can lead to **permanently locked funds** (if `check()` always returns `false`) or **unauthorized access** (if `check()` always returns `true`). Test on Base Sepolia before mainnet deployment.
</Warning>

## Testing

Test custom conditions with Forge:

```solidity theme={null}
contract TimeOfDayConditionTest is Test {
    TimeOfDayCondition condition;

    function setUp() public {
        condition = new TimeOfDayCondition(9, 17);
    }

    function test_allowsDuringBusinessHours() public {
        // Set block.timestamp to 10 AM UTC
        vm.warp(10 * 3600);
        assertTrue(condition.check(paymentInfo, 0, caller, ""));
    }

    function test_deniesOutsideBusinessHours() public {
        // Set block.timestamp to 8 PM UTC
        vm.warp(20 * 3600);
        assertFalse(condition.check(paymentInfo, 0, caller, ""));
    }
}
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Conditions Overview" icon="filter" href="/contracts/conditions/overview">
    Review the condition system architecture.
  </Card>

  <Card title="Custom Hooks" icon="database" href="/contracts/hooks/custom">
    Build custom state hooks.
  </Card>
</CardGroup>
