Ethereum Smart Contract Notary
Published on June 23, 2025
Create a permanent, queryable, and structured proof-of-existence for any file by storing its hash in a dedicated smart contract using the Foundry toolkit.
This guide covers an advanced method for developers. For a simpler approach using just MetaMask, see our Ethereum Notary Guide.
While embedding data in a transaction's input field is simple and effective, a more robust and extensible method is to store the data in a smart contract's state. This approach creates structured, on-chain records that can be easily read and integrated into other decentralized applications.
This guide provides an advanced walkthrough using Foundry, a leading toolkit for Ethereum application development, to deploy and interact with a dedicated Notary
contract.
Step 1: The Notary Smart Contract
First, we need a smart contract that can receive, store, and expose notarization records. This simple Notary.sol
contract stores the data hash, the sender's address, and a timestamp for each entry.
Create a file named src/Notary.sol
in your Foundry project:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract Notary {
struct Record {
address sender;
uint256 timestamp;
bytes32 data;
}
Record[] public notarizations;
function notarize(bytes32 _data) public {
notarizations.push(Record({
sender: msg.sender,
timestamp: block.timestamp,
data: _data
}));
}
function getNotarizationCount() public view returns (uint256) {
return notarizations.length;
}
}
Step 2: Deploy the Contract with `forge create`
With the contract code ready, use Foundry's forge
tool to compile and deploy it to a test network like Sepolia. This command broadcasts the creation transaction.
forge create --rpc-url YOUR_SEPOLIA_RPC_URL \
--private-key YOUR_PRIVATE_KEY \
src/Notary.sol:Notary --broadcast
Command Breakdown:
--rpc-url
: Your connection endpoint to the Ethereum network.--private-key
: The key of the account that will deploy the contract and pay for the gas. Never commit this to version control.src/Notary.sol:Notary
: The path to the source file and the name of the contract to deploy.--broadcast
: Submits the transaction to the network.
Forge will output the address of your newly deployed Notary
contract. Save this address for the next steps.
Step 3: Notarize a File Hash with `cast send`
Now, you can call the notarize
function on your live contract. First, get the SHA-256 hash of your document using the tool in our Bitcoin Notary Guide.
Use Foundry's cast
tool to send the transaction that calls the function, passing your document's hash as the argument.
cast send YOUR_CONTRACT_ADDRESS \
"notarize(bytes32)" \
YOUR_DOCUMENT_HASH \
--rpc-url YOUR_SEPOLIA_RPC_URL \
--private-key YOUR_PRIVATE_KEY
This transaction will create a new Record
in the contract's notarizations
array, permanently storing your hash alongside your address and the block's timestamp.
Step 4: Verify the On-Chain Data with `cast call`
Since the notarized data is stored in the contract's public state, you can read it back at any time without needing a private key or paying for gas. Use cast call
to read the record at a specific index (e.g., 0
for the first record).
cast call YOUR_CONTRACT_ADDRESS \
"notarizations(uint256)" 0 \
--rpc-url YOUR_SEPOLIA_RPC_URL
The command will return the raw, 32-byte-aligned data for the struct, which you can then decode.
A More Robust Foundation
Using a smart contract for notarization provides a powerful, extensible foundation. The stored data is structured, machine-readable, and can be used as a trusted oracle by other smart contracts, opening up possibilities for automated verification, royalty systems, and more.
Nanar Consulting specializes in developing these robust, on-chain solutions. If you need to integrate blockchain notarization into your business workflow or protect high-value intellectual property, contact us for a full consultation and custom software development services.