Reading attestations onchain

This step-by-step guide will run you through reading attestations onchain by looking at an example of a uniswap-v4 hook.

Full code can be found here.

More info on V4 hooks here.

In this example we are going to look at a hook; which checks for an attestation value (boolean in this example). Only holders of attestations with a value of true will be allow to swap using this hook. For this example, we are going to be interested in looking at the beforeSwap hook.

When working with Clique's onchain attestations SDK, the first step is to configure which type of attestations we are working with.

/**
 * One way is to define 2 attestation types, 
 * one for EAS and one Verax attestations
 */
enum AttestationType {
    EAS,
    VERAX
}
bytes32 _easSchema = 0x000..;
bytes32 _veraxSchema = 0x00..;

Now we can define functions for retrieving attestations from users performing swaps. In this example we will define a function for EAS and a function Verax. For more detail, you can check the implementation of the Connector smart contract here.

/**
 * @dev Function to get the EAS attestation value.
 * @return The EAS attestation vamue.
 */
function _easAttestation() internal view returns (bytes memory) {
    bytes32 attestationId = _connector.getReceivedAttestationUIDs(
        tx.origin,
        _easSchema,
        0,
        1,
        false
    )[0];

    return
        _connector.getAttestationValueById(
            _connector.EAS(),
            attestationId
        );
}

/**
 * @dev Function to get the Verax attestation value.
 * @return The Verax attestation value.
 */
function _veraxAttestation() internal view returns (bytes memory) {
    bytes32 attestationId = _connector.getReceivedAttestationUIDs(
        tx.origin,
        _veraxSchema,
        0,
        1,
        false
    )[0];

    return
        _connector.getAttestationValueById(
            _connector.VERAX(),
            attestationId
        );
}

After choosing a schema, the schemaId is stored as a variable. In our case, our shema type definition is just a boolean. So we can simply decode the attestation value into a boolean and check that the result is "true" in the beforeSwap function.

bytes32 _easSchema = 0x000..;
bytes32 _veraxSchema = 0x00..;

/**
 * @dev Function to be called before a swap. Performs attestation checks.
 * @return The selector of the beforeSwap function.
 */
function beforeSwap(
    address,
    PoolKey calldata,
    IPoolManager.SwapParams calldata,
    bytes calldata
) external view override returns (bytes4) {
    bytes memory value = _attestationType == AttestationType.EAS
        ? _easAttestation()
        : _veraxAttestation();

    if (abi.decode(value, (bool)) != true) revert AttestationNotValid();

    return BaseHook.beforeSwap.selector;
}

We now have all that we need to read attestations onchain inside a Uniswap V4 hook. The code explored in the guide is below, and the full smart contract can be found in the gihtub repo.

/**
 * @dev Enum to represent the type of attestation.
 */
enum AttestationType {
    EAS,
    VERAX
}

bytes32 _easSchema = 0x000..;
bytes32 _veraxSchema = 0x00..;

/**
 * @dev Function to be called before a swap. Performs attestation checks.
 * @return The selector of the beforeSwap function.
 */
function beforeSwap(
    address,
    PoolKey calldata,
    IPoolManager.SwapParams calldata,
    bytes calldata
) external view override returns (bytes4) {
    bytes memory value = _attestationType == AttestationType.EAS
        ? _easAttestation()
        : _veraxAttestation();

    if (abi.decode(value, (bool)) != true) revert AttestationNotValid();

    return BaseHook.beforeSwap.selector;
}

/**
 * @dev Function to get the EAS attestation value.
 * @return The EAS attestation vamue.
 */
function _easAttestation() internal view returns (bytes memory) {
    bytes32 attestationId = _connector.getReceivedAttestationUIDs(
        tx.origin,
        _easSchema,
        0,
        1,
        false
    )[0];

    return
        _connector.getAttestationValueById(
            _connector.VERAX(),
            attestationId
        );
}

/**
 * @dev Function to get the Verax attestation value.
 * @return The Verax attestation value.
 */
function _veraxAttestation() internal view returns (bytes memory) {
    bytes32 attestationId = _connector.getReceivedAttestationUIDs(
        tx.origin,
        _veraxSchema,
        0,
        1,
        false
    )[0];

    return
        _connector.getAttestationValueById(
            _connector.VERAX(),
            attestationId
        );
}

Last updated