# Guess The Secret

Example of a guessing game contract that rewards winners in Vite.

Copy // // GuessToWin.solpp // // Simple contract allowing anyone to guess secret passwords. If they guess any right, they // will be awarded an amount of Vite based on the amount funded to the contract. // // Contract initially has no rewards balances stored. Any user can create rewards for a guess // by calling the Fund function and providing the appropriate hash of the secret guess they // would like to award, along with a patment of the amount of Vite they want to fund the award with. // // The hash of the guesses can be generated via the shell command: // echo -n YOURSECRETPASSWORD | b2sum -l 256 // // Guesses are submitted by sending a string of the guess to the Guess function. Correct // guessers are awarded the entire fund for that hash/guess pair // // Warning: If you send funds with a hash value of an unknown string, those funds will be // permanently locked in the contract! Also be warned that all guesses/hashes are logged // into the ledger, so testing a particular hash/guess combination permanently reveals it. // It's good to test this with a known hash/guess and a small value first, before putting // in a larger reward with a truly secret hash/guess. // // Example: // Fund() with 10 Vite and the 32 byte hash "324dcf027dd4a30a932c441f365a25e86b173defa4b8e58948253471b81b72cf" // Guess() with 0 Vite and the string "hello" pragma soliditypp ^0.4.2; contract GuessToWin { // use Vite as token for funding and rewards, for ids see https://vitescan.io/tokens tokenId token = tokenId("tti_5649544520544f4b454e6e40"); // mapping from hashes of correct guesses to the reward balance for that guess. mapping(bytes32 => uint) public balances; // events event Funded(address indexed addr, uint256 amount, bytes32 hashval, string log); event Awarded(address indexed addr, uint256 amount, string guess, string log); event Failed(address indexed addr, uint256 amount, string guess, string log); // function for creating and funding awards, must send Vite and provide hash of secret as argument. onMessage Fund(bytes32 hashval) payable { require(msg.tokenid == token, "Please send vite rewards only."); require(msg.amount > 0, "Must send tokens to fund award."); balances[hashval] += msg.amount; emit Funded(msg.sender, msg.amount, hashval, "Thanks for funding!"); } onMessage Guess(string calldata body) { // here we encode and hash the input string and check if an award fund/balance // exists for this hashed string. bytes32 hashval = blake2b(abi.encodePacked(body)); if( balances[hashval] > 0 ) { // Note: The following order of the transfer and the setting balances to zero // would expose a Solidity contract to reentrancy attacks, but this NOT an // issue in Solidity++ due to async design. Also easier to write this way. msg.sender.transfer(token, balances[hashval]); emit Awarded(msg.sender, balances[hashval], body, "Correct guess! Awarded!"); balances[hashval] = 0; } else { emit Failed(msg.sender, 0, body, "Failed guess, try again!"); } } }

# Key features

  • mapping(bytes32 => uint) public balances; Mappings are extremely useful data structures. In this example we use them to track an award balance for each "secret hash". Another common use is mapping(address => uint), which stores a per-account balance.

  • tokenId token = tokenId("tti_5649544520544f4b454e6e40"); tokenId are the data type for native tokens on the Vite blockchain. The tokenId strings can be looked up, for example, on vitescan.io (opens new window).

  • bytes32 hashval = blake2b(abi.encodePacked(body)); Here, blake2b is the Vite chain's hash function. To use it properly, the data must be encoded properly through use of the abi.encodePacked.