INDEPENDENT VERIFICATION

Verify on-chain anchors without trusting anyone

You don't need ChainMemory's API to verify that a project state was anchored at a specific block. This page shows how to verify directly against the blockchain using standard Web3 tools.

What you need

  • The project's state hash (from the API or shared by someone)
  • The transaction hash or block number of the anchor
  • Node.js with ethers installed — or any Web3 library

Step 1 — Get the anchor data

Use ChainMemory's public (no auth) endpoint or get it from whoever shared the proof:

bash
curl https://api.chainmemory.ai/v1/project/chainmemory/state/anchor
Response
{
  "project": "chainmemory",
  "projectId": "0x77f7d980...",
  "version": 8,
  "state_hash": "0xa6c45d1db753b1ec96240d169b2d91fb0ce76112558b302a8822b2988aeb8212",
  "anchor": {
    "status": "anchored",
    "onchain_anchor_id": 8,
    "tx_hash": "0x95b732d20b8935a2...",
    "block_number": 173831,
    "contract": "0xa7A8BA51950255b3e223a6745597C67009Fe7875"
  },
  "verify": "ProjectStateAnchor.getStateAnchor(projectId, version)"
}

Step 2 — Verify on-chain with Ethers.js

Connect directly to the ChainMemory RPC and read the smart contract. No API key, no account, no trust required.

javascript
import { ethers } from 'ethers';

// Connect to ChainMemory RPC — no API key needed
const provider = new ethers.JsonRpcProvider('https://rpc.chainmemory.ai');

// ProjectStateAnchor contract
const CONTRACT = '0xa7A8BA51950255b3e223a6745597C67009Fe7875';
const ABI = [
  'function getStateAnchor(bytes32 projectId, uint64 version) view returns (bytes32 stateHash, uint256 anchoredAt, address anchoredBy, uint256 anchorId)'
];

const contract = new ethers.Contract(CONTRACT, ABI, provider);

// The project ID is the keccak256 of the project name
const projectId = ethers.keccak256(ethers.toUtf8Bytes('chainmemory'));
const version = 8;

// Read directly from the blockchain
const [stateHash, anchoredAt, anchoredBy, anchorId] = await contract.getStateAnchor(projectId, version);

console.log('On-chain state hash:', stateHash);
console.log('Anchor ID:', anchorId.toString());
console.log('Anchored at:', new Date(Number(anchoredAt) * 1000).toISOString());

// Compare with the hash you received
const expectedHash = '0xa6c45d1db753b1ec96240d169b2d91fb0ce76112558b302a8822b2988aeb8212';
if (stateHash === expectedHash) {
  console.log('VERIFIED — state matches on-chain anchor');
} else {
  console.log('MISMATCH — state has been tampered with');
}
javascript
const Web3 = require('web3');

const web3 = new Web3('https://rpc.chainmemory.ai');

const CONTRACT = '0xa7A8BA51950255b3e223a6745597C67009Fe7875';
const ABI = [{
  name: 'getStateAnchor',
  type: 'function',
  stateMutability: 'view',
  inputs: [
    { name: 'projectId', type: 'bytes32' },
    { name: 'version', type: 'uint64' }
  ],
  outputs: [
    { name: 'stateHash', type: 'bytes32' },
    { name: 'anchoredAt', type: 'uint256' },
    { name: 'anchoredBy', type: 'address' },
    { name: 'anchorId', type: 'uint256' }
  ]
}];

const contract = new web3.eth.Contract(ABI, CONTRACT);

const projectId = web3.utils.keccak256('chainmemory');

const result = await contract.methods.getStateAnchor(projectId, 8).call();
console.log('On-chain state hash:', result.stateHash);
console.log('Anchor ID:', result.anchorId);

Step 3 — Verify the transaction

You can also verify the raw transaction that created the anchor:

javascript
// Read the transaction directly
const tx = await provider.getTransaction('0x95b732d20b8935a286869d90e60a40f5c31d350a94e27bfd7845770fe0c3e2c3');
console.log('From:', tx.from);       // Should be a known validator
console.log('To:', tx.to);           // Should be the contract address
console.log('Block:', tx.blockNumber);

// Read the block to confirm timestamp
const block = await provider.getBlock(tx.blockNumber);
console.log('Block time:', new Date(block.timestamp * 1000).toISOString());
Zero-trust verification This entire process requires zero interaction with ChainMemory's servers. You connect directly to the blockchain's RPC endpoint and read the smart contract. Even if ChainMemory's API were compromised or offline, the on-chain data remains verifiable.
MetaMask alternative You can also verify visually: add the ChainMemory network to MetaMask, navigate to the contract address in the Explorer, and inspect the transaction data manually.