Skip to main content
Research Preview — Under active development.

Policy Attestations

Policy Attestations are the signed outputs of geospatial operations. They are signed by the Astral signing key, which is held exclusively inside the TEE (trusted execution environment). This is how you know the computation was performed correctly — only code running inside the TEE can produce valid signatures.
When submitted onchain via EAS resolvers, policy attestations can trigger any smart contract logic on EVM-compatible chains.

What is a Policy Attestation?

When you call a compute operation, Astral returns a Policy Attestation:
Code snippets need testing — Verify against actual implementation before use.
const result = await astral.compute.within({
  geometry: userLocationUID,
  target: landmarkUID,
  radius: 500,
  chainId: 84532,
  schema: SCHEMA_UID,
  recipient: userAddress
});

// result is a PolicyAttestationResult
console.log(result.result);      // true
console.log(result.operation);   // "within"
console.log(result.attestation); // { uid, schema, signature, ... }
The attestation proves:
  • The computation was performed by the Astral signing key
  • The inputs were exactly as specified
  • The result is accurate

Schema Types

Policy Attestations use per-result-type schemas. The SDK auto-selects based on the operation.

BooleanPolicyAttestation

For predicates (contains, within, intersects):
// Schema: "bool result, bytes32[] inputRefs, uint64 timestamp, string operation"
struct BooleanPolicyAttestation {
    bool result;              // The boolean result
    bytes32[] inputRefs;      // Input references (UIDs or hashes)
    uint64 timestamp;         // When computation was performed
    string operation;         // "contains", "within", "intersects"
}

NumericPolicyAttestation

For measurements (distance, length, area):
// Schema: "uint256 result, string units, bytes32[] inputRefs, uint64 timestamp, string operation"
struct NumericPolicyAttestation {
    uint256 result;           // Scaled integer (centimeters)
    string units;             // "meters" or "square_meters"
    bytes32[] inputRefs;      // Input references
    uint64 timestamp;         // When computation was performed
    string operation;         // "distance", "length", "area"
}

GeometryPolicyAttestation (Future)

For transformations (buffer, centroid, union):
// Schema: "bytes geometry, string geometryType, bytes32[] inputRefs, uint64 timestamp, string operation"
struct GeometryPolicyAttestation {
    bytes geometry;           // Encoded geometry result
    string geometryType;      // "Point", "Polygon", etc.
    bytes32[] inputRefs;      // Input references
    uint64 timestamp;         // When computation was performed
    string operation;         // "buffer", "centroid", "union"
}

Input References

The inputRefs array contains a bytes32 reference for each input:
Input TypeReference Value
Location Attestation UIDThe UID itself
Offchain AttestationThe attestation UID
Raw GeoJSONkeccak256(abi.encode(geojson))
This enables verification that specific inputs were used:
// In your resolver
(bool result, bytes32[] memory inputRefs, , ) = abi.decode(...);

// Verify the expected location was checked
require(inputRefs[1] == EXPECTED_LANDMARK_UID, "Wrong location checked");
For raw GeoJSON, the hash allows verification if the original geometry is known, but does not reveal the geometry itself.

SDK Return Object

interface PolicyAttestationResult<T> {
  // Decoded result (convenience)
  result: T;                          // boolean | number | GeoJSON.Geometry
  units?: string;                     // For measurements
  operation: string;                  // Operation name
  timestamp: number;                  // Unix timestamp
  inputRefs: string[];                // Input references

  // Full attestation data
  attestation: {
    uid: string;                      // EAS UID (if submitted onchain)
    schema: string;                   // Schema UID
    attester: string;                 // Astral signer address
    recipient: string;                // Developer-specified recipient
    data: string;                     // ABI-encoded attestation data
    signature: string;                // EIP-712 signature
  };

  // For delegated onchain submission
  delegatedAttestation: {
    signature: string;                // Astral's signature
    attester: string;                 // Astral's address
    deadline: number;                 // Signature expiry
  };
}

Using Policy Attestations

Offchain

Use the result directly in your application:
const result = await astral.compute.within({
  geometry: uid1,
  target: uid2,
  radius: 500,
  chainId: 84532,
  schema: SCHEMA_UID
});

if (result.result) {
  // User is nearby — enable feature
  enableFeature();
}

Onchain

Submit using delegated attestation:
const result = await astral.compute.within({
  geometry: uid1,
  target: uid2,
  radius: 500,
  chainId: 84532,
  schema: RESOLVER_SCHEMA_UID,
  recipient: userAddress
});

// Submit to EAS — triggers your resolver
const tx = await astral.eas.submitDelegated(result.delegatedAttestation);
await tx.wait();
To connect policy attestations to smart contract logic, you need to register an EAS resolver with your schema first.

Result Scaling

Numeric results are stored as scaled integers for determinism:
OriginalStoredTo Recover
523.45 meters52345divide by 100
1234.5678 m²12345678divide by 10000
// In your resolver
(uint256 resultCm, , , , ) = abi.decode(...);
uint256 meters = resultCm / 100;

Attestation Expiry

The delegatedAttestation.deadline indicates when the signature expires. Submissions after the deadline will fail.
if (Date.now() / 1000 < result.delegatedAttestation.deadline) {
  await astral.eas.submitDelegated(result.delegatedAttestation);
}

Next: EAS Resolvers

Learn how to gate smart contracts with Policy Attestations