From 2d8e800231356baa074b4163d4167ce4c19e3d93 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 25 Aug 2023 11:12:42 +0700 Subject: [PATCH 1/4] add Vietnamese translation --- client/src/gamedata/ar/strings.json | 2 +- client/src/gamedata/en/strings.json | 1 + client/src/gamedata/es/strings.json | 1 + client/src/gamedata/fr/strings.json | 1 + client/src/gamedata/ja/strings.json | 1 + client/src/gamedata/pt_br/strings.json | 1 + client/src/gamedata/ru/strings.json | 1 + client/src/gamedata/tr/strings.json | 1 + .../vi/descriptions/levels/aliencodex.md | 7 ++ .../levels/aliencodex_complete.md | 5 + .../vi/descriptions/levels/coinflip.md | 5 + .../descriptions/levels/coinflip_complete.md | 6 + .../vi/descriptions/levels/delegate.md | 7 ++ .../descriptions/levels/delegate_complete.md | 5 + .../gamedata/vi/descriptions/levels/denial.md | 5 + .../vi/descriptions/levels/denial_complete.md | 12 ++ .../gamedata/vi/descriptions/levels/dex.md | 18 +++ .../gamedata/vi/descriptions/levels/dex2.md | 9 ++ .../vi/descriptions/levels/dex2_complete.md | 9 ++ .../vi/descriptions/levels/dex_complete.md | 58 +++++++++ .../descriptions/levels/doubleentrypoint.md | 10 ++ .../levels/doubleentrypoint_complete.md | 13 ++ .../vi/descriptions/levels/elevator.md | 5 + .../descriptions/levels/elevator_complete.md | 4 + .../vi/descriptions/levels/fallback.md | 12 ++ .../descriptions/levels/fallback_complete.md | 5 + .../vi/descriptions/levels/fallout.md | 5 + .../descriptions/levels/fallout_complete.md | 15 +++ .../gamedata/vi/descriptions/levels/force.md | 9 ++ .../vi/descriptions/levels/force_complete.md | 3 + .../vi/descriptions/levels/gatekeeper1.md | 5 + .../levels/gatekeeper1_complete.md | 1 + .../vi/descriptions/levels/gatekeeper2.md | 6 + .../levels/gatekeeper2_complete.md | 1 + .../vi/descriptions/levels/gatekeeper3.md | 6 + .../levels/gatekeeper3_complete.md | 1 + .../vi/descriptions/levels/goodsamaritan.md | 7 ++ .../levels/goodsamaritan_complete.md | 3 + .../vi/descriptions/levels/instances.md | 69 +++++++++++ .../descriptions/levels/instances_complete.md | 6 + .../gamedata/vi/descriptions/levels/king.md | 5 + .../vi/descriptions/levels/king_complete.md | 3 + .../vi/descriptions/levels/magicnum.md | 11 ++ .../descriptions/levels/magicnum_complete.md | 3 + .../vi/descriptions/levels/motorbike.md | 9 ++ .../descriptions/levels/motorbike_complete.md | 9 ++ .../vi/descriptions/levels/naughtcoin.md | 6 + .../levels/naughtcoin_complete.md | 1 + .../vi/descriptions/levels/preservation.md | 13 ++ .../levels/preservation_complete.md | 6 + .../vi/descriptions/levels/privacy.md | 11 ++ .../descriptions/levels/privacy_complete.md | 3 + .../vi/descriptions/levels/puzzle_wallet.md | 18 +++ .../levels/puzzle_wallet_complete.md | 7 ++ .../vi/descriptions/levels/recovery.md | 4 + .../descriptions/levels/recovery_complete.md | 10 ++ .../vi/descriptions/levels/reentrancy.md | 9 ++ .../levels/reentrancy_complete.md | 12 ++ .../gamedata/vi/descriptions/levels/shop.md | 5 + .../vi/descriptions/levels/shop_complete.md | 3 + .../gamedata/vi/descriptions/levels/switch.md | 4 + .../vi/descriptions/levels/switch_complete.md | 1 + .../vi/descriptions/levels/telephone.md | 5 + .../descriptions/levels/telephone_complete.md | 21 ++++ .../gamedata/vi/descriptions/levels/token.md | 7 ++ .../vi/descriptions/levels/token_complete.md | 12 ++ .../vi/descriptions/levels/unstoppable.md | 5 + .../gamedata/vi/descriptions/levels/vault.md | 1 + .../vi/descriptions/levels/vault_complete.md | 3 + client/src/gamedata/vi/strings.json | 113 ++++++++++++++++++ client/src/gamedata/zh_cn/strings.json | 7 +- client/src/gamedata/zh_tw/strings.json | 1 + 72 files changed, 665 insertions(+), 4 deletions(-) create mode 100644 client/src/gamedata/vi/descriptions/levels/aliencodex.md create mode 100644 client/src/gamedata/vi/descriptions/levels/aliencodex_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/coinflip.md create mode 100644 client/src/gamedata/vi/descriptions/levels/coinflip_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/delegate.md create mode 100644 client/src/gamedata/vi/descriptions/levels/delegate_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/denial.md create mode 100644 client/src/gamedata/vi/descriptions/levels/denial_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/dex.md create mode 100644 client/src/gamedata/vi/descriptions/levels/dex2.md create mode 100644 client/src/gamedata/vi/descriptions/levels/dex2_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/dex_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/doubleentrypoint.md create mode 100644 client/src/gamedata/vi/descriptions/levels/doubleentrypoint_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/elevator.md create mode 100644 client/src/gamedata/vi/descriptions/levels/elevator_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/fallback.md create mode 100644 client/src/gamedata/vi/descriptions/levels/fallback_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/fallout.md create mode 100644 client/src/gamedata/vi/descriptions/levels/fallout_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/force.md create mode 100644 client/src/gamedata/vi/descriptions/levels/force_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/gatekeeper1.md create mode 100644 client/src/gamedata/vi/descriptions/levels/gatekeeper1_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/gatekeeper2.md create mode 100644 client/src/gamedata/vi/descriptions/levels/gatekeeper2_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/gatekeeper3.md create mode 100644 client/src/gamedata/vi/descriptions/levels/gatekeeper3_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/goodsamaritan.md create mode 100644 client/src/gamedata/vi/descriptions/levels/goodsamaritan_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/instances.md create mode 100644 client/src/gamedata/vi/descriptions/levels/instances_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/king.md create mode 100644 client/src/gamedata/vi/descriptions/levels/king_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/magicnum.md create mode 100644 client/src/gamedata/vi/descriptions/levels/magicnum_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/motorbike.md create mode 100644 client/src/gamedata/vi/descriptions/levels/motorbike_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/naughtcoin.md create mode 100644 client/src/gamedata/vi/descriptions/levels/naughtcoin_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/preservation.md create mode 100644 client/src/gamedata/vi/descriptions/levels/preservation_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/privacy.md create mode 100644 client/src/gamedata/vi/descriptions/levels/privacy_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/puzzle_wallet.md create mode 100644 client/src/gamedata/vi/descriptions/levels/puzzle_wallet_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/recovery.md create mode 100644 client/src/gamedata/vi/descriptions/levels/recovery_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/reentrancy.md create mode 100644 client/src/gamedata/vi/descriptions/levels/reentrancy_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/shop.md create mode 100644 client/src/gamedata/vi/descriptions/levels/shop_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/switch.md create mode 100644 client/src/gamedata/vi/descriptions/levels/switch_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/telephone.md create mode 100644 client/src/gamedata/vi/descriptions/levels/telephone_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/token.md create mode 100644 client/src/gamedata/vi/descriptions/levels/token_complete.md create mode 100644 client/src/gamedata/vi/descriptions/levels/unstoppable.md create mode 100644 client/src/gamedata/vi/descriptions/levels/vault.md create mode 100644 client/src/gamedata/vi/descriptions/levels/vault_complete.md create mode 100644 client/src/gamedata/vi/strings.json diff --git a/client/src/gamedata/ar/strings.json b/client/src/gamedata/ar/strings.json index 16f79acfb..2130547d0 100644 --- a/client/src/gamedata/ar/strings.json +++ b/client/src/gamedata/ar/strings.json @@ -18,6 +18,7 @@ "chinese_traditional": "正體中文", "french": "Français", "russian": "Русский", + "vietnamese": "Vietnamese", "playNow": "العب الان!", "toggleNavigation": "تصفح", "levelCompleted": "انتهي المستوى!", @@ -110,5 +111,4 @@ "Languages": "اللغات", "PageNotFoundTitle": "خطأ 404 - الصفحة غير موجودة", "PageNotFoundText": "عفوًا! لا يمكن العثور على الصفحة التي تبحث عنها." - } diff --git a/client/src/gamedata/en/strings.json b/client/src/gamedata/en/strings.json index 331462fc4..9240a7e3b 100644 --- a/client/src/gamedata/en/strings.json +++ b/client/src/gamedata/en/strings.json @@ -18,6 +18,7 @@ "chinese_traditional": "正體中文", "french": "Français", "russian": "Русский", + "vietnamese": "Vietnamese", "playNow": "Play now!", "toggleNavigation": "Toggle navigation", "levelCompleted": "Level completed!", diff --git a/client/src/gamedata/es/strings.json b/client/src/gamedata/es/strings.json index 8b3f5bfe6..6acc6d9bb 100644 --- a/client/src/gamedata/es/strings.json +++ b/client/src/gamedata/es/strings.json @@ -18,6 +18,7 @@ "chinese_traditional": "正體中文", "french": "Français", "russian": "Русский", + "vietnamese": "Vietnamese", "playNow": "Juega ahora!", "toggleNavigation": "Despliega la navegación", "levelCompleted": "Nivel completado!", diff --git a/client/src/gamedata/fr/strings.json b/client/src/gamedata/fr/strings.json index 3fa13c08f..cabe080a9 100644 --- a/client/src/gamedata/fr/strings.json +++ b/client/src/gamedata/fr/strings.json @@ -18,6 +18,7 @@ "chinese_traditional": "正體中文", "french": "Français", "russian": "Русский", + "vietnamese": "Vietnamese", "playNow": "Jouer maintenant!", "toggleNavigation": "Basculer la navigation", "levelCompleted": "Niveau terminé!", diff --git a/client/src/gamedata/ja/strings.json b/client/src/gamedata/ja/strings.json index dac3bddd3..5c059d73e 100644 --- a/client/src/gamedata/ja/strings.json +++ b/client/src/gamedata/ja/strings.json @@ -18,6 +18,7 @@ "chinese_traditional": "正體中文", "french": "Français", "russian": "Русский", + "vietnamese": "Vietnamese", "playNow": "プレイ!", "toggleNavigation": "トグルナビゲーション", "levelCompleted": "レベル クリア!", diff --git a/client/src/gamedata/pt_br/strings.json b/client/src/gamedata/pt_br/strings.json index dd74eebcd..371a44f18 100644 --- a/client/src/gamedata/pt_br/strings.json +++ b/client/src/gamedata/pt_br/strings.json @@ -18,6 +18,7 @@ "chinese_traditional": "正體中文", "french": "Français", "russian": "Русский", + "vietnamese": "Vietnamese", "playNow": "Jogue agora!", "toggleNavigation": "Exibir a navegação", "levelCompleted": "Nível completado!", diff --git a/client/src/gamedata/ru/strings.json b/client/src/gamedata/ru/strings.json index 74c6d6500..2cfcf9718 100644 --- a/client/src/gamedata/ru/strings.json +++ b/client/src/gamedata/ru/strings.json @@ -19,6 +19,7 @@ "french": "Français", "russian": "Русский", "playNow": "Играть!", + "vietnamese": "Vietnamese", "toggleNavigation": "Показать или скрыть панель навигации", "levelCompleted": "Уровень пройден!", "sources": "Исходный код", diff --git a/client/src/gamedata/tr/strings.json b/client/src/gamedata/tr/strings.json index 56eed471c..5bc790a16 100644 --- a/client/src/gamedata/tr/strings.json +++ b/client/src/gamedata/tr/strings.json @@ -18,6 +18,7 @@ "chinese_traditional": "正體中文", "french": "Français", "russian": "Русский", + "vietnamese": "Vietnamese", "playNow": "Şimdi oyna!", "toggleNavigation": "Gezinmeyi Aç/Kapa", "levelCompleted": "Seviye tamamlandı!", diff --git a/client/src/gamedata/vi/descriptions/levels/aliencodex.md b/client/src/gamedata/vi/descriptions/levels/aliencodex.md new file mode 100644 index 000000000..061e47c5d --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/aliencodex.md @@ -0,0 +1,7 @@ +You've uncovered an Alien contract. Claim ownership to complete the level. + +  +Things that might help +* Understanding how array storage works +* Understanding [ABI specifications](https://solidity.readthedocs.io/en/v0.4.21/abi-spec.html) +* Using a very `underhanded` approach diff --git a/client/src/gamedata/vi/descriptions/levels/aliencodex_complete.md b/client/src/gamedata/vi/descriptions/levels/aliencodex_complete.md new file mode 100644 index 000000000..99479e714 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/aliencodex_complete.md @@ -0,0 +1,5 @@ +This level exploits the fact that the EVM doesn't validate an array's ABI-encoded length vs its actual payload. + +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. + +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) \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/coinflip.md b/client/src/gamedata/vi/descriptions/levels/coinflip.md new file mode 100644 index 000000000..64a2d9bc0 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/coinflip.md @@ -0,0 +1,5 @@ +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. + +  +Things that might help +* See the ["?"](https://ethernaut.openzeppelin.com/help) page above in the top right corner menu, section "Beyond the console" \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/coinflip_complete.md b/client/src/gamedata/vi/descriptions/levels/coinflip_complete.md new file mode 100644 index 000000000..47710b6d5 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/coinflip_complete.md @@ -0,0 +1,6 @@ +Generating random numbers in solidity can be tricky. There currently isn't a native way to generate them, and everything you use in smart contracts is publicly visible, including the local variables and state variables marked as private. Miners also have control over things like blockhashes, timestamps, and whether to include certain transactions - which allows them to bias these values in their favor. + +To get cryptographically proven random numbers, you can use [Chainlink VRF](https://docs.chain.link/docs/get-a-random-number), which uses an oracle, the LINK token, and an on-chain contract to verify that the number is truly random. + +Some other options include using Bitcoin block headers (verified through [BTC Relay](http://btcrelay.org)), [RANDAO](https://github.com/randao/randao), or [Oraclize](http://www.oraclize.it/)). + diff --git a/client/src/gamedata/vi/descriptions/levels/delegate.md b/client/src/gamedata/vi/descriptions/levels/delegate.md new file mode 100644 index 000000000..7a8fed34a --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/delegate.md @@ -0,0 +1,7 @@ +The goal of this level is for you to claim ownership of the instance you are given. + +  +Things that might help +* 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. +* Fallback methods +* Method ids diff --git a/client/src/gamedata/vi/descriptions/levels/delegate_complete.md b/client/src/gamedata/vi/descriptions/levels/delegate_complete.md new file mode 100644 index 000000000..42e2f87ef --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/delegate_complete.md @@ -0,0 +1,5 @@ +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. + + +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. + diff --git a/client/src/gamedata/vi/descriptions/levels/denial.md b/client/src/gamedata/vi/descriptions/levels/denial.md new file mode 100644 index 000000000..330d3e0ff --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/denial.md @@ -0,0 +1,5 @@ +This is a simple wallet that drips funds over time. You can withdraw the funds +slowly by becoming a withdrawing partner. + +If you can deny the owner from withdrawing funds when they call `withdraw()` +(whilst the contract still has funds, and the transaction is of 1M gas or less) you will win this level. diff --git a/client/src/gamedata/vi/descriptions/levels/denial_complete.md b/client/src/gamedata/vi/descriptions/levels/denial_complete.md new file mode 100644 index 000000000..43970a1c7 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/denial_complete.md @@ -0,0 +1,12 @@ +This level demonstrates that external calls to unknown contracts can still +create denial of service attack vectors if a fixed amount of gas is not +specified. + +If you are using a low level `call` to continue executing in the event an external call reverts, ensure that you specify a fixed gas stipend. For example `call.gas(100000).value()`. + +Typically one should follow the [checks-effects-interactions](http://solidity.readthedocs.io/en/latest/security-considerations.html#use-the-checks-effects-interactions-pattern) pattern to avoid reentrancy attacks, there can be other circumstances (such as multiple external calls at the end of a function) where issues such as this can arise. + +*Note*: An external `CALL` can use at most 63/64 of the gas currently available +at the time of the `CALL`. Thus, depending on how much gas is required to +complete a transaction, a transaction of sufficiently high gas (i.e. one such +that 1/64 of the gas is capable of completing the remaining opcodes in the parent call) can be used to mitigate this particular attack. \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/dex.md b/client/src/gamedata/vi/descriptions/levels/dex.md new file mode 100644 index 000000000..3abcb1d22 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/dex.md @@ -0,0 +1,18 @@ +The goal of this level is for you to hack the basic [DEX](https://en.wikipedia.org/wiki/Decentralized_exchange) contract below and steal the funds by price manipulation. + +You will start with 10 tokens of `token1` and 10 of `token2`. The DEX contract starts with 100 of each token. + +You will be successful in this level if you manage to drain all of at least 1 of the 2 tokens from the contract, and allow the contract to report a "bad" price of the assets. + +  +### Quick note +Normally, when you make a swap with an ERC20 token, you have to `approve` the contract to spend your tokens for you. To keep with the syntax of the game, we've just added the `approve` method to the contract itself. So feel free to use `contract.approve(contract.address, )` instead of calling the tokens directly, and it will automatically approve spending the two tokens by the desired amount. Feel free to ignore the `SwappableToken` contract otherwise. + +  +Things that might help: +* How is the price of the token calculated? +* How does the `swap` method work? +* How do you `approve` a transaction of an ERC20? +* Theres more than one way to interact with a contract! +* Remix might help +* What does "At Address" do? diff --git a/client/src/gamedata/vi/descriptions/levels/dex2.md b/client/src/gamedata/vi/descriptions/levels/dex2.md new file mode 100644 index 000000000..7a4a2a56d --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/dex2.md @@ -0,0 +1,9 @@ +This level will ask you to break `DexTwo`, a subtlely modified `Dex` contract from the previous level, in a different way. + +You need to drain all balances of token1 and token2 from the `DexTwo` contract to succeed in this level. + +You will still start with 10 tokens of `token1` and 10 of `token2`. The DEX contract still starts with 100 of each token. + +  +Things that might help: +* How has the `swap` method been modified? diff --git a/client/src/gamedata/vi/descriptions/levels/dex2_complete.md b/client/src/gamedata/vi/descriptions/levels/dex2_complete.md new file mode 100644 index 000000000..64cc56917 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/dex2_complete.md @@ -0,0 +1,9 @@ +As we've repeatedly seen, interaction between contracts can be a source of unexpected behavior. + +Just because a contract claims to implement the [ERC20 spec](https://eips.ethereum.org/EIPS/eip-20) does not mean it's trust worthy. + +Some tokens deviate from the ERC20 spec by not returning a boolean value from their `transfer` methods. See [Missing return value bug - At least 130 tokens affected](https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca). + +Other ERC20 tokens, especially those designed by adversaries could behave more maliciously. + +If you design a DEX where anyone could list their own tokens without the permission of a central authority, then the correctness of the DEX could depend on the interaction of the DEX contract and the token contracts being traded. diff --git a/client/src/gamedata/vi/descriptions/levels/dex_complete.md b/client/src/gamedata/vi/descriptions/levels/dex_complete.md new file mode 100644 index 000000000..a9af3062f --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/dex_complete.md @@ -0,0 +1,58 @@ +The integer math portion aside, getting prices or any sort of data from any single source is a massive attack vector in smart contracts. + +You can clearly see from this example, that someone with a lot of capital could manipulate the price in one fell swoop, and cause any applications relying on it to use the the wrong price. + +The exchange itself is decentralized, but the price of the asset is centralized, since it comes from 1 dex. However, if we were to consider tokens that represent actual assets rather than fictitious ones, most of them would have exchange pairs in several dexes and networks. This would decrease the effect on the asset's price in case a specific dex is targeted by an attack like this. + +[Oracles](https://betterprogramming.pub/what-is-a-blockchain-oracle-f5ccab8dbd72?source=friends_link&sk=d921a38466df8a9176ed8dd767d8c77d) are used to get data into and out of smart contracts. + +[Chainlink Data Feeds](https://docs.chain.link/docs/get-the-latest-price) are a secure, reliable, way to get decentralized data into your smart contracts. They have a vast library of many different sources, and also offer [secure randomness](https://docs.chain.link/docs/chainlink-vrf), ability to make [any API call](https://docs.chain.link/docs/make-a-http-get-request), [modular oracle network creation](https://docs.chain.link/docs/architecture-decentralized-model), [upkeep, actions, and maintainance](https://docs.chain.link/docs/kovan-keeper-network-beta), and unlimited customization. + +[Uniswap TWAP Oracles](https://docs.uniswap.org/contracts/v2/concepts/core-concepts/oracles) relies on a time weighted price model called [TWAP](https://en.wikipedia.org/wiki/Time-weighted_average_price#). While the design can be attractive, this protocol heavily depends on the liquidity of the DEX protocol, and if this is too low, prices can be easily manipulated. + + +Here is an example of getting the price of Bitcoin in USD from a Chainlink data feed (on the Sepolia testnet): + +``` +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.7; + +import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; + +contract PriceConsumerV3 { + AggregatorV3Interface internal priceFeed; + + /** + * Network: Sepolia + * Aggregator: BTC/USD + * Address: 0x1b44F3514812d835EB1BDB0acB33d3fA3351Ee43 + */ + constructor() { + priceFeed = AggregatorV3Interface( + 0x1b44F3514812d835EB1BDB0acB33d3fA3351Ee43 + ); + } + + /** + * Returns the latest price. + */ + function getLatestPrice() public view returns (int) { + // prettier-ignore + ( + /* uint80 roundID */, + int price, + /*uint startedAt*/, + /*uint timeStamp*/, + /*uint80 answeredInRound*/ + ) = priceFeed.latestRoundData(); + return price; + } +} + +``` +[Try it on Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/PriceFeeds/PriceConsumerV3.sol) + +Check the Chainlink feed [page](https://data.chain.link/ethereum/mainnet/crypto-usd/btc-usd) to see that the price of Bitcoin is queried from up to 31 different sources. + +You can check also, the [list](https://docs.chain.link/data-feeds/price-feeds/addresses/) all Chainlink price feeds addresses. + diff --git a/client/src/gamedata/vi/descriptions/levels/doubleentrypoint.md b/client/src/gamedata/vi/descriptions/levels/doubleentrypoint.md new file mode 100644 index 000000000..4cadf9de9 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/doubleentrypoint.md @@ -0,0 +1,10 @@ +This level features a `CryptoVault` with special functionality, the `sweepToken` function. This is a common function used to retrieve tokens stuck in a contract. The `CryptoVault` operates with an `underlying` token that can't be swept, as it is an important core logic component of the `CryptoVault`. Any other tokens can be swept. + +The underlying token is an instance of the DET token implemented in the `DoubleEntryPoint` contract definition and the `CryptoVault` holds 100 units of it. Additionally the `CryptoVault` also holds 100 of `LegacyToken LGT`. + +In this level you should figure out where the bug is in `CryptoVault` and protect it from being drained out of tokens. + +The contract features a `Forta` contract where any user can register its own `detection bot` contract. Forta is a decentralized, community-based monitoring network to detect threats and anomalies on DeFi, NFT, governance, bridges and other Web3 systems as quickly as possible. Your job is to implement a `detection bot` and register it in the `Forta` contract. The bot's implementation will need to raise correct alerts to prevent potential attacks or bug exploits. + +Things that might help: +- How does a double entry point work for a token contract? diff --git a/client/src/gamedata/vi/descriptions/levels/doubleentrypoint_complete.md b/client/src/gamedata/vi/descriptions/levels/doubleentrypoint_complete.md new file mode 100644 index 000000000..5137f9b31 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/doubleentrypoint_complete.md @@ -0,0 +1,13 @@ +Congratulations! + +This is the first experience you have with a [Forta bot](https://docs.forta.network/en/latest/). + +Forta comprises a decentralized network of independent node operators who scan all transactions and block-by-block state changes for outlier transactions and threats. When an issue is detected, node operators send alerts to subscribers of potential risks, which enables them to take action. + +The presented example is just for educational purpose since Forta bot is not modeled into smart contracts. In Forta, a bot is a code script to detect specific conditions or events, but when an alert is emitted it does not trigger automatic actions - at least not yet. In this level, the bot's alert effectively trigger a revert in the transaction, deviating from the intended Forta's bot design. + +Detection bots heavily depends on contract's final implementations and some might be upgradeable and break bot's integrations, but to mitigate that you can even create a specific bot to look for contract upgrades and react to it. Learn how to do it [here](https://docs.forta.network/en/latest/quickstart/). + +You have also passed through a recent security issue that has been uncovered during OpenZeppelin's latest [collaboration with Compound protocol](https://compound.finance/governance/proposals/76). + +Having tokens that present a double entry point is a non-trivial pattern that might affect many protocols. This is because it is commonly assumed to have one contract per token. But it was not the case this time :) You can read the entire details of what happened [here](https://blog.openzeppelin.com/compound-tusd-integration-issue-retrospective/). diff --git a/client/src/gamedata/vi/descriptions/levels/elevator.md b/client/src/gamedata/vi/descriptions/levels/elevator.md new file mode 100644 index 000000000..b6fda6f57 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/elevator.md @@ -0,0 +1,5 @@ +This elevator won't let you reach the top of your building. Right? + +##### Things that might help: +* Sometimes solidity is not good at keeping promises. +* This `Elevator` expects to be used from a `Building`. \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/elevator_complete.md b/client/src/gamedata/vi/descriptions/levels/elevator_complete.md new file mode 100644 index 000000000..3d3f059b8 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/elevator_complete.md @@ -0,0 +1,4 @@ +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. +Make sure you read [Solidity's documentation](http://solidity.readthedocs.io/en/develop/contracts.html#view-functions) and learn its caveats. + +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()`. \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/fallback.md b/client/src/gamedata/vi/descriptions/levels/fallback.md new file mode 100644 index 000000000..d80e7e8cb --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/fallback.md @@ -0,0 +1,12 @@ +Look carefully at the contract's code below. + +You will beat this level if +1) you claim ownership of the contract +2) you reduce its balance to 0 + +  +Things that might help +* How to send ether when interacting with an ABI +* How to send ether outside of the ABI +* Converting to and from wei/ether units (see `help()` command) +* Fallback methods diff --git a/client/src/gamedata/vi/descriptions/levels/fallback_complete.md b/client/src/gamedata/vi/descriptions/levels/fallback_complete.md new file mode 100644 index 000000000..941136c47 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/fallback_complete.md @@ -0,0 +1,5 @@ +You know the basics of how ether goes in and out of contracts, including the usage of the fallback method. + +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. + +Move on to the next level when you're ready! diff --git a/client/src/gamedata/vi/descriptions/levels/fallout.md b/client/src/gamedata/vi/descriptions/levels/fallout.md new file mode 100644 index 000000000..4063c71dc --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/fallout.md @@ -0,0 +1,5 @@ +Claim ownership of the contract below to complete this level. + +  +Things that might help +* Solidity Remix IDE diff --git a/client/src/gamedata/vi/descriptions/levels/fallout_complete.md b/client/src/gamedata/vi/descriptions/levels/fallout_complete.md new file mode 100644 index 000000000..ebbfbdbe6 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/fallout_complete.md @@ -0,0 +1,15 @@ +That was silly wasn't it? Real world contracts must be much more secure than this and so must it be much harder to hack them right? + +Well... Not quite. + +The story of Rubixi is a very well known case in the Ethereum ecosystem. The company changed its name from 'Dynamic Pyramid' to 'Rubixi' but somehow they didn't rename the constructor method of its contract: + +``` +contract Rubixi { + address private owner; + function DynamicPyramid() { owner = msg.sender; } + function collectAllFees() { owner.transfer(this.balance) } + ... +``` + +This allowed the attacker to call the old constructor and claim ownership of the contract, and steal some funds. Yep. Big mistakes can be made in smartcontractland. diff --git a/client/src/gamedata/vi/descriptions/levels/force.md b/client/src/gamedata/vi/descriptions/levels/force.md new file mode 100644 index 000000000..896868f23 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/force.md @@ -0,0 +1,9 @@ +Some contracts will simply not take your money `¯\_(ツ)_/¯` + +The goal of this level is to make the balance of the contract greater than zero. + +  +Things that might help: +* Fallback methods +* Sometimes the best way to attack a contract is with another contract. +* See the ["?"](https://ethernaut.openzeppelin.com/help) page above, section "Beyond the console" diff --git a/client/src/gamedata/vi/descriptions/levels/force_complete.md b/client/src/gamedata/vi/descriptions/levels/force_complete.md new file mode 100644 index 000000000..e70b2366c --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/force_complete.md @@ -0,0 +1,3 @@ +In solidity, for a contract to be able to receive ether, the fallback function must be marked `payable`. + +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. diff --git a/client/src/gamedata/vi/descriptions/levels/gatekeeper1.md b/client/src/gamedata/vi/descriptions/levels/gatekeeper1.md new file mode 100644 index 000000000..68e521bb2 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/gatekeeper1.md @@ -0,0 +1,5 @@ +Make it past the gatekeeper and register as an entrant to pass this level. + +##### Things that might help: +* Remember what you've learned from the Telephone and Token levels. +* You can learn more about the special function `gasleft()`, in Solidity's documentation (see [here](https://docs.soliditylang.org/en/v0.8.3/units-and-global-variables.html) and [here](https://docs.soliditylang.org/en/v0.8.3/control-structures.html#external-function-calls)). diff --git a/client/src/gamedata/vi/descriptions/levels/gatekeeper1_complete.md b/client/src/gamedata/vi/descriptions/levels/gatekeeper1_complete.md new file mode 100644 index 000000000..3b24cfaff --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/gatekeeper1_complete.md @@ -0,0 +1 @@ +Well done! Next, try your hand with the second gatekeeper... \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/gatekeeper2.md b/client/src/gamedata/vi/descriptions/levels/gatekeeper2.md new file mode 100644 index 000000000..5f7acfc64 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/gatekeeper2.md @@ -0,0 +1,6 @@ +This gatekeeper introduces a few new challenges. Register as an entrant to pass this level. + +##### Things that might help: +* Remember what you've learned from getting past the first gatekeeper - the first gate is the same. +* The `assembly` keyword in the second gate allows a contract to access functionality that is not native to vanilla Solidity. See [here](http://solidity.readthedocs.io/en/v0.4.23/assembly.html) for more information. The `extcodesize` call in this gate will get the size of a contract's code at a given address - you can learn more about how and when this is set in section 7 of the [yellow paper](https://ethereum.github.io/yellowpaper/paper.pdf). +* The `^` character in the third gate is a bitwise operation (XOR), and is used here to apply another common bitwise operation (see [here](http://solidity.readthedocs.io/en/v0.4.23/miscellaneous.html#cheatsheet)). The Coin Flip level is also a good place to start when approaching this challenge. \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/gatekeeper2_complete.md b/client/src/gamedata/vi/descriptions/levels/gatekeeper2_complete.md new file mode 100644 index 000000000..f1fa92bc6 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/gatekeeper2_complete.md @@ -0,0 +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). \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/gatekeeper3.md b/client/src/gamedata/vi/descriptions/levels/gatekeeper3.md new file mode 100644 index 000000000..e58998e60 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/gatekeeper3.md @@ -0,0 +1,6 @@ +Cope with gates and become an entrant. + +##### Things that might help: +* Recall return values of low-level functions. +* Be attentive with semantic. +* Refresh how storage works in Ethereum. diff --git a/client/src/gamedata/vi/descriptions/levels/gatekeeper3_complete.md b/client/src/gamedata/vi/descriptions/levels/gatekeeper3_complete.md new file mode 100644 index 000000000..e57bd7eb6 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/gatekeeper3_complete.md @@ -0,0 +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). \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/goodsamaritan.md b/client/src/gamedata/vi/descriptions/levels/goodsamaritan.md new file mode 100644 index 000000000..6035a7d30 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/goodsamaritan.md @@ -0,0 +1,7 @@ +This instance represents a Good Samaritan that is wealthy and ready to donate some coins to anyone requesting it. + +Would you be able to drain all the balance from his Wallet? + +Things that might help: + +- [Solidity Custom Errors](https://blog.soliditylang.org/2021/04/21/custom-errors/) \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/goodsamaritan_complete.md b/client/src/gamedata/vi/descriptions/levels/goodsamaritan_complete.md new file mode 100644 index 000000000..f154ee434 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/goodsamaritan_complete.md @@ -0,0 +1,3 @@ +Congratulations! + +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. diff --git a/client/src/gamedata/vi/descriptions/levels/instances.md b/client/src/gamedata/vi/descriptions/levels/instances.md new file mode 100644 index 000000000..796a20877 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/instances.md @@ -0,0 +1,69 @@ +Cấp độ này sẽ hướng dẫn bạn những điều cơ bản về cách chơi trò chơi. + +  +#### 1. Thiết lập MetaMask +Nếu bạn chưa có thì hãy cài đặt [tiện ích mở rộng trình duyệt MetaMask](https://metamask.io/) (trong Chrome, Firefox, Brave hoặc Opera trên máy tính để bàn của bạn). +Thiết lập ví của tiện ích mở rộng và sử dụng bộ chọn mạng để trỏ đến mạng ưa thích ở phía trên bên trái giao diện của tiện ích mở rộng. Ngoài ra, bạn có thể sử dụng nút UI để chuyển đổi giữa các mạng. Nếu bạn chọn mạng không được hỗ trợ, trò chơi sẽ thông báo cho bạn và đưa bạn đến mạng thử nghiệm Sepolia mặc định. + +#### 2. Mở bảng điều khiển của trình duyệt +Mở bảng điều khiển của trình duyệt của bạn: `Tools > Developer Tools`. + +Bạn sẽ thấy một vài thông báo từ trò chơi. Một trong số họ sẽ nêu địa chỉ người chơi của bạn. Điều này sẽ rất quan trọng trong trò chơi! Bạn luôn có thể xem địa chỉ người chơi của mình bằng cách nhập lệnh sau: + +`player` + +Hãy để ý đến các cảnh báo và lỗi vì chúng có thể cung cấp thông tin quan trọng trong quá trình chơi trò chơi. + +#### 3. Sử dụng trợ giúp của bảng điều khiển + +Bạn cũng có thể xem số dư ether hiện tại của mình bằng cách nhập: + +`getBalance(player)` + +###### LƯU Ý: Mở rộng lời hứa để xem giá trị thực tế, ngay cả khi nó ghi "đang chờ xử lý". Nếu đang sử dụng Chrome v62, bạn có thể sử dụng `await getBalance(player)` để có trải nghiệm bảng điều khiển rõ ràng hơn. + +Tuyệt vời! Để xem bạn có những chức năng tiện ích nào khác trong loại bảng điều khiển: + +`help()` + +Những thứ này sẽ cực kỳ tiện dụng trong quá trình chơi game. + +#### 4. Hợp đồng ethernaut +Nhập lệnh sau vào bảng điều khiển: + +`ethernaut` + +Đây là hợp đồng thông minh chính của trò chơi. Bạn không cần phải tương tác trực tiếp với nó thông qua bảng điều khiển (vì ứng dụng này sẽ làm điều đó cho bạn) nhưng bạn có thể làm điều đó nếu muốn. Chơi đùa với đối tượng này bây giờ là một cách tuyệt vời để tìm hiểu cách tương tác với các hợp đồng thông minh khác của trò chơi. + +Hãy tiếp tục và mở rộng đối tượng ethernaut để xem có gì bên trong. + +#### 5. Tương tác với ABI +`ethernaut` là một đối tượng `TruffleContract` bao bọc hợp đồng `Ethernaut.sol` đã được triển khai trên blockchain. + +Trong số những thứ khác, ABI của hợp đồng tiết lộ tất cả các phương thức công khai của `Ethernaut.sol`, chẳng hạn như `chủ sở hữu`. Nhập lệnh sau đây chẳng hạn: + +`ethernaut.owner()` hoặc `await ethernaut.owner()` nếu bạn đang sử dụng Chrome v62. + +Bạn có thể xem chủ sở hữu của hợp đồng ethernaut là ai. + +#### 6. Nhận ether thử nghiệm +Để chơi trò chơi, bạn sẽ cần ether thử nghiệm. Cách dễ nhất để nhận một số ether testnet là thông qua một vòi hợp lệ cho mạng bạn đã chọn. + +Khi bạn thấy một số xu trong số dư của mình, hãy chuyển sang bước tiếp theo. + +#### 7. Lấy một phiên bản cấp độ +Khi chơi một cấp độ, bạn không tương tác trực tiếp với hợp đồng ethernaut. Thay vào đó, bạn yêu cầu nó tạo một **phiên bản cấp độ** cho bạn. Để làm như vậy, hãy nhấp vào nút "Nhận phiên bản mới" ở cuối trang. Hãy làm điều đó ngay bây giờ và quay lại! + +Bạn sẽ được MetaMask nhắc nhở ủy quyền giao dịch. Làm như vậy và bạn sẽ thấy một số thông báo trong bảng điều khiển. Lưu ý rằng quá trình này đang triển khai một hợp đồng mới trong chuỗi khối và có thể mất vài giây, vì vậy hãy kiên nhẫn khi yêu cầu các phiên bản cấp mới! + +#### 8. Kiểm tra hợp đồng +Giống như bạn đã làm với hợp đồng ethernaut, bạn có thể kiểm tra ABI của hợp đồng này thông qua bảng điều khiển bằng cách sử dụng biến `hợp đồng`. + +#### 9. Tương tác với hợp đồng để hoàn thành cấp độ +Hãy xem phương thức thông tin của cấp độ `contract.info()` hoặc `await Contract.info()` nếu bạn đang sử dụng Chrome v62. +Bạn nên có tất cả những gì bạn cần để hoàn thành cấp độ trong hợp đồng. +Khi bạn biết mình đã hoàn thành cấp độ, hãy gửi hợp đồng bằng nút gửi ở cuối trang. +Thao tác này sẽ gửi phiên bản của bạn trở lại ethernaut, điều này sẽ xác định xem bạn đã hoàn thành nó chưa. + + +##### Mẹo: Đừng quên rằng bạn luôn có thể xem ABI của hợp đồng! diff --git a/client/src/gamedata/vi/descriptions/levels/instances_complete.md b/client/src/gamedata/vi/descriptions/levels/instances_complete.md new file mode 100644 index 000000000..d65b9d350 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/instances_complete.md @@ -0,0 +1,6 @@ +Chúc mừng! Bạn đã hoàn thành phần hướng dẫn. +Hãy xem mã Solidity cho hợp đồng bạn vừa tương tác bên dưới. + +Bây giờ bạn đã sẵn sàng để hoàn thành trò chơi và tiếp theo, bạn sẽ phải tự làm một mình. + +Chúc may mắn!! diff --git a/client/src/gamedata/vi/descriptions/levels/king.md b/client/src/gamedata/vi/descriptions/levels/king.md new file mode 100644 index 000000000..2a93f20fa --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/king.md @@ -0,0 +1,5 @@ +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 + +Such a fun game. Your goal is to break it. + +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. diff --git a/client/src/gamedata/vi/descriptions/levels/king_complete.md b/client/src/gamedata/vi/descriptions/levels/king_complete.md new file mode 100644 index 000000000..f040a0689 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/king_complete.md @@ -0,0 +1,3 @@ +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. + +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). diff --git a/client/src/gamedata/vi/descriptions/levels/magicnum.md b/client/src/gamedata/vi/descriptions/levels/magicnum.md new file mode 100644 index 000000000..9e7374f82 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/magicnum.md @@ -0,0 +1,11 @@ +To solve this level, you only need to provide the Ethernaut with a `Solver`, a contract that responds to `whatIsTheMeaningOfLife()` with the right number. + +Easy right? +Well... there's a catch. + +The solver's code needs to be really tiny. Really reaaaaaallly tiny. Like freakin' really really itty-bitty tiny: 10 opcodes at most. + +Hint: Perhaps its time to leave the comfort of the Solidity compiler momentarily, and build this one by hand O_o. +That's right: Raw EVM bytecode. + +Good luck! diff --git a/client/src/gamedata/vi/descriptions/levels/magicnum_complete.md b/client/src/gamedata/vi/descriptions/levels/magicnum_complete.md new file mode 100644 index 000000000..20503aac2 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/magicnum_complete.md @@ -0,0 +1,3 @@ +Congratulations! If you solved this level, consider yourself a Master of the Universe. + +Go ahead and pierce a random object in the room with your Magnum look. Now, try to move it from afar; Your telekinesis habilities might have just started working. diff --git a/client/src/gamedata/vi/descriptions/levels/motorbike.md b/client/src/gamedata/vi/descriptions/levels/motorbike.md new file mode 100644 index 000000000..3335a510a --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/motorbike.md @@ -0,0 +1,9 @@ +Ethernaut's motorbike has a brand new upgradeable engine design. + +Would you be able to `selfdestruct` its engine and make the motorbike unusable ? + +Things that might help: + +- [EIP-1967](https://eips.ethereum.org/EIPS/eip-1967) +- [UUPS](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786) upgradeable pattern +- [Initializable](https://github.com/OpenZeppelin/openzeppelin-upgrades/blob/master/packages/core/contracts/Initializable.sol) contract \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/motorbike_complete.md b/client/src/gamedata/vi/descriptions/levels/motorbike_complete.md new file mode 100644 index 000000000..741035dea --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/motorbike_complete.md @@ -0,0 +1,9 @@ +The advantage of following an UUPS pattern is to have very minimal proxy to be deployed. The proxy acts as storage layer so any state modification in the implementation contract normally doesn't produce side effects to systems using it, since only the logic is used through delegatecalls. + +This doesn't mean that you shouldn't watch out for vulnerabilities that can be exploited if we leave an implementation contract uninitialized. + +This was a slightly simplified version of what has really been discovered after months of the release of UUPS pattern. + +Takeways: never leave implementation contracts uninitialized ;) + +If you're interested in what happened, read more [here](https://forum.openzeppelin.com/t/uupsupgradeable-vulnerability-post-mortem/15680). \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/naughtcoin.md b/client/src/gamedata/vi/descriptions/levels/naughtcoin.md new file mode 100644 index 000000000..d4f680dca --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/naughtcoin.md @@ -0,0 +1,6 @@ +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. + +  +Things that might help +* The [ERC20](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) Spec +* The [OpenZeppelin](https://github.com/OpenZeppelin/zeppelin-solidity/tree/master/contracts) codebase diff --git a/client/src/gamedata/vi/descriptions/levels/naughtcoin_complete.md b/client/src/gamedata/vi/descriptions/levels/naughtcoin_complete.md new file mode 100644 index 000000000..c5d39755b --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/naughtcoin_complete.md @@ -0,0 +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. \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/preservation.md b/client/src/gamedata/vi/descriptions/levels/preservation.md new file mode 100644 index 000000000..aea6b23e4 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/preservation.md @@ -0,0 +1,13 @@ +This contract utilizes a library to store two different times for two different +timezones. The constructor creates two instances of the library for each time +to be stored. + +The goal of this level is for you to claim ownership of the instance you are given. + +  Things that might help +* 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. +* Understanding what it means for `delegatecall` to be context-preserving. +* Understanding how storage variables are stored and accessed. +* Understanding how casting works between different data types. diff --git a/client/src/gamedata/vi/descriptions/levels/preservation_complete.md b/client/src/gamedata/vi/descriptions/levels/preservation_complete.md new file mode 100644 index 000000000..30ad0781a --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/preservation_complete.md @@ -0,0 +1,6 @@ +As the previous level, `delegate` mentions, the use of `delegatecall` to call +libraries can be risky. This is particularly true for contract libraries that +have their own state. This example demonstrates why the `library` keyword +should be used for building libraries, as it prevents the libraries from +storing and accessing state variables. + diff --git a/client/src/gamedata/vi/descriptions/levels/privacy.md b/client/src/gamedata/vi/descriptions/levels/privacy.md new file mode 100644 index 000000000..ed4b8bc20 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/privacy.md @@ -0,0 +1,11 @@ +The creator of this contract was careful enough to protect the sensitive areas of its storage. + +Unlock this contract to beat the level. + +Things that might help: +* Understanding how storage works +* Understanding how parameter parsing works +* Understanding how casting works + +Tips: +* 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. diff --git a/client/src/gamedata/vi/descriptions/levels/privacy_complete.md b/client/src/gamedata/vi/descriptions/levels/privacy_complete.md new file mode 100644 index 000000000..478506f22 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/privacy_complete.md @@ -0,0 +1,3 @@ +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. + +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) diff --git a/client/src/gamedata/vi/descriptions/levels/puzzle_wallet.md b/client/src/gamedata/vi/descriptions/levels/puzzle_wallet.md new file mode 100644 index 000000000..3c3689564 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/puzzle_wallet.md @@ -0,0 +1,18 @@ +Nowadays, paying for DeFi operations is impossible, fact. + +A group of friends discovered how to slightly decrease the cost of performing multiple transactions by batching them in one transaction, so they developed a smart contract for doing this. + +They needed this contract to be upgradeable in case the code contained a bug, and they also wanted to prevent people from outside the group from using it. To do so, they voted and assigned two people with special roles in the system: +The admin, which has the power of updating the logic of the smart contract. +The owner, which controls the whitelist of addresses allowed to use the contract. +The contracts were deployed, and the group was whitelisted. Everyone cheered for their accomplishments against evil miners. + +Little did they know, their lunch money was at risk… + +  +You'll need to hijack this wallet to become the admin of the proxy. + +  +Things that might help: +* Understanding how `delegatecall` works and how `msg.sender` and `msg.value` behaves when performing one. +* Knowing about proxy patterns and the way they handle storage variables. diff --git a/client/src/gamedata/vi/descriptions/levels/puzzle_wallet_complete.md b/client/src/gamedata/vi/descriptions/levels/puzzle_wallet_complete.md new file mode 100644 index 000000000..c98af3a7d --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/puzzle_wallet_complete.md @@ -0,0 +1,7 @@ +Next time, those friends will request an audit before depositing any money on a contract. Congrats! + +Frequently, using proxy contracts is highly recommended to bring upgradeability features and reduce the deployment's gas cost. However, developers must be careful not to introduce storage collisions, as seen in this level. + +Furthermore, iterating over operations that consume ETH can lead to issues if it is not handled correctly. Even if ETH is spent, `msg.value` will remain the same, so the developer must manually keep track of the actual remaining amount on each iteration. This can also lead to issues when using a multi-call pattern, as performing multiple `delegatecall`s to a function that looks safe on its own could lead to unwanted transfers of ETH, as `delegatecall`s keep the original `msg.value` sent to the contract. + +Move on to the next level when you're ready! diff --git a/client/src/gamedata/vi/descriptions/levels/recovery.md b/client/src/gamedata/vi/descriptions/levels/recovery.md new file mode 100644 index 000000000..4ed9a93da --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/recovery.md @@ -0,0 +1,4 @@ + +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. + +This level will be completed if you can recover (or remove) the `0.001` ether from the lost contract address. diff --git a/client/src/gamedata/vi/descriptions/levels/recovery_complete.md b/client/src/gamedata/vi/descriptions/levels/recovery_complete.md new file mode 100644 index 000000000..37eebb07f --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/recovery_complete.md @@ -0,0 +1,10 @@ + +Contract addresses are deterministic and are calculated by `keccak256(address, nonce)` where the `address` is the address of the contract (or ethereum address that created the transaction) and `nonce` is the number of contracts the spawning contract has created (or the transaction nonce, for regular transactions). + +Because of this, one can send ether to a pre-determined address (which has no private key) and later create a contract at that address which recovers the ether. This is a non-intuitive and somewhat secretive way to (dangerously) store ether without holding a private key. + +An interesting [blog post](https://swende.se/blog/Ethereum_quirks_and_vulns.html) by Martin Swende details potential use cases of this. + +If you're going to implement this technique, make sure you don't miss the nonce, or your funds will be lost forever. + + diff --git a/client/src/gamedata/vi/descriptions/levels/reentrancy.md b/client/src/gamedata/vi/descriptions/levels/reentrancy.md new file mode 100644 index 000000000..0e70cf36a --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/reentrancy.md @@ -0,0 +1,9 @@ +The goal of this level is for you to steal all the funds from the contract. + +  +Things that might help: +* Untrusted contracts can execute code where you least expect it. +* Fallback methods +* Throw/revert bubbling +* Sometimes the best way to attack a contract is with another contract. +* See the ["?"](https://ethernaut.openzeppelin.com/help) page above, section "Beyond the console" diff --git a/client/src/gamedata/vi/descriptions/levels/reentrancy_complete.md b/client/src/gamedata/vi/descriptions/levels/reentrancy_complete.md new file mode 100644 index 000000000..461a5f208 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/reentrancy_complete.md @@ -0,0 +1,12 @@ +In order to prevent re-entrancy attacks when moving funds out of your contract, use the [Checks-Effects-Interactions pattern](https://solidity.readthedocs.io/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern) being aware that `call` will only return false without interrupting the execution flow. Solutions such as [ReentrancyGuard](https://docs.openzeppelin.com/contracts/2.x/api/utils#ReentrancyGuard) or [PullPayment](https://docs.openzeppelin.com/contracts/2.x/api/payment#PullPayment) can also be used. + +`transfer` and `send` are no longer recommended solutions as they can potentially break contracts after the Istanbul hard fork [Source 1](https://diligence.consensys.net/blog/2019/09/stop-using-soliditys-transfer-now/) [Source 2](https://forum.openzeppelin.com/t/reentrancy-after-istanbul/1742). + +Always assume that the receiver of the funds you are sending can be another contract, not just a regular address. Hence, it can execute code in its payable fallback method and *re-enter* your contract, possibly messing up your state/logic. + +Re-entrancy is a common attack. You should always be prepared for it! + +  +#### The DAO Hack + +The famous DAO hack used reentrancy to extract a huge amount of ether from the victim contract. See [15 lines of code that could have prevented TheDAO Hack](https://blog.openzeppelin.com/15-lines-of-code-that-could-have-prevented-thedao-hack-782499e00942). diff --git a/client/src/gamedata/vi/descriptions/levels/shop.md b/client/src/gamedata/vi/descriptions/levels/shop.md new file mode 100644 index 000000000..ab86e5079 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/shop.md @@ -0,0 +1,5 @@ +Сan you get the item from the shop for less than the price asked? + +##### Things that might help: +* `Shop` expects to be used from a `Buyer` +* Understanding restrictions of view functions diff --git a/client/src/gamedata/vi/descriptions/levels/shop_complete.md b/client/src/gamedata/vi/descriptions/levels/shop_complete.md new file mode 100644 index 000000000..0bc6ca34d --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/shop_complete.md @@ -0,0 +1,3 @@ +Contracts can manipulate data seen by other contracts in any way they want. + +It's unsafe to change the state based on external and untrusted contracts logic. diff --git a/client/src/gamedata/vi/descriptions/levels/switch.md b/client/src/gamedata/vi/descriptions/levels/switch.md new file mode 100644 index 000000000..1ece812ff --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/switch.md @@ -0,0 +1,4 @@ +Just have to flip the switch. Can't be that hard, right? + +##### Things that might help: +Understanding how `CALLDATA` is encoded. diff --git a/client/src/gamedata/vi/descriptions/levels/switch_complete.md b/client/src/gamedata/vi/descriptions/levels/switch_complete.md new file mode 100644 index 000000000..d392b177a --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/switch_complete.md @@ -0,0 +1 @@ +Assuming positions in `CALLDATA` with dynamic types can be erroneous, especially when using hard-coded `CALLDATA` positions. diff --git a/client/src/gamedata/vi/descriptions/levels/telephone.md b/client/src/gamedata/vi/descriptions/levels/telephone.md new file mode 100644 index 000000000..0f9a0dedd --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/telephone.md @@ -0,0 +1,5 @@ +Claim ownership of the contract below to complete this level. + +  +Things that might help +* See the ["?"](https://ethernaut.openzeppelin.com/help) page above, section "Beyond the console" diff --git a/client/src/gamedata/vi/descriptions/levels/telephone_complete.md b/client/src/gamedata/vi/descriptions/levels/telephone_complete.md new file mode 100644 index 000000000..f19d3b627 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/telephone_complete.md @@ -0,0 +1,21 @@ +While this example may be simple, confusing `tx.origin` with `msg.sender` can lead to phishing-style attacks, such as [this](https://blog.ethereum.org/2016/06/24/security-alert-smart-contract-wallets-created-in-frontier-are-vulnerable-to-phishing-attacks/). + +An example of a possible attack is outlined below. + +1) Use `tx.origin` to determine whose tokens to transfer, e.g. + +``` +function transfer(address _to, uint _value) { + tokens[tx.origin] -= _value; + tokens[_to] += _value; +} +``` +2) Attacker gets victim to send funds to a malicious contract that calls the transfer function of the token contract, e.g. + +``` +function () payable { + token.transfer(attackerAddress, 10000); +} +``` + +3) In this scenario, `tx.origin` will be the victim's address (while `msg.sender` will be the malicious contract's address), resulting in the funds being transferred from the victim to the attacker. diff --git a/client/src/gamedata/vi/descriptions/levels/token.md b/client/src/gamedata/vi/descriptions/levels/token.md new file mode 100644 index 000000000..9b90a1ca2 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/token.md @@ -0,0 +1,7 @@ +The goal of this level is for you to hack the basic token contract below. + +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. + +  +Things that might help: +* What is an odometer? \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/token_complete.md b/client/src/gamedata/vi/descriptions/levels/token_complete.md new file mode 100644 index 000000000..5c3254d2b --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/token_complete.md @@ -0,0 +1,12 @@ +Overflows are very common in solidity and must be checked for with control statements such as: +``` +if(a + c > a) { + a = a + c; +} +``` + +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: +``` +a = a.add(c); +``` +If there is an overflow, the code will revert. \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/unstoppable.md b/client/src/gamedata/vi/descriptions/levels/unstoppable.md new file mode 100644 index 000000000..cc0a1a19f --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/unstoppable.md @@ -0,0 +1,5 @@ +There's a lending pool with a million tokens in balance, offering flash loans for free. + +If only there was a way to attack and stop the pool from offering flash loans ... + +You start with 100 tokens in balance. diff --git a/client/src/gamedata/vi/descriptions/levels/vault.md b/client/src/gamedata/vi/descriptions/levels/vault.md new file mode 100644 index 000000000..8f0400e45 --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/vault.md @@ -0,0 +1 @@ +Unlock the vault to pass the level! \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/vault_complete.md b/client/src/gamedata/vi/descriptions/levels/vault_complete.md new file mode 100644 index 000000000..cb6af991a --- /dev/null +++ b/client/src/gamedata/vi/descriptions/levels/vault_complete.md @@ -0,0 +1,3 @@ +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. + +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. \ No newline at end of file diff --git a/client/src/gamedata/vi/strings.json b/client/src/gamedata/vi/strings.json new file mode 100644 index 000000000..eeb63a50f --- /dev/null +++ b/client/src/gamedata/vi/strings.json @@ -0,0 +1,113 @@ +{ + "ethernaut": "Ethernaut", + "title": "The Ethernaut", + "hiring": "Chung tôi đang cần tuyển dụng!", + "info": "

Ethernaut là một trò chơi lập trình sử dụng Web3/Solidity lấy cảm hứng từ overthewire.org, được chơi trong Máy ảo Ethereum. Mỗi cấp độ là một hợp đồng thông minh cần được “hack”. 100% trò chơi là mã nguồn mở và tất cả các cấp độ đều được đóng góp bởi những người chơi khác. Bạn có ý tưởng muốn đóng góp? Mọi PR đều được

", + "home": "Trang chủ", + "help": "Trợ giúp", + "stats": "Thống kê", + "ethernautHelp": "Trợ giúp", + "footer": "được phát triển với bởi đội ngũ OpenZeppelin", + "english": "English", + "arabic": "عربي", + "spanish": "Español", + "portuguese": "Português", + "japanese": "日本語", + "turkish": "Türkçe", + "chinese_simplified": "簡體中文", + "chinese_traditional": "正體中文", + "french": "Français", + "russian": "Русский", + "vietnamese": "Vietnamese", + "playNow": "Bắt đầu!", + "toggleNavigation": "Bật tắt điều hướng", + "levelCompleted": "Hoàn thành!", + "sources": "Nguồn", + "submitInstance": "Nộp bài", + "getNewInstance": "Tạo phiên bản mới", + "deployMessageTitle": "Trò chơi chưa được triển khai", + "deployMessage": "Hiện tại game chỉ hỗ trợ các mạng này:", + "deployConfirmation": "Bạn muốn triển khai các hợp đồng trên mạng này hay chuyển sang mạng Sepolia?", + "deployNote": "Lưu ý: Nếu bạn triển khai tất cả các cấp độ, chúng tôi sẽ hướng dẫn bạn gửi toàn bộ trò chơi đã triển khai trên mạng này.", + "deployGame": "Triển khai trò chơi", + "switchToSepolia": "Chuyển sang Sepolia", + "deployLevel": "Triển khai cấp độ", + "helperDeployAllContracts": "Triển khai tất cả các hợp đồng còn lại trên mạng hiện tại.", + "confirmMainnetDeploy": "Bạn đang ở trên mạng chính, trò chơi không có giá trị tiền tệ, bạn không nên triển khai trên mạng này.", + "submitLevelFooter": "Triển khai tất cả các cấp độ (deployAllContracts() in console) để thêm mạng hiện tại vào Github repository dưới dạng mạng được hỗ trợ mới.", + "submitGameFooter": "Tuyệt vời! Toàn bộ trò chơi được triển khai trên mạng này. Nhấp vào đây để tạo vấn đề GitHub và gửi cho chúng tôi :)", + "nextLevel": "Đi đến cấp độ tiếp theo", + "uLevels": "Cấp độ", + "lLevels": "cấp độ", + "refresh": "Làm mới", + "uCompleted": "Hoàn thành", + "lCompleted": "hoàn thành", + "players": "người chơi", + "player": "Người chơi", + "levelName": "Tên cấp độ", + "levelAddress": "Địa chỉ của cấp độ", + "blockNum": "Block num", + "uCreated": "Tạo", + "lCreated": "tạo", + "instance": "Instance", + "numberOf": "Number of", + "warning": "Cảnh báo", + "warningMessage": "Không có nhà cung cấp Web3 và trò chơi ở chế độ chỉ đọc", + "levelAuthor": "Cấp độ tác giả:", + "pleaseWait": "VUI LÒNG CHỜ", + "donate": "Bài tập này có dạy cho bạn điều gì hữu ích không? Đóng góp cho tác giả của bài tập (trên mainnet):", + "openConsole": "MỞ CONSOLE CỦA BẠN ĐỂ CHƠI", + "difficulty": "Độ khó", + "error": "Lỗi", + "retrying": "thử lại...", + "typeHelpMessage": "Nhập help() để có danh sách các tiện ích bổ sung web3 tùy chỉnh", + "slowNetworkMessage": "Thông báo 'Phát hiện mạng chậm' gây khó chịu? Hãy thử cài đặt Công cụ dành cho nhà phát triển -> Chỉ tin nhắn của người dùng hoặc tắt 'chrome://flags/#enable-webfonts-intervention-v2", + "notContractSetMessage": "Không có hợp đồng nào được sử dụng, hãy chuyển đến một cấp độ và nhấp vào 'Tạo phiên bản mới'", + "levelAddressMessage": "Địa chỉ cấp độ", + "instanceAddressMessage": "Instance address", + "playerAddressMessage": "Địa chỉ người chơi", + "selectedNetworkMessage": "Mạng hiện tại: ", + "ethernautAddressMessage": "Địa chỉ Ethernaut", + "noLevelsDataMessage": "Không thể tìm thấy dữ liệu cấp độ", + "ethernautNotFoundMessage": "Hợp đồng Ethernaut không được tìm thấy trong mạng hiện tại. Vui lòng đảm bảo (1) rằng bạn đang sử dụng metamask, (2) nó nằm trên mạng được hỗ trợ, (3) nó đã được mở khóa, (4 tùy chọn) Từ ngày 2 tháng 11, bạn có thể BẬT chế độ bảo mật (TẮT theo mặc định) trong Metamask cài đặt nếu bạn không muốn hiển thị thông tin của mình theo mặc định. (5 tùy chọn) Nếu chế độ bảo mật được BẬT, bạn phải ủy quyền cho siêu mặt nạ để sử dụng trang này. và (6) sau đó làm mới.", + "requestingNewInstanceMessage": "Yêu cầu hợp đồng mới từ bài tập...", + "unableToRetrieveLevelMessage": "Không thể tạo được hợp đồng mới cho bài tập! Hãy kiểm tra gas và thử lại lần nữa.", + "transactionNoLogsMessage": "Giao dịch không được lưu lại", + "noPlayerAddressMessage": "Không có địa chỉ người chơi được phát hiện! Đảm bảo rằng 1) Bạn đã cài đặt tiện ích mở rộng trình duyệt metamask và 2) nó đã được mở khóa. 3 tùy chọn) Từ ngày 2 tháng 11, bạn có thể BẬT chế độ bảo mật (TẮT theo mặc định) trong cài đặt nếu bạn không muốn tiết lộ thông tin của mình theo mặc định. 4 tùy chọn) Nếu chế độ riêng tư được BẬT, bạn phải ủy quyền cho Metamask sử dụng trang này. 5) sau đó làm mới", + "submitLevelMessage": "Nộp bài...", + "wellDoneMessage": "Rất tốt", + "completedLevelMessage": "Bạn đã hoàn thành cấp độ này!!!", + "uncompletedLevelMessage": "Ối! Có vẻ như bạn chưa vượt qua được cấp độ này", + "metamaskKnownIssue": "Ôi! Có vẻ như bạn đã gặp phải sự cố Metamask đã biết. Hãy thử tắt và bật lại plugin metamask của bạn. Nếu cách đó không hiệu quả, tôi e rằng bạn cần phải đóng tất cả các quy trình của Chrome và khởi động lại để xử lý plugin cho đến khi bản sửa lỗi được đưa ra. Đừng lo lắng, sau khi khởi động lại, bạn sẽ không thấy thông báo này nữa.", + "eventsCompletionMessage": "Lỗi khi xem sự kiện hoàn thành:", + "unexpectedAddressMessage": "Địa chỉ không mong đợi trong sự kiện LevelCompletedLog (bỏ qua):", + "helperPlayer": "địa chỉ người chơi hiện tại", + "helperEthernaut": "hợp đồng trò chơi chính", + "helperLevel": "địa chỉ hợp đồng cấp hiện tại", + "helperContract": "phiên bản hợp đồng cấp hiện tại (nếu được tạo)", + "helperInstance": "địa chỉ hợp đồng cấp hiện tại (nếu được tạo)", + "helperVersion": "phiên bản trò chơi hiện tại", + "helperGetBalance": "lấy số dư địa chỉ trong ether", + "helperGetBlockNumber": "lấy số khối mạng hiện tại", + "helperSendTransaction": "gửi giao dịch", + "helperGetNetworkId": "lấy id mạng ethereum", + "helperToWei": "chuyển đổi đơn vị ether sang wei", + "helperFromWei": "chuyển đổi đơn vị wei sang ether", + "levelNotTranslated": "Cấp độ này chưa được dịch hoặc bản dịch chưa đầy đủ.", + "contributeTranslation": "Bấm vào đây để cải thiện bản dịch", + "usingConsole": "Hầu hết tương tác trò chơi đều thông qua bảng điều khiển của trình duyệt: `Dev Tools -> Console`. Mở bảng điều khiển và nhập lệnh: \n\n`help()`\n\n để xem danh sách các đối tượng và chức năng được trò chơi đưa vào bảng điều khiển. Vì hầu hết các tương tác đều không đồng bộ, chúng tôi khuyên bạn nên sử dụng Chrome v62 để bật từ khóa `async/await` trong bảng điều khiển, thay vì viết: \n\n`getBalance(player)> PROMISE`\n\n và mở lời hứa. Với chờ đợi/không đồng bộ, bạn có thể viết:\n\n`await getBalance(player) > '1.11002387' `\n\n", + "gameMechanics": "Trò chơi sử dụng hợp đồng chính `Ethernaut.sol` để quản lý tiến trình của người chơi và ủy quyền tương tác với việc triển khai `Level.sol`. Mỗi hợp đồng cấp độ sẽ tạo ra các phiên bản để người chơi thao tác, phá vỡ, phá hủy, sửa chữa, v.v. Người chơi yêu cầu một phiên bản, thao túng nó và trả lại nó cho trò chơi để đánh giá mức độ hoàn thành cấp độ.\n\n Cả hai yêu cầu phiên bản và gửi lại phiên bản vào trò chơi được thực hiện bằng các nút trong giao diện người dùng ở mỗi cấp độ. Khi ứng dụng này truy xuất một phiên bản từ `Ethernaut.sol`, nó sẽ gói phiên bản đó trong một đối tượng `TruffleContract` và hiển thị phiên bản đó trong bảng điều khiển của trình duyệt. Xem cấp độ đầu tiên để có hướng dẫn đầy đủ về cách chơi trò chơi.", + "beyondConsole": "Một số cấp độ sẽ yêu cầu làm việc bên ngoài bảng điều khiển trình duyệt. Tức là viết mã vững chắc và triển khai nó trong mạng để tấn công hợp đồng cá thể của cấp độ đó với một hợp đồng khác. Việc này có thể được thực hiện theo nhiều cách, ví dụ: \n\n1) Sử dụng Remix để viết mã và triển khai mã đó trong mạng tương ứng Xem [Remix Solidity IDE](https://remix.ethereum.org/). \n\n2) Thiết lập dự án truffle cục bộ để phát triển và triển khai các hợp đồng tấn công. Xem [Truffle Framework](http://truffleframework.com/).", + "troubleshooting": "Đôi khi \n\n(a) trạng thái ứng dụng hoặc (b) trạng thái plugin MetaMask \n\ncó thể hơi rối, đặc biệt là sau khi chuyển mạng, mở khóa, v.v. Nếu những gì bạn đang thấy không có nhiều ý nghĩa , hãy thử làm mới ứng dụng, làm mới ứng dụng, tắt và bật lại plugin metamask hoặc thậm chí khởi động lại trình duyệt của bạn. \n\nNếu bạn gặp vấn đề, vui lòng cho chúng tôi biết theo địa chỉ ethernaut@zeppelin.solutions", + "poweredBy": "được cung cấp bởi ", + "setupMetamask": "Nếu bạn chưa có nó, hãy cài đặt [MetaMask browser extension](https://metamask.io/) (trong Chrome, Firefox, Brave hoặc Opera trên máy tính để bàn của bạn). \n\nThiết lập ví của tiện ích mở rộng và sử dụng bộ chọn mạng để trỏ đến mạng ưa thích ở phía trên bên trái giao diện của tiện ích mở rộng. Ngoài ra bạn có thể sử dụng nút UI để chuyển đổi giữa các mạng. Nếu bạn chọn mạng không được hỗ trợ, trò chơi sẽ thông báo cho bạn và đưa bạn đến mạng thử nghiệm Sepolia mặc định. \n\nSau khi hoàn tất, hãy quay lại đây và tải lại trang web", + "FifthyPercentMessage": "Công việc tuyệt vời! Bạn đã đi được nửa chặng đường của Ethernaut và đang khá giỏi trong việc phá vỡ mọi thứ. Làm việc với tư cách là Nhà nghiên cứu bảo mật Blockchain tại OpenZeppelin có thể rất thú vị... https://grnh.se/fdbf1c043us", + "SeventyFivePercentMessage": "75%: Làm tốt lắm…bây giờ bạn đang ở sâu trong hố thỏ…ai biết nó sẽ đưa bạn đến đâu… https://grnh.se/d4a786e43us", + "NinetyPercentMessage": "90%: Bạn sắp đến đích rồi! Chỉ còn một vài thử thách nữa là bạn sẽ hoàn thành Ethernaut! Bạn đã cân nhắc sự nghiệp trong lĩnh vực Bảo mật Blockchain chưa?https://grnh.se/cfcca8c83us", + "HundredPercentMessage": "100%: Xin chúc mừng! Cuộc hành trình của bạn xuống hố thỏ Web3 thật ấn tượng và đáng được tôn vinh! Bây giờ bạn có kỹ năng để phá vỡ hợp đồng thông minh! Điều gì tiếp theo từ đây? Đăng ký làm Nhà nghiên cứu bảo mật Blockchain tại OpenZeppelin và góp phần bảo mật các giao thức hàng đầu trong Web3! https://grnh.se/26c05aac3us", + "Menu": "Menu", + "Networks": "Mạng", + "Languages": "Ngôn ngữ", + "PageNotFoundTitle": "404 Lỗi - Không tìm thấy trang", + "PageNotFoundText": "Ối! Trang bạn đang tìm kiếm không thể được tìm thấy." +} diff --git a/client/src/gamedata/zh_cn/strings.json b/client/src/gamedata/zh_cn/strings.json index 981a5429a..514495294 100644 --- a/client/src/gamedata/zh_cn/strings.json +++ b/client/src/gamedata/zh_cn/strings.json @@ -18,6 +18,7 @@ "chinese_traditional": "正體中文", "french": "Français", "russian": "Русский", + "vietnamese": "Vietnamese", "playNow": "开始!", "toggleNavigation": "切换导航", "levelCompleted": "完成关卡!", @@ -95,9 +96,9 @@ "helperFromWei": "从wei转换到ether", "levelNotTranslated": "这一关卡还没有被翻译或是翻译不完全 ", "contributeTranslation": "来帮助我们翻译吧", - "usingConsole": "大多数的游戏互动时通过浏览器的控制台: `Dev Tools -> Console`. 打开控制台然后输入这个命令:\n\n`help()`\n\n 可以得到一个列表, 包含了被这个游戏放入控制台的对象和函数. 鉴于多数的互动是异步的, 我们推荐使用Chrome v62 并且使用 `async`/`await` 关键词, 所以相比于使用:\n\n`getBalance(player)> PROMISE`\n\n我们推荐使用 await/async, 你可以这样使用: \n\n`await getBalance(player)> 1.11002387`\n\n", - "gameMechanics": "这个游戏使用主合约 `Ethernaut.sol` 来管理玩家进度, 代理玩家和 `Level.sol` 互动. 每一关的合约会产生一个实例供玩家操作, 攻破, 摧毁, 修复等等. 玩家请求一个实例, 操作之后返回,然后将会被评判完成度.\n\n 请求和提交实例都是通过每一关界面上的按钮. 当这个 app 从 `Ethernaut.sol` 取回实例时, 会把它包装在 `TruffleContract` 对象中, 然后暴露在浏览器的控制台里. 尝试第一关来看看怎么玩这个游戏.", - "beyondConsole": "有些关卡需要在控制台之外的操作. 比如, 用 solidity 写一些代码, 部署合约在网络上, 然后攻击实例. 这可以通过很多方式完成, 比如: \n\n1) 使用 Remix 写代码并部署在相应的网络上 参见 [Remix Solidity IDE](https://remix.ethereum.org/).\n\n2) 设置一个本地 truffle 项目, 开发并部署攻击合约. 参见 [Truffle Framework](http://truffleframework.com/).", + "usingConsole": "大多数的游戏互动时通过浏览器的控制台: `Dev Tools -> Console`. 打开控制台然后输入这个命令:\n\n`help()`\n\n 可以得到一个列表, 包含了被这个游戏放入控制台的对象和函数. 鉴于多数的互动是异步的, 我们推荐使用Chrome v62 并且使用 `async`/`await` 关键词, 所以相比于使用:\n\n`getBalance(player)> PROMISE`\n\n我们推荐使用 await/async, 你可以这样使用: \n\n`await getBalance(player)> 1.11002387`\n\n", + "gameMechanics": "这个游戏使用主合约 `Ethernaut.sol` 来管理玩家进度, 代理玩家和 `Level.sol` 互动. 每一关的合约会产生一个实例供玩家操作, 攻破, 摧毁, 修复等等. 玩家请求一个实例, 操作之后返回,然后将会被评判完成度.\n\n 请求和提交实例都是通过每一关界面上的按钮. 当这个 app 从 `Ethernaut.sol` 取回实例时, 会把它包装在 `TruffleContract` 对象中, 然后暴露在浏览器的控制台里. 尝试第一关来看看怎么玩这个游戏.", + "beyondConsole": "有些关卡需要在控制台之外的操作. 比如, 用 solidity 写一些代码, 部署合约在网络上, 然后攻击实例. 这可以通过很多方式完成, 比如: \n\n1) 使用 Remix 写代码并部署在相应的网络上 参见 [Remix Solidity IDE](https://remix.ethereum.org/).\n\n2) 设置一个本地 truffle 项目, 开发并部署攻击合约. 参见 [Truffle Framework](http://truffleframework.com/).", "troubleshooting": "有的时候, \n\napp 或者 MetaMask 插件会有点问题, 特别是当你转换网络和解锁时. \n\n如果你遇到什么莫名其妙的问题, 尝试刷新 app, 多次刷新. 重启 MetaMask 插件, 甚至是重启浏览器.\n\n如果你发现其他问题, 欢迎提交给我们 ethernaut@zeppelin.solutions", "poweredBy": "powered by ", "setupMetamask": "如果你还没有,请安装[MetaMask浏览器扩展](https://metamask.io/)(在电脑上的Chrome、Firefox、Brave或Opera浏览器中)。\n\n配置好浏览器扩展的钱包,然后在扩展界面的左上角选择偏好的网络,或者你也可以用网页界面的按钮来切换网络。\n\n如果你选择了一个不支持的网络,这个游戏将提示你并且为你切换到默认的Sepolia测试网络", diff --git a/client/src/gamedata/zh_tw/strings.json b/client/src/gamedata/zh_tw/strings.json index ce97df2b9..9ec04fc1d 100644 --- a/client/src/gamedata/zh_tw/strings.json +++ b/client/src/gamedata/zh_tw/strings.json @@ -18,6 +18,7 @@ "chinese_traditional": "正體中文", "french": "Français", "russian": "Русский", + "vietnamese": "Vietnamese", "playNow": "開始!", "toggleNavigation": "切換導覽", "levelCompleted": "過關!", From ac0bf38549e0c3f25f00cea6610ae9d2dc377ed5 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 25 Aug 2023 11:18:22 +0700 Subject: [PATCH 2/4] added language --- client/src/containers/Header.js | 67 ++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/client/src/containers/Header.js b/client/src/containers/Header.js index f9b94e192..e7fcbe993 100644 --- a/client/src/containers/Header.js +++ b/client/src/containers/Header.js @@ -1,5 +1,5 @@ import React from "react"; -import onClickOutside from 'react-onclickoutside' +import onClickOutside from "react-onclickoutside"; import { connect } from "react-redux"; import { withRouter } from "../hoc/withRouter"; import { Link } from "react-router-dom"; @@ -223,7 +223,7 @@ class Header extends React.Component { handleClickOutside = () => { this.closeDropdown(); - } + }; render() { let strings = loadTranslations(this.state.lang); @@ -239,8 +239,9 @@ class Header extends React.Component { ru: strings.russian, ar: strings.arabic, tr: strings.turkish, + vi: strings.vietnamese, }; - + const ddOpen = Boolean(this.state.multiDDOpen); return (
this.closeDropdown()}> @@ -316,14 +317,14 @@ class Header extends React.Component {
{window.location.pathname === constants.PATH_ROOT && !!this.props.web3 && ( - this.toggleDropdownState()} - to={constants.PATH_LEADERBOARD}> -
- + this.toggleDropdownState()} + to={constants.PATH_LEADERBOARD} + > +
+
- )} { @@ -345,26 +346,29 @@ class Header extends React.Component { {strings.Networks}

- {Object.values(constants.NETWORKS_INGAME).map((network, index) => { - if (network && network.name !== "local") { - if (Number(network.id) === this.state.chainId) - return false; // filter out current network - return ( -
{ - e.preventDefault(); - this.changeNetwork(network); - }} - className="dropdown-pill" - > - - {network.name} - -
- ); + {Object.values(constants.NETWORKS_INGAME).map( + (network, index) => { + if (network && network.name !== "local") { + if (Number(network.id) === this.state.chainId) + return false; // filter out current network + return ( +
{ + e.preventDefault(); + this.changeNetwork(network); + }} + className="dropdown-pill" + > + + {network.name} + +
+ ); + } + return null; } - return null; - })} + )}
@@ -375,7 +379,8 @@ class Header extends React.Component {

{Object.keys(LANGUAGES_MAP).map((languageString, index) => ( -
{ this.changeLanguage(e, languageString); }} @@ -455,4 +460,6 @@ function mapDispatchToProps(dispatch) { ); } -export default withRouter(connect(mapStateToProps, mapDispatchToProps)(onClickOutside(Header))); +export default withRouter( + connect(mapStateToProps, mapDispatchToProps)(onClickOutside(Header)) +); From 096b1a34c742a30a04e8dcbe036ebac6e78e120c Mon Sep 17 00:00:00 2001 From: GianfrancoBazzani Date: Thu, 11 Sep 2025 17:58:19 +0200 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=94=A8=20fix:=20minor=20issues?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/gamedata/ar/strings.json | 4 ++-- client/src/gamedata/en/strings.json | 2 +- client/src/gamedata/es/strings.json | 24 ++++++++++++------------ client/src/gamedata/fr/strings.json | 2 +- client/src/gamedata/ja/strings.json | 4 ++-- client/src/gamedata/ko/strings.json | 5 +++-- client/src/gamedata/pt_br/strings.json | 2 +- client/src/gamedata/ru/strings.json | 2 +- client/src/gamedata/tr/strings.json | 2 +- client/src/gamedata/uk/strings.json | 9 +++++++++ client/src/gamedata/vi/strings.json | 21 ++++++++++++++++----- client/src/gamedata/zh_cn/strings.json | 2 +- client/src/gamedata/zh_tw/strings.json | 2 +- 13 files changed, 51 insertions(+), 30 deletions(-) diff --git a/client/src/gamedata/ar/strings.json b/client/src/gamedata/ar/strings.json index 31d4d9c96..cf9ddab7c 100644 --- a/client/src/gamedata/ar/strings.json +++ b/client/src/gamedata/ar/strings.json @@ -21,7 +21,7 @@ "chinese_traditional": "正體中文", "french": "Français", "russian": "Русский", - "vietnamese": "Vietnamese", + "vietnamese": "tiếng Việt", "korean": "한국어", "playNow": "العب الان!", "toggleNavigation": "تصفح", @@ -33,9 +33,9 @@ "accountNotConnectedMessage": "لبدء مغامرتك، قم بتوصيل محفظة MetaMask الخاصة بك! تتفاعل لعبتنا بشكل مباشر مع عقود Ethernaut على السلسلة، مما يعني أن أفعالك في اللعبة مسجلة على blockchain. من خلال ربط حساب MetaMask الخاص بك، يمكنك التفاعل بأمان مع هذه العقود الذكية، مما يسمح لك بحل التحديات والتقدم في اللعبة.", "connectAccount": "يتصل", "deployMessageTitle": "لم يتم نشر اللعبة", - "deployMessage": "تدُعم اللُعبة حاليًا هذه الشبكات فقط:", "deprecatedNetwork": "شبكة عفا عليها الزمن", "networkBeingDeprecated": "يتم إهمال الشبكة", + "deployMessage": "تدُعم اللُعبة حاليًا هذه الشبكات فقط:", "deployConfirmation": "هل تريد نشر العقود على هذه الشبكة أم التبديل إلى شبكة Sepolia", "deployNote": "ملاحظة: إذا قمت بنشر جميع المستويات ، فسنرشدك إلى إرسال اللعبة المنشورة بالكامل على هذه الشبكة.", "deployGame": "نشر اللعبة", diff --git a/client/src/gamedata/en/strings.json b/client/src/gamedata/en/strings.json index b680e0ad1..94accda9d 100644 --- a/client/src/gamedata/en/strings.json +++ b/client/src/gamedata/en/strings.json @@ -21,7 +21,7 @@ "chinese_traditional": "正體中文", "french": "Français", "russian": "Русский", - "vietnamese": "Vietnamese", + "vietnamese": "tiếng Việt", "korean": "한국어", "playNow": "Play now!", "toggleNavigation": "Toggle navigation", diff --git a/client/src/gamedata/es/strings.json b/client/src/gamedata/es/strings.json index 6d1067173..e61ee610d 100644 --- a/client/src/gamedata/es/strings.json +++ b/client/src/gamedata/es/strings.json @@ -21,7 +21,7 @@ "chinese_traditional": "正體中文", "french": "Français", "russian": "Русский", - "vietnamese": "Vietnamese", + "vietnamese": "tiếng Việt", "korean": "한국어", "playNow": "Juega ahora!", "toggleNavigation": "Despliega la navegación", @@ -76,7 +76,7 @@ "levelAddressMessage": "Dirección del nivel", "instanceAddressMessage": "Dirección de la instancia", "playerAddressMessage": "Dirección del jugador", - "selectedNetworkMessage": "Current network: ", + "selectedNetworkMessage": "Red actual: ", "ethernautAddressMessage": "Dirección de Ethernaut", "noLevelsDataMessage": "No se encuentran los datos de los niveles", "ethernautNotFoundMessage": "El contrato de Ethernaut no se ha encontrado en la red seleccionada. Por favor averigua que 1) Estás usando MetaMask, 2) Estas en una red soportada, 3) Que MetaMask esté desbloqueado, 4 opcional) Puedes habilitar y setear en ON el modo privado (desactivado por defecto) en los ajustes si no quieres que tus informaciones sean automáticamente expuestas. 5 opcional) Si el modo privado esta habilitado tienes que autorizar MetaMask a utilizar esta página web. 6) Actualiza la página.", @@ -84,7 +84,7 @@ "unableToRetrieveLevelMessage": "No se puede obtener la instancia del nivel! Por favor, controle la cantidad de gas proporcionada e inténtelo de nuevo.", "transactionNoLogsMessage": "La transacción no contiene logs", "noPlayerAddressMessage": "Ninguna dirección encontrada para el jugador! Asegúrate de que 1) Tengas instalada la extensión MetaMask para tu navegador y 2) Que esté desbloqueada. 3 opcional) Puedes habilitar y setear en ON el modo privado (desactivado por defecto) en los ajustes si no quieres que tus informaciones sean automáticamente expuestas. 4 opcional) Si el modo privado esta habilitado tienes que autorizar MetaMask a utilizar esta página web. 5) Actualiza la página.", - "noEthersMessage": "Yikes, you have no ether! Get some at valid faucet for your chosen network", + "noEthersMessage": "Vaya, no tienes ether. Consigue algo en un faucet válido para la red seleccionada", "submitLevelMessage": "Enviando la instancia del nivel", "wellDoneMessage": "Bien hecho", "completedLevelMessage": "Has completado ese nivel!!!", @@ -106,16 +106,16 @@ "helperFromWei": "convierte wei en ether", "levelNotTranslated": "Este nivel no está traducido o la traducción es incompleta. ", "contributeTranslation": "Haz clic aquí para contribuir en mejorar la traducción", - "usingConsole": "Most game interaction is via the browser's console: `Dev Tools -> Console`. Open the console and enter the command: \n\n`help()`\n\n to see a list of objects and functions injected by the game to the console. Since most interactions are asynchronous, we recommend using Chrome v62 which enables the `async`/`await` keywords in the console, so instead of writting:\n\n`getBalance(player)> PROMISE`\n\nand opening the promise. With await/async, you can write:\n\n`await getBalance(player) > '1.11002387' `\n\n", - "gameMechanics": "The game uses the main contract `Ethernaut.sol` to manage player progress and delegate interaction with `Level.sol` implementations. Each level contract emits instances for players to manipulate, break, destroy, fix, etc. The player requests an instance, manipulates it and returns it to the game for evaluation of level completion.\n\n Both requesting instances and submitting instances back to the game are done with the buttons in the user interface in each level. When this app retrieves an instance from `Ethernaut.sol`, it wraps it in a `TruffleContract` object and exposes it in the browser's console. See the first level for a full tutorial on how to play the game.", - "beyondConsole": "Some levels will require working outside of the browser console. That is, writing solidity code and deploying it in the network to attack the level's instance contract with another contract. This can be done in multiple ways, for example: \n\n1) Use Remix to write the code and deploy it in the corresponding network See [Remix Solidity IDE](https://remix.ethereum.org/).\n\n 2) Setup a local truffle project to develop and deploy the attack contracts. See [Truffle Framework](https://trufflesuite.com/).", - "troubleshooting": "Sometimes \n\n(a) the app state or (b) the MetaMask plugin state \n\ncan become a bit messed up, specially after switching networks, unlocking, etc. If what you're seeing doesn't make much sense, try refreshing the app, hard-refreshing it, disabling and re-enabling your metamask plugin or even restarting your browser. \n\nIf you find issues, please let us know at ethernaut@zeppelin.solutions", - "poweredBy": "powered by ", + "usingConsole": "La mayoría de la interacción del juego se realiza mediante la consola del navegador: `Dev Tools -> Console`. Abre la consola e ingresa el comando:\n\n`help()`\n\n para ver una lista de objetos y funciones que el juego inyecta en la consola. Dado que la mayoría de las interacciones son asíncronas, recomendamos usar Chrome v62 o superior que habilita las palabras clave `async`/`await` en la consola, así en lugar de escribir:\n\n`getBalance(player) > PROMISE`\n\n y abrir la promesa. Con async/await puedes escribir:\n\n`await getBalance(player) > '1.11002387' `\n\n", + "gameMechanics": "El juego usa el contrato principal `Ethernaut.sol` para gestionar el progreso de los jugadores y delegar la interacción con las implementaciones de `Level.sol`. Cada contrato de nivel emite instancias para que los jugadores las manipulen, rompan, destruyan, arreglen, etc. El jugador solicita una instancia, la manipula y la devuelve al juego para evaluar la finalización del nivel.\n\n Tanto la solicitud de instancias como el envío de instancias de vuelta al juego se realizan con los botones en la interfaz de usuario de cada nivel. Cuando esta aplicación obtiene una instancia de `Ethernaut.sol`, la envuelve en un objeto `TruffleContract` y la expone en la consola del navegador. Consulta el primer nivel para un tutorial completo sobre cómo jugar.", + "beyondConsole": "Algunos niveles requerirán trabajar fuera de la consola del navegador. Es decir, escribir código Solidity y desplegarlo en la red para atacar el contrato de la instancia del nivel con otro contrato. Esto puede hacerse de varias maneras, por ejemplo: \n\n1) Usa Remix para escribir el código y desplegarlo en la red correspondiente. Ver [Remix Solidity IDE](https://remix.ethereum.org/).\n\n2) Configura un proyecto local de Truffle para desarrollar y desplegar los contratos de ataque. Ver [Truffle Framework](https://trufflesuite.com/).", + "troubleshooting": "A veces \n\n(a) el estado de la aplicación o (b) el estado del plugin MetaMask \n\npueden quedar un poco desordenados, especialmente después de cambiar de red, desbloquear, etc. Si lo que estás viendo no tiene mucho sentido, intenta recargar la aplicación, hacer una recarga forzada, desactivar y volver a activar la extensión de MetaMask o incluso reiniciar el navegador. \n\nSi encuentras problemas, avísanos en ethernaut@zeppelin.solutions", + "poweredBy": "impulsado por ", "setupMetamask": "Si aún no lo tienes, instala la [extensión del navegador MetaMask](https://metamask.io/). \n\nConfigura la billetera de la extensión y usa el selector de red para apuntar a tu red preferida en la parte superior izquierda de la interfaz de la extensión. De forma alternativa, puedes usar el boton en la interfaz de usuario para cambiar entre diferentes redes. Si seleccionas una red no soportada, el juego te notificarà y llevarà a la red de test por defecto de Sepolia. \n\nUna vez hecho, vuelve aqui y vuelve a carga la pagin", - "FifthyPercentMessage": "Awesome work! You’re halfway through Ethernaut and getting pretty good at breaking things. Working as a Blockchain Security Researcher at OpenZeppelin could be fun... https://grnh.se/fdbf1c043us", - "SeventyFivePercentMessage": "75%: Good work anon…you’re deep down the rabbit hole now....who knows where it will take you... https://grnh.se/d4a786e43us", - "NinetyPercentMessage": "90%: You’re almost there anon! Just a few more challenges left until you complete Ethernaut! Have you considered a career in Blockchain Security?https://grnh.se/cfcca8c83us", - "HundredPercentMessage": "100%: Congratulations! Your journey down the web3 rabbit hole is impressive and should be celebrated! You now have the skills to break smart contracts! What’s next from here anon? Apply to be a Blockchain Security Researcher at OpenZeppelin, and contribute to securing the top protocols in web3! https://grnh.se/26c05aac3us", + "FifthyPercentMessage": "¡Excelente trabajo! Vas a mitad de camino en Ethernaut y te estás volviendo bastante bueno rompiendo cosas. Trabajar como Blockchain Security Researcher en OpenZeppelin podría ser divertido... https://grnh.se/fdbf1c043us", + "SeventyFivePercentMessage": "75%: Buen trabajo anon... ya estás muy dentro de la madriguera del conejo... quién sabe a dónde te llevará... https://grnh.se/d4a786e43us", + "NinetyPercentMessage": "90%: ¡Ya casi llegas anon! Solo unos pocos desafíos más hasta completar Ethernaut. ¿Has considerado una carrera en Seguridad Blockchain? https://grnh.se/cfcca8c83us", + "HundredPercentMessage": "100%: ¡Felicidades! Tu viaje por la madriguera de web3 es impresionante y merece celebrarse. ¡Ahora tienes las habilidades para romper smart contracts! ¿Qué sigue desde aquí anon? Postula para ser Blockchain Security Researcher en OpenZeppelin y contribuye a asegurar los principales protocolos en web3. https://grnh.se/26c05aac3us", "Menu": "Menú", "Networks": "Redes", "Languages": "Idiomas", diff --git a/client/src/gamedata/fr/strings.json b/client/src/gamedata/fr/strings.json index 7a4b4f4c2..a3c030d4c 100644 --- a/client/src/gamedata/fr/strings.json +++ b/client/src/gamedata/fr/strings.json @@ -21,7 +21,7 @@ "chinese_traditional": "正體中文", "french": "Français", "russian": "Русский", - "vietnamese": "Vietnamese", + "vietnamese": "tiếng Việt", "korean": "한국어", "playNow": "Jouer maintenant!", "toggleNavigation": "Basculer la navigation", diff --git a/client/src/gamedata/ja/strings.json b/client/src/gamedata/ja/strings.json index d49091411..09f9b75e4 100644 --- a/client/src/gamedata/ja/strings.json +++ b/client/src/gamedata/ja/strings.json @@ -21,7 +21,7 @@ "chinese_traditional": "正體中文", "french": "Français", "russian": "Русский", - "vietnamese": "Vietnamese", + "vietnamese": "tiếng Việt", "korean": "한국어", "playNow": "プレイ!", "toggleNavigation": "トグルナビゲーション", @@ -33,9 +33,9 @@ "accountNotConnectedMessage": "冒険を始めるには、MetaMask ウォレットを接続してください。私たちのゲームは Ethernaut オンチェーン コントラクトと直接やり取りします。つまり、ゲーム内でのアクションはブロックチェーンに記録されます。MetaMask アカウントをリンクすることで、これらのスマート コントラクトに安全に関与し、課題を解決してゲームを進めることができます。", "connectAccount": "接続する", "deployMessageTitle": "ゲームが展開されていません", - "deployMessage": "現在、ゲームはこれらのネットワークのみをサポートしています:", "deprecatedNetwork": "ネットワークは放棄されています", "networkBeingDeprecated": "将来的には、ネットワークは使用できなくなります。", + "deployMessage": "現在、ゲームはこれらのネットワークのみをサポートしています:", "deployConfirmation": "コントラクトをこのネットワークに展開しますか、それとも Sepolia ネットワークに切り替えますか?", "deployNote": "注: すべてのレベルを展開する場合は、展開されたゲーム全体をこのネットワークに送信するように案内されます。", "deployGame": "ゲームを展開する", diff --git a/client/src/gamedata/ko/strings.json b/client/src/gamedata/ko/strings.json index 5b33d105a..4524b9ec1 100644 --- a/client/src/gamedata/ko/strings.json +++ b/client/src/gamedata/ko/strings.json @@ -21,6 +21,7 @@ "chinese_traditional": "正體中文", "french": "Français", "russian": "Русский", + "vietnamese": "tiếng Việt", "korean": "한국어", "playNow": "지금 플레이!", "toggleNavigation": "내비게이션 전환", @@ -31,10 +32,10 @@ "accountNotConnectedTitle": "MetaMask 계정 연결되지 않음", "accountNotConnectedMessage": "모험을 시작하려면 MetaMask 지갑을 연결하세요! 게임은 Ethernaut의 온체인 계약과 직접 상호작용하며, 게임 내에서의 모든 행동은 블록체인에 기록됩니다. MetaMask 계정을 연결하면 이러한 스마트 계약과 안전하게 상호작용할 수 있습니다.", "connectAccount": "연결", - "deployMessageTitle": "게임이 배포되지 않음", + "deployMessage": "현재 게임은 다음 네트워크만 지원합니다:", "deprecatedNetwork": "네트워크가 더 이상 지원되지 않음", "networkBeingDeprecated": "네트워크가 더 이상 지원되지 않음", - "deployMessage": "현재 게임은 다음 네트워크만 지원합니다:", + "deployMessageTitle": "게임이 배포되지 않음", "deployConfirmation": "이 네트워크에 계약을 배포하시겠습니까, 아니면 Sepolia 네트워크로 전환하시겠습니까?", "deployNote": "참고: 모든 레벨을 배포하면, 우리는 이 네트워크에서 전체 게임을 제출할 수 있도록 안내할 것입니다.", "deployGame": "게임 배포", diff --git a/client/src/gamedata/pt_br/strings.json b/client/src/gamedata/pt_br/strings.json index ff6e16764..24a20ecda 100644 --- a/client/src/gamedata/pt_br/strings.json +++ b/client/src/gamedata/pt_br/strings.json @@ -21,7 +21,7 @@ "chinese_traditional": "正體中文", "french": "Français", "russian": "Русский", - "vietnamese": "Vietnamese", + "vietnamese": "tiếng Việt", "korean": "한국어", "playNow": "Jogue agora!", "toggleNavigation": "Exibir a navegação", diff --git a/client/src/gamedata/ru/strings.json b/client/src/gamedata/ru/strings.json index 3e09a1c64..5659ada7c 100644 --- a/client/src/gamedata/ru/strings.json +++ b/client/src/gamedata/ru/strings.json @@ -21,9 +21,9 @@ "chinese_traditional": "正體中文", "french": "Français", "russian": "Русский", + "vietnamese": "tiếng Việt", "korean": "한국어", "playNow": "Играть!", - "vietnamese": "Vietnamese", "toggleNavigation": "Показать или скрыть панель навигации", "levelCompleted": "Уровень пройден!", "sources": "Исходный код", diff --git a/client/src/gamedata/tr/strings.json b/client/src/gamedata/tr/strings.json index df448849f..5c65e4226 100644 --- a/client/src/gamedata/tr/strings.json +++ b/client/src/gamedata/tr/strings.json @@ -21,7 +21,7 @@ "chinese_traditional": "正體中文", "french": "Français", "russian": "Русский", - "vietnamese": "Vietnamese", + "vietnamese": "tiếng Việt", "korean": "한국어", "playNow": "Şimdi oyna!", "toggleNavigation": "Menüyü Aç/Kapat", diff --git a/client/src/gamedata/uk/strings.json b/client/src/gamedata/uk/strings.json index 608d35ad4..c6b16d0e2 100644 --- a/client/src/gamedata/uk/strings.json +++ b/client/src/gamedata/uk/strings.json @@ -2,6 +2,8 @@ "ethernaut": "Ethernaut", "title": "Ethernaut", "hiring": "Ми наймаємо", + "ctfRegister": "Register now!", + "ctfInfo": "We are hosting Ethernaut CTF: A 48-hour capture the flag event with prizes and blockchain challenges, starting 16/03.", "info": "

Ethernaut це Web3/Solidity варгейм на базі Ethereum Virtual Machine, натхненний overthewire.org. Кожен рівень є смарт-контрактом, який потрібно 'зламати'. Вихідний код гри повністю відкритий, а всі рівні створені іншими гравцями. У тебе є цікава ідея для нового рівня?

", "home": "Назад", "help": "Допомога", @@ -19,6 +21,7 @@ "chinese_traditional": "正體中文", "french": "Français", "russian": "Русский", + "vietnamese": "tiếng Việt", "korean": "한국어", "playNow": "Грати!", "toggleNavigation": "Показати або приховати панель навігації", @@ -26,12 +29,18 @@ "sources": "Вихідний код", "submitInstance": "Надіслати інстанс на перевірку", "getNewInstance": "Створити новий інстанс", + "accountNotConnectedTitle": "Обліковий запис MetaMask не підключений", + "accountNotConnectedMessage": "Щоб розпочати свою пригоду, підключіть свій гаманець MetaMask! Наша гра взаємодіє безпосередньо з ончейн‑контрактами Ethernaut, тож ваші дії в грі записуються в блокчейн. Підключивши свій обліковий запис MetaMask, ви зможете безпечно взаємодіяти з цими смарт‑контрактами, розв’язувати завдання та просуватися у грі.", + "connectAccount": "Підключити", "deployMessageTitle": "Гра не розгорнута", + "deprecatedNetwork": "Мережа застаріла", + "networkBeingDeprecated": "Мережа позначена як застаріла", "deployMessage": "На даний момент гра підтримує тільки ці мережі:", "deployConfirmation": "Ви хочете розгорнути контракти в цій мережі або переключитись на мережу Sepolia?", "deployNote": "Примітка. Якщо ви розгорнете всі рівні, ми порадимо вам відправити всю розгорнуту гру в цю мережу.", "deployGame": "Розгорнути гру", "switchToSepolia": "Переключитись на Sepolia", + "continueAnyway": "Продовжити все одно", "deployLevel": "Рівень розгортання", "helperDeployAllContracts": "Розгорніть всі залишені контракти в поточній мережі.", "confirmMainnetDeploy": "Ви перебуваєте в основній мережі, гра не має грошової вартості, вам не слід розгортати її в цій мережі.", diff --git a/client/src/gamedata/vi/strings.json b/client/src/gamedata/vi/strings.json index eeb63a50f..e73cd67cc 100644 --- a/client/src/gamedata/vi/strings.json +++ b/client/src/gamedata/vi/strings.json @@ -2,6 +2,8 @@ "ethernaut": "Ethernaut", "title": "The Ethernaut", "hiring": "Chung tôi đang cần tuyển dụng!", + "ctfRegister": "Register now!", + "ctfInfo": "We are hosting Ethernaut CTF: A 48-hour capture the flag event with prizes and blockchain challenges, starting 16/03.", "info": "

Ethernaut là một trò chơi lập trình sử dụng Web3/Solidity lấy cảm hứng từ overthewire.org, được chơi trong Máy ảo Ethereum. Mỗi cấp độ là một hợp đồng thông minh cần được “hack”. 100% trò chơi là mã nguồn mở và tất cả các cấp độ đều được đóng góp bởi những người chơi khác. Bạn có ý tưởng muốn đóng góp? Mọi PR đều được

", "home": "Trang chủ", "help": "Trợ giúp", @@ -11,6 +13,7 @@ "english": "English", "arabic": "عربي", "spanish": "Español", + "ukrainian": "Українська", "portuguese": "Português", "japanese": "日本語", "turkish": "Türkçe", @@ -18,19 +21,26 @@ "chinese_traditional": "正體中文", "french": "Français", "russian": "Русский", - "vietnamese": "Vietnamese", + "vietnamese": "tiếng Việt", + "korean": "한국어", "playNow": "Bắt đầu!", "toggleNavigation": "Bật tắt điều hướng", "levelCompleted": "Hoàn thành!", "sources": "Nguồn", "submitInstance": "Nộp bài", "getNewInstance": "Tạo phiên bản mới", + "accountNotConnectedTitle": "Tài khoản MetaMask chưa được kết nối", + "accountNotConnectedMessage": "Để bắt đầu hành trình, hãy kết nối ví MetaMask của bạn! Trò chơi tương tác trực tiếp với các hợp đồng Ethernaut on-chain, nghĩa là mọi hành động của bạn trong game đều được ghi lại trên blockchain. Bằng cách liên kết tài khoản MetaMask, bạn có thể tương tác an toàn với các hợp đồng thông minh này, giải các thử thách và tiến bộ trong trò chơi.", + "connectAccount": "Kết nối", "deployMessageTitle": "Trò chơi chưa được triển khai", + "deprecatedNetwork": "Mạng đã bị ngừng hỗ trợ", + "networkBeingDeprecated": "Mạng đang bị ngừng hỗ trợ", "deployMessage": "Hiện tại game chỉ hỗ trợ các mạng này:", "deployConfirmation": "Bạn muốn triển khai các hợp đồng trên mạng này hay chuyển sang mạng Sepolia?", "deployNote": "Lưu ý: Nếu bạn triển khai tất cả các cấp độ, chúng tôi sẽ hướng dẫn bạn gửi toàn bộ trò chơi đã triển khai trên mạng này.", "deployGame": "Triển khai trò chơi", "switchToSepolia": "Chuyển sang Sepolia", + "continueAnyway": "Vẫn tiếp tục", "deployLevel": "Triển khai cấp độ", "helperDeployAllContracts": "Triển khai tất cả các hợp đồng còn lại trên mạng hiện tại.", "confirmMainnetDeploy": "Bạn đang ở trên mạng chính, trò chơi không có giá trị tiền tệ, bạn không nên triển khai trên mạng này.", @@ -46,11 +56,11 @@ "player": "Người chơi", "levelName": "Tên cấp độ", "levelAddress": "Địa chỉ của cấp độ", - "blockNum": "Block num", + "blockNum": "Số khối", "uCreated": "Tạo", "lCreated": "tạo", - "instance": "Instance", - "numberOf": "Number of", + "instance": "Phiên bản", + "numberOf": "Số lượng", "warning": "Cảnh báo", "warningMessage": "Không có nhà cung cấp Web3 và trò chơi ở chế độ chỉ đọc", "levelAuthor": "Cấp độ tác giả:", @@ -64,7 +74,7 @@ "slowNetworkMessage": "Thông báo 'Phát hiện mạng chậm' gây khó chịu? Hãy thử cài đặt Công cụ dành cho nhà phát triển -> Chỉ tin nhắn của người dùng hoặc tắt 'chrome://flags/#enable-webfonts-intervention-v2", "notContractSetMessage": "Không có hợp đồng nào được sử dụng, hãy chuyển đến một cấp độ và nhấp vào 'Tạo phiên bản mới'", "levelAddressMessage": "Địa chỉ cấp độ", - "instanceAddressMessage": "Instance address", + "instanceAddressMessage": "Địa chỉ phiên bản", "playerAddressMessage": "Địa chỉ người chơi", "selectedNetworkMessage": "Mạng hiện tại: ", "ethernautAddressMessage": "Địa chỉ Ethernaut", @@ -74,6 +84,7 @@ "unableToRetrieveLevelMessage": "Không thể tạo được hợp đồng mới cho bài tập! Hãy kiểm tra gas và thử lại lần nữa.", "transactionNoLogsMessage": "Giao dịch không được lưu lại", "noPlayerAddressMessage": "Không có địa chỉ người chơi được phát hiện! Đảm bảo rằng 1) Bạn đã cài đặt tiện ích mở rộng trình duyệt metamask và 2) nó đã được mở khóa. 3 tùy chọn) Từ ngày 2 tháng 11, bạn có thể BẬT chế độ bảo mật (TẮT theo mặc định) trong cài đặt nếu bạn không muốn tiết lộ thông tin của mình theo mặc định. 4 tùy chọn) Nếu chế độ riêng tư được BẬT, bạn phải ủy quyền cho Metamask sử dụng trang này. 5) sau đó làm mới", + "noEthersMessage": "Ôi, bạn không có ether! Hãy nhận một ít từ faucet hợp lệ cho mạng bạn chọn", "submitLevelMessage": "Nộp bài...", "wellDoneMessage": "Rất tốt", "completedLevelMessage": "Bạn đã hoàn thành cấp độ này!!!", diff --git a/client/src/gamedata/zh_cn/strings.json b/client/src/gamedata/zh_cn/strings.json index 783522007..988f18a34 100644 --- a/client/src/gamedata/zh_cn/strings.json +++ b/client/src/gamedata/zh_cn/strings.json @@ -21,7 +21,7 @@ "chinese_traditional": "正體中文", "french": "Français", "russian": "Русский", - "vietnamese": "Vietnamese", + "vietnamese": "tiếng Việt", "korean": "한국어", "playNow": "开始!", "toggleNavigation": "切换导航", diff --git a/client/src/gamedata/zh_tw/strings.json b/client/src/gamedata/zh_tw/strings.json index 565b7daea..1a3f14812 100644 --- a/client/src/gamedata/zh_tw/strings.json +++ b/client/src/gamedata/zh_tw/strings.json @@ -21,7 +21,7 @@ "chinese_traditional": "正體中文", "french": "Français", "russian": "Русский", - "vietnamese": "Vietnamese", + "vietnamese": "tiếng Việt", "korean": "한국어", "playNow": "開始!", "toggleNavigation": "切換導覽", From 7715c0183b137f0d2deaf75cb0d8a320e83389e5 Mon Sep 17 00:00:00 2001 From: ippo Date: Mon, 22 Sep 2025 15:53:59 +0700 Subject: [PATCH 4/4] update --- .../vi/descriptions/levels/aliencodex.md | 10 ++++---- .../levels/aliencodex_complete.md | 6 ++--- .../vi/descriptions/levels/coinflip.md | 6 ++--- .../descriptions/levels/coinflip_complete.md | 6 ++--- .../vi/descriptions/levels/delegate.md | 10 ++++---- .../descriptions/levels/delegate_complete.md | 4 ++-- .../gamedata/vi/descriptions/levels/denial.md | 8 +++---- .../vi/descriptions/levels/denial_complete.md | 17 +++++++------ .../gamedata/vi/descriptions/levels/dex.md | 24 +++++++++---------- .../gamedata/vi/descriptions/levels/dex2.md | 10 ++++---- .../vi/descriptions/levels/dex2_complete.md | 10 ++++---- .../vi/descriptions/levels/dex_complete.md | 20 ++++++++-------- .../descriptions/levels/doubleentrypoint.md | 12 +++++----- .../levels/doubleentrypoint_complete.md | 14 +++++------ .../vi/descriptions/levels/elevator.md | 8 +++---- .../descriptions/levels/elevator_complete.md | 6 ++--- .../vi/descriptions/levels/fallback.md | 18 +++++++------- .../descriptions/levels/fallback_complete.md | 6 ++--- .../vi/descriptions/levels/fallout.md | 4 ++-- .../descriptions/levels/fallout_complete.md | 8 +++---- .../gamedata/vi/descriptions/levels/force.md | 12 +++++----- .../vi/descriptions/levels/force_complete.md | 4 ++-- .../vi/descriptions/levels/gatekeeper1.md | 8 +++---- .../levels/gatekeeper1_complete.md | 2 +- .../vi/descriptions/levels/gatekeeper2.md | 10 ++++---- .../levels/gatekeeper2_complete.md | 2 +- .../vi/descriptions/levels/gatekeeper3.md | 10 ++++---- .../levels/gatekeeper3_complete.md | 2 +- .../vi/descriptions/levels/goodsamaritan.md | 6 ++--- .../levels/goodsamaritan_complete.md | 4 ++-- .../gamedata/vi/descriptions/levels/king.md | 6 ++--- .../vi/descriptions/levels/king_complete.md | 4 ++-- .../vi/descriptions/levels/magicnum.md | 14 +++++------ .../descriptions/levels/magicnum_complete.md | 4 ++-- .../vi/descriptions/levels/motorbike.md | 6 ++--- .../descriptions/levels/motorbike_complete.md | 10 ++++---- .../vi/descriptions/levels/naughtcoin.md | 8 +++---- .../levels/naughtcoin_complete.md | 2 +- .../vi/descriptions/levels/preservation.md | 20 +++++++--------- .../levels/preservation_complete.md | 10 ++++---- .../vi/descriptions/levels/privacy.md | 16 ++++++------- .../descriptions/levels/privacy_complete.md | 4 ++-- .../vi/descriptions/levels/puzzle_wallet.md | 22 ++++++++--------- .../levels/puzzle_wallet_complete.md | 8 +++---- .../vi/descriptions/levels/recovery.md | 4 ++-- .../descriptions/levels/recovery_complete.md | 8 +++---- .../vi/descriptions/levels/reentrancy.md | 12 +++++----- .../levels/reentrancy_complete.md | 12 +++++----- .../gamedata/vi/descriptions/levels/shop.md | 8 +++---- .../vi/descriptions/levels/shop_complete.md | 4 ++-- .../gamedata/vi/descriptions/levels/switch.md | 6 ++--- .../vi/descriptions/levels/switch_complete.md | 2 +- .../vi/descriptions/levels/telephone.md | 6 ++--- .../descriptions/levels/telephone_complete.md | 10 ++++---- .../gamedata/vi/descriptions/levels/token.md | 8 +++---- .../vi/descriptions/levels/token_complete.md | 8 +++---- .../vi/descriptions/levels/unstoppable.md | 6 ++--- .../gamedata/vi/descriptions/levels/vault.md | 2 +- .../vi/descriptions/levels/vault_complete.md | 4 ++-- client/src/gamedata/vi/strings.json | 8 +++---- 60 files changed, 253 insertions(+), 256 deletions(-) diff --git a/client/src/gamedata/vi/descriptions/levels/aliencodex.md b/client/src/gamedata/vi/descriptions/levels/aliencodex.md index 061e47c5d..48365b6de 100644 --- a/client/src/gamedata/vi/descriptions/levels/aliencodex.md +++ b/client/src/gamedata/vi/descriptions/levels/aliencodex.md @@ -1,7 +1,7 @@ -You've uncovered an Alien contract. Claim ownership to complete the level. +Bạn đã phát hiện ra một hợp đồng Alien. Hãy chiếm quyền sở hữu để hoàn thành cấp độ này.   -Things that might help -* Understanding how array storage works -* Understanding [ABI specifications](https://solidity.readthedocs.io/en/v0.4.21/abi-spec.html) -* Using a very `underhanded` approach +Những điều có thể hữu ích +* Hiểu cách lưu trữ mảng hoạt động +* Hiểu [đặc tả ABI](https://solidity.readthedocs.io/en/v0.4.21/abi-spec.html) +* Sử dụng một cách tiếp cận rất `gian lận` diff --git a/client/src/gamedata/vi/descriptions/levels/aliencodex_complete.md b/client/src/gamedata/vi/descriptions/levels/aliencodex_complete.md index 99479e714..e78884878 100644 --- a/client/src/gamedata/vi/descriptions/levels/aliencodex_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/aliencodex_complete.md @@ -1,5 +1,5 @@ -This level exploits the fact that the EVM doesn't validate an array's ABI-encoded length vs its actual payload. +Cấp độ này khai thác thực tế rằng EVM không xác thực độ dài được mã hóa ABI của mảng so với payload thực tế của nó. -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. +Ngoài ra, nó khai thác underflow số học của độ dài mảng, bằng cách mở rộng giới hạn của mảng đến toàn bộ vùng lưu trữ của `2^256`. Người dùng sau đó có thể sửa đổi tất cả lưu trữ hợp đồng. -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) \ No newline at end of file +Cả hai lỗ hổng đều được lấy cảm hứng từ [cuộc thi lập trình Underhanded 2017](https://medium.com/@weka/announcing-the-winners-of-the-first-underhanded-solidity-coding-contest-282563a87079) \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/coinflip.md b/client/src/gamedata/vi/descriptions/levels/coinflip.md index 64a2d9bc0..1b6540521 100644 --- a/client/src/gamedata/vi/descriptions/levels/coinflip.md +++ b/client/src/gamedata/vi/descriptions/levels/coinflip.md @@ -1,5 +1,5 @@ -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. +Đây là trò chơi tung đồng xu nơi bạn cần xây dựng chuỗi thắng bằng cách đoán kết quả của việc tung đồng xu. Để hoàn thành cấp độ này, bạn cần sử dụng khả năng tâm linh để đoán đúng kết quả 10 lần liên tiếp.   -Things that might help -* See the ["?"](https://ethernaut.openzeppelin.com/help) page above in the top right corner menu, section "Beyond the console" \ No newline at end of file +Những điều có thể hữu ích +* Xem trang ["?"](https://ethernaut.openzeppelin.com/help) ở trên trong menu góc trên bên phải, phần "Beyond the console" \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/coinflip_complete.md b/client/src/gamedata/vi/descriptions/levels/coinflip_complete.md index 47710b6d5..9424ad62f 100644 --- a/client/src/gamedata/vi/descriptions/levels/coinflip_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/coinflip_complete.md @@ -1,6 +1,6 @@ -Generating random numbers in solidity can be tricky. There currently isn't a native way to generate them, and everything you use in smart contracts is publicly visible, including the local variables and state variables marked as private. Miners also have control over things like blockhashes, timestamps, and whether to include certain transactions - which allows them to bias these values in their favor. +Tạo số ngẫu nhiên trong solidity có thể khó khăn. Hiện tại không có cách bản địa để tạo chúng, và mọi thứ bạn sử dụng trong hợp đồng thông minh đều có thể nhìn thấy công khai, bao gồm các biến cục bộ và biến trạng thái được đánh dấu là private. Các thợ mỏ cũng có quyền kiểm soát những thứ như blockhashes, timestamps, và việc có bao gồm các giao dịch nhất định hay không - điều này cho phép họ thiên vị các giá trị này có lợi cho họ. -To get cryptographically proven random numbers, you can use [Chainlink VRF](https://docs.chain.link/docs/get-a-random-number), which uses an oracle, the LINK token, and an on-chain contract to verify that the number is truly random. +Để có được số ngẫu nhiên được chứng minh bằng mật mã, bạn có thể sử dụng [Chainlink VRF](https://docs.chain.link/docs/get-a-random-number), sử dụng oracle, token LINK, và hợp đồng on-chain để xác minh rằng số đó thực sự ngẫu nhiên. -Some other options include using Bitcoin block headers (verified through [BTC Relay](http://btcrelay.org)), [RANDAO](https://github.com/randao/randao), or [Oraclize](http://www.oraclize.it/)). +Một số tùy chọn khác bao gồm sử dụng Bitcoin block headers (được xác minh thông qua [BTC Relay](http://btcrelay.org)), [RANDAO](https://github.com/randao/randao), hoặc [Oraclize](http://www.oraclize.it/)). diff --git a/client/src/gamedata/vi/descriptions/levels/delegate.md b/client/src/gamedata/vi/descriptions/levels/delegate.md index 7a8fed34a..f849d1bc9 100644 --- a/client/src/gamedata/vi/descriptions/levels/delegate.md +++ b/client/src/gamedata/vi/descriptions/levels/delegate.md @@ -1,7 +1,7 @@ -The goal of this level is for you to claim ownership of the instance you are given. +Mục tiêu của cấp độ này là bạn phải chiếm quyền sở hữu của phiên bản được cung cấp.   -Things that might help -* 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. -* Fallback methods -* Method ids +Những điều có thể hữu ích +* Tìm hiểu tài liệu Solidity về hàm cấp thấp `delegatecall`, cách nó hoạt động, cách sử dụng để ủy quyền các thao tác cho thư viện on-chain, và những tác động của nó đến phạm vi thực thi. +* Phương thức fallback +* ID phương thức diff --git a/client/src/gamedata/vi/descriptions/levels/delegate_complete.md b/client/src/gamedata/vi/descriptions/levels/delegate_complete.md index 42e2f87ef..ba3a0a63a 100644 --- a/client/src/gamedata/vi/descriptions/levels/delegate_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/delegate_complete.md @@ -1,5 +1,5 @@ -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. +Việc sử dụng `delegatecall` đặc biệt rủi ro và đã được sử dụng làm vector tấn công trong nhiều vụ hack lịch sử. Với nó, hợp đồng của bạn thực tế đang nói "đây, -hợp đồng khác- hoặc -thư viện khác-, làm bất cứ điều gì bạn muốn với trạng thái của tôi". Các delegate có quyền truy cập hoàn toàn vào trạng thái hợp đồng của bạn. Hàm `delegatecall` là một tính năng mạnh mẽ, nhưng nguy hiểm, và phải được sử dụng với sự cẩn thận tối đa. -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. +Vui lòng tham khảo bài viết [The Parity Wallet Hack Explained](https://blog.openzeppelin.com/on-the-parity-wallet-multisig-hack-405a8c12e8f7) để có giải thích chính xác về cách ý tưởng này được sử dụng để đánh cắp 30M USD. diff --git a/client/src/gamedata/vi/descriptions/levels/denial.md b/client/src/gamedata/vi/descriptions/levels/denial.md index 330d3e0ff..99b8777cc 100644 --- a/client/src/gamedata/vi/descriptions/levels/denial.md +++ b/client/src/gamedata/vi/descriptions/levels/denial.md @@ -1,5 +1,5 @@ -This is a simple wallet that drips funds over time. You can withdraw the funds -slowly by becoming a withdrawing partner. +Đây là một ví đơn giản nhỏ giọt tiền theo thời gian. Bạn có thể rút tiền +từ từ bằng cách trở thành đối tác rút tiền. -If you can deny the owner from withdrawing funds when they call `withdraw()` -(whilst the contract still has funds, and the transaction is of 1M gas or less) you will win this level. +Nếu bạn có thể ngăn chủ sở hữu rút tiền khi họ gọi `withdraw()` +(trong khi hợp đồng vẫn còn tiền, và giao dịch có gas 1M hoặc ít hơn) bạn sẽ thắng cấp độ này. diff --git a/client/src/gamedata/vi/descriptions/levels/denial_complete.md b/client/src/gamedata/vi/descriptions/levels/denial_complete.md index 43970a1c7..4a3df7ad2 100644 --- a/client/src/gamedata/vi/descriptions/levels/denial_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/denial_complete.md @@ -1,12 +1,11 @@ -This level demonstrates that external calls to unknown contracts can still -create denial of service attack vectors if a fixed amount of gas is not -specified. +Cấp độ này chứng minh rằng các lệnh gọi bên ngoài đến các hợp đồng không xác định vẫn có thể +tạo ra các vector tấn công từ chối dịch vụ nếu không chỉ định một lượng gas cố định. -If you are using a low level `call` to continue executing in the event an external call reverts, ensure that you specify a fixed gas stipend. For example `call.gas(100000).value()`. +Nếu bạn đang sử dụng `call` cấp thấp để tiếp tục thực thi trong trường hợp lệnh gọi bên ngoài revert, hãy đảm bảo rằng bạn chỉ định một khoản gas cố định. Ví dụ `call.gas(100000).value()`. -Typically one should follow the [checks-effects-interactions](http://solidity.readthedocs.io/en/latest/security-considerations.html#use-the-checks-effects-interactions-pattern) pattern to avoid reentrancy attacks, there can be other circumstances (such as multiple external calls at the end of a function) where issues such as this can arise. +Thông thường người ta nên tuân theo mẫu [checks-effects-interactions](http://solidity.readthedocs.io/en/latest/security-considerations.html#use-the-checks-effects-interactions-pattern) để tránh các cuộc tấn công reentrancy, có thể có các trường hợp khác (như nhiều lệnh gọi bên ngoài ở cuối hàm) nơi các vấn đề như vậy có thể phát sinh. -*Note*: An external `CALL` can use at most 63/64 of the gas currently available -at the time of the `CALL`. Thus, depending on how much gas is required to -complete a transaction, a transaction of sufficiently high gas (i.e. one such -that 1/64 of the gas is capable of completing the remaining opcodes in the parent call) can be used to mitigate this particular attack. \ No newline at end of file +*Lưu ý*: Một `CALL` bên ngoài có thể sử dụng tối đa 63/64 gas hiện có +tại thời điểm `CALL`. Do đó, tùy thuộc vào lượng gas cần thiết để +hoàn thành một giao dịch, một giao dịch có gas đủ cao (tức là một giao dịch như vậy +mà 1/64 gas có khả năng hoàn thành các opcode còn lại trong lệnh gọi cha) có thể được sử dụng để giảm thiểu cuộc tấn công cụ thể này. \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/dex.md b/client/src/gamedata/vi/descriptions/levels/dex.md index 3abcb1d22..a0d3c8292 100644 --- a/client/src/gamedata/vi/descriptions/levels/dex.md +++ b/client/src/gamedata/vi/descriptions/levels/dex.md @@ -1,18 +1,18 @@ -The goal of this level is for you to hack the basic [DEX](https://en.wikipedia.org/wiki/Decentralized_exchange) contract below and steal the funds by price manipulation. +Mục tiêu của cấp độ này là bạn phải hack hợp đồng [DEX](https://en.wikipedia.org/wiki/Decentralized_exchange) cơ bản bên dưới và đánh cắp tiền bằng cách thao túng giá. -You will start with 10 tokens of `token1` and 10 of `token2`. The DEX contract starts with 100 of each token. +Bạn sẽ bắt đầu với 10 token của `token1` và 10 của `token2`. Hợp đồng DEX bắt đầu với 100 của mỗi token. -You will be successful in this level if you manage to drain all of at least 1 of the 2 tokens from the contract, and allow the contract to report a "bad" price of the assets. +Bạn sẽ thành công trong cấp độ này nếu bạn quản lý để rút hết ít nhất 1 trong 2 token từ hợp đồng, và cho phép hợp đồng báo cáo giá "xấu" của tài sản.   -### Quick note -Normally, when you make a swap with an ERC20 token, you have to `approve` the contract to spend your tokens for you. To keep with the syntax of the game, we've just added the `approve` method to the contract itself. So feel free to use `contract.approve(contract.address, )` instead of calling the tokens directly, and it will automatically approve spending the two tokens by the desired amount. Feel free to ignore the `SwappableToken` contract otherwise. +### Lưu ý nhanh +Thông thường, khi bạn thực hiện swap với token ERC20, bạn phải `approve` hợp đồng để chi tiêu token của bạn. Để phù hợp với cú pháp của trò chơi, chúng tôi đã thêm phương thức `approve` vào chính hợp đồng. Vì vậy hãy thoải mái sử dụng `contract.approve(contract.address, )` thay vì gọi token trực tiếp, và nó sẽ tự động phê duyệt chi tiêu hai token với số lượng mong muốn. Hãy thoải mái bỏ qua hợp đồng `SwappableToken` nếu không.   -Things that might help: -* How is the price of the token calculated? -* How does the `swap` method work? -* How do you `approve` a transaction of an ERC20? -* Theres more than one way to interact with a contract! -* Remix might help -* What does "At Address" do? +Những điều có thể hữu ích: +* Giá của token được tính như thế nào? +* Phương thức `swap` hoạt động như thế nào? +* Làm thế nào để `approve` một giao dịch của ERC20? +* Có nhiều hơn một cách để tương tác với hợp đồng! +* Remix có thể hữu ích +* "At Address" làm gì? diff --git a/client/src/gamedata/vi/descriptions/levels/dex2.md b/client/src/gamedata/vi/descriptions/levels/dex2.md index 7a4a2a56d..b41e579a4 100644 --- a/client/src/gamedata/vi/descriptions/levels/dex2.md +++ b/client/src/gamedata/vi/descriptions/levels/dex2.md @@ -1,9 +1,9 @@ -This level will ask you to break `DexTwo`, a subtlely modified `Dex` contract from the previous level, in a different way. +Cấp độ này sẽ yêu cầu bạn phá vỡ `DexTwo`, một hợp đồng `Dex` được sửa đổi tinh tế từ cấp độ trước, theo một cách khác. -You need to drain all balances of token1 and token2 from the `DexTwo` contract to succeed in this level. +Bạn cần rút hết số dư của token1 và token2 từ hợp đồng `DexTwo` để thành công trong cấp độ này. -You will still start with 10 tokens of `token1` and 10 of `token2`. The DEX contract still starts with 100 of each token. +Bạn vẫn sẽ bắt đầu với 10 token của `token1` và 10 của `token2`. Hợp đồng DEX vẫn bắt đầu với 100 của mỗi token.   -Things that might help: -* How has the `swap` method been modified? +Những điều có thể hữu ích: +* Phương thức `swap` đã được sửa đổi như thế nào? diff --git a/client/src/gamedata/vi/descriptions/levels/dex2_complete.md b/client/src/gamedata/vi/descriptions/levels/dex2_complete.md index 64cc56917..4c3135ec1 100644 --- a/client/src/gamedata/vi/descriptions/levels/dex2_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/dex2_complete.md @@ -1,9 +1,9 @@ -As we've repeatedly seen, interaction between contracts can be a source of unexpected behavior. +Như chúng ta đã thấy nhiều lần, tương tác giữa các hợp đồng có thể là nguồn gốc của hành vi không mong đợi. -Just because a contract claims to implement the [ERC20 spec](https://eips.ethereum.org/EIPS/eip-20) does not mean it's trust worthy. +Chỉ vì một hợp đồng tuyên bố triển khai [đặc tả ERC20](https://eips.ethereum.org/EIPS/eip-20) không có nghĩa là nó đáng tin cậy. -Some tokens deviate from the ERC20 spec by not returning a boolean value from their `transfer` methods. See [Missing return value bug - At least 130 tokens affected](https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca). +Một số token lệch khỏi đặc tả ERC20 bằng cách không trả về giá trị boolean từ các phương thức `transfer` của chúng. Xem [Lỗi thiếu giá trị trả về - Ít nhất 130 token bị ảnh hưởng](https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca). -Other ERC20 tokens, especially those designed by adversaries could behave more maliciously. +Các token ERC20 khác, đặc biệt là những token được thiết kế bởi kẻ thù có thể hành xử độc hại hơn. -If you design a DEX where anyone could list their own tokens without the permission of a central authority, then the correctness of the DEX could depend on the interaction of the DEX contract and the token contracts being traded. +Nếu bạn thiết kế một DEX nơi bất kỳ ai cũng có thể liệt kê token của riêng họ mà không cần sự cho phép của cơ quan trung ương, thì tính đúng đắn của DEX có thể phụ thuộc vào tương tác của hợp đồng DEX và các hợp đồng token được giao dịch. diff --git a/client/src/gamedata/vi/descriptions/levels/dex_complete.md b/client/src/gamedata/vi/descriptions/levels/dex_complete.md index a9af3062f..46a37daa3 100644 --- a/client/src/gamedata/vi/descriptions/levels/dex_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/dex_complete.md @@ -1,17 +1,17 @@ -The integer math portion aside, getting prices or any sort of data from any single source is a massive attack vector in smart contracts. +Bỏ qua phần toán học số nguyên, việc lấy giá hoặc bất kỳ loại dữ liệu nào từ một nguồn duy nhất là một vector tấn công lớn trong hợp đồng thông minh. -You can clearly see from this example, that someone with a lot of capital could manipulate the price in one fell swoop, and cause any applications relying on it to use the the wrong price. +Bạn có thể thấy rõ từ ví dụ này, rằng ai đó có nhiều vốn có thể thao túng giá trong một cú đánh, và khiến bất kỳ ứng dụng nào dựa vào nó sử dụng giá sai. -The exchange itself is decentralized, but the price of the asset is centralized, since it comes from 1 dex. However, if we were to consider tokens that represent actual assets rather than fictitious ones, most of them would have exchange pairs in several dexes and networks. This would decrease the effect on the asset's price in case a specific dex is targeted by an attack like this. +Bản thân sàn giao dịch là phi tập trung, nhưng giá của tài sản lại tập trung, vì nó đến từ 1 dex. Tuy nhiên, nếu chúng ta xem xét các token đại diện cho tài sản thực tế thay vì tài sản hư cấu, hầu hết chúng sẽ có các cặp trao đổi trong nhiều dex và mạng. Điều này sẽ giảm tác động đến giá tài sản trong trường hợp một dex cụ thể bị tấn công như vậy. -[Oracles](https://betterprogramming.pub/what-is-a-blockchain-oracle-f5ccab8dbd72?source=friends_link&sk=d921a38466df8a9176ed8dd767d8c77d) are used to get data into and out of smart contracts. +[Oracles](https://betterprogramming.pub/what-is-a-blockchain-oracle-f5ccab8dbd72?source=friends_link&sk=d921a38466df8a9176ed8dd767d8c77d) được sử dụng để lấy dữ liệu vào và ra khỏi hợp đồng thông minh. -[Chainlink Data Feeds](https://docs.chain.link/docs/get-the-latest-price) are a secure, reliable, way to get decentralized data into your smart contracts. They have a vast library of many different sources, and also offer [secure randomness](https://docs.chain.link/docs/chainlink-vrf), ability to make [any API call](https://docs.chain.link/docs/make-a-http-get-request), [modular oracle network creation](https://docs.chain.link/docs/architecture-decentralized-model), [upkeep, actions, and maintainance](https://docs.chain.link/docs/kovan-keeper-network-beta), and unlimited customization. +[Chainlink Data Feeds](https://docs.chain.link/docs/get-the-latest-price) là một cách an toàn, đáng tin cậy để lấy dữ liệu phi tập trung vào hợp đồng thông minh của bạn. Chúng có một thư viện rộng lớn với nhiều nguồn khác nhau, và cũng cung cấp [tính ngẫu nhiên an toàn](https://docs.chain.link/docs/chainlink-vrf), khả năng thực hiện [bất kỳ lệnh gọi API nào](https://docs.chain.link/docs/make-a-http-get-request), [tạo mạng oracle mô-đun](https://docs.chain.link/docs/architecture-decentralized-model), [bảo trì, hành động và duy trì](https://docs.chain.link/docs/kovan-keeper-network-beta), và tùy chỉnh không giới hạn. -[Uniswap TWAP Oracles](https://docs.uniswap.org/contracts/v2/concepts/core-concepts/oracles) relies on a time weighted price model called [TWAP](https://en.wikipedia.org/wiki/Time-weighted_average_price#). While the design can be attractive, this protocol heavily depends on the liquidity of the DEX protocol, and if this is too low, prices can be easily manipulated. +[Uniswap TWAP Oracles](https://docs.uniswap.org/contracts/v2/concepts/core-concepts/oracles) dựa vào mô hình giá trọng số thời gian gọi là [TWAP](https://en.wikipedia.org/wiki/Time-weighted_average_price#). Mặc dù thiết kế có thể hấp dẫn, giao thức này phụ thuộc nhiều vào tính thanh khoản của giao thức DEX, và nếu điều này quá thấp, giá có thể dễ dàng bị thao túng. -Here is an example of getting the price of Bitcoin in USD from a Chainlink data feed (on the Sepolia testnet): +Đây là một ví dụ về việc lấy giá Bitcoin bằng USD từ Chainlink data feed (trên Sepolia testnet): ``` // SPDX-License-Identifier: MIT @@ -50,9 +50,9 @@ contract PriceConsumerV3 { } ``` -[Try it on Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/PriceFeeds/PriceConsumerV3.sol) +[Thử trên Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/PriceFeeds/PriceConsumerV3.sol) -Check the Chainlink feed [page](https://data.chain.link/ethereum/mainnet/crypto-usd/btc-usd) to see that the price of Bitcoin is queried from up to 31 different sources. +Kiểm tra [trang](https://data.chain.link/ethereum/mainnet/crypto-usd/btc-usd) Chainlink feed để xem rằng giá Bitcoin được truy vấn từ tối đa 31 nguồn khác nhau. -You can check also, the [list](https://docs.chain.link/data-feeds/price-feeds/addresses/) all Chainlink price feeds addresses. +Bạn cũng có thể kiểm tra [danh sách](https://docs.chain.link/data-feeds/price-feeds/addresses/) tất cả địa chỉ Chainlink price feeds. diff --git a/client/src/gamedata/vi/descriptions/levels/doubleentrypoint.md b/client/src/gamedata/vi/descriptions/levels/doubleentrypoint.md index 4cadf9de9..98324cfe8 100644 --- a/client/src/gamedata/vi/descriptions/levels/doubleentrypoint.md +++ b/client/src/gamedata/vi/descriptions/levels/doubleentrypoint.md @@ -1,10 +1,10 @@ -This level features a `CryptoVault` with special functionality, the `sweepToken` function. This is a common function used to retrieve tokens stuck in a contract. The `CryptoVault` operates with an `underlying` token that can't be swept, as it is an important core logic component of the `CryptoVault`. Any other tokens can be swept. +Cấp độ này có một `CryptoVault` với chức năng đặc biệt, hàm `sweepToken`. Đây là một hàm phổ biến được sử dụng để lấy lại token bị kẹt trong hợp đồng. `CryptoVault` hoạt động với một token `underlying` không thể bị quét, vì nó là thành phần logic cốt lõi quan trọng của `CryptoVault`. Bất kỳ token nào khác đều có thể bị quét. -The underlying token is an instance of the DET token implemented in the `DoubleEntryPoint` contract definition and the `CryptoVault` holds 100 units of it. Additionally the `CryptoVault` also holds 100 of `LegacyToken LGT`. +Token underlying là một phiên bản của token DET được triển khai trong định nghĩa hợp đồng `DoubleEntryPoint` và `CryptoVault` nắm giữ 100 đơn vị của nó. Ngoài ra `CryptoVault` cũng nắm giữ 100 `LegacyToken LGT`. -In this level you should figure out where the bug is in `CryptoVault` and protect it from being drained out of tokens. +Trong cấp độ này bạn nên tìm ra lỗi ở đâu trong `CryptoVault` và bảo vệ nó khỏi bị rút hết token. -The contract features a `Forta` contract where any user can register its own `detection bot` contract. Forta is a decentralized, community-based monitoring network to detect threats and anomalies on DeFi, NFT, governance, bridges and other Web3 systems as quickly as possible. Your job is to implement a `detection bot` and register it in the `Forta` contract. The bot's implementation will need to raise correct alerts to prevent potential attacks or bug exploits. +Hợp đồng có một hợp đồng `Forta` nơi bất kỳ người dùng nào cũng có thể đăng ký hợp đồng `detection bot` của riêng mình. Forta là một mạng giám sát phi tập trung, dựa trên cộng đồng để phát hiện các mối đe dọa và bất thường trên DeFi, NFT, quản trị, cầu nối và các hệ thống Web3 khác một cách nhanh chóng nhất có thể. Nhiệm vụ của bạn là triển khai một `detection bot` và đăng ký nó trong hợp đồng `Forta`. Việc triển khai bot sẽ cần đưa ra cảnh báo chính xác để ngăn chặn các cuộc tấn công tiềm ẩn hoặc khai thác lỗi. -Things that might help: -- How does a double entry point work for a token contract? +Những điều có thể hữu ích: +- Double entry point hoạt động như thế nào cho hợp đồng token? diff --git a/client/src/gamedata/vi/descriptions/levels/doubleentrypoint_complete.md b/client/src/gamedata/vi/descriptions/levels/doubleentrypoint_complete.md index 5137f9b31..50e0d4bca 100644 --- a/client/src/gamedata/vi/descriptions/levels/doubleentrypoint_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/doubleentrypoint_complete.md @@ -1,13 +1,13 @@ -Congratulations! +Chúc mừng! -This is the first experience you have with a [Forta bot](https://docs.forta.network/en/latest/). +Đây là trải nghiệm đầu tiên của bạn với [Forta bot](https://docs.forta.network/en/latest/). -Forta comprises a decentralized network of independent node operators who scan all transactions and block-by-block state changes for outlier transactions and threats. When an issue is detected, node operators send alerts to subscribers of potential risks, which enables them to take action. +Forta bao gồm một mạng phi tập trung của các nhà điều hành nút độc lập quét tất cả các giao dịch và thay đổi trạng thái theo từng khối để tìm các giao dịch bất thường và mối đe dọa. Khi phát hiện vấn đề, các nhà điều hành nút gửi cảnh báo cho người đăng ký về các rủi ro tiềm ẩn, cho phép họ hành động. -The presented example is just for educational purpose since Forta bot is not modeled into smart contracts. In Forta, a bot is a code script to detect specific conditions or events, but when an alert is emitted it does not trigger automatic actions - at least not yet. In this level, the bot's alert effectively trigger a revert in the transaction, deviating from the intended Forta's bot design. +Ví dụ được trình bày chỉ dành cho mục đích giáo dục vì Forta bot không được mô hình hóa thành hợp đồng thông minh. Trong Forta, bot là một script mã để phát hiện các điều kiện hoặc sự kiện cụ thể, nhưng khi cảnh báo được phát ra, nó không kích hoạt các hành động tự động - ít nhất là chưa. Trong cấp độ này, cảnh báo của bot hiệu quả kích hoạt revert trong giao dịch, lệch khỏi thiết kế bot dự định của Forta. -Detection bots heavily depends on contract's final implementations and some might be upgradeable and break bot's integrations, but to mitigate that you can even create a specific bot to look for contract upgrades and react to it. Learn how to do it [here](https://docs.forta.network/en/latest/quickstart/). +Detection bot phụ thuộc nhiều vào triển khai cuối cùng của hợp đồng và một số có thể nâng cấp và phá vỡ tích hợp bot, nhưng để giảm thiểu điều đó, bạn thậm chí có thể tạo một bot cụ thể để tìm kiếm nâng cấp hợp đồng và phản ứng với nó. Tìm hiểu cách làm điều đó [tại đây](https://docs.forta.network/en/latest/quickstart/). -You have also passed through a recent security issue that has been uncovered during OpenZeppelin's latest [collaboration with Compound protocol](https://compound.finance/governance/proposals/76). +Bạn cũng đã trải qua một vấn đề bảo mật gần đây đã được phát hiện trong [hợp tác mới nhất của OpenZeppelin với giao thức Compound](https://compound.finance/governance/proposals/76). -Having tokens that present a double entry point is a non-trivial pattern that might affect many protocols. This is because it is commonly assumed to have one contract per token. But it was not the case this time :) You can read the entire details of what happened [here](https://blog.openzeppelin.com/compound-tusd-integration-issue-retrospective/). +Có token trình bày double entry point là một mẫu không tầm thường có thể ảnh hưởng đến nhiều giao thức. Điều này là do người ta thường giả định có một hợp đồng cho mỗi token. Nhưng lần này không phải vậy :) Bạn có thể đọc toàn bộ chi tiết về những gì đã xảy ra [tại đây](https://blog.openzeppelin.com/compound-tusd-integration-issue-retrospective/). diff --git a/client/src/gamedata/vi/descriptions/levels/elevator.md b/client/src/gamedata/vi/descriptions/levels/elevator.md index b6fda6f57..8e633b6cc 100644 --- a/client/src/gamedata/vi/descriptions/levels/elevator.md +++ b/client/src/gamedata/vi/descriptions/levels/elevator.md @@ -1,5 +1,5 @@ -This elevator won't let you reach the top of your building. Right? +Thang máy này sẽ không cho phép bạn lên đến đỉnh tòa nhà. Đúng không? -##### Things that might help: -* Sometimes solidity is not good at keeping promises. -* This `Elevator` expects to be used from a `Building`. \ No newline at end of file +##### Những điều có thể hữu ích: +* Đôi khi solidity không giỏi giữ lời hứa. +* `Elevator` này mong đợi được sử dụng từ một `Building`. \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/elevator_complete.md b/client/src/gamedata/vi/descriptions/levels/elevator_complete.md index 3d3f059b8..7072188e4 100644 --- a/client/src/gamedata/vi/descriptions/levels/elevator_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/elevator_complete.md @@ -1,4 +1,4 @@ -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. -Make sure you read [Solidity's documentation](http://solidity.readthedocs.io/en/develop/contracts.html#view-functions) and learn its caveats. +Bạn có thể sử dụng modifier hàm `view` trên một interface để ngăn chặn các thay đổi trạng thái. Modifier `pure` cũng ngăn các hàm thay đổi trạng thái. +Hãy đảm bảo bạn đọc [tài liệu Solidity](http://solidity.readthedocs.io/en/develop/contracts.html#view-functions) và tìm hiểu các lưu ý của nó. -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()`. \ No newline at end of file +Một cách khác để giải cấp độ này là xây dựng một hàm view trả về kết quả khác nhau tùy thuộc vào dữ liệu đầu vào nhưng không thay đổi trạng thái, ví dụ `gasleft()`. \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/fallback.md b/client/src/gamedata/vi/descriptions/levels/fallback.md index d80e7e8cb..b6a57db34 100644 --- a/client/src/gamedata/vi/descriptions/levels/fallback.md +++ b/client/src/gamedata/vi/descriptions/levels/fallback.md @@ -1,12 +1,12 @@ -Look carefully at the contract's code below. +Hãy xem kỹ mã hợp đồng bên dưới. -You will beat this level if -1) you claim ownership of the contract -2) you reduce its balance to 0 +Bạn sẽ thắng cấp độ này nếu +1) bạn chiếm quyền sở hữu của hợp đồng +2) bạn giảm số dư của nó xuống 0   -Things that might help -* How to send ether when interacting with an ABI -* How to send ether outside of the ABI -* Converting to and from wei/ether units (see `help()` command) -* Fallback methods +Những điều có thể hữu ích +* Cách gửi ether khi tương tác với ABI +* Cách gửi ether bên ngoài ABI +* Chuyển đổi từ và sang đơn vị wei/ether (xem lệnh `help()`) +* Phương thức fallback diff --git a/client/src/gamedata/vi/descriptions/levels/fallback_complete.md b/client/src/gamedata/vi/descriptions/levels/fallback_complete.md index 941136c47..8ed52713f 100644 --- a/client/src/gamedata/vi/descriptions/levels/fallback_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/fallback_complete.md @@ -1,5 +1,5 @@ -You know the basics of how ether goes in and out of contracts, including the usage of the fallback method. +Bạn biết những điều cơ bản về cách ether vào và ra khỏi hợp đồng, bao gồm việc sử dụng phương thức fallback. -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. +Bạn cũng đã học về hợp đồng Ownable của OpenZeppelin, và cách nó có thể được sử dụng để hạn chế việc sử dụng một số phương thức cho một địa chỉ đặc quyền. -Move on to the next level when you're ready! +Chuyển sang cấp độ tiếp theo khi bạn sẵn sàng! diff --git a/client/src/gamedata/vi/descriptions/levels/fallout.md b/client/src/gamedata/vi/descriptions/levels/fallout.md index 4063c71dc..4354ed8a4 100644 --- a/client/src/gamedata/vi/descriptions/levels/fallout.md +++ b/client/src/gamedata/vi/descriptions/levels/fallout.md @@ -1,5 +1,5 @@ -Claim ownership of the contract below to complete this level. +Chiếm quyền sở hữu của hợp đồng bên dưới để hoàn thành cấp độ này.   -Things that might help +Những điều có thể hữu ích * Solidity Remix IDE diff --git a/client/src/gamedata/vi/descriptions/levels/fallout_complete.md b/client/src/gamedata/vi/descriptions/levels/fallout_complete.md index ebbfbdbe6..44576011b 100644 --- a/client/src/gamedata/vi/descriptions/levels/fallout_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/fallout_complete.md @@ -1,8 +1,8 @@ -That was silly wasn't it? Real world contracts must be much more secure than this and so must it be much harder to hack them right? +Điều đó thật ngớ ngẩn phải không? Các hợp đồng thực tế phải an toàn hơn nhiều so với điều này và vì vậy phải khó hack hơn nhiều phải không? -Well... Not quite. +Chà... Không hẳn vậy. -The story of Rubixi is a very well known case in the Ethereum ecosystem. The company changed its name from 'Dynamic Pyramid' to 'Rubixi' but somehow they didn't rename the constructor method of its contract: +Câu chuyện của Rubixi là một trường hợp rất nổi tiếng trong hệ sinh thái Ethereum. Công ty đã đổi tên từ 'Dynamic Pyramid' thành 'Rubixi' nhưng bằng cách nào đó họ không đổi tên phương thức constructor của hợp đồng: ``` contract Rubixi { @@ -12,4 +12,4 @@ contract Rubixi { ... ``` -This allowed the attacker to call the old constructor and claim ownership of the contract, and steal some funds. Yep. Big mistakes can be made in smartcontractland. +Điều này cho phép kẻ tấn công gọi constructor cũ và chiếm quyền sở hữu hợp đồng, và đánh cắp một số tiền. Vâng. Những sai lầm lớn có thể được thực hiện trong smartcontractland. diff --git a/client/src/gamedata/vi/descriptions/levels/force.md b/client/src/gamedata/vi/descriptions/levels/force.md index 896868f23..3aa4bb5d8 100644 --- a/client/src/gamedata/vi/descriptions/levels/force.md +++ b/client/src/gamedata/vi/descriptions/levels/force.md @@ -1,9 +1,9 @@ -Some contracts will simply not take your money `¯\_(ツ)_/¯` +Một số hợp đồng sẽ đơn giản không nhận tiền của bạn `¯\_(ツ)_/¯` -The goal of this level is to make the balance of the contract greater than zero. +Mục tiêu của cấp độ này là làm cho số dư của hợp đồng lớn hơn không.   -Things that might help: -* Fallback methods -* Sometimes the best way to attack a contract is with another contract. -* See the ["?"](https://ethernaut.openzeppelin.com/help) page above, section "Beyond the console" +Những điều có thể hữu ích: +* Phương thức fallback +* Đôi khi cách tốt nhất để tấn công một hợp đồng là với một hợp đồng khác. +* Xem trang ["?"](https://ethernaut.openzeppelin.com/help) ở trên, phần "Beyond the console" diff --git a/client/src/gamedata/vi/descriptions/levels/force_complete.md b/client/src/gamedata/vi/descriptions/levels/force_complete.md index e70b2366c..177095e86 100644 --- a/client/src/gamedata/vi/descriptions/levels/force_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/force_complete.md @@ -1,3 +1,3 @@ -In solidity, for a contract to be able to receive ether, the fallback function must be marked `payable`. +Trong solidity, để một hợp đồng có thể nhận ether, hàm fallback phải được đánh dấu `payable`. -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. +Tuy nhiên, không có cách nào để ngăn kẻ tấn công gửi ether đến hợp đồng bằng cách tự hủy. Do đó, điều quan trọng là không dựa vào bất biến `address(this).balance == 0` cho bất kỳ logic hợp đồng nào. diff --git a/client/src/gamedata/vi/descriptions/levels/gatekeeper1.md b/client/src/gamedata/vi/descriptions/levels/gatekeeper1.md index 68e521bb2..47fd77ca9 100644 --- a/client/src/gamedata/vi/descriptions/levels/gatekeeper1.md +++ b/client/src/gamedata/vi/descriptions/levels/gatekeeper1.md @@ -1,5 +1,5 @@ -Make it past the gatekeeper and register as an entrant to pass this level. +Vượt qua người gác cổng và đăng ký như một người tham gia để vượt qua cấp độ này. -##### Things that might help: -* Remember what you've learned from the Telephone and Token levels. -* You can learn more about the special function `gasleft()`, in Solidity's documentation (see [here](https://docs.soliditylang.org/en/v0.8.3/units-and-global-variables.html) and [here](https://docs.soliditylang.org/en/v0.8.3/control-structures.html#external-function-calls)). +##### Những điều có thể hữu ích: +* Hãy nhớ những gì bạn đã học từ các cấp độ Telephone và Token. +* Bạn có thể tìm hiểu thêm về hàm đặc biệt `gasleft()`, trong tài liệu Solidity (xem [đây](https://docs.soliditylang.org/en/v0.8.3/units-and-global-variables.html) và [đây](https://docs.soliditylang.org/en/v0.8.3/control-structures.html#external-function-calls)). diff --git a/client/src/gamedata/vi/descriptions/levels/gatekeeper1_complete.md b/client/src/gamedata/vi/descriptions/levels/gatekeeper1_complete.md index 3b24cfaff..d501b07f8 100644 --- a/client/src/gamedata/vi/descriptions/levels/gatekeeper1_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/gatekeeper1_complete.md @@ -1 +1 @@ -Well done! Next, try your hand with the second gatekeeper... \ No newline at end of file +Làm tốt lắm! Tiếp theo, hãy thử sức với người gác cổng thứ hai... \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/gatekeeper2.md b/client/src/gamedata/vi/descriptions/levels/gatekeeper2.md index 5f7acfc64..883745dd3 100644 --- a/client/src/gamedata/vi/descriptions/levels/gatekeeper2.md +++ b/client/src/gamedata/vi/descriptions/levels/gatekeeper2.md @@ -1,6 +1,6 @@ -This gatekeeper introduces a few new challenges. Register as an entrant to pass this level. +Người gác cổng này giới thiệu một vài thử thách mới. Đăng ký như một người tham gia để vượt qua cấp độ này. -##### Things that might help: -* Remember what you've learned from getting past the first gatekeeper - the first gate is the same. -* The `assembly` keyword in the second gate allows a contract to access functionality that is not native to vanilla Solidity. See [here](http://solidity.readthedocs.io/en/v0.4.23/assembly.html) for more information. The `extcodesize` call in this gate will get the size of a contract's code at a given address - you can learn more about how and when this is set in section 7 of the [yellow paper](https://ethereum.github.io/yellowpaper/paper.pdf). -* The `^` character in the third gate is a bitwise operation (XOR), and is used here to apply another common bitwise operation (see [here](http://solidity.readthedocs.io/en/v0.4.23/miscellaneous.html#cheatsheet)). The Coin Flip level is also a good place to start when approaching this challenge. \ No newline at end of file +##### Những điều có thể hữu ích: +* Hãy nhớ những gì bạn đã học từ việc vượt qua người gác cổng đầu tiên - cánh cổng đầu tiên là giống nhau. +* Từ khóa `assembly` trong cánh cổng thứ hai cho phép hợp đồng truy cập chức năng không có sẵn trong vanilla Solidity. Xem [đây](http://solidity.readthedocs.io/en/v0.4.23/assembly.html) để biết thêm thông tin. Lệnh gọi `extcodesize` trong cánh cổng này sẽ lấy kích thước mã của hợp đồng tại một địa chỉ nhất định - bạn có thể tìm hiểu thêm về cách và khi nào điều này được thiết lập trong phần 7 của [yellow paper](https://ethereum.github.io/yellowpaper/paper.pdf). +* Ký tự `^` trong cánh cổng thứ ba là một phép toán bitwise (XOR), và được sử dụng ở đây để áp dụng một phép toán bitwise phổ biến khác (xem [đây](http://solidity.readthedocs.io/en/v0.4.23/miscellaneous.html#cheatsheet)). Cấp độ Coin Flip cũng là một nơi tốt để bắt đầu khi tiếp cận thử thách này. \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/gatekeeper2_complete.md b/client/src/gamedata/vi/descriptions/levels/gatekeeper2_complete.md index f1fa92bc6..40de03481 100644 --- a/client/src/gamedata/vi/descriptions/levels/gatekeeper2_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/gatekeeper2_complete.md @@ -1 +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). \ No newline at end of file +Tuyệt vời! Bây giờ bạn có thể vượt qua người gác cổng, bạn có những gì cần thiết để tham gia [theCyber](https://etherscan.io/address/thecyber.eth#code), một câu lạc bộ phi tập trung trên Ethereum mainnet. Lấy mật khẩu bằng cách liên hệ với người tạo trên [reddit](https://www.reddit.com/user/0age) hoặc qua [email](mailto:0age@protonmail.com) và sử dụng nó để đăng ký với hợp đồng tại [gatekeepertwo.thecyber.eth](https://etherscan.io/address/gatekeepertwo.thecyber.eth#code) (lưu ý rằng chỉ 128 người tham gia đầu tiên sẽ được hợp đồng chấp nhận). \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/gatekeeper3.md b/client/src/gamedata/vi/descriptions/levels/gatekeeper3.md index e58998e60..32c124e1a 100644 --- a/client/src/gamedata/vi/descriptions/levels/gatekeeper3.md +++ b/client/src/gamedata/vi/descriptions/levels/gatekeeper3.md @@ -1,6 +1,6 @@ -Cope with gates and become an entrant. +Đối phó với các cánh cổng và trở thành người tham gia. -##### Things that might help: -* Recall return values of low-level functions. -* Be attentive with semantic. -* Refresh how storage works in Ethereum. +##### Những điều có thể hữu ích: +* Nhớ lại giá trị trả về của các hàm cấp thấp. +* Chú ý đến ngữ nghĩa. +* Làm mới cách lưu trữ hoạt động trong Ethereum. diff --git a/client/src/gamedata/vi/descriptions/levels/gatekeeper3_complete.md b/client/src/gamedata/vi/descriptions/levels/gatekeeper3_complete.md index e57bd7eb6..9b2de3c61 100644 --- a/client/src/gamedata/vi/descriptions/levels/gatekeeper3_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/gatekeeper3_complete.md @@ -1 +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). \ No newline at end of file +Làm tốt lắm! Để biết thêm thông tin hãy đọc [này](https://web3js.readthedocs.io/en/v1.2.9/web3-eth.html?highlight=getStorageAt#getstorageat) và [này](https://medium.com/loom-network/ethereum-solidity-memory-vs-storage-how-to-initialize-an-array-inside-a-struct-184baf6aa2eb). \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/goodsamaritan.md b/client/src/gamedata/vi/descriptions/levels/goodsamaritan.md index 6035a7d30..14d3cc95c 100644 --- a/client/src/gamedata/vi/descriptions/levels/goodsamaritan.md +++ b/client/src/gamedata/vi/descriptions/levels/goodsamaritan.md @@ -1,7 +1,7 @@ -This instance represents a Good Samaritan that is wealthy and ready to donate some coins to anyone requesting it. +Phiên bản này đại diện cho một Người Samaritan Tốt Bụng giàu có và sẵn sàng quyên góp một số coin cho bất kỳ ai yêu cầu. -Would you be able to drain all the balance from his Wallet? +Bạn có thể rút hết số dư từ Ví của anh ấy không? -Things that might help: +Những điều có thể hữu ích: - [Solidity Custom Errors](https://blog.soliditylang.org/2021/04/21/custom-errors/) \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/goodsamaritan_complete.md b/client/src/gamedata/vi/descriptions/levels/goodsamaritan_complete.md index f154ee434..f53c2bd54 100644 --- a/client/src/gamedata/vi/descriptions/levels/goodsamaritan_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/goodsamaritan_complete.md @@ -1,3 +1,3 @@ -Congratulations! +Chúc mừng! -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. +Custom errors trong Solidity được xác định bởi 'selector' 4-byte của chúng, giống như lệnh gọi hàm. Chúng được nổi bọt lên qua chuỗi lệnh gọi cho đến khi được bắt bởi câu lệnh catch trong khối try-catch, như được thấy trong hàm `requestDonation()` của GoodSamaritan. Vì những lý do này, không an toàn khi giả định rằng lỗi được ném bởi mục tiêu trực tiếp của lệnh gọi hợp đồng (tức là Wallet trong trường hợp này). Bất kỳ hợp đồng nào khác xa hơn trong chuỗi lệnh gọi có thể khai báo cùng một lỗi và ném nó ở một vị trí không mong đợi, chẳng hạn như trong hàm `notify(uint256 amount)` trong hợp đồng tấn công của bạn. diff --git a/client/src/gamedata/vi/descriptions/levels/king.md b/client/src/gamedata/vi/descriptions/levels/king.md index 2a93f20fa..5b8a3c4bf 100644 --- a/client/src/gamedata/vi/descriptions/levels/king.md +++ b/client/src/gamedata/vi/descriptions/levels/king.md @@ -1,5 +1,5 @@ -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 +Hợp đồng bên dưới đại diện cho một trò chơi rất đơn giản: bất kỳ ai gửi cho nó một lượng ether lớn hơn giải thưởng hiện tại sẽ trở thành vua mới. Trong sự kiện như vậy, vua bị lật đổ sẽ được trả giải thưởng mới, kiếm được một chút ether trong quá trình! Ponzi như nó có thể xD -Such a fun game. Your goal is to break it. +Một trò chơi thú vị như vậy. Mục tiêu của bạn là phá vỡ nó. -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. +Khi bạn gửi phiên bản trở lại cấp độ, cấp độ sẽ tái chiếm vương quyền. Bạn sẽ thắng cấp độ nếu bạn có thể tránh được sự tự tuyên bố như vậy. diff --git a/client/src/gamedata/vi/descriptions/levels/king_complete.md b/client/src/gamedata/vi/descriptions/levels/king_complete.md index f040a0689..c5f9a8f05 100644 --- a/client/src/gamedata/vi/descriptions/levels/king_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/king_complete.md @@ -1,3 +1,3 @@ -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. +Hầu hết các cấp độ của Ethernaut cố gắng phơi bày (dưới dạng đơn giản hóa quá mức tất nhiên) một cái gì đó thực sự đã xảy ra — một vụ hack thực sự hoặc một lỗi thực sự. -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). +Trong trường hợp này, xem: [King of the Ether](https://www.kingoftheether.com/thrones/kingoftheether/index.html) và [King of the Ether Postmortem](http://www.kingoftheether.com/postmortem.html). diff --git a/client/src/gamedata/vi/descriptions/levels/magicnum.md b/client/src/gamedata/vi/descriptions/levels/magicnum.md index 9e7374f82..6c75ca2ed 100644 --- a/client/src/gamedata/vi/descriptions/levels/magicnum.md +++ b/client/src/gamedata/vi/descriptions/levels/magicnum.md @@ -1,11 +1,11 @@ -To solve this level, you only need to provide the Ethernaut with a `Solver`, a contract that responds to `whatIsTheMeaningOfLife()` with the right number. +Để giải cấp độ này, bạn chỉ cần cung cấp cho Ethernaut một `Solver`, một hợp đồng phản hồi `whatIsTheMeaningOfLife()` với số đúng. -Easy right? -Well... there's a catch. +Dễ phải không? +Chà... có một cái bẫy. -The solver's code needs to be really tiny. Really reaaaaaallly tiny. Like freakin' really really itty-bitty tiny: 10 opcodes at most. +Mã của solver cần phải thực sự nhỏ. Thực sự rất nhỏ. Như thực sự thực sự rất nhỏ: tối đa 10 opcode. -Hint: Perhaps its time to leave the comfort of the Solidity compiler momentarily, and build this one by hand O_o. -That's right: Raw EVM bytecode. +Gợi ý: Có lẽ đã đến lúc rời khỏi sự thoải mái của trình biên dịch Solidity trong chốc lát, và xây dựng cái này bằng tay O_o. +Đúng vậy: Raw EVM bytecode. -Good luck! +Chúc may mắn! diff --git a/client/src/gamedata/vi/descriptions/levels/magicnum_complete.md b/client/src/gamedata/vi/descriptions/levels/magicnum_complete.md index 20503aac2..dc63315f6 100644 --- a/client/src/gamedata/vi/descriptions/levels/magicnum_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/magicnum_complete.md @@ -1,3 +1,3 @@ -Congratulations! If you solved this level, consider yourself a Master of the Universe. +Chúc mừng! Nếu bạn đã giải cấp độ này, hãy coi mình là Bậc thầy của Vũ trụ. -Go ahead and pierce a random object in the room with your Magnum look. Now, try to move it from afar; Your telekinesis habilities might have just started working. +Hãy tiếp tục và đâm một vật ngẫu nhiên trong phòng với vẻ ngoài Magnum của bạn. Bây giờ, hãy thử di chuyển nó từ xa; Khả năng thần giao cách cảm của bạn có thể vừa bắt đầu hoạt động. diff --git a/client/src/gamedata/vi/descriptions/levels/motorbike.md b/client/src/gamedata/vi/descriptions/levels/motorbike.md index 3335a510a..55193ab30 100644 --- a/client/src/gamedata/vi/descriptions/levels/motorbike.md +++ b/client/src/gamedata/vi/descriptions/levels/motorbike.md @@ -1,8 +1,8 @@ -Ethernaut's motorbike has a brand new upgradeable engine design. +Xe máy của Ethernaut có thiết kế động cơ có thể nâng cấp hoàn toàn mới. -Would you be able to `selfdestruct` its engine and make the motorbike unusable ? +Bạn có thể `selfdestruct` động cơ của nó và làm cho xe máy không sử dụng được không? -Things that might help: +Những điều có thể hữu ích: - [EIP-1967](https://eips.ethereum.org/EIPS/eip-1967) - [UUPS](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786) upgradeable pattern diff --git a/client/src/gamedata/vi/descriptions/levels/motorbike_complete.md b/client/src/gamedata/vi/descriptions/levels/motorbike_complete.md index 741035dea..4ab42a94e 100644 --- a/client/src/gamedata/vi/descriptions/levels/motorbike_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/motorbike_complete.md @@ -1,9 +1,9 @@ -The advantage of following an UUPS pattern is to have very minimal proxy to be deployed. The proxy acts as storage layer so any state modification in the implementation contract normally doesn't produce side effects to systems using it, since only the logic is used through delegatecalls. +Ưu điểm của việc tuân theo mẫu UUPS là có proxy tối thiểu để triển khai. Proxy hoạt động như lớp lưu trữ nên bất kỳ thay đổi trạng thái nào trong hợp đồng triển khai thường không tạo ra tác dụng phụ cho các hệ thống sử dụng nó, vì chỉ logic được sử dụng thông qua delegatecalls. -This doesn't mean that you shouldn't watch out for vulnerabilities that can be exploited if we leave an implementation contract uninitialized. +Điều này không có nghĩa là bạn không nên đề phòng các lỗ hổng có thể bị khai thác nếu chúng ta để hợp đồng triển khai không được khởi tạo. -This was a slightly simplified version of what has really been discovered after months of the release of UUPS pattern. +Đây là phiên bản đơn giản hóa một chút của những gì thực sự đã được phát hiện sau nhiều tháng phát hành mẫu UUPS. -Takeways: never leave implementation contracts uninitialized ;) +Bài học: không bao giờ để hợp đồng triển khai không được khởi tạo ;) -If you're interested in what happened, read more [here](https://forum.openzeppelin.com/t/uupsupgradeable-vulnerability-post-mortem/15680). \ No newline at end of file +Nếu bạn quan tâm đến những gì đã xảy ra, hãy đọc thêm [tại đây](https://forum.openzeppelin.com/t/uupsupgradeable-vulnerability-post-mortem/15680). \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/naughtcoin.md b/client/src/gamedata/vi/descriptions/levels/naughtcoin.md index d4f680dca..c12521140 100644 --- a/client/src/gamedata/vi/descriptions/levels/naughtcoin.md +++ b/client/src/gamedata/vi/descriptions/levels/naughtcoin.md @@ -1,6 +1,6 @@ -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. +NaughtCoin là một token ERC20 và bạn đã nắm giữ tất cả chúng. Cái bẫy là bạn chỉ có thể chuyển chúng sau thời gian khóa 10 năm. Bạn có thể tìm ra cách để chuyển chúng ra địa chỉ khác để bạn có thể chuyển chúng tự do không? Hoàn thành cấp độ này bằng cách đưa số dư token của bạn về 0.   -Things that might help -* The [ERC20](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) Spec -* The [OpenZeppelin](https://github.com/OpenZeppelin/zeppelin-solidity/tree/master/contracts) codebase +Những điều có thể hữu ích +* [ERC20](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) Spec +* [OpenZeppelin](https://github.com/OpenZeppelin/zeppelin-solidity/tree/master/contracts) codebase diff --git a/client/src/gamedata/vi/descriptions/levels/naughtcoin_complete.md b/client/src/gamedata/vi/descriptions/levels/naughtcoin_complete.md index c5d39755b..625d41456 100644 --- a/client/src/gamedata/vi/descriptions/levels/naughtcoin_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/naughtcoin_complete.md @@ -1 +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. \ No newline at end of file +Khi sử dụng mã không phải của bạn, nên làm quen với nó để hiểu rõ cách mọi thứ kết hợp với nhau. Điều này có thể đặc biệt quan trọng khi có nhiều cấp độ import (import của bạn có import) hoặc khi bạn đang triển khai kiểm soát ủy quyền, ví dụ khi bạn cho phép hoặc không cho phép mọi người làm những việc. Trong ví dụ này, một nhà phát triển có thể quét qua mã và nghĩ rằng `transfer` là cách duy nhất để di chuyển token xung quanh, thấp và kìa có những cách khác để thực hiện cùng một thao tác với một triển khai khác. \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/preservation.md b/client/src/gamedata/vi/descriptions/levels/preservation.md index aea6b23e4..3e2673cd0 100644 --- a/client/src/gamedata/vi/descriptions/levels/preservation.md +++ b/client/src/gamedata/vi/descriptions/levels/preservation.md @@ -1,13 +1,11 @@ -This contract utilizes a library to store two different times for two different -timezones. The constructor creates two instances of the library for each time -to be stored. +Hợp đồng này sử dụng một thư viện để lưu trữ hai thời gian khác nhau cho hai múi giờ khác nhau. Constructor tạo hai phiên bản của thư viện cho mỗi thời gian cần được lưu trữ. -The goal of this level is for you to claim ownership of the instance you are given. +Mục tiêu của cấp độ này là bạn phải chiếm quyền sở hữu của phiên bản được cung cấp. -  Things that might help -* 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. -* Understanding what it means for `delegatecall` to be context-preserving. -* Understanding how storage variables are stored and accessed. -* Understanding how casting works between different data types. +  Những điều có thể hữu ích +* Tìm hiểu tài liệu Solidity về hàm cấp thấp `delegatecall`, + cách nó hoạt động, cách sử dụng để ủy quyền các thao tác cho + thư viện on-chain, và những tác động của nó đến phạm vi thực thi. +* Hiểu ý nghĩa của việc `delegatecall` bảo toàn ngữ cảnh. +* Hiểu cách các biến lưu trữ được lưu trữ và truy cập. +* Hiểu cách casting hoạt động giữa các kiểu dữ liệu khác nhau. diff --git a/client/src/gamedata/vi/descriptions/levels/preservation_complete.md b/client/src/gamedata/vi/descriptions/levels/preservation_complete.md index 30ad0781a..c45fd15da 100644 --- a/client/src/gamedata/vi/descriptions/levels/preservation_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/preservation_complete.md @@ -1,6 +1,6 @@ -As the previous level, `delegate` mentions, the use of `delegatecall` to call -libraries can be risky. This is particularly true for contract libraries that -have their own state. This example demonstrates why the `library` keyword -should be used for building libraries, as it prevents the libraries from -storing and accessing state variables. +Như cấp độ trước, `delegate` đề cập, việc sử dụng `delegatecall` để gọi +thư viện có thể rủi ro. Điều này đặc biệt đúng với các thư viện hợp đồng có +trạng thái riêng của chúng. Ví dụ này chứng minh tại sao từ khóa `library` +nên được sử dụng để xây dựng thư viện, vì nó ngăn các thư viện +lưu trữ và truy cập các biến trạng thái. diff --git a/client/src/gamedata/vi/descriptions/levels/privacy.md b/client/src/gamedata/vi/descriptions/levels/privacy.md index ed4b8bc20..74a2123b6 100644 --- a/client/src/gamedata/vi/descriptions/levels/privacy.md +++ b/client/src/gamedata/vi/descriptions/levels/privacy.md @@ -1,11 +1,11 @@ -The creator of this contract was careful enough to protect the sensitive areas of its storage. +Người tạo hợp đồng này đã cẩn thận đủ để bảo vệ các khu vực nhạy cảm của bộ nhớ của nó. -Unlock this contract to beat the level. +Mở khóa hợp đồng này để thắng cấp độ. -Things that might help: -* Understanding how storage works -* Understanding how parameter parsing works -* Understanding how casting works +Những điều có thể hữu ích: +* Hiểu cách lưu trữ hoạt động +* Hiểu cách phân tích tham số hoạt động +* Hiểu cách casting hoạt động -Tips: -* 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. +Mẹo: +* Hãy nhớ rằng metamask chỉ là một hàng hóa. Sử dụng công cụ khác nếu nó gây ra vấn đề. Gameplay nâng cao có thể liên quan đến việc sử dụng remix, hoặc web3 provider của riêng bạn. diff --git a/client/src/gamedata/vi/descriptions/levels/privacy_complete.md b/client/src/gamedata/vi/descriptions/levels/privacy_complete.md index 478506f22..ea8e6521a 100644 --- a/client/src/gamedata/vi/descriptions/levels/privacy_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/privacy_complete.md @@ -1,3 +1,3 @@ -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. +Không có gì trong blockchain ethereum là riêng tư. Từ khóa private chỉ là một cấu trúc nhân tạo của ngôn ngữ Solidity. `getStorageAt(...)` của Web3 có thể được sử dụng để đọc bất cứ thứ gì từ lưu trữ. Tuy nhiên, có thể khó khăn để đọc những gì bạn muốn, vì một số quy tắc tối ưu hóa và kỹ thuật được sử dụng để nén lưu trữ càng nhiều càng tốt. -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) +Nó không thể phức tạp hơn nhiều so với những gì được phơi bày trong cấp độ này. Để biết thêm, hãy xem bài viết tuyệt vời này của "Darius": [Cách đọc lưu trữ hợp đồng Ethereum](https://medium.com/aigang-network/how-to-read-ethereum-contract-storage-44252c8af925) diff --git a/client/src/gamedata/vi/descriptions/levels/puzzle_wallet.md b/client/src/gamedata/vi/descriptions/levels/puzzle_wallet.md index 3c3689564..24cb6f3d4 100644 --- a/client/src/gamedata/vi/descriptions/levels/puzzle_wallet.md +++ b/client/src/gamedata/vi/descriptions/levels/puzzle_wallet.md @@ -1,18 +1,18 @@ -Nowadays, paying for DeFi operations is impossible, fact. +Ngày nay, việc thanh toán cho các hoạt động DeFi là không thể, thực tế. -A group of friends discovered how to slightly decrease the cost of performing multiple transactions by batching them in one transaction, so they developed a smart contract for doing this. +Một nhóm bạn đã khám phá ra cách giảm nhẹ chi phí thực hiện nhiều giao dịch bằng cách gộp chúng thành một giao dịch, vì vậy họ đã phát triển một hợp đồng thông minh để làm điều này. -They needed this contract to be upgradeable in case the code contained a bug, and they also wanted to prevent people from outside the group from using it. To do so, they voted and assigned two people with special roles in the system: -The admin, which has the power of updating the logic of the smart contract. -The owner, which controls the whitelist of addresses allowed to use the contract. -The contracts were deployed, and the group was whitelisted. Everyone cheered for their accomplishments against evil miners. +Họ cần hợp đồng này có thể nâng cấp trong trường hợp mã chứa lỗi, và họ cũng muốn ngăn những người bên ngoài nhóm sử dụng nó. Để làm điều này, họ đã bỏ phiếu và chỉ định hai người với vai trò đặc biệt trong hệ thống: +Admin, người có quyền cập nhật logic của hợp đồng thông minh. +Owner, người kiểm soát whitelist các địa chỉ được phép sử dụng hợp đồng. +Các hợp đồng đã được triển khai, và nhóm đã được whitelist. Mọi người đều vui mừng vì thành tích của họ chống lại các thợ mỏ xấu. -Little did they know, their lunch money was at risk… +Họ không biết rằng, tiền ăn trưa của họ đang gặp rủi ro...   -You'll need to hijack this wallet to become the admin of the proxy. +Bạn sẽ cần cướp ví này để trở thành admin của proxy.   -Things that might help: -* Understanding how `delegatecall` works and how `msg.sender` and `msg.value` behaves when performing one. -* Knowing about proxy patterns and the way they handle storage variables. +Những điều có thể hữu ích: +* Hiểu cách `delegatecall` hoạt động và cách `msg.sender` và `msg.value` hoạt động khi thực hiện một. +* Biết về các mẫu proxy và cách chúng xử lý các biến lưu trữ. diff --git a/client/src/gamedata/vi/descriptions/levels/puzzle_wallet_complete.md b/client/src/gamedata/vi/descriptions/levels/puzzle_wallet_complete.md index c98af3a7d..a23443271 100644 --- a/client/src/gamedata/vi/descriptions/levels/puzzle_wallet_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/puzzle_wallet_complete.md @@ -1,7 +1,7 @@ -Next time, those friends will request an audit before depositing any money on a contract. Congrats! +Lần sau, những người bạn đó sẽ yêu cầu kiểm toán trước khi gửi tiền vào hợp đồng. Chúc mừng! -Frequently, using proxy contracts is highly recommended to bring upgradeability features and reduce the deployment's gas cost. However, developers must be careful not to introduce storage collisions, as seen in this level. +Thường xuyên, việc sử dụng hợp đồng proxy được khuyến nghị cao để mang lại tính năng nâng cấp và giảm chi phí gas triển khai. Tuy nhiên, các nhà phát triển phải cẩn thận không để xảy ra va chạm lưu trữ, như được thấy trong cấp độ này. -Furthermore, iterating over operations that consume ETH can lead to issues if it is not handled correctly. Even if ETH is spent, `msg.value` will remain the same, so the developer must manually keep track of the actual remaining amount on each iteration. This can also lead to issues when using a multi-call pattern, as performing multiple `delegatecall`s to a function that looks safe on its own could lead to unwanted transfers of ETH, as `delegatecall`s keep the original `msg.value` sent to the contract. +Hơn nữa, lặp qua các thao tác tiêu thụ ETH có thể dẫn đến vấn đề nếu không được xử lý đúng cách. Ngay cả khi ETH được chi tiêu, `msg.value` sẽ vẫn giữ nguyên, vì vậy nhà phát triển phải theo dõi thủ công số tiền còn lại thực tế trong mỗi lần lặp. Điều này cũng có thể dẫn đến vấn đề khi sử dụng mẫu multi-call, vì thực hiện nhiều `delegatecall` đến một hàm trông an toàn có thể dẫn đến chuyển ETH không mong muốn, vì `delegatecall` giữ nguyên `msg.value` gốc được gửi đến hợp đồng. -Move on to the next level when you're ready! +Chuyển sang cấp độ tiếp theo khi bạn sẵn sàng! diff --git a/client/src/gamedata/vi/descriptions/levels/recovery.md b/client/src/gamedata/vi/descriptions/levels/recovery.md index 4ed9a93da..339260251 100644 --- a/client/src/gamedata/vi/descriptions/levels/recovery.md +++ b/client/src/gamedata/vi/descriptions/levels/recovery.md @@ -1,4 +1,4 @@ -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. +Một người tạo hợp đồng đã xây dựng một hợp đồng nhà máy token rất đơn giản. Bất kỳ ai cũng có thể tạo token mới một cách dễ dàng. Sau khi triển khai hợp đồng token đầu tiên, người tạo đã gửi `0.001` ether để có thêm token. Họ đã mất địa chỉ hợp đồng. -This level will be completed if you can recover (or remove) the `0.001` ether from the lost contract address. +Cấp độ này sẽ được hoàn thành nếu bạn có thể khôi phục (hoặc xóa) `0.001` ether từ địa chỉ hợp đồng bị mất. diff --git a/client/src/gamedata/vi/descriptions/levels/recovery_complete.md b/client/src/gamedata/vi/descriptions/levels/recovery_complete.md index 37eebb07f..5d76086aa 100644 --- a/client/src/gamedata/vi/descriptions/levels/recovery_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/recovery_complete.md @@ -1,10 +1,10 @@ -Contract addresses are deterministic and are calculated by `keccak256(address, nonce)` where the `address` is the address of the contract (or ethereum address that created the transaction) and `nonce` is the number of contracts the spawning contract has created (or the transaction nonce, for regular transactions). +Địa chỉ hợp đồng là xác định và được tính bằng `keccak256(address, nonce)` trong đó `address` là địa chỉ của hợp đồng (hoặc địa chỉ ethereum đã tạo giao dịch) và `nonce` là số lượng hợp đồng mà hợp đồng tạo ra đã tạo (hoặc nonce giao dịch, cho các giao dịch thông thường). -Because of this, one can send ether to a pre-determined address (which has no private key) and later create a contract at that address which recovers the ether. This is a non-intuitive and somewhat secretive way to (dangerously) store ether without holding a private key. +Vì điều này, người ta có thể gửi ether đến một địa chỉ được xác định trước (không có khóa riêng) và sau đó tạo hợp đồng tại địa chỉ đó để khôi phục ether. Đây là một cách không trực quan và phần nào bí mật để (nguy hiểm) lưu trữ ether mà không cần giữ khóa riêng. -An interesting [blog post](https://swende.se/blog/Ethereum_quirks_and_vulns.html) by Martin Swende details potential use cases of this. +Một [bài đăng blog](https://swende.se/blog/Ethereum_quirks_and_vulns.html) thú vị của Martin Swende mô tả chi tiết các trường hợp sử dụng tiềm năng của điều này. -If you're going to implement this technique, make sure you don't miss the nonce, or your funds will be lost forever. +Nếu bạn sẽ triển khai kỹ thuật này, hãy đảm bảo bạn không bỏ lỡ nonce, hoặc tiền của bạn sẽ bị mất mãi mãi. diff --git a/client/src/gamedata/vi/descriptions/levels/reentrancy.md b/client/src/gamedata/vi/descriptions/levels/reentrancy.md index 0e70cf36a..747431586 100644 --- a/client/src/gamedata/vi/descriptions/levels/reentrancy.md +++ b/client/src/gamedata/vi/descriptions/levels/reentrancy.md @@ -1,9 +1,9 @@ -The goal of this level is for you to steal all the funds from the contract. +Mục tiêu của cấp độ này là bạn phải đánh cắp tất cả tiền từ hợp đồng.   -Things that might help: -* Untrusted contracts can execute code where you least expect it. -* Fallback methods +Những điều có thể hữu ích: +* Các hợp đồng không đáng tin cậy có thể thực thi mã ở nơi bạn ít mong đợi nhất. +* Phương thức fallback * Throw/revert bubbling -* Sometimes the best way to attack a contract is with another contract. -* See the ["?"](https://ethernaut.openzeppelin.com/help) page above, section "Beyond the console" +* Đôi khi cách tốt nhất để tấn công một hợp đồng là với một hợp đồng khác. +* Xem trang ["?"](https://ethernaut.openzeppelin.com/help) ở trên, phần "Beyond the console" diff --git a/client/src/gamedata/vi/descriptions/levels/reentrancy_complete.md b/client/src/gamedata/vi/descriptions/levels/reentrancy_complete.md index 461a5f208..42038bd8c 100644 --- a/client/src/gamedata/vi/descriptions/levels/reentrancy_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/reentrancy_complete.md @@ -1,12 +1,12 @@ -In order to prevent re-entrancy attacks when moving funds out of your contract, use the [Checks-Effects-Interactions pattern](https://solidity.readthedocs.io/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern) being aware that `call` will only return false without interrupting the execution flow. Solutions such as [ReentrancyGuard](https://docs.openzeppelin.com/contracts/2.x/api/utils#ReentrancyGuard) or [PullPayment](https://docs.openzeppelin.com/contracts/2.x/api/payment#PullPayment) can also be used. +Để ngăn chặn các cuộc tấn công re-entrancy khi di chuyển tiền ra khỏi hợp đồng của bạn, hãy sử dụng mẫu [Checks-Effects-Interactions](https://solidity.readthedocs.io/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern) biết rằng `call` sẽ chỉ trả về false mà không làm gián đoạn luồng thực thi. Các giải pháp như [ReentrancyGuard](https://docs.openzeppelin.com/contracts/2.x/api/utils#ReentrancyGuard) hoặc [PullPayment](https://docs.openzeppelin.com/contracts/2.x/api/payment#PullPayment) cũng có thể được sử dụng. -`transfer` and `send` are no longer recommended solutions as they can potentially break contracts after the Istanbul hard fork [Source 1](https://diligence.consensys.net/blog/2019/09/stop-using-soliditys-transfer-now/) [Source 2](https://forum.openzeppelin.com/t/reentrancy-after-istanbul/1742). +`transfer` và `send` không còn là giải pháp được khuyến nghị vì chúng có thể phá vỡ hợp đồng sau hard fork Istanbul [Nguồn 1](https://diligence.consensys.net/blog/2019/09/stop-using-soliditys-transfer-now/) [Nguồn 2](https://forum.openzeppelin.com/t/reentrancy-after-istanbul/1742). -Always assume that the receiver of the funds you are sending can be another contract, not just a regular address. Hence, it can execute code in its payable fallback method and *re-enter* your contract, possibly messing up your state/logic. +Luôn giả định rằng người nhận tiền bạn đang gửi có thể là một hợp đồng khác, không chỉ là địa chỉ thông thường. Do đó, nó có thể thực thi mã trong phương thức fallback payable của nó và *tái nhập* hợp đồng của bạn, có thể làm rối tung trạng thái/logic của bạn. -Re-entrancy is a common attack. You should always be prepared for it! +Re-entrancy là một cuộc tấn công phổ biến. Bạn nên luôn chuẩn bị sẵn sàng cho nó!   -#### The DAO Hack +#### Vụ hack DAO -The famous DAO hack used reentrancy to extract a huge amount of ether from the victim contract. See [15 lines of code that could have prevented TheDAO Hack](https://blog.openzeppelin.com/15-lines-of-code-that-could-have-prevented-thedao-hack-782499e00942). +Vụ hack DAO nổi tiếng đã sử dụng reentrancy để trích xuất một lượng ether khổng lồ từ hợp đồng nạn nhân. Xem [15 dòng mã có thể ngăn chặn vụ hack DAO](https://blog.openzeppelin.com/15-lines-of-code-that-could-have-prevented-thedao-hack-782499e00942). diff --git a/client/src/gamedata/vi/descriptions/levels/shop.md b/client/src/gamedata/vi/descriptions/levels/shop.md index ab86e5079..8b1622da2 100644 --- a/client/src/gamedata/vi/descriptions/levels/shop.md +++ b/client/src/gamedata/vi/descriptions/levels/shop.md @@ -1,5 +1,5 @@ -Сan you get the item from the shop for less than the price asked? +Bạn có thể lấy mặt hàng từ cửa hàng với giá thấp hơn giá được yêu cầu không? -##### Things that might help: -* `Shop` expects to be used from a `Buyer` -* Understanding restrictions of view functions +##### Những điều có thể hữu ích: +* `Shop` mong đợi được sử dụng từ một `Buyer` +* Hiểu các hạn chế của hàm view diff --git a/client/src/gamedata/vi/descriptions/levels/shop_complete.md b/client/src/gamedata/vi/descriptions/levels/shop_complete.md index 0bc6ca34d..aafdb9032 100644 --- a/client/src/gamedata/vi/descriptions/levels/shop_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/shop_complete.md @@ -1,3 +1,3 @@ -Contracts can manipulate data seen by other contracts in any way they want. +Hợp đồng có thể thao túng dữ liệu được nhìn thấy bởi các hợp đồng khác theo bất kỳ cách nào chúng muốn. -It's unsafe to change the state based on external and untrusted contracts logic. +Không an toàn khi thay đổi trạng thái dựa trên logic của các hợp đồng bên ngoài và không đáng tin cậy. diff --git a/client/src/gamedata/vi/descriptions/levels/switch.md b/client/src/gamedata/vi/descriptions/levels/switch.md index 1ece812ff..162c091e3 100644 --- a/client/src/gamedata/vi/descriptions/levels/switch.md +++ b/client/src/gamedata/vi/descriptions/levels/switch.md @@ -1,4 +1,4 @@ -Just have to flip the switch. Can't be that hard, right? +Chỉ cần bật công tắc. Không thể khó đến vậy, phải không? -##### Things that might help: -Understanding how `CALLDATA` is encoded. +##### Những điều có thể hữu ích: +Hiểu cách `CALLDATA` được mã hóa. diff --git a/client/src/gamedata/vi/descriptions/levels/switch_complete.md b/client/src/gamedata/vi/descriptions/levels/switch_complete.md index d392b177a..c81841afa 100644 --- a/client/src/gamedata/vi/descriptions/levels/switch_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/switch_complete.md @@ -1 +1 @@ -Assuming positions in `CALLDATA` with dynamic types can be erroneous, especially when using hard-coded `CALLDATA` positions. +Giả định các vị trí trong `CALLDATA` với các kiểu động có thể sai, đặc biệt khi sử dụng các vị trí `CALLDATA` được mã hóa cứng. diff --git a/client/src/gamedata/vi/descriptions/levels/telephone.md b/client/src/gamedata/vi/descriptions/levels/telephone.md index 0f9a0dedd..6568cbd3c 100644 --- a/client/src/gamedata/vi/descriptions/levels/telephone.md +++ b/client/src/gamedata/vi/descriptions/levels/telephone.md @@ -1,5 +1,5 @@ -Claim ownership of the contract below to complete this level. +Chiếm quyền sở hữu của hợp đồng bên dưới để hoàn thành cấp độ này.   -Things that might help -* See the ["?"](https://ethernaut.openzeppelin.com/help) page above, section "Beyond the console" +Những điều có thể hữu ích +* Xem trang ["?"](https://ethernaut.openzeppelin.com/help) ở trên, phần "Beyond the console" diff --git a/client/src/gamedata/vi/descriptions/levels/telephone_complete.md b/client/src/gamedata/vi/descriptions/levels/telephone_complete.md index f19d3b627..a8108ba3e 100644 --- a/client/src/gamedata/vi/descriptions/levels/telephone_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/telephone_complete.md @@ -1,8 +1,8 @@ -While this example may be simple, confusing `tx.origin` with `msg.sender` can lead to phishing-style attacks, such as [this](https://blog.ethereum.org/2016/06/24/security-alert-smart-contract-wallets-created-in-frontier-are-vulnerable-to-phishing-attacks/). +Mặc dù ví dụ này có thể đơn giản, việc nhầm lẫn `tx.origin` với `msg.sender` có thể dẫn đến các cuộc tấn công kiểu phishing, chẳng hạn như [này](https://blog.ethereum.org/2016/06/24/security-alert-smart-contract-wallets-created-in-frontier-are-vulnerable-to-phishing-attacks/). -An example of a possible attack is outlined below. +Một ví dụ về cuộc tấn công có thể được mô tả dưới đây. -1) Use `tx.origin` to determine whose tokens to transfer, e.g. +1) Sử dụng `tx.origin` để xác định token của ai để chuyển, ví dụ: ``` function transfer(address _to, uint _value) { @@ -10,7 +10,7 @@ function transfer(address _to, uint _value) { tokens[_to] += _value; } ``` -2) Attacker gets victim to send funds to a malicious contract that calls the transfer function of the token contract, e.g. +2) Kẻ tấn công khiến nạn nhân gửi tiền đến một hợp đồng độc hại gọi hàm transfer của hợp đồng token, ví dụ: ``` function () payable { @@ -18,4 +18,4 @@ function () payable { } ``` -3) In this scenario, `tx.origin` will be the victim's address (while `msg.sender` will be the malicious contract's address), resulting in the funds being transferred from the victim to the attacker. +3) Trong trường hợp này, `tx.origin` sẽ là địa chỉ của nạn nhân (trong khi `msg.sender` sẽ là địa chỉ của hợp đồng độc hại), dẫn đến việc chuyển tiền từ nạn nhân sang kẻ tấn công. diff --git a/client/src/gamedata/vi/descriptions/levels/token.md b/client/src/gamedata/vi/descriptions/levels/token.md index 9b90a1ca2..4f2f59c78 100644 --- a/client/src/gamedata/vi/descriptions/levels/token.md +++ b/client/src/gamedata/vi/descriptions/levels/token.md @@ -1,7 +1,7 @@ -The goal of this level is for you to hack the basic token contract below. +Mục tiêu của cấp độ này là bạn phải hack hợp đồng token cơ bản bên dưới. -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. +Bạn được cung cấp 20 token để bắt đầu và bạn sẽ thắng cấp độ nếu bạn bằng cách nào đó quản lý để có thêm bất kỳ token nào. Tốt nhất là một lượng token rất lớn.   -Things that might help: -* What is an odometer? \ No newline at end of file +Những điều có thể hữu ích: +* Đồng hồ đo quãng đường là gì? \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/token_complete.md b/client/src/gamedata/vi/descriptions/levels/token_complete.md index 5c3254d2b..86e928a28 100644 --- a/client/src/gamedata/vi/descriptions/levels/token_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/token_complete.md @@ -1,12 +1,12 @@ -Overflows are very common in solidity and must be checked for with control statements such as: +Overflow rất phổ biến trong solidity và phải được kiểm tra bằng các câu lệnh điều khiển như: ``` if(a + c > a) { a = a + c; } ``` -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: +Một lựa chọn dễ dàng hơn là sử dụng thư viện SafeMath của OpenZeppelin tự động kiểm tra overflow trong tất cả các toán tử toán học. Mã kết quả trông như thế này: ``` a = a.add(c); -``` -If there is an overflow, the code will revert. \ No newline at end of file +``` +Nếu có overflow, mã sẽ revert. \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/unstoppable.md b/client/src/gamedata/vi/descriptions/levels/unstoppable.md index cc0a1a19f..4942fe346 100644 --- a/client/src/gamedata/vi/descriptions/levels/unstoppable.md +++ b/client/src/gamedata/vi/descriptions/levels/unstoppable.md @@ -1,5 +1,5 @@ -There's a lending pool with a million tokens in balance, offering flash loans for free. +Có một pool cho vay với một triệu token trong số dư, cung cấp flash loan miễn phí. -If only there was a way to attack and stop the pool from offering flash loans ... +Nếu chỉ có cách để tấn công và ngăn pool cung cấp flash loan... -You start with 100 tokens in balance. +Bạn bắt đầu với 100 token trong số dư. diff --git a/client/src/gamedata/vi/descriptions/levels/vault.md b/client/src/gamedata/vi/descriptions/levels/vault.md index 8f0400e45..4ec2d8832 100644 --- a/client/src/gamedata/vi/descriptions/levels/vault.md +++ b/client/src/gamedata/vi/descriptions/levels/vault.md @@ -1 +1 @@ -Unlock the vault to pass the level! \ No newline at end of file +Mở khóa kho bạc để vượt qua cấp độ! \ No newline at end of file diff --git a/client/src/gamedata/vi/descriptions/levels/vault_complete.md b/client/src/gamedata/vi/descriptions/levels/vault_complete.md index cb6af991a..d771d463e 100644 --- a/client/src/gamedata/vi/descriptions/levels/vault_complete.md +++ b/client/src/gamedata/vi/descriptions/levels/vault_complete.md @@ -1,3 +1,3 @@ -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. +Điều quan trọng cần nhớ là việc đánh dấu một biến là private chỉ ngăn các hợp đồng khác truy cập nó. Các biến trạng thái được đánh dấu là private và các biến cục bộ vẫn có thể truy cập công khai. -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. \ No newline at end of file +Để đảm bảo rằng dữ liệu là riêng tư, nó cần được mã hóa trước khi được đưa lên blockchain. Trong trường hợp này, khóa giải mã không bao giờ nên được gửi on-chain, vì nó sẽ có thể nhìn thấy bởi bất kỳ ai tìm kiếm nó. [zk-SNARKs](https://blog.ethereum.org/2016/12/05/zksnarks-in-a-nutshell/) cung cấp một cách để xác định xem ai đó có sở hữu một tham số bí mật hay không, mà không bao giờ phải tiết lộ tham số đó. \ No newline at end of file diff --git a/client/src/gamedata/vi/strings.json b/client/src/gamedata/vi/strings.json index e73cd67cc..575ff6f91 100644 --- a/client/src/gamedata/vi/strings.json +++ b/client/src/gamedata/vi/strings.json @@ -1,9 +1,9 @@ { "ethernaut": "Ethernaut", - "title": "The Ethernaut", + "title": "Ethernaut", "hiring": "Chung tôi đang cần tuyển dụng!", - "ctfRegister": "Register now!", - "ctfInfo": "We are hosting Ethernaut CTF: A 48-hour capture the flag event with prizes and blockchain challenges, starting 16/03.", + "ctfRegister": "Đăng ký ngay!", + "ctfInfo": "Chúng tôi đang tổ chức Ethernaut CTF: Sự kiện bắt cờ 48 giờ với giải thưởng và thử thách blockchain, bắt đầu từ 16/03.", "info": "

Ethernaut là một trò chơi lập trình sử dụng Web3/Solidity lấy cảm hứng từ overthewire.org, được chơi trong Máy ảo Ethereum. Mỗi cấp độ là một hợp đồng thông minh cần được “hack”. 100% trò chơi là mã nguồn mở và tất cả các cấp độ đều được đóng góp bởi những người chơi khác. Bạn có ý tưởng muốn đóng góp? Mọi PR đều được

", "home": "Trang chủ", "help": "Trợ giúp", @@ -121,4 +121,4 @@ "Languages": "Ngôn ngữ", "PageNotFoundTitle": "404 Lỗi - Không tìm thấy trang", "PageNotFoundText": "Ối! Trang bạn đang tìm kiếm không thể được tìm thấy." -} +} \ No newline at end of file