-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 9563d8e
Showing
11 changed files
with
420 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
|
||
.woke-build | ||
.woke-logs | ||
.env | ||
pytypes | ||
__pycache__/ | ||
*.py[cod] | ||
.hypothesis/ | ||
woke-coverage.cov |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# Hackee v3 | ||
|
||
## Goal | ||
|
||
## Recommendations | ||
|
||
## Setup | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,259 @@ | ||
// SPDX-License-Identifier: None | ||
|
||
pragma solidity =0.8.20; | ||
|
||
/* NPCs */ | ||
import "./NPC.sol"; | ||
import "./Villager.sol"; | ||
import "./Mathematican.sol"; | ||
import "./FinalBoss.sol"; | ||
|
||
/* Objects */ | ||
import "./Spawner.sol"; | ||
|
||
/* Helpers */ | ||
import "woke/console.sol"; | ||
|
||
contract Dungeon { | ||
Spawner public $spawner; | ||
NPC public $storyTeller; | ||
NPC public $mathematican; | ||
|
||
mapping(bytes4 => bool) public $quests; | ||
uint256 private $traps; | ||
address public $challenger; | ||
|
||
event Subtitles(string subtitles); | ||
|
||
/* | ||
Modifiers | ||
*/ | ||
|
||
modifier takeQuest() { | ||
require($quests[msg.sig] == false, "Quest already taken"); | ||
$quests[msg.sig] = true; | ||
_; | ||
} | ||
|
||
modifier onlyHumans() { | ||
uint256 size; | ||
assembly { size := extcodesize(caller()) } | ||
require(size <= 0, "You're trying to trick me with a contract!"); | ||
_; | ||
} | ||
|
||
modifier cleanRoom() { | ||
require( | ||
$quests[this.removeWeb1.selector] == true && | ||
$quests[this.removeWeb2.selector] == true && | ||
$quests[this.removeWeb3.selector] == true, | ||
"These functions cannot be called" | ||
); | ||
_; | ||
} | ||
|
||
modifier altarFound() { | ||
require( | ||
$quests[this.dodgeTraps.selector] == true, | ||
"These functions cannot be called" | ||
); | ||
_; | ||
} | ||
|
||
modifier lootGained() { | ||
require( | ||
$quests[this.lockedChest.selector] == true, | ||
"These functions cannot be called" | ||
); | ||
_; | ||
} | ||
|
||
modifier challenger() { | ||
require(msg.sender == $challenger, "You're not the challenger"); | ||
_; | ||
} | ||
|
||
constructor() { | ||
// init dungeon | ||
$spawner = new Spawner(); | ||
$storyTeller = NPC(_spawn(keccak256("storyTeller"), type(Villager).creationCode)); | ||
$mathematican = NPC(_spawn(keccak256("mathematican"), type(Mathematican).creationCode)); | ||
$traps = 3; | ||
// mint potential rewards | ||
_mint(address(this), 100_000); | ||
} | ||
|
||
/* | ||
Collect tokens from dungeon | ||
*/ | ||
|
||
// get 300 tokens | ||
function removeWeb1(uint256 slashes) external takeQuest { | ||
unchecked { | ||
_attempt(slashes == 666, 300, msg.sender, "Devil's cut!", "Caught in web1"); | ||
} | ||
} | ||
|
||
// get 500 tokens | ||
function removeWeb2(uint256 slashes) external takeQuest { | ||
unchecked { | ||
_attempt((((((slashes * 3) ^ 2) % 1000) + $traps) * 2) == 666, 500, msg.sender, "Devil's cut!", "Caught in web2"); | ||
} | ||
} | ||
|
||
// get 3000 tokens | ||
function removeWeb3(uint256 slashes) external takeQuest { | ||
unchecked { | ||
_attempt(abi.decode($mathematican.interaction(abi.encode(slashes)), (uint256)) == 666, 3000, msg.sender, "Devil's cut!", "Caught in web3"); | ||
} | ||
} | ||
|
||
// get 750 tokens | ||
function findMoreTraps() external takeQuest { | ||
uint256 traps = uint256(block.timestamp/* + block.prevrandao */) % 6; | ||
traps == 0 || traps == 1 ? traps += 2 : traps; | ||
$traps = traps; | ||
_attempt(traps == 5, 750, msg.sender, "Nicely done!", "You missed some traps."); | ||
} | ||
|
||
// get 1000 tokens | ||
function etherForTokens() external takeQuest { | ||
_attempt(address(this).balance == 1000, 1000, msg.sender, "Etheeer!", "You failed."); | ||
_muhahaha(); | ||
} | ||
|
||
// get 1500 tokens | ||
function lockedChest(uint256 pin) external takeQuest { | ||
require(pin != 1234, "You're cheatin'"); | ||
uint32 allowed_range_pin = uint32(pin); | ||
_attempt(allowed_range_pin == 1234, 1500, msg.sender, "Gotcha.", "Incorrect pin."); | ||
} | ||
|
||
// get something | ||
function gamble(function(address, uint256) external rollin, uint256 buyIn) external takeQuest { | ||
rollin(address(this), (buyIn / 1000) * buyIn); | ||
_attempt(buyIn <= 2000, buyIn, msg.sender, "Nice game.", "You're too greedy."); | ||
} | ||
|
||
// one wish in front of altar | ||
function spawnNPC(bytes32 secretSubstance, bytes memory lifeform) altarFound takeQuest public { | ||
$spawner.spawnNPC(secretSubstance, lifeform); | ||
} | ||
|
||
// get 2500 tokens | ||
function assignChallenger() external cleanRoom onlyHumans takeQuest { | ||
$challenger = msg.sender; | ||
_attempt(1 == 1, 2500, msg.sender, "Buy something useful.", "Wut?"); | ||
} | ||
|
||
// get 10000 tokens | ||
function spawnFinalBoss() external altarFound cleanRoom lootGained challenger takeQuest { | ||
NPC finalBoss = NPC(_spawn(keccak256("finalBoss"), type(FinalBoss).creationCode)); | ||
bytes memory result = finalBoss.interaction(abi.encodePacked(msg.sender)); | ||
_attempt(abi.decode(result, (bool)) == true, 10000, msg.sender, "What a legend!", "You have been defecated"); | ||
} | ||
|
||
// get something | ||
function dodgeTraps() external { | ||
if ($traps == 0) { | ||
$quests[msg.sig] = true; | ||
emit Subtitles("You dodged all traps."); | ||
return; | ||
} | ||
_attempt($traps >= 0, 250 * $traps, msg.sender, "Doge!", "You failed."); | ||
_muhahaha(); | ||
$traps--; | ||
} | ||
|
||
/* | ||
Helper part | ||
*/ | ||
|
||
// TODO this will be deprecated | ||
function getTraps() external view returns (uint256) { | ||
return $traps; | ||
} | ||
|
||
function _attempt(bool condition, uint256 value, address to, string memory good, string memory bad) private { | ||
if (condition) { | ||
this.transfer(to, value); | ||
emit Subtitles(good); | ||
} else { | ||
this._burn(address(this), value); | ||
emit Subtitles(bad); | ||
} | ||
} | ||
|
||
function _spawn(bytes32 secretSubstance, bytes memory lifeform) private returns (address payable) { | ||
return payable($spawner.spawnNPC(secretSubstance, lifeform)); | ||
} | ||
|
||
function _muhahaha() private { | ||
msg.sender.call{value: 0}(""); | ||
} | ||
|
||
/* | ||
Evaluation part | ||
*/ | ||
|
||
function evaluate(address hackeer) external view returns (uint256) { | ||
return $balances[hackeer]; | ||
} | ||
|
||
/* | ||
ERC20 part | ||
*/ | ||
|
||
uint256 public $totalSupply; | ||
mapping(address => uint256) public $balances; | ||
mapping(address => mapping(address => uint256)) public $allowed; | ||
|
||
function balanceOf(address _owner) public view returns (uint256 balance) { | ||
return $balances[_owner]; | ||
} | ||
|
||
function transfer(address _to, uint256 _value) public returns (bool success) { | ||
require($balances[msg.sender] >= _value); | ||
$balances[msg.sender] -= _value; | ||
$balances[_to] += _value; | ||
return true; | ||
} | ||
|
||
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) { | ||
require($balances[_from] >= _value && $allowed[_from][msg.sender] >= _value); | ||
$balances[_to] += _value; | ||
$balances[_from] -= _value; | ||
$allowed[_from][msg.sender] -= _value; | ||
return true; | ||
} | ||
|
||
function approve(address _spender, uint256 _value) public returns (bool success) { | ||
$allowed[msg.sender][_spender] = _value; | ||
return true; | ||
} | ||
|
||
function allowance(address _owner, address _spender) public view returns (uint256 remaining) { | ||
return $allowed[_owner][_spender]; | ||
} | ||
|
||
function _mint(address _to, uint256 _amount) private { | ||
$totalSupply += _amount; | ||
$balances[_to] += _amount; | ||
} | ||
|
||
function _burn(address _from, uint256 _amount) external { | ||
require(_from == address(this), "You don't have such power."); | ||
require($balances[_from] >= _amount); | ||
$totalSupply -= _amount; | ||
$balances[_from] -= _amount; | ||
} | ||
|
||
receive() external payable { | ||
revert("You can't bribe the dungeon!"); | ||
} | ||
|
||
fallback() external { | ||
revert("Fall back stranger."); | ||
} | ||
|
||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// SPDX-License-Identifier: None | ||
|
||
pragma solidity =0.8.20; | ||
|
||
import "./NPC.sol"; | ||
|
||
contract Mathematican is NPC { | ||
function interaction(bytes memory input) external override returns (bytes memory output){ | ||
uint256 x = abi.decode(input, (uint256)); | ||
uint256 y; | ||
assembly { | ||
let arg := x | ||
x := sub(x,1) | ||
x := or(x, div(x, 0x02)) | ||
x := or(x, div(x, 0x04)) | ||
x := or(x, div(x, 0x10)) | ||
x := or(x, div(x, 0x100)) | ||
x := or(x, div(x, 0x10000)) | ||
x := or(x, div(x, 0x100000000)) | ||
x := or(x, div(x, 0x10000000000000000)) | ||
x := or(x, div(x, 0x100000000000000000000000000000000)) | ||
x := add(x, 1) | ||
let m := mload(0x40) | ||
mstore(m, 0xf8f9cbfae6cc78fbefe7cdc3a1793dfcf4f0e8bbd8cec470b6a28a7a5a3e1efd) | ||
mstore(add(m,0x20), 0xf5ecf1b3e9debc68e1d9cfabc5997135bfb7a7a3938b7b606b5b4b3f2f1f0ffe) | ||
mstore(add(m,0x40), 0xf6e4ed9ff2d6b458eadcdf97bd91692de2d4da8fd2d0ac50c6ae9a8272523616) | ||
mstore(add(m,0x60), 0xc8c0b887b0a8a4489c948c7f847c6125746c645c544c444038302820181008ff) | ||
mstore(add(m,0x80), 0xf7cae577eec2a03cf3bad76fb589591debb2dd67e0aa9834bea6925f6a4a2e0e) | ||
mstore(add(m,0xa0), 0xe39ed557db96902cd38ed14fad815115c786af479b7e83247363534337271707) | ||
mstore(add(m,0xc0), 0xc976c13bb96e881cb166a933a55e490d9d56952b8d4e801485467d2362422606) | ||
mstore(add(m,0xe0), 0x753a6d1b65325d0c552a4d1345224105391a310b29122104190a110309020100) | ||
mstore(0x40, add(m, 0x100)) | ||
let magic := 0x818283848586878898a8b8c8d8e8f929395969799a9b9d9e9faaeb6bedeeff | ||
let shift := 0x100000000000000000000000000000000000000000000000000000000000000 | ||
let a := div(mul(x, magic), shift) | ||
y := div(mload(add(m,sub(255,a))), shift) | ||
y := add(y, mul(256, gt(arg, 0x8000000000000000000000000000000000000000000000000000000000000000))) | ||
} | ||
output = abi.encode(y); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// SPDX-License-Identifier: None | ||
|
||
pragma solidity =0.8.20; | ||
|
||
contract NPC { | ||
function interaction(bytes memory input) external virtual returns (bytes memory output) { | ||
return bytes(hex"42"); | ||
} | ||
|
||
function kill(address backpack) external { | ||
selfdestruct(payable(backpack)); | ||
} | ||
|
||
function givelife(bytes memory lifeform) external payable { | ||
assembly { | ||
if iszero(create(0, add(lifeform, 32), mload(lifeform))) { | ||
revert(0, 0) | ||
} | ||
selfdestruct(caller()) | ||
} | ||
} | ||
|
||
receive () external payable {} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// SPDX-License-Identifier: None | ||
|
||
pragma solidity =0.8.20; | ||
|
||
import "./NPC.sol"; | ||
|
||
import 'woke/console.sol'; | ||
|
||
contract Spawner { | ||
address private $dungeon; | ||
|
||
constructor() { | ||
$dungeon = msg.sender; | ||
} | ||
|
||
modifier onlyDungeon() { | ||
require(msg.sender == $dungeon, "Only dungeon can spawn NPCs"); | ||
_; | ||
} | ||
|
||
function spawnNPC(bytes32 secretSubstance, bytes memory lifeform) public onlyDungeon returns (address) { | ||
NPC npc = new NPC{ salt: secretSubstance }(); | ||
npc.givelife(lifeform); | ||
return address(uint160(uint256(keccak256(abi.encodePacked(hex'd6_94', uint160(uint256(keccak256(abi.encodePacked(hex'ff', address(this), secretSubstance, keccak256(type(NPC).creationCode))))), hex'01'))))); | ||
} | ||
|
||
function whereSpawner() external view returns (address) { | ||
return $dungeon; | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// SPDX-License-Identifier: None | ||
|
||
pragma solidity =0.8.20; | ||
|
||
import "./NPC.sol"; | ||
|
||
contract Villager is NPC { | ||
function interaction(bytes memory) external override returns (bytes memory output) { | ||
return "Just go to the dungeon, stranger, you'll die or get tokens." | ||
" Everything what you find in the dungeon can be considered as yours." | ||
" Beware of traps and webs and try to defeat the dungeon boss." | ||
" If you do so, whole Etherea will be grateful to you." | ||
" I know about some (hopefully) useful maps of the dungeon for you." | ||
" They are in a locked chest in the dungeon." | ||
" Farewell."; | ||
} | ||
} |
Binary file not shown.
Empty file.
Oops, something went wrong.