Testnet Guide
Current limitation: this is a V5 deployment and smoke-test runbook, not a currently executable public testnet flow. Use it only after a verified V5 Sepolia address and matching deployment record are published and configured in oak-chain-infra. Local mock mode remains the executable evaluation path.
Get Sepolia ETH first, configure the environment, then run one settlement plus write proposal cycle.
Sepolia Testnet
Smart Contract
ValidatorPaymentV5
The intended V5 deployment record must provide:
<SEPOLIA_V5_ADDRESS>The canonical address is set in OAK_BLOCKCHAIN_CONTRACT_ADDRESS within sepolia.env. Validator processes load it at startup.
Contract Surface
// Settlement
function settleWrite(bytes32 proposalId, uint32 capabilityFlags) external payable;
function settleDelete(bytes32 proposalId, uint32 capabilityFlags) external payable;
// Quote (view)
function quotePriceETH(ProposalKind proposalKind, uint32 capabilityFlags) external view returns (uint256);
// Capability flags (bitfield)
uint32 constant CAPABILITY_NONE = 0;
uint32 constant CAPABILITY_VALIDATOR_HOSTED_BINARY = 1 << 0;
// Load-bearing event watched by validators
event ProposalSettledV5(
bytes32 indexed proposalId,
address indexed payer,
ProposalKind proposalKind,
uint256 amount,
uint32 capabilityFlags
);
For the full surface (treasury management, owner controls, gas baseline), see Smart Contract.
Get Test ETH
Faucets
Steps
- Install MetaMask
- Add Sepolia network (or select from network list)
- Copy your wallet address
- Visit faucet and request test ETH
- Wait for transaction confirmation
Each settlement costs the write price (see Smart Contract) plus gas, so one faucet drip covers many test writes.
Configure Validator
Environment Variables
# The validator reads its Sepolia RPC endpoint from OAK_BLOCKCHAIN_RPC_URL
export OAK_BLOCKCHAIN_RPC_URL=https://sepolia.infura.io/v3/your-infura-project-id
# Or set only the Infura key; sepolia.env builds OAK_BLOCKCHAIN_RPC_URL from it
export INFURA_API_KEY=your-infura-project-id
modes/sepolia/validators/lifecycle/start-cluster.sh loads modes/sepolia/validators/config/sepolia.env, which sets OAK_BLOCKCHAIN_MODE=sepolia and OAK_BLOCKCHAIN_CONTRACT_ADDRESS. Check that this address is the verified V5 deployment before you run. INFURA_API_KEY is read only by the infra scripts, not by the validator.
Get Infura API Key
- Go to infura.io
- Create free account
- Create new project
- Copy Project ID (this is your API key)
Run the Sepolia Workflow
mkdir oak-chain-workspace
cd oak-chain-workspace
git clone https://github.com/somarc/oak-chain-infra.git
git clone https://github.com/somarc/jackrabbit-oak.git
cd oak-chain-infra
./modes/sepolia/validators/lifecycle/start-cluster.sh --build --fresh
Make a Test Settlement
Using ethers.js
import { ethers } from 'ethers';
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
// From modes/sepolia/validators/config/sepolia.env
const contractAddress = '<SEPOLIA_V5_ADDRESS>';
const abi = [
'function settleWrite(bytes32 proposalId, uint32 capabilityFlags) payable',
'event ProposalSettledV5(bytes32 indexed proposalId, address indexed payer, uint8 proposalKind, uint256 amount, uint32 capabilityFlags)',
];
const contract = new ethers.Contract(contractAddress, abi, signer);
const proposalId = ethers.keccak256(
ethers.toUtf8Bytes(`proposal:${Date.now()}`)
);
// Standard write, no capability flags
const CAPABILITY_NONE = 0;
const PRICE = ethers.parseEther('0.001');
const tx = await contract.settleWrite(proposalId, CAPABILITY_NONE, {
value: PRICE,
});
console.log('Settlement tx:', tx.hash);
const receipt = await tx.wait();
console.log('Settlement confirmed!');
Oak validators expect the transaction hash from the settleWrite call. Reuse the same proposalId when you call POST /v1/propose-write. Excess ETH is refunded automatically, so over-funding is safe.
Verify Settlement
Check Transaction
# Using curl + Infura
curl https://sepolia.infura.io/v3/${INFURA_API_KEY} \
-X POST \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "eth_getTransactionReceipt",
"params": ["0xYourTxHash"],
"id": 1
}'
Look for the ProposalSettledV5 event log in the receipt. In sepolia mode, the validator queues the write proposal and releases it to consensus only after that event is confirmed for the corresponding proposal id. Chain-backed payments are not yet validated.
Etherscan
After deployment, record the transaction and use an address-specific Sepolia Etherscan verification link. A placeholder is not a deployed contract.
Pricing (Sepolia)
Prices and gas costs are on Smart Contract. Use quotePriceETH(proposalKind, capabilityFlags) off-chain to compute the exact value before the call. A deployed testnet contract must be verified before you treat its prices as operational.
Complete Test Flow
async function testSepoliaWrite() {
// 1. Connect wallet
const accounts = await window.ethereum.request({
method: 'eth_requestAccounts'
});
const wallet = accounts[0];
// 2. Settle on-chain
const proposalId = ethers.keccak256(
ethers.toUtf8Bytes(`proposal:${Date.now()}`)
);
const settleTx = await contract.settleWrite(
proposalId,
0, // CAPABILITY_NONE
{ value: ethers.parseEther('0.001') }
);
// 3. Wait for confirmation
console.log('Settlement tx:', settleTx.hash);
await settleTx.wait();
// 4. Sign content
const content = { title: 'Sepolia Test!' };
const message = JSON.stringify({ content, timestamp: Date.now() });
const signature = await window.ethereum.request({
method: 'personal_sign',
params: [message, wallet],
});
// 5. Submit to validator
const response = await fetch('http://localhost:8090/v1/propose-write', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
proposalId,
walletAddress: wallet,
message,
ethereumTxHash: settleTx.hash,
signature,
}),
});
// 202 Accepted, state PENDING. Poll GET /v1/ops/operations/{proposalId} for COMMITTED.
console.log('Write result:', await response.json());
}
Troubleshooting
"Settlement not found"
- Wait for transaction confirmation (1-2 blocks)
- Verify the transaction emitted
ProposalSettledV5on Etherscan - Check the validator is in Sepolia mode
- Confirm the validator and your client are using the same contract address from
sepolia.env
"Already paid"
The contract enforces replay protection. A given proposalId can be settled exactly once. Generate a fresh proposal id and retry.
"Insufficient funds"
- Get more test ETH from a faucet
- Check wallet balance on Etherscan
- Remember settlement requires the
WRITE_PRICE_ETHplus gas
"Invalid API key"
- Verify
OAK_BLOCKCHAIN_RPC_URL(orINFURA_API_KEYfor the infra scripts) is set - Check Infura project is active
- Confirm the project has Sepolia enabled
Next Steps
- Smart Contract. Full V5 surface, events, gas profile.
- API Reference. Full validator endpoint docs.
- Authentication. Wallet integration.
- Run a Validator. Production setup.