Functionality
Overview
The zkVerify Smart Contract is deployed on different chains, where it receives an aggregation from the zkVerify authorized relayer. Here is a list of the chains in which zkVerify contracts are deployed.
Storage Variables
The zkVerify Smart Contract keeps the aggregations as storage variables:
// Mapping of domain Ids to aggregationIds to proofsAggregations.
mapping(uint256 => mapping(uint256 => bytes32)) public proofsAggregations;
Methods
Submit Aggregation Method (for bot only)
function submitAggregation(
uint256 _domainId,
uint256 _aggregationId,
bytes32 _proofsAggregation
)external onlyRole(OPERATOR);
- Adds a new entry to the mapping using aggregationId and domainId and stores the proofsAggregation.
- Emits a new AggregationPosted(domainId, aggregationId, proofsAggregation) event.
Submit Aggregations Batch Method (for bot only)
This method is used in the situation when multiple aggregations have been published on zkVerify while the relayer is down but recovers later on.
function submitAggregationBatchByDomainId(
uint256 _domainId,
uint256[] calldata _aggregationIds,
bytes32[] calldata _proofsAggregations
) external onlyRole(OPERATOR)
- Checks that
_aggregationIds.len() == _proofsAggregations.len()
. - Invokes the
registerAggregation
internal method multiple times.
It’s a bit cheaper than calling submitAggregation externally multiple times, as you’ll pay the initial gas fee only one time. Additionally, it avoids edge cases related to Ethereum nonce management.
onAccept Method (submit aggregation for Hyperbridge only)
This method receives hyperbridge message containing an aggregation and is defined by Hyperbridge interface
function onAccept(IncomingPostRequest memory incoming) external override onlyHost
- Parse and unpacks message payload to get domainId, aggregationId, and proofsAggregation
- Invokes the
registerAggregation
internal method.
Verify Proof Aggregation Method
This method is used by proof submitters’ contracts to verify that their proof has been attested by a published aggregation.
function verifyProofAggregation(
uint256 _domainId,
uint256 _aggregationId,
bytes32 _leaf,
bytes32[] calldata _merklePath,
uint256 _leafCount,
uint256 _index
) external view returns (bool)
- Checks
__aggregationId
exists in theproofsAggregations
storage mapping. - Returns
Merkle.verifyProofKeccak(proofsAggregation, _merklePath, _leafCount, _index, _leaf)
The verification of the Merkle path is carried out by employing the Merkle.sol library contract provided by EigenDA. We preferred this choice over OpenZeppelin, as it is assuming that both leaves and internal nodes are ordered lexicographically, which is something not necessarily true for us. Moreover, EigenDA implementation is more optimized.
However, such implementation needs to be modified to accommodate the fact that Substrate uses a slightly optimized version of a Binary Merkle tree, while the contract assumes the Merkle tree to be always complete and balanced. Please refer to the Substrate source code for more info.