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

# KYC Whitelist Assertion

> Unified KYC Registry for DeFi Protocols

Assert that only KYC-verified addresses can perform privileged actions across multiple dapps using a shared registry

## When to Use This Pattern

Since regulated funds and prime brokerages can only gain exposure into regulated products, a DeFi protocol may want to attract greater fund deployment by proving itself as a compliant venue. This assertion is a simple proof-of-concept that demonstrates a single, shared registry that multiple applications can reference.

It’s designed such that

* Users complete KYC once and gain access to all integrated protocols; no redundant process to verify on each protocol
* The protocol can adopt KYC requirements without implementing their own verification systems
* Registry owners maintain centralized control over access permissions, the owner may revoke an investor accrediation once and have it impact access for all integrated protocols

## What This Pattern Checks

What you should know about this KYC assertion example:

* It is triggered on a specific function call. For example, a mint or transfer request on the implementation contract.
* When triggered, the assertion references a shared registry contract, here named the `AccreditedInvestorRegistry` which maintains the whitelist of KYC-verified addresses.
* The assertion validates that `msg.sender` exists in the KYC registry before allowing execution of protected functions. This prevents non-KYC addresses from interacting with regulated tokens or permissioned protocol functions.
* It is assumed the admin that controls the Registry may be different than the integrating protocol’s admin.

## Assertion Pattern

```solidity theme={null}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {Assertion} from "credible-std/Assertion.sol";
import {AssertionSpec} from "credible-std/SpecRecorder.sol";
import {PhEvm} from "credible-std/PhEvm.sol";
import {OnlyAccreditedCanMint} from "../../src/ass4-only-accredited-can-mint.sol";
import {AccreditedInvestorRegistry} from "../../src/AccreditedInvestorRegistry.sol";

contract OnlyAccreditedCanMintAssertion is Assertion {
    AccreditedInvestorRegistry public immutable registry;

    constructor(address registry_) {
        registerAssertionSpec(AssertionSpec.Reshiram);
        registry = AccreditedInvestorRegistry(registry_);
    }

    function triggers() external view override {
        registerFnCallTrigger(this.assertOnlyAccreditedMint.selector, OnlyAccreditedCanMint.mint.selector);
        registerFnCallTrigger(this.assertOnlyAccreditedTransfer.selector, OnlyAccreditedCanMint.transfer.selector);
    }

    /// @notice Checks that the caller of `mint` is accredited.
    function assertOnlyAccreditedMint() external view {
        _assertMatchingCallersAccredited(OnlyAccreditedCanMint.mint.selector);
    }

    /// @notice Checks that the caller of `transfer` is accredited.
    function assertOnlyAccreditedTransfer() external view {
        _assertMatchingCallersAccredited(OnlyAccreditedCanMint.transfer.selector);
    }

    function _assertMatchingCallersAccredited(bytes4 selector) internal view {
        PhEvm.TriggerCall[] memory calls = ph.matchingCalls(ph.getAssertionAdopter(), selector, _successfulCalls(), 32);
        for (uint256 i = 0; i < calls.length; i++) {
            require(registry.isAccredited(calls[i].caller), "caller is not accredited");
        }
    }

    function _successfulCalls() internal pure returns (PhEvm.CallFilter memory filter) {
        filter.callType = 1;
        filter.successOnly = true;
    }
}
```

<Note>Full examples and mock protocol code are available in [credible-std](https://github.com/phylaxsystems/credible-std/tree/master/examples/assertions-book).</Note>

## Related Patterns

* [Owner Change](/assertions-book/assertions/ass05-ownership-change)
* [Timelock Verification](/assertions-book/assertions/ass01-impl-addr-change)
