Using Proven Data in your Smart Contract
Explaining how to use data that is proven by Axiom in a smart contract.
Generally, when using the data proven by Axiom in a smart contract, you'll want to follow two steps:
- 1.Verify user inputs against proven data in
AxiomV1Query
- 2.Check application logic with the data in your contract
Additionally, it can be helpful to create a struct that holds all of the data
struct ResponseStruct {
bytes32 keccakBlockResponse;
bytes32 keccakAccountResponse;
bytes32 keccakStorageResponse;
IAxiomV1Query.BlockResponse[] blockResponses;
IAxiomV1Query.AccountResponse[] accountResponses;
IAxiomV1Query.StorageResponse[] storageResponses;
}
Using the appropriate AxiomV1Contract address (use the proxy address), send all of the data to
areResponsesValid
:IAxiomV1Query axiomV1Query = IAxiomV1Query(AXIOM_V1_QUERY_GOERLI_ADDR);
bool valid = axiomV1Query.areResponsesValid(
response.keccakBlockResponse,
response.keccakAccountResponse,
response.keccakStorageResponse,
response.blockResponses,
response.accountResponses,
response.storageResponses
);
if (!valid) {
revert ProofError(); // custom error
}
Now that you've checked the data was validly read from the history of Ethereum by verifying it against
AxiomV1Query
, you will want to check that it passes your application logic. // Decode the query metadata
uint256 length = response.accountResponses.length;
if (length != 1) {
revert InvalidDataLengthError(); // custom error
}
// Get values for first transaction from submitted proof response struct
uint256 blockNumber = response.accountResponses[0].blockNumber;
uint256 nonce = response.accountResponses[0].nonce;
address addr = response.accountResponses[0].addr;
// Get current block
uint256 currentBlock = block.number;
// Check that the account nonce at the end of the bear market is a set threshold
// above the account nonce at the start of the bear market, since it acts as a
// transaction counter
if (nonce != 1) {
revert InvalidNonceError(); // custom error
}
// Check that the proof submitted is for the same address that is submitting the
// transaction
if (addr != _msgSender()) {
revert InvalidSenderError(); // custom error
}
// Check that the start and end blocks proved match the values set in the contract
if (currentBlock - ACCOUNT_AGE_THRESHOLD < blockNumber) {
revert AccountAgeBelowThresholdError(); // custom error
}
A full example can be found here: https://github.com/axiom-crypto/examples/blob/main/age-gate-mint/contracts/src/Distributor.sol