Created
April 12, 2024 19:21
-
-
Save Wollac/b0f0188a7ae8d6219e0565ee5006f428 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.8.25+commit.b61c2a91.js&optimize=false&runs=200&gist=
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
pragma solidity ^0.8.0; | |
import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; | |
contract ProofMarketFIFO is ReentrancyGuard { | |
Proof public emptyProof; | |
uint256 public constant MIN_REQUEST_VALUE = 0.00001 ether; | |
address constant STARK_VERIFIER = address(0x51); | |
/// @notice Special public claims about a zkVM guest execution. | |
/// @dev This is essentially a ReceiptClaim of an Halted execution with no addiional assumptions. | |
struct Assertion { | |
/// @notice Digest of the SystemState just before execution has begun. | |
bytes32 preState; | |
/// @notice Digest of the SystemState just after execution has completed. | |
bytes32 postState; | |
/// @notice A digest of the input to the guest. | |
bytes32 input; | |
/// @notice Digest of the journal committed to by the guest execution. | |
bytes32 journal; | |
} | |
/// @notice Result of an execution proof creation. | |
/// @dev The actiual receipt is not stored on chain. | |
struct Proof { | |
Assertion assertion; | |
string receiptURI; | |
} | |
struct ProofRequest { | |
bytes32 imageID; | |
string programURI; | |
string inputURI; | |
uint256 reward; | |
bytes32[] merkleProof; | |
} | |
mapping(uint256 => ProofRequest) private requests; // Maps request IDs to proof requests | |
mapping(uint256 => Proof) private proofs; // Maps request IDs to proofs | |
mapping(bytes32 => address) private merkleRoots; // Maps merkle roots to L2 addresses for reward claims | |
uint256 private requestCount; | |
event RequestProcessed(uint256 indexed requestID, uint256 reward); | |
event RequestProven(uint256 indexed requestID, Assertion assertion); | |
event RequestAggregated(uint256 indexed requestID, bytes32[] merkleProof); | |
constructor() { | |
requestCount = 0; | |
} | |
function submitRequest( | |
bytes32 imageID, | |
string calldata programURI, | |
string calldata inputURI | |
) external payable { | |
require(msg.value >= MIN_REQUEST_VALUE, "Insufficient payment to submit request"); | |
uint256 newRequestID = requestCount++; | |
requests[newRequestID] = ProofRequest({ | |
imageID: imageID, | |
programURI: programURI, | |
inputURI: inputURI, | |
reward: msg.value, | |
merkleProof: new bytes32[](0) | |
}); | |
emit RequestProcessed(newRequestID, msg.value); | |
} | |
function submitProof( | |
uint256 requestID, | |
bytes32 pre, | |
bytes32 post, | |
bytes32 journal, | |
string calldata receiptURI | |
) external nonReentrant { | |
require(requestID < requestCount, "Invalid request ID"); | |
ProofRequest storage request = requests[requestID]; | |
require(request.reward > 0, "Request already proven"); | |
require(verify(request.imageID, receiptURI), "Proof verification failed"); | |
Assertion memory assertion = Assertion(pre, post, bytes32(0), journal); | |
proofs[requestID] = Proof(assertion, receiptURI); | |
uint256 payment = request.reward; | |
request.reward = 0; | |
payable(msg.sender).transfer(payment); | |
emit RequestProven(requestID, assertion); | |
} | |
function submitMerkleRoot(bytes32 root, address aggregator) external { | |
require(merkleRoots[root] == address(0), "Merkle root allready present"); | |
merkleRoots[root] = aggregator; | |
} | |
function submitMerkleProof(uint256 requestID, bytes32[] calldata proof) external { | |
require(requestID < requestCount, "Invalid request ID"); | |
require(requests[requestID].merkleProof.length == 0, "Merkle proof allready present"); | |
require(bytes(proofs[requestID].receiptURI).length > 0, "Request not proven"); | |
bytes32 hash = hashAssertion(proofs[requestID].assertion); | |
for (uint256 i = 0; i < proof.length; i++) { | |
hash = hashPair(proof[i], hash); | |
} | |
require(merkleRoots[hash] == msg.sender, "Invalid Merkle root"); | |
requests[requestID].merkleProof = proof; | |
emit RequestAggregated(requestID, proof); | |
} | |
function hashAssertion(Assertion memory a) internal pure returns (bytes32) { | |
return sha256(abi.encodePacked("Leaf", a.preState, a.postState, a.input, a.journal)); | |
} | |
function hashPair(bytes32 a, bytes32 b) internal pure returns (bytes32) { | |
return a < b ? sha256(abi.encodePacked(a, b)) : sha256(abi.encodePacked(b, a)); | |
} | |
function verify(bytes32 imageID, string memory receiptURI) internal view returns (bool) { | |
(bool success, bytes memory result) = STARK_VERIFIER.staticcall(abi.encodePacked(imageID, receiptURI)); | |
require(success, "Verification call failed"); | |
return abi.decode(result, (bool)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment