2022-12-06 14:27:15 +00:00
|
|
|
/**
|
|
|
|
*Submitted for verification at polygonscan.com on 2022-08-24
|
|
|
|
*/
|
|
|
|
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
// Authors: six and Silur
|
|
|
|
pragma solidity ^0.8.16;
|
|
|
|
|
|
|
|
import "./verifier.sol";
|
|
|
|
|
|
|
|
|
|
|
|
contract CCTF9 is Verifier{
|
|
|
|
address public admin;
|
|
|
|
uint256 public volMaxPoints;
|
|
|
|
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 Hash {
|
|
|
|
uint32[8] value;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Flag {
|
|
|
|
Hash flagHash;
|
|
|
|
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, Hash flagHash);
|
|
|
|
event FlagRemoved(uint256 indexed flagId);
|
|
|
|
event FlagSolved(uint256 indexed flagId, address indexed solver);
|
|
|
|
|
2022-12-06 17:38:46 +00:00
|
|
|
constructor(uint256 _volMaxPoints) {
|
2022-12-06 14:27:15 +00:00
|
|
|
admin = msg.sender;
|
|
|
|
volMaxPoints = _volMaxPoints;
|
|
|
|
started = false;
|
|
|
|
}
|
|
|
|
|
2022-12-06 17:56:40 +00:00
|
|
|
/// transfers the admin privilege to _admin address
|
2022-12-06 14:27:15 +00:00
|
|
|
function setAdmin(address _admin) external onlyAdmin {
|
|
|
|
require(_admin != address(0));
|
|
|
|
admin = _admin;
|
|
|
|
}
|
|
|
|
|
2022-12-06 17:56:40 +00:00
|
|
|
/// can be used to set the status of the cctf to started or finished
|
2022-12-06 14:27:15 +00:00
|
|
|
function setCCTFStatus(bool _started) external onlyAdmin {
|
|
|
|
started = _started;
|
|
|
|
}
|
|
|
|
|
2022-12-06 17:56:40 +00:00
|
|
|
/// creates a new capturable flag according to the arguments
|
2022-12-06 14:27:15 +00:00
|
|
|
function setFlag(uint256 _flagId,Hash memory _flagHash, bool _onlyFirstSolver, uint256 _points, string memory _skill) external onlyAdmin{
|
|
|
|
flags[_flagId] = Flag(_flagHash, _onlyFirstSolver, _points, _skill);
|
|
|
|
emit FlagAdded(_flagId, _flagHash);
|
|
|
|
}
|
|
|
|
|
2022-12-06 17:56:40 +00:00
|
|
|
/// registers the caller as a player
|
|
|
|
function register() external {
|
2022-12-06 14:27:15 +00:00
|
|
|
require(players[msg.sender].status == PlayerStatus.Unverified, 'Already registered or banned');
|
|
|
|
players[msg.sender].status = PlayerStatus.Verified;
|
|
|
|
}
|
2022-12-06 17:56:40 +00:00
|
|
|
/// sets the player's status either to Unverified, Verified or Banned
|
2022-12-06 14:27:15 +00:00
|
|
|
function setPlayerStatus(address player, PlayerStatus status) external onlyAdmin {
|
|
|
|
players[player].status = status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
////////// Submit flags
|
|
|
|
mapping (address => mapping (uint256 => bool)) Solves; // address -> challenge ID -> solved/not
|
|
|
|
uint256 public submission_success_count = 0; // For statistics
|
|
|
|
|
|
|
|
function SubmitFlag(Proof memory p, uint256 _submitFor) external onlyActive {
|
|
|
|
require(players[msg.sender].status == PlayerStatus.Verified, "You are not even playing");
|
|
|
|
|
|
|
|
uint[13] memory inputs;
|
|
|
|
for(uint i =0 ; i < 8;++i){
|
|
|
|
inputs[i] = flags[_submitFor].flagHash.value[i];
|
|
|
|
}
|
|
|
|
uint32[5] memory addr = addressToUint32(msg.sender);
|
|
|
|
for(uint i =0; i < 5;++i){
|
|
|
|
inputs[8+i] = addr[i];
|
|
|
|
}
|
|
|
|
bool valid = verifyTx(p,inputs);
|
2022-12-06 17:56:40 +00:00
|
|
|
assert(valid);
|
2022-12-06 14:27:15 +00:00
|
|
|
|
2022-12-06 17:56:40 +00:00
|
|
|
require(!Solves[msg.sender][_submitFor]); // can't submit the same flag multiple times
|
2022-12-06 14:27:15 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2022-12-06 17:56:40 +00:00
|
|
|
/// maps an address to unsigned int
|
2022-12-06 17:38:46 +00:00
|
|
|
function addressToUint32 (address _addr) public pure returns (uint32[5] memory)
|
2022-12-06 14:27:15 +00:00
|
|
|
{
|
|
|
|
uint256 targetUint = uint256(uint160(_addr));
|
2022-12-06 17:56:40 +00:00
|
|
|
uint32[5] memory addr = [uint32(targetUint/4294967296**4),
|
|
|
|
uint32(targetUint/4294967296**3),
|
|
|
|
uint32(targetUint/4294967296**2),
|
|
|
|
uint32(targetUint/4294967296),
|
|
|
|
uint32(targetUint)];
|
2022-12-06 14:27:15 +00:00
|
|
|
return addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
////////// 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
function getFlag(uint256 id) external view returns (Flag memory) {
|
|
|
|
return flags[id];
|
|
|
|
}
|
2022-12-06 17:56:40 +00:00
|
|
|
}
|