diff --git a/contracts/CCTF_2022.sol b/contracts/CCTF_2022.sol deleted file mode 100644 index 018dca2..0000000 --- a/contracts/CCTF_2022.sol +++ /dev/null @@ -1,138 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Authors: six and Silur -pragma solidity ^0.8.16; - -contract CCTF9 { - address public admin; - uint256 public volStart; - uint256 public volMaxPoints; - uint256 public powDiff; - bool public started; - - enum PlayerStatus { - Unverified, - Verified, - Banned - } - - struct Player { - PlayerStatus status; - uint256 points; - } - - modifier onlyAdmin { - require(msg.sender == admin, "Not admin"); - _; - } - - modifier onlyActive { - require(started == true, "CCTF not started."); - _; - } - - struct Flag { - address signer; - bool onlyFirstSolver; - uint256 points; - string skill_name; - } - - mapping (address => Player) public players; - mapping (uint256 => Flag) public flags; - - event CCTFStarted(uint256 timestamp); - event FlagAdded(uint256 indexed flagId, address flagSigner); - event FlagRemoved(uint256 indexed flagId); - event FlagSolved(uint256 indexed flagId, address indexed solver); - - constructor(uint256 _volMaxPoints, uint256 _powDiff) { - admin = msg.sender; - volMaxPoints = _volMaxPoints; - powDiff = _powDiff; - started = false; - } - - function setAdmin(address _admin) external onlyAdmin { - require(_admin != address(0)); - admin = _admin; - } - - function setCCTFStatus(bool _started) external onlyAdmin { - started = _started; - } - - function setFlag(uint256 _flagId, address _flagSigner, bool _onlyFirstSolver, uint256 _points, string memory _skill) external onlyAdmin{ - flags[_flagId] = Flag(_flagSigner, _onlyFirstSolver, _points, _skill); - emit FlagAdded(_flagId, _flagSigner); - } - - function setPowDiff(uint256 _powDiff) external onlyAdmin { - powDiff = _powDiff; - } - - - function register(string memory _RTFM) external { - require(players[msg.sender].status == PlayerStatus.Unverified, 'Already registered or banned'); - //uint256 pow = uint256(keccak256(abi.encodePacked("CCTF", msg.sender,"registration", nonce))); - //require(pow < powDiff, "invalid pow"); - require(keccak256(abi.encodePacked('I_read_it')) == keccak256(abi.encodePacked(_RTFM))); // PoW can be used for harder challenges, this is Entry! - players[msg.sender].status = PlayerStatus.Verified; - } - - function setPlayerStatus(address player, PlayerStatus status) external onlyAdmin { - players[player].status = status; - } - - -////////// Submit flags - mapping(bytes32 => bool) usedNs; // Against replay attack (we only check message signer) - mapping (address => mapping (uint256 => bool)) Solves; // address -> challenge ID -> solved/not - uint256 public submission_success_count = 0; // For statistics - - function SubmitFlag(bytes32 _message, bytes memory signature, uint256 _submitFor) external onlyActive { - require(players[msg.sender].status == PlayerStatus.Verified, "You are not even playing"); - require(bytes32(_message).length <= 256, "Too long message."); - require(!usedNs[_message]); - usedNs[_message] = true; - require(recoverSigner(_message, signature) == flags[_submitFor].signer, "Not signed with the correct key."); - require(Solves[msg.sender][_submitFor] == false); - - Solves[msg.sender][_submitFor] = true; - players[msg.sender].points += flags[_submitFor].points; - players[msg.sender].points = players[msg.sender].points < volMaxPoints ? players[msg.sender].points : volMaxPoints; - - if (flags[_submitFor].onlyFirstSolver) { - flags[_submitFor].points = 0; - } - - submission_success_count = submission_success_count + 1; - emit FlagSolved(_submitFor, msg.sender); - } - - function recoverSigner(bytes32 _ethSignedMessageHash, bytes memory _signature) public pure returns (address) { - (bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature); - return ecrecover(_ethSignedMessageHash, v, r, s); - } - - function splitSignature(bytes memory sig) public pure returns (bytes32 r, bytes32 s, uint8 v){ - require(sig.length == 65, "Invalid signature length"); - assembly { - r := mload(add(sig, 32)) - s := mload(add(sig, 64)) - v := byte(0, mload(add(sig, 96))) - } - } - -////////// Check status, scores, etc - function getPlayerStatus(address _player) external view returns (PlayerStatus) { - return players[_player].status; - } - - function getPlayerPoints(address _player) external view returns (uint256) { - return players[_player].points < volMaxPoints ? players[_player].points : volMaxPoints; - } - - function getSuccessfulSubmissionCount() external view returns (uint256){ - return submission_success_count; - } -} diff --git a/contracts/CCTF_by_Anonz.sol b/contracts/CCTF_by_Anonz.sol deleted file mode 100644 index 58d93df..0000000 --- a/contracts/CCTF_by_Anonz.sol +++ /dev/null @@ -1,130 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Authors: Anonz team, developed at Polkadot Metaverse Championship, as part of their CCTF track solution. -// Based on Six's and Silur's CCTF 2022 code. -pragma solidity ^0.8.16; - -contract CryptoCTFX { - enum PlayerStatus { - Unverified, - Verified, - Banned - } - - struct Player { - PlayerStatus status; - uint score; - } - - modifier onlyExistingContest(uint contestID) { - require(contests[contestID].admin != address(0), "Unknown contest ID"); - _; - } - - modifier onlyAdmin(uint contestID) { - require(msg.sender == contests[contestID].admin, "You are not the admin of this contest"); - _; - } - - modifier onlyOpen(uint contestID) { - require(contests[contestID].submissionsOpen, "Submissions are not open for this contest at this time"); - _; - } - - modifier onlyExistingChallenge(uint contestID, uint challengeID) { - require(contests[contestID].challenges[challengeID].obscuredFlag != address(0), "Unknown challenge ID"); - _; - } - - struct Challenge { - address obscuredFlag; // public key of the flag - uint worth; - uint256 descriptionFingerprint; - bool onlyFirstSolver; - string skill; - } - - struct Contest { - address admin; - mapping (uint => Challenge) challenges; - mapping (address => Player) players; - bool submissionsOpen; - mapping (address => mapping (uint => bool)) solves; // address -> challengeID -> solved/not - mapping (uint => bool) anySolves; // challengeID -> solved/not - } - - mapping (uint => Contest) public contests; - - event ChallengeAddedOrUpdated(uint contestID, uint indexed challengeID); - event ChallengeSolved(uint contestID, uint indexed challengeID, address indexed solver); - - function createContest(uint contestID) external { - require(contests[contestID].admin == address(0), "This contest ID has already been registered"); - contests[contestID].admin = msg.sender; - contests[contestID].submissionsOpen = false; - } - - function setAdmin(uint contestID, address newAdmin) external onlyExistingContest(contestID) onlyAdmin(contestID) { - require(newAdmin != address(0)); - contests[contestID].admin = newAdmin; - } - - function setSubmissionsStatus(uint contestID, bool open) external onlyExistingContest(contestID) onlyAdmin(contestID) { - contests[contestID].submissionsOpen = open; - } - - function addOrUpdateChallenge(uint contestID, uint challengeID, address obscuredFlag, uint worth, uint256 descriptionFingerprint, bool onlyFirstSolver, string memory skill) external onlyExistingContest(contestID) onlyAdmin(contestID) { - require(obscuredFlag != address(0), "The obscured flag value must not be 0"); - contests[contestID].challenges[challengeID] = Challenge(obscuredFlag, worth, descriptionFingerprint, onlyFirstSolver, skill); - emit ChallengeAddedOrUpdated(contestID, challengeID); - } - - function register(uint contestID, string memory password) external onlyExistingContest(contestID) { - require(contests[contestID].players[msg.sender].status == PlayerStatus.Unverified, "You are already registered or banned in this contest"); - require(keccak256(abi.encodePacked("I_read_it")) == keccak256(abi.encodePacked(password))); - contests[contestID].players[msg.sender].status = PlayerStatus.Verified; - } - - function setPlayerStatus(uint contestID, address player, PlayerStatus status) external onlyExistingContest(contestID) onlyAdmin(contestID) { - contests[contestID].players[player].status = status; - } - - function submitFlag(uint contestID, uint challengeID, bytes memory signature) external onlyExistingContest(contestID) onlyExistingChallenge(contestID, challengeID) onlyOpen(contestID) { - require(contests[contestID].players[msg.sender].status == PlayerStatus.Verified, "You are unverified or banned in this contest"); - // the correct signature is an ECDSA signature where (1) the message (hash) is the sender address and (2) the private key is the flag; - // (2) is checked by testing against the public key, which can then be public information - address recoveredSigner = recoverSigner(bytes32(abi.encodePacked(msg.sender)), signature); - require(recoveredSigner != address(0), "Invalid signature"); - require(recoveredSigner == contests[contestID].challenges[challengeID].obscuredFlag, "Wrong answer"); - require(!contests[contestID].solves[msg.sender][challengeID], "You have already solved this challenge of this contest"); - - if (!contests[contestID].anySolves[challengeID] || !contests[contestID].challenges[challengeID].onlyFirstSolver) { - contests[contestID].players[msg.sender].score += contests[contestID].challenges[challengeID].worth; - } - contests[contestID].solves[msg.sender][challengeID] = true; - contests[contestID].anySolves[challengeID] = true; - - emit ChallengeSolved(contestID, challengeID, msg.sender); - } - - function recoverSigner(bytes32 messageHash, bytes memory signature) public pure returns (address) { - (bytes32 r, bytes32 s, uint8 v) = splitSignature(signature); - return ecrecover(messageHash, v, r, s); - } - - function splitSignature(bytes memory sig) public pure returns (bytes32 r, bytes32 s, uint8 v) { - require(sig.length == 65, "Invalid signature length"); - assembly { - r := mload(add(sig, 32)) - s := mload(add(sig, 64)) - v := byte(0, mload(add(sig, 96))) - } - } - - function getPlayerStatus(uint contestID, address player) external view onlyExistingContest(contestID) returns (PlayerStatus) { - return contests[contestID].players[player].status; - } - - function getPlayerScore(uint contestID, address player) external view onlyExistingContest(contestID) returns (uint) { - return contests[contestID].players[player].score; - } -} diff --git a/contracts/Hall_of_Fame.sol b/contracts/Hall_of_Fame.sol new file mode 100644 index 0000000..20ed906 --- /dev/null +++ b/contracts/Hall_of_Fame.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-3.0 +// Author: six +// State: v0.1 +pragma solidity ^0.8.17; + +contract CCTF_Hall_of_Fame { + +address fame_manager; + +constructor () { + fame_manager = msg.sender; // TBA There should be more, eg. DAO-like feature. +} + +modifier only_famman { + require(msg.sender == fame_manager, 'Not Fame Manager.'); + _; +} + + //Contributors + uint contributor_count; + struct Contributor{ + uint256 id; + string name; + string skills; + uint record_date; + } + Contributor[] public contributors; + + // Players + uint player_count; + struct Player{ + uint256 id; + string name; + string team_name; + string skills; + uint record_date; + } + Player[] public players; + + function addContributor(string memory _name, string memory _skills) external { + contributor_count = contributor_count+1; + contributors.push(Contributor(contributor_count, _name, _skills, block.timestamp)); + } + + // There is no remove, once someone contributed it is safu. + + function addPlayer(string memory _name, string memory _skills, string memory _team_name) external { + player_count = player_count+1; + players.push(Player(contributor_count, _name, _skills, _team_name, block.timestamp)); + } + + function listContributors() public view returns (Contributor[] memory) { + return contributors; + } + + function listTopPlayers() public view returns (Player[] memory) { + return players; + } + +}