Created
October 21, 2021 18:50
-
-
Save lpinilla/a13cd48f9726a634813ccea89b1dcbbf to your computer and use it in GitHub Desktop.
TuringChallenge for Ekoparty 2021
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//SDPX-License-Identifier: MIT | |
pragma solidity ^0.8.0; | |
import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | |
contract TuringCoin is ERC20 { | |
constructor(uint256 initialSupply) ERC20("TuringCoin", "TNGC") { | |
_mint(msg.sender, initialSupply); | |
} | |
} | |
contract TuringLoan{ | |
TuringCoin public tngc; | |
constructor(address turingCoinAddress){ | |
tngc = TuringCoin(turingCoinAddress); | |
} | |
function flashLoan(uint256 amount) external { | |
uint256 balanceBefore = tngc.balanceOf(address(this)); | |
require(amount <= balanceBefore, "Not enough TuringCoins balance"); | |
tngc.transfer(msg.sender, amount); | |
(bool success,) = msg.sender.call( | |
abi.encodeWithSignature("receiveFlashLoan(uint256)", amount) | |
); | |
require(success, "External call failed"); | |
require(tngc.balanceOf(address(this)) >= balanceBefore, "Flash loan not paid back"); | |
} | |
} | |
contract TuringGambleChance{ | |
function gamble() external view returns (bool){ | |
return block.number % 17 == 2; | |
} | |
} | |
contract TuringChallenge{ | |
address public owner; | |
TuringCoin private tngc; | |
TuringGambleChance public gambleChallenge; | |
mapping(address => uint256) public balanceOf; | |
mapping(address => string) public usernameOf; | |
mapping(address => bool) public already_registered; | |
mapping(address => bool) winners; | |
uint256 constant DECIMALS = 1; | |
address public fut_level; | |
event newWinner(address _winner, string _username); | |
event newGambleFunction(address _sender, address _newfun); | |
modifier onlyOwner{ | |
require(msg.sender == owner); | |
_; | |
} | |
constructor(address _turingCoinAddr, address _gambleChallenge) { | |
tngc = TuringCoin(_turingCoinAddr); | |
owner = msg.sender; | |
gambleChallenge = TuringGambleChance(_gambleChallenge); | |
fut_level = address(0); | |
} | |
function register(string memory _username) external { | |
require(already_registered[msg.sender] == false, "Usuario ya registrado"); | |
require(tngc.balanceOf(msg.sender) >= 250_000 * DECIMALS, "Lo siento. No tenes suficientes Turing Coins"); | |
usernameOf[msg.sender] = _username; | |
already_registered[msg.sender] = true; | |
} | |
function get_chance(uint256 n, string memory secret) external returns (bool) { | |
require(already_registered[msg.sender], "Usuario no registrado"); | |
require(balanceOf[msg.sender] == 0, "Ya tenes una chance"); | |
require(n > 0, "Solamente numeros positivos"); | |
require(keccak256(abi.encodePacked(secret)) != keccak256(bytes("TuringCTF")), "Secreto incorrecto"); | |
bool status = false; | |
//unchecked block, what could go wrong? | |
unchecked{ | |
if( (n +1) < 1){ | |
balanceOf[msg.sender]++; | |
status = true; | |
} | |
} | |
return status; | |
} | |
//gamble chance | |
function gamble_chance() external returns (bool) { | |
require(already_registered[msg.sender], "Usuario no registrado"); | |
require(balanceOf[msg.sender] > 0, "No tienes chances para apostar"); | |
balanceOf[msg.sender]++; | |
bool success = gambleChallenge.gamble(); | |
if(!success){ | |
balanceOf[msg.sender]--; | |
} | |
return success; | |
} | |
//function to change gamble function in case gamble is too easy | |
function change_gamble_function(address _gambleChallenge) external { | |
gambleChallenge = TuringGambleChance(_gambleChallenge); | |
emit newGambleFunction(msg.sender, _gambleChallenge); | |
} | |
//user our chances | |
function use_chances() external returns (bool){ | |
require(balanceOf[msg.sender] >= 5, "No tenes suficientes chances"); | |
//spend 5 chances | |
balanceOf[msg.sender] -= 5; | |
bool win_status; | |
//50 % chance | |
if((random() % 10) < 6){ | |
win_status = true; | |
emit newWinner(msg.sender, usernameOf[msg.sender]); | |
}else{ | |
win_status = false; | |
} | |
winners[msg.sender] = win_status; | |
return win_status; | |
} | |
//posibility to add level | |
function set_future_level(address _addr) external onlyOwner{ | |
require(_addr != address(0), "addr is null"); | |
fut_level = _addr; | |
} | |
//level completed, reward user | |
function ext_level_reward(address rewarded_addr) external{ | |
require(msg.sender == fut_level, "Can only be called from fut_level"); | |
balanceOf[rewarded_addr]++; | |
} | |
function is_winner(address _addr) external view returns (bool) { | |
return winners[_addr]; | |
} | |
function random() private view returns(uint){ | |
return uint(keccak256(abi.encodePacked(block.timestamp))); | |
} | |
} | |
contract TuringCTF{ | |
TuringCoin public tngc; | |
TuringLoan public flashLoan; | |
uint256 constant DECIMALS = 1; | |
TuringChallenge public challenge; | |
TuringGambleChance public gamble; | |
constructor() { | |
tngc = new TuringCoin(1_000_000); | |
flashLoan = new TuringLoan(address(tngc)); | |
tngc.transfer(address(flashLoan), 500_000 * DECIMALS); | |
gamble = new TuringGambleChance(); | |
challenge = new TuringChallenge(address(tngc), address(gamble)); | |
} | |
function turingCoin_address() external view returns (address){ | |
return address(tngc); | |
} | |
function turingLoan_address() external view returns (address){ | |
return address(flashLoan); | |
} | |
function turingChallenge_address() external view returns (address){ | |
return address(challenge); | |
} | |
function turingGambleChanceFunc_address() external view returns (address){ | |
return address(gamble); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment