Skip to content

Instantly share code, notes, and snippets.

@nizhunt
Created December 6, 2023 22:36
Show Gist options
  • Save nizhunt/1e779613ca38bea0aacaa0640fc9fb6d to your computer and use it in GitHub Desktop.
Save nizhunt/1e779613ca38bea0aacaa0640fc9fb6d to your computer and use it in GitHub Desktop.
Incognito Insight EthIndia
[
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "NotVerified",
"type": "error"
},
{
"inputs": [],
"name": "StringTooLong",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "challengeId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "challenger",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "expectedProfit",
"type": "uint256"
}
],
"name": "ChallengeCreated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "challengeId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "bool",
"name": "verified",
"type": "bool"
},
{
"indexed": true,
"internalType": "string",
"name": "solverNickname",
"type": "string"
}
],
"name": "ChallengeVerified",
"type": "event"
},
{
"inputs": [],
"name": "challengeIdCount",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "challenges",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "challengerAddress",
"type": "address"
},
{
"internalType": "uint256",
"name": "expected_profit_percentage",
"type": "uint256"
},
{
"internalType": "address[5]",
"name": "holdings",
"type": "address[5]"
},
{
"internalType": "address",
"name": "platform",
"type": "address"
}
],
"name": "createChallenge",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "challengeId",
"type": "uint256"
}
],
"name": "getChallengeDetails",
"outputs": [
{
"internalType": "address",
"name": "challengerAddress",
"type": "address"
},
{
"internalType": "address",
"name": "platform",
"type": "address"
},
{
"internalType": "address[5]",
"name": "holdings",
"type": "address[5]"
},
{
"internalType": "uint256",
"name": "expected_profit_percentage",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "challengeId",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "_proof",
"type": "bytes"
},
{
"internalType": "string",
"name": "solverNickname",
"type": "string"
}
],
"name": "getVerified",
"outputs": [
{
"internalType": "bool",
"name": "verified",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
}
]
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {UltraVerifier} from "contracts/Ecdsa.sol";
/// @title A contract for creating and verifying investment challenges
/// @notice This contract allows users to create investment challenges and get them verified
contract IncognitoInsight {
UltraVerifier private verifier;
error NotVerified();
error StringTooLong();
uint256 public challengeIdCount = 1;
mapping(uint256 => bytes32[]) public challenges;
// Events
event ChallengeCreated(
uint256 indexed challengeId,
address indexed challenger,
uint256 indexed expectedProfit
);
event ChallengeVerified(
uint256 indexed challengeId,
bool indexed verified,
string indexed solverNickname
);
/// @notice Constructor to set the stake amount
constructor() {
verifier = new UltraVerifier();
}
/// @notice Verifies a given challenge
/// @param challengeId The ID of the challenge to be verified
/// @param _proof The proof to be verified
/// @return verified Returns true if the verification is successful
/// Known Issue: susseptible to frontrunning.
function getVerified(
uint256 challengeId,
bytes calldata _proof,
string calldata solverNickname
) external returns (bool verified) {
bytes32[] storage challenge = challenges[challengeId];
challenge.push(stringToBytes32(solverNickname));
try verifier.verify(_proof, challenge) returns (
bool _verified
) {
delete challenges[challengeId];
emit ChallengeVerified(challengeId, _verified, solverNickname);
return _verified;
} catch {
revert NotVerified();
}
}
/// @notice Creates a new challenge
/// @param challengerAddress The address of the challenger
/// @param expected_profit_percentage The expected profit percentage for the challenge
/// @param holdings The holdings associated with the challenge
/// @param platform The platform where the challenge is created
function createChallenge(
address challengerAddress,
uint256 expected_profit_percentage,
address[5] calldata holdings,
address platform
) external {
bytes32[] memory publicInputs = new bytes32[](8);
publicInputs[0] = bytes32(uint256(uint160(challengerAddress)));
publicInputs[1] = bytes32(uint256(uint160(platform)));
publicInputs[2] = bytes32(uint256(uint160(holdings[0])));
publicInputs[3] = bytes32(uint256(uint160(holdings[1])));
publicInputs[4] = bytes32(uint256(uint160(holdings[2])));
publicInputs[5] = bytes32(uint256(uint160(holdings[3])));
publicInputs[6] = bytes32(uint256(uint160(holdings[4])));
publicInputs[7] = bytes32(expected_profit_percentage);
challenges[challengeIdCount] = publicInputs;
emit ChallengeCreated(
challengeIdCount,
challengerAddress,
expected_profit_percentage
);
++challengeIdCount;
}
/// @notice Retrieves details for a specified challenge
/// @param challengeId Unique identifier of the challenge
/// @return challengerAddress Address of the challenger
/// @return platform Platform address related to the challenge
/// @return holdings Array of addresses representing holdings
/// @return expected_profit_percentage Expected profit percentage of the challenge
function getChallengeDetails(uint256 challengeId)
public
view
returns (
address challengerAddress,
address platform,
address[5] memory holdings,
uint256 expected_profit_percentage
)
{
require(challengeId < challengeIdCount, "Invalid challenge ID");
bytes32[] memory publicInputs = challenges[challengeId];
require(publicInputs.length == 8, "Invalid challenge data");
challengerAddress = address(uint160(uint256(publicInputs[0])));
platform = address(uint160(uint256(publicInputs[1])));
for (uint i = 0; i < 5; i++) {
holdings[i] = address(uint160(uint256(publicInputs[i + 2])));
}
expected_profit_percentage = uint256(publicInputs[7]);
}
/// @notice Converts a string to a bytes32 type
/// @param source The string to be converted
/// @return result The resulting bytes32 representation
function stringToBytes32(string memory source)
internal
pure
returns (bytes32 result)
{
// Check that the string is not too long
if (bytes(source).length > 32) revert StringTooLong();
// Copy the string's bytes to the fixed-size array
assembly {
result := mload(add(source, 32))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment