|
1 | | -// SPDX-License-Identifier: MIT |
| 1 | +// SPDX-License-Identifier: GNU |
2 | 2 | pragma solidity ^0.8.24; |
3 | 3 |
|
4 | | -import {ERC1155} from "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; |
5 | | -import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; |
| 4 | +import "./TaskToken.sol"; |
| 5 | +import "./TaskCreatorAccess.sol"; |
| 6 | +import "./Verifier.sol"; |
6 | 7 |
|
7 | | -contract CTFProof is ERC1155, Ownable { |
8 | | - // Mapping: taskId => metadata URI |
9 | | - mapping(uint256 => string) private _taskURIs; |
| 8 | +contract TaskManager { |
| 9 | + CTFProof public ctfProof; |
| 10 | + PlonkVerifier public verifier; |
| 11 | + TaskCreatorAccess public accessControl; |
10 | 12 |
|
11 | | - // Optional: track existing task IDs |
12 | | - uint256 public nextTaskId = 1; |
| 13 | + struct Task { |
| 14 | + uint256 commit; // Poseidon(solution, taskId, salt) |
| 15 | + uint256 salt; // Public salt |
| 16 | + bool exists; |
| 17 | + } |
13 | 18 |
|
14 | | - constructor(address initialOwner) |
15 | | - ERC1155("") // base URI not used; we override uri() |
16 | | - Ownable(initialOwner) |
17 | | - {} |
| 19 | + mapping(uint256 => Task) public tasks; |
| 20 | + uint256 public nextTaskId; |
18 | 21 |
|
19 | | - /// @notice Add a new CTF task with its metadata URI |
20 | | - function addTask(string memory taskURI) external onlyOwner returns (uint256 taskId) { |
21 | | - taskId = nextTaskId++; |
22 | | - _taskURIs[taskId] = taskURI; |
23 | | - } |
| 22 | + event TaskCreated(uint256 indexed taskId, uint256 commit, uint256 salt); |
| 23 | + event TaskSolved(uint256 indexed taskId, address indexed solver); |
24 | 24 |
|
25 | | - /// @notice Mint proof token after validating solution (you call this after verification) |
26 | | - function mintProof(address to, uint256 taskId) external onlyOwner { |
27 | | - require(bytes(_taskURIs[taskId]).length > 0, "Invalid taskId"); |
28 | | - require(balanceOf(to, taskId) == 0, "Already claimed"); |
29 | | - _mint(to, taskId, 1, ""); |
| 25 | + constructor( |
| 26 | + address _ctfProof, |
| 27 | + address _verifier, |
| 28 | + address _accessControl |
| 29 | + ) { |
| 30 | + ctfProof = CTFProof(_ctfProof); |
| 31 | + verifier = PlonkVerifier(_verifier); |
| 32 | + accessControl = TaskCreatorAccess(_accessControl); |
30 | 33 | } |
31 | 34 |
|
32 | | - /// @dev Prevent transfers except mint (from == 0) or burn (to == 0) |
33 | | - function _update( |
34 | | - address from, |
35 | | - address to, |
36 | | - uint256[] memory ids, |
37 | | - uint256[] memory amounts |
38 | | - ) internal override { |
39 | | - if (from != address(0) && to != address(0)) { |
40 | | - revert("Transfers disabled"); |
41 | | - } |
42 | | - super._update(from, to, ids, amounts); |
| 35 | + function addTask(uint256 commit, uint256 salt) external { |
| 36 | + require(accessControl.isTaskCreator(msg.sender), "Not TaskCreator"); |
| 37 | + |
| 38 | + uint256 taskId = ++nextTaskId; |
| 39 | + tasks[taskId] = Task(commit, salt, true); |
| 40 | + |
| 41 | + emit TaskCreated(taskId, commit, salt); |
43 | 42 | } |
44 | 43 |
|
45 | | - /// @notice Return token-specific URI |
46 | | - function uri(uint256 taskId) public view override returns (string memory) { |
47 | | - return _taskURIs[taskId]; |
| 44 | + function solveTask( |
| 45 | + uint256 taskId, |
| 46 | + address recipient, |
| 47 | + uint256[24] calldata proof, |
| 48 | + uint256[4] calldata publicSignals |
| 49 | + ) external { |
| 50 | + Task storage task = tasks[taskId]; |
| 51 | + require(task.exists, "Task not found"); |
| 52 | + |
| 53 | + // Verify zkSNARK proof |
| 54 | + require(verifier.verifyProof(proof, publicSignals), "Invalid proof"); |
| 55 | + |
| 56 | + // Public signals expected order: |
| 57 | + // [0] = commit, [1] = taskId, [2] = salt, [3] = recipient |
| 58 | + require(publicSignals[0] == task.commit, "Commit mismatch"); |
| 59 | + require(publicSignals[1] == taskId, "TaskId mismatch"); |
| 60 | + require(publicSignals[2] == task.salt, "Salt mismatch"); |
| 61 | + require(publicSignals[3] == uint256(uint160(recipient)), "Recipient mismatch"); |
| 62 | + require(recipient == msg.sender, "Recipient must be caller"); |
| 63 | + |
| 64 | + // Mint ERC-1155 token (1 per solver per task) |
| 65 | + ctfProof.mintProof(msg.sender, taskId); |
| 66 | + |
| 67 | + emit TaskSolved(taskId, msg.sender); |
48 | 68 | } |
49 | 69 | } |
0 commit comments