Skip to content

Instantly share code, notes, and snippets.

@lpinilla
Created October 21, 2021 18:50
Show Gist options
  • Save lpinilla/a13cd48f9726a634813ccea89b1dcbbf to your computer and use it in GitHub Desktop.
Save lpinilla/a13cd48f9726a634813ccea89b1dcbbf to your computer and use it in GitHub Desktop.
TuringChallenge for Ekoparty 2021
//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