// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; contract H4H_CTF { // keep track of owner address private admin; uint256 constant rewardAmount = 5.0 ether; uint256 constant fundingAmount = 0.1 ether; // struct for riddles struct Riddle { // owner = account belonging to privkey = sha(answer) address owner; // who solved it address solver; // when solved uint256 timestamp; } // all riddles Riddle[] public riddles; // initialize all vars constructor() payable { admin = msg.sender; // authorized accounts: add(0xA36BcBB6029256d6B2801b618813723F3B60c5c4); add(0x1863478703d356a3592c160eEeb72C1dCEf539eb); add(0x2f4418BA86fE0825B3929Bbf139c1fe9520dc90B); add(0x92753Ff635AA2A93bEc82613a61177C05995e3E5); add(0xe45C7a1AAfA83b1155bFA120568D606c578C881e); add(0x222dd9d3468b2809224c75E93d02a3a77Cd43dAa); add(0x1335B17eFeA0724cFc0dBD8e04feA80C70640dFA); add(0x5835bC860E1c7bd24c64cFA3946dD4D1848CDe53); add(0xcDd1f0b9029c0B80AF076B902054b263D536DeF9); add(0xb20bb6857d2F1Ce000B9ae241BE2dD39063bC4d1); add(0x0266A8bfb13981D7BFAB07723ef8784b5340597E); add(0x59e5F8C938E204cF0dD855868F9D20E874ED0688); add(0xeB1e9661Be47CB5039f16813C7aC2f56Df03BFF6); add(0xb5610D737e4031A68E6EdE82F142b228ABdb0980); add(0x31CA01c46fC9BF89989A4dC3DaAA4D0Fb79eeDF8); add(0xf7F384E9592B47dEA65e9439Af2A4d09D0F6a668); add(0xd57982F3c715CB6636532A79Bd78Bf5D3D26f584); add(0xD7CA9c71fD2Ca48518311a03Bfe923A002092F14); add(0x5046eC8DEB9a512DB8559Bfc81C26a26145481d3); add(0xBB985013743f23B79D52fC1DFF163A80529305Da); add(0xdE997697ba6964c8382be38d2eC82f5fA021cc97); } // allow us to receive funds receive() external payable { } function getStats() public view returns(address[] memory, address[] memory, uint256[] memory){ address[] memory owner = new address[](riddles.length); address[] memory solver = new address[](riddles.length); uint256[] memory timestamp = new uint256[](riddles.length); for (uint i=0; i < riddles.length; i++) { owner[i] = riddles[i].owner; solver[i] = riddles[i].solver; timestamp[i] = riddles[i].timestamp; } return (owner, solver, timestamp); } // find riddle index function getRiddleIndex(address a) private view returns (bool, uint) { for (uint i=0; i < riddles.length; i++) { if (riddles[i].owner == a) { return (true, i); } } return (false, 0); } // send your solution here function solve(address payable payout_address) payable public { // you need to call this from the address // of which you just figured out its private key address caller = msg.sender; // use your own address as payout to make sure // no one will steal your price ;) if (payout_address == caller) { revert("error: do not use a riddle address for payout (use your own!)"); } // make sure you do not accidently send it to address 0 // as this would be gone forever (no one knows the private key of 0x0...) if (payout_address == address(0)) { revert("error: refusing to send anything to address 0..."); } // see if this is a correct answer at all (bool known, uint index) = getRiddleIndex(caller); if (!known) { revert("error: no riddle associated to this caller"); } // see if this riddle was already solved if (riddles[index].solver != address(0)) { revert("error: looks like you're late, this riddle has been solved"); } // wohooo, nobody solved it yet! congratulations! // let's write down some notes for the scoreboard riddles[index].solver = payout_address; riddles[index].timestamp = block.timestamp; // read, understand, adapt, cashout, lambo: if (caller == 0x5046eC8DEB9a512DB8559Bfc81C26a26145481d3) { require(msg.value == 0.0001337 ether, "!lambo"); } // this should never happen... if (address(this).balance < rewardAmount) { revert("error: out of funds. looks like i forgot to add enough funds..."); } // paycheck time! (bool success, ) = payout_address.call{value: rewardAmount}(""); require(success, "error: oooops, that was close. you were right but something failed."); } modifier onlyAdmin() { if (msg.sender != admin) { revert("not authorized"); } _; } function add(address a) public onlyAdmin { riddles.push(Riddle({owner: a, solver: address(0), timestamp: 0})); (bool success, ) = payable(a).call{value: fundingAmount}(""); require(success, "error: this looks bad..."); } // used for cleanup after contest function withdraw() public onlyAdmin { (bool success,) = admin.call{value: address(this).balance}(""); require(success,"transfer failed"); } }