Skip to main content
What you’ll be able to do
  • Read contract data through its ABI.
  • Submit transactions that call contract functions.
  • Process finalized contract events.
An application uses a contract’s address and ABI to read its state and call its functions. This guide connects to RecordBook, whose owner can update stored values. The same steps apply to other contracts using their ABIs, caller permissions and completion checks.

Obtain the deployment inputs

Request a deployment record containing the chain ID, address, ABI, source and compiler version, and administrator configuration. Configure the application with the record for the network it will use. Require nonempty code at the supplied address. Compare the source and build artifact with the deployer’s verification record to check that the ABI describes the deployed contract.
Here config is the application’s environment configuration, containing the contractAddress and numeric chainId from that deployment record.

Use the record contract

RecordBook stores a value and revision for each bytes32 key. Its owner can update a record by supplying its current revision. Each update increments the revision, so repeating the same call fails with StaleRevision. Use an existing RecordBook deployment, or deploy the contract below with the project setup and compiler settings in Deploy an application contract, using src/RecordBook.sol as the source. Follow the deployment guide’s build and deployment steps, changing the forge create target to src/RecordBook.sol:RecordBook and omitting --constructor-args. Use the checks at the end of this page to test RecordBook. Save its address, creation receipt, source and ABI, and verify its owner, initial records and deployment finality before integrating it.
Keys and values are public onchain, so use test identifiers that contain no personal information. An untouched key reads as a zero value and revision zero. When integrating a contract that collects tokens, also follow the spending approval procedure.

Read at a specific block

The ABI below describes the record reads, updates and events used by the application:
Supply key and nextValue as application-chosen 32-byte hexadecimal values. Read consensus_status using the public finality procedure in Verify and reconcile payments. Use its finalized height as blockNumber for both reads so the record and owner come from the same block:
Save the intended key, nextValue and returned revision with an application operation ID before signing. These fields identify the update you will verify after submission.

Submit an authorized update

The signing account for RecordBook.set must have the address stored in owner. Set signerAddress to the signing account’s address and simulate set with the saved arguments. Simulation checks whether the call succeeds against the current state. The revision check also runs during execution, so another update before inclusion can cause this transaction to revert.
Estimate gas without fee fields, apply the headroom from Estimate and record fees, and check that the signing account’s balance in the gas token covers the maximum gas cost. Follow the procedure for saving outgoing attempts to reserve the signing account and save the intended call. Use the wallet client, selected gasToken, and estimated gasLimit and maxFeePerGas to sign:
Save signed.txHash and signed.raw in the attempt record before calling signed.send(), then check that its returned hash matches signed.txHash. The SDK uses a Metal 0x7f envelope with zero native value. See TypeScript SDK for its signing and fee behavior.

Verify execution, the event, and state

For direct contract calls, fetch the transaction by hash and compare its from, to, and input with the saved signing account, contract address, and ABI-encoded function call. When another party supplies the hash, use the application’s own saved instruction for this comparison. Read the receipt by the same hash. Check that its from and to match the transaction, then check the execution result. Wait until consensus_status.finalized.number reaches the receipt’s block number, then verify that the canonical block hash matches the receipt. Record a finalized revert as a failed attempt. For successful execution, verify the event and state before updating the application record. Decode only logs from the intended contract and require the exact update:
An eth_call at the receipt’s block returns the state at the end of that block, which may include later updates to the same record. The matching event verifies your update, while the state read must show its revision or a later one. Process any later revisions through their events before displaying the current value.

Process events durably

Identify each event by (chain ID, transaction hash, log index). Save the verified event, application record update and cursor in one database transaction. The cursor records the last processed block’s number and hash. Follow the storage and uniqueness rules in Verify and reconcile payments, adapting the expected fields and event decoder to RecordUpdated. Discover logs using the contract address, RecordUpdated ABI, and bounded block ranges from the saved cursor plus one through the finalized height. Process blocks in order and events by transaction index and log index. Apply each record’s events in revision order, retrieving any missing revisions before applying later values. Skip events already recorded in the database.

Recover and test

After a lost response, use the saved hash and bytes to recover the same submission. Resolve that attempt before deciding whether another update is needed. For a finalized StaleRevision revert, read the newer record and decide whether the intended change still applies before preparing a new transaction. Test the integration with these scenarios: Retain the contract deployment record, dependency lockfile, signed attempt, receipt, matching event, block hashes, and database observations for verification.