Astral’s signed results can be submitted onchain as EAS attestations, making them available to smart contracts. This guide covers the full blockchain integration flow.
The Ethereum Attestation Service (EAS) is an open protocol for making onchain and offchain attestations. Attestations are structured, signed claims — “entity X attests that Y is true.”EAS supports two storage modes:
Onchain attestations — stored directly in EAS contracts, referenced by UID
Offchain attestations — signed with EIP-712, stored on IPFS or other storage, verifiable without gas costs
Astral uses EAS to package signed spatial results as attestations that smart contracts can consume and act on.
About the Astral signer: The astralSigner address is the key that signs attestations inside the TEE. Signer management (multisig, key rotation, etc.) is on the roadmap. See Security for more details.
Copy
// SPDX-License-Identifier: MITpragma solidity ^0.8.0;import "@eas/contracts/resolver/SchemaResolver.sol";import "@openzeppelin/contracts/access/Ownable.sol";contract LocationGatedAction is SchemaResolver, Ownable { address public astralSigner; constructor(IEAS eas, address _astralSigner) SchemaResolver(eas) { astralSigner = _astralSigner; } function onAttest( Attestation calldata attestation, uint256 /* value */ ) internal override returns (bool) { // 1. Verify from Astral require(attestation.attester == astralSigner, "Not from Astral"); // 2. Decode policy result (BooleanPolicyAttestation) ( bool result, bytes32[] memory inputRefs, uint64 timestamp, string memory operation ) = abi.decode( attestation.data, (bool, bytes32[], uint64, string) ); // 3. Execute business logic require(result, "Policy check failed"); _executeAction(attestation.recipient); return true; } function onRevoke(Attestation calldata, uint256) internal pure override returns (bool) { return false; // Don't allow revocation } function _executeAction(address recipient) internal virtual { // Override in child contracts } // Owner-controlled signer update for key rotation function updateAstralSigner(address newSigner) external onlyOwner { astralSigner = newSigner; }}
contract LocationAirdrop is LocationGatedAction { IERC20 public token; uint256 public amount; function _executeAction(address recipient) internal override { token.transfer(recipient, amount); }}
Use numeric attestations (distance, area, length) for more sophisticated logic like spatial demurrage — where transfer fees vary based on distance from a target location.