diff --git a/Languages/en/S01_ReentrancyAttack_en/readme.md b/Languages/en/S01_ReentrancyAttack_en/readme.md index f0cfd1e45..5e7e3276a 100644 --- a/Languages/en/S01_ReentrancyAttack_en/readme.md +++ b/Languages/en/S01_ReentrancyAttack_en/readme.md @@ -21,7 +21,7 @@ English translations by: [@to_22X](https://twitter.com/to_22X) --- -In this lesson, we will introduce the most common type of smart contract attack - reentrancy attack, which has led to the Ethereum fork into ETH and ETC (Ethereum Classic), and discuss how to prevent it. +In this lesson, we will introduce the most common type of smart contract attack - a reentrancy attack, which has led to the Ethereum fork into ETH and ETC (Ethereum Classic), and discuss how to prevent it. ## Reentrancy Attack @@ -58,7 +58,7 @@ One day, the hacker `0xAA` came to the bank and had the following conversation w - 0xAA: Wait, I want to withdraw `1 ETH`. - ... -In the end, `0xAA` emptied the bank's assets through the vulnerability of reentrancy attack, and the bank collapsed. +In the end, `0xAA` emptied the bank's assets through the vulnerability of a reentrancy attack, and the bank collapsed. ![](./img/S01-1.png) @@ -68,8 +68,8 @@ In the end, `0xAA` emptied the bank's assets through the vulnerability of reentr The bank contract is very simple and includes `1` state variable `balanceOf` to record the Ethereum balance of all users. It also includes `3` functions: -- `deposit()`: Deposit function that allows users to deposit `ETH` into the bank contract and updates their balances. -- `withdraw()`: Withdraw function that transfers the caller's balance to them. The steps are the same as in the story above: check balance, transfer funds, update balance. **Note: This function has a reentrancy vulnerability!** +- `deposit()`: Deposit function that allows users to deposit `ETH` into the bank contract and update their balances. +- `withdraw()`: Withdraw function that transfers the caller's balance to them. The steps are the same as in the story above: check balance, transfer funds, and update balance. **Note: This function has a reentrancy vulnerability!** - `getBalance()`: Get the `ETH` balance in the bank contract. ```solidity @@ -101,7 +101,7 @@ contract Bank { ### Attack Contract -One vulnerability point of reentrancy attack is the transfer of `ETH` in the contract: if the target address of the transfer is a contract, it will trigger the fallback function of the contract, potentially causing a loop. If you are not familiar with fallback functions, you can read [WTF Solidity: 19: Receive ETH](https://github.com/AmazingAng/WTF-Solidity/blob/main/Languages/en/19_Fallback_en/readme.md). The `Bank` contract has an `ETH` transfer in the `withdraw()` function: +One vulnerability point of a reentrancy attack is the transfer of `ETH` in the contract: if the target address of the transfer is a contract, it will trigger the fallback function of the contract, potentially causing a loop. If you are not familiar with fallback functions, you can read [WTF Solidity: 19: Receive ETH](https://github.com/AmazingAng/WTF-Solidity/blob/main/Languages/en/19_Fallback_en/readme.md). The `Bank` contract has an `ETH` transfer in the `withdraw()` function: ``` (bool success, ) = msg.sender.call{value: balance}(""); @@ -216,4 +216,4 @@ function withdraw() external nonReentrant{ ## Summary -In this lesson, we introduced the most common attack in Ethereum - the reentrancy attack, and made a story of robbing a bank with `0xAA` to help understand it. Finally, we discussed two methods to prevent reentrancy attacks: the checks-effect-interaction pattern and the reentrant lock. In the example, the hacker exploited the fallback function to perform a reentrancy attack during `ETH` transfer in the target contract. In real-world scenarios, the `safeTransfer()` and `safeTransferFrom()` functions of `ERC721` and `ERC1155`, as well as the fallback function of `ERC777`, can also potentially trigger reentrancy attacks. For beginners, my suggestion is to use a reentrant lock to protect all `external` functions that can change the contract state. Although it may consume more `gas`, it can prevent greater losses. +In this lesson, we introduced the most common attack in Ethereum - the reentrancy attack and made a story of robbing a bank with `0xAA` to help understand it. Finally, we discussed two methods to prevent reentrancy attacks: the checks-effect-interaction pattern and the reentrant lock. In the example, the hacker exploited the fallback function to perform a reentrancy attack during the `ETH` transfer in the target contract. In real-world scenarios, the `safeTransfer()` and `safeTransferFrom()` functions of `ERC721` and `ERC1155`, as well as the fallback function of `ERC777`, can also potentially trigger reentrancy attacks. For beginners, my suggestion is to use a reentrant lock to protect all `external` functions that can change the contract state. Although it may consume more `gas`, it can prevent greater losses. diff --git a/Languages/en/S02_SelectorClash_en/readme.md b/Languages/en/S02_SelectorClash_en/readme.md index 71883cdd0..dac72e30f 100644 --- a/Languages/en/S02_SelectorClash_en/readme.md +++ b/Languages/en/S02_SelectorClash_en/readme.md @@ -21,7 +21,7 @@ English translations by: [@to_22X](https://twitter.com/to_22X) --- -In this lesson, we will introduce the selector clash attack, which is one of the reasons behind the hack of the cross-chain bridge Poly Network. In August 2021, the cross-chain bridge contracts of Poly Network on ETH, BSC, and Polygon were hacked, resulting in a loss of up to $611 million ([summary](https://rekt.news/zh/polynetwork-rekt/)). This is the largest blockchain hack of 2021 and the second-largest in history, second only to the Ronin bridge hack. +In this lesson, we will introduce the selector clash attack, which is one of the reasons behind the hack of the cross-chain bridge Poly Network. In August 2021, the cross-chain bridge contracts of Poly Network on ETH, BSC, and Polygon were hacked, resulting in a loss of up to $611 million ([summary](https://rekt.news/zh/polynetwork-rekt/)). This is the largest blockchain hack of 2021 and the second-largest in history, second only to the Ronin Bridge hack. ## Selector Clash @@ -46,9 +46,9 @@ In contrast, the public key of a wallet is `64` bytes long and the probability o The people of Ethereum have angered the gods, and the gods are furious. In order to punish the people of Ethereum, the goddess Hera sends down a Sphinx, a creature with the head of a human and the body of a lion, to the cliffs of Ethereum. The Sphinx presents a riddle to every Ethereum user who passes by the cliff: "What walks on four legs in the morning, two legs at noon, and three legs in the evening? It is the only creature that walks on different numbers of legs throughout its life. When it has the most legs, it is at its slowest and weakest." Those who solve this enigmatic riddle will be spared, while those who fail to solve it will be devoured. The Sphinx uses the selector `0x10cd2dc7` to verify the correct answer. -One morning, Oedipus passes by and encounters the Sphinx. He solves the mysterious riddle and says, "It is `function man()`. In the morning of life, he is a child who crawls on two legs and two hands. At noon, he becomes an adult who walks on two legs. In the evening, he grows old and weak, and needs a cane to walk, hence he is called three-legged." After guessing the riddle correctly, Oedipus is allowed to live. +One morning, Oedipus passes by and encounters the Sphinx. He solves the mysterious riddle and says, "It is `function man()`. In the morning of life, he is a child who crawls on two legs and two hands. At noon, he becomes an adult who walks on two legs. In the evening, he grows old and weak and needs a cane to walk, hence he is called three-legged." After guessing the riddle correctly, Oedipus is allowed to live. -Later that afternoon, `0xAA` passes by and encounters the Sphinx. He also solves the mysterious riddle and says, "It is `function peopleLduohW(uint256)`. In the morning of life, he is a child who crawls on two legs and two hands. At noon, he becomes an adult who walks on two legs. In the evening, he grows old and weak, and needs a cane to walk, hence he is called three-legged." Once again, the riddle is guessed correctly, and the Sphinx becomes furious. In a fit of anger, the Sphinx slips and falls from the towering cliff to its death. +Later that afternoon, `0xAA` passes by and encounters the Sphinx. He also solves the mysterious riddle and says, "It is `function peopleLduohW(uint256)`. In the morning of life, he is a child who crawls on two legs and two hands. At noon, he becomes an adult who walks on two legs. In the evening, he grows old and weak and needs a cane to walk, hence he is called three-legged." Once again, the riddle is guessed correctly, and the Sphinx becomes furious. In a fit of anger, the Sphinx slips and falls from the towering cliff to its death. ![](./img/S02-2.png) @@ -88,7 +88,7 @@ In the Poly Network hack, the hacker collided the `_method` as `f1121318093`, wh ## Reproduce on `Remix` 1. Deploy the `SelectorClash` contract. -2. Call `executeCrossChainTx()` with the parameters `0x6631313231333138303933`, `0x`, `0x`, `0`, to initiate the attack. +2. Call `executeCrossChainTx()` with the parameters `0x6631313231333138303933`, `0x`, `0x`, and `0`, to initiate the attack. 3. Check the value of the `solved` variable, which should be modified to `true`, indicating a successful attack. ## Summary diff --git a/Languages/en/S04_AccessControlExploit_en/readme.md b/Languages/en/S04_AccessControlExploit_en/readme.md index 8e1ec3ff3..2a93c5a60 100644 --- a/Languages/en/S04_AccessControlExploit_en/readme.md +++ b/Languages/en/S04_AccessControlExploit_en/readme.md @@ -82,4 +82,4 @@ function goodBurn(address account, uint amount) public { ## Summary -In this lesson, we discussed access control vulnerabilities in smart contracts. There are two main forms: incorrect access configuration and authorization check errors. To avoid these vulnerabilities, we should use a access control library to configure appropriate accesses for special functions and ensure that the caller of the function has sufficient authorization within the function's logic. +In this lesson, we discussed access control vulnerabilities in smart contracts. There are two main forms: incorrect access configuration and authorization check errors. To avoid these vulnerabilities, we should use an access control library to configure appropriate accesses for special functions and ensure that the caller of the function has sufficient authorization within the function's logic. diff --git a/Languages/en/S06_SignatureReplay_en/readme.md b/Languages/en/S06_SignatureReplay_en/readme.md index 1934303fd..01809eced 100644 --- a/Languages/en/S06_SignatureReplay_en/readme.md +++ b/Languages/en/S06_SignatureReplay_en/readme.md @@ -20,7 +20,7 @@ English translations by: [@to_22X](https://twitter.com/to_22X) --- -In this lesson, we will introduce the Signature Replay attack and how to prevent in smart contracts, which indirectly led to the theft of 20 million $OP tokens from the famous market maker Wintermute. +In this lesson, we will introduce the Signature Replay attack and how to prevent it in smart contracts, which indirectly led to the theft of 20 million $OP tokens from the famous market maker Wintermute. ## Signature Replay @@ -37,7 +37,7 @@ There are generally two common types of replay attacks on digital signatures: ## Vulnerable Contract Example -The `SigReplay` contract below is an `ERC20` token contract that has a signature replay vulnerability in its minting function. It uses off-chain signatures to allow whitelisted address `to` to mint a corresponding amount `amount` of tokens. The contract stores the `signer` address to verify the validity of the signature. +The `SigReplay` contract below is an `ERC20` token contract that has a signature replay vulnerability in its minting function. It uses off-chain signatures to allow whitelisted addresses `to` mint a corresponding amount `amount` of tokens. The contract stores the `signer` address to verify the validity of the signature. ```solidity // SPDX-License-Identifier: MIT @@ -162,7 +162,7 @@ There are two main methods to prevent signature replay attacks: ## Summary -In this lesson, we discussed the signature replay vulnerability in smart contracts and introduced two methods to prevent: +In this lesson, we discussed the signature replay vulnerability in smart contracts and introduced two methods to prevent it: 1. Keep a record of used signatures to prevent their reuse. diff --git a/Languages/en/S07_BadRandomness_en/readme.md b/Languages/en/S07_BadRandomness_en/readme.md index 2493c19c6..816250d57 100644 --- a/Languages/en/S07_BadRandomness_en/readme.md +++ b/Languages/en/S07_BadRandomness_en/readme.md @@ -85,9 +85,9 @@ Since the Remix VM does not support the `blockhash` function, you need to deploy ## How to Prevent -To prevent such vulnerabilities, we often use off-chain random numbers provided by oracle projects, such as Chainlink VRF. These random numbers are generated off-chain and then uploaded to the blockchain, ensuring that the numbers are unpredictable. For more information, you can read [WTF Solidity 39: Pseudo-random Numbers](https://github.com/AmazingAng/WTF-Solidity/tree/main/39_Random). +To prevent such vulnerabilities, we often use off-chain random numbers provided by Oracle projects, such as Chainlink VRF. These random numbers are generated off-chain and then uploaded to the blockchain, ensuring that the numbers are unpredictable. For more information, you can read [WTF Solidity 39: Pseudo-random Numbers](https://github.com/AmazingAng/WTF-Solidity/tree/main/39_Random). ## Summary -In this lesson, we introduced the Bad Randomness vulnerability and discussed a simple method to prevent it: using off-chain random numbers provided by oracle projects. NFT and GameFi projects should avoid using on-chain pseudorandom numbers for lotteries to prevent exploitation by hackers. +In this lesson, we introduced the Bad Randomness vulnerability and discussed a simple method to prevent it: using off-chain random numbers provided by Oracle projects. NFT and GameFi projects should avoid using on-chain pseudorandom numbers for lotteries to prevent exploitation by hackers. diff --git a/Languages/en/S09_DoS_en/readme.md b/Languages/en/S09_DoS_en/readme.md index 27ff8d1ef..9ed5f146c 100644 --- a/Languages/en/S09_DoS_en/readme.md +++ b/Languages/en/S09_DoS_en/readme.md @@ -26,7 +26,7 @@ In this lesson, we will introduce the Denial of Service (DoS) vulnerability in s In Web2, a Denial of Service (DoS) attack refers to the phenomenon of overwhelming a server with a large amount of junk or disruptive information, rendering it unable to serve legitimate users. In Web3, it refers to exploiting vulnerabilities that prevent a smart contract from functioning properly. -In April 2022, a popular NFT project called Akutar raised 11,539.5 ETH through a Dutch auction for its public launch, achieving great success. Participants who held their community Pass were supposed to receive a refund of 0.5 ETH. However, when they attempted to process the refunds, they discovered that the smart contract was unable to function correctly, resulting in all funds being permanently locked in the contract. Their smart contract had a DoS vulnerability. +In April 2022, a popular NFT project called Akutar raised 11,539.5 ETH through a Dutch auction for its public launch, achieving great success. Participants who held their community Passes were supposed to receive a refund of 0.5 ETH. However, when they attempted to process the refunds, they discovered that the smart contract was unable to function correctly, resulting in all funds being permanently locked in the contract. Their smart contract had a DoS vulnerability. ![](./img/S09-1.png) diff --git a/Languages/en/S10_Honeypot_en/readme.md b/Languages/en/S10_Honeypot_en/readme.md index 9977f3c1a..878fc99c7 100644 --- a/Languages/en/S10_Honeypot_en/readme.md +++ b/Languages/en/S10_Honeypot_en/readme.md @@ -31,8 +31,8 @@ In this lesson, we will introduce the Pixiu contract and stay away from Pixiu to Typically, a Pixiu scam follows the following lifecycle: -1. Malicious project owner deploys the Pixiu token contract. -2. Promote the Pixiu token to retail investors, and due to the inability to sell, the token price keeps rising. +1. A malicious project owner deploys the Pixiu token contract. +2. They promote the Pixiu token to retail investors, and due to the inability to sell, the token price keeps rising. 3. The project owner performs a "rug pull" and runs away with the funds. ![](./img/S10-1.png) diff --git a/Languages/en/S11_Frontrun_en/readme.md b/Languages/en/S11_Frontrun_en/readme.md index 2d85aeb51..486b88c88 100644 --- a/Languages/en/S11_Frontrun_en/readme.md +++ b/Languages/en/S11_Frontrun_en/readme.md @@ -166,7 +166,7 @@ main(); **5. Call the `mint()` function:** Call the `mint()` function of the Freemint contract on the deployment page of Remix to mint an NFT. -**6. Script detects and frontruns the transaction:** We can see in the terminal that the `frontrun.js` script successfully detects the transaction and frontruns it. If you call the `ownerOf()` function of the NFT contract to check the owner of `tokenId` 0, and it matches the wallet address in the frontrun script, it proves that the frontrun was successful!. +**6. The script detects and frontruns the transaction:** We can see in the terminal that the `frontrun.js` script successfully detects the transaction and frontruns it. If you call the `ownerOf()` function of the NFT contract to check the owner of `tokenId` 0, and it matches the wallet address in the frontrun script, it proves that the frontrun was successful! ![](./img/S11-4.png) ## How to Prevent @@ -174,7 +174,7 @@ main(); Frontrunning is a common issue on Ethereum and other public blockchains. While we cannot eliminate it entirely, we can reduce the profitability of frontrunning by minimizing the importance of transaction order or time: - Use a commit-reveal scheme. -- Use dark pools, where user transactions bypass the public mempool and go directly to miners. Examples include flashbots and TaiChi. +- Use dark pools, where user transactions bypass the public mempool and go directly to miners. Examples include Flashbots and TaiChi. ## Summary diff --git a/Languages/en/S12_TxOrigin_en/img/S12-4.jpg b/Languages/en/S12_TxOrigin_en/img/S12-4.jpg index 58909597c..10ed99333 100644 Binary files a/Languages/en/S12_TxOrigin_en/img/S12-4.jpg and b/Languages/en/S12_TxOrigin_en/img/S12-4.jpg differ diff --git a/Languages/en/S12_TxOrigin_en/img/S12_1.jpg b/Languages/en/S12_TxOrigin_en/img/S12_1.jpg index fcb7b7b59..ee568e607 100644 Binary files a/Languages/en/S12_TxOrigin_en/img/S12_1.jpg and b/Languages/en/S12_TxOrigin_en/img/S12_1.jpg differ diff --git a/Languages/en/S13_UncheckedCall_en/readme.md b/Languages/en/S13_UncheckedCall_en/readme.md index e551d585e..e9b6ccc48 100644 --- a/Languages/en/S13_UncheckedCall_en/readme.md +++ b/Languages/en/S13_UncheckedCall_en/readme.md @@ -24,7 +24,7 @@ In this lesson, we will discuss the unchecked low-level calls in smart contracts ## Low-Level Calls -Low-level calls in Ethereum include `call()`, `delegatecall()`, `staticcall()`, and `send()`. These functions are different from other functions in Solidity. When an exception occurs, they do not pass it to the upper layer, nor do they cause the transaction to revert; they only return a boolean value `false` to indicate that the call failed. Therefore, if the return value of the low-level function call is not checked, the code of the upper layer function will continue to run regardless of whether the low-level call fails or not. For more information about low-level calls, please read [WTF Solidity 20-23](https://github.com/AmazingAng/WTF-Solidity) +Low-level calls in Ethereum include `call()`, `delegatecall()`, `staticcall()`, and `send()`. These functions are different from other functions in Solidity. When an exception occurs, they do not pass it to the upper layer, nor do they cause the transaction to revert; they only return a boolean value `false` to indicate that the call failed. Therefore, if the return value of the low-level function call is not checked, the code of the upper-layer function will continue to run regardless of whether the low-level call fails or not. For more information about low-level calls, please read [WTF Solidity 20-23](https://github.com/AmazingAng/WTF-Solidity) Calling `send()` is the most error-prone: some contracts use `send()` to send `ETH`, but `send()` limits the gas to be less than 2300, otherwise it will fail. When the callback function of the target address is more complicated, the gas spent will be higher than 2300, which will cause `send()` to fail. If the return value is not checked in the upper layer function at this time, the transaction will continue to execute, and unexpected problems will occur. In 2016, there was a chain game called `King of Ether`, which caused the refund to fail to be sent normally due to this vulnerability (["autopsy" report](https://www.kingoftheether.com/postmortem.html)). @@ -128,4 +128,4 @@ You can use the following methods to prevent the unchecked low-level call vulner ## Summary -We introduced the vulnerability of unchecked low-level calls and how to prevent. Ethereum's low-level calls (`call`, `delegatecall`, `staticcall`, `send`) will return a boolean value `false` when they fail, but they will not cause the entire transaction to revert. If the developer does not check it, an accident will occur. \ No newline at end of file +We introduced the vulnerability of unchecked low-level calls and how to prevent them. Ethereum's low-level calls (`call`, `delegatecall`, `staticcall`, `send`) will return a boolean value `false` when they fail, but they will not cause the entire transaction to revert. If the developer does not check it, an accident will occur. diff --git a/Languages/en/S14_TimeManipulation_en/readme.md b/Languages/en/S14_TimeManipulation_en/readme.md index c20126dae..d550792c3 100644 --- a/Languages/en/S14_TimeManipulation_en/readme.md +++ b/Languages/en/S14_TimeManipulation_en/readme.md @@ -54,7 +54,7 @@ contract TimeManipulation is ERC721 { ## Reproduce on Foundry -Attackers only need to manipulate the block timestamp and set it to a number that can be divided by 170, and they can successfully mint NFTs. We choose Foundry to reproduce this attack because it provides cheatcode to modify the block timestamp. If you are not familiar with Foundry/cheatcode, you can read the [Foundry tutorial](https://github.com/AmazingAng/WTF-Solidity/blob/main/Topics/Tools/TOOL07_Foundry/readme.md) and [Foundry Book](https://book.getfoundry.sh/forge/cheatcodes). +Attackers only need to manipulate the block timestamp and set it to a number that can be divided by 170, and they can successfully mint NFTs. We chose Foundry to reproduce this attack because it provides a cheat code to modify the block timestamp. If you are not familiar with Foundry/cheatcode, you can read the [Foundry tutorial](https://github.com/AmazingAng/WTF-Solidity/blob/main/Topics/Tools/TOOL07_Foundry/readme.md) and [Foundry Book](https://book.getfoundry.sh/forge/cheatcodes). 1. Create a `TimeManipulation` contract variable `nft`. 2. Create a wallet address `alice`. diff --git a/Languages/en/S15_OracleManipulation_en/readme.md b/Languages/en/S15_OracleManipulation_en/readme.md index 1d2c12f0c..3b3e44f4d 100644 --- a/Languages/en/S15_OracleManipulation_en/readme.md +++ b/Languages/en/S15_OracleManipulation_en/readme.md @@ -40,9 +40,9 @@ One of the most commonly used oracles is a price oracle, which refers to any dat If an oracle is not used correctly by developers, it can pose significant security risks. -- In October 2021, Cream Finance, a DeFi platform on the Binance Smart Chain, suffered a [theft of $130 million in user funds](https://rekt.news/cream-rekt-2/) due to an oracle vulnerability. -- In May 2022, Mirror Protocol, a synthetic asset platform on the Terra blockchain, suffered a [theft of $115 million in user funds](https://rekt.news/mirror-rekt/) due to an oracle vulnerability. -- In October 2022, Mango Market, a decentralized lending platform on the Solana blockchain, suffered a [theft of $115 million in user funds](https://rekt.news/mango-markets-rekt/) due to an oracle vulnerability. +- In October 2021, Cream Finance, a DeFi platform on the Binance Smart Chain, suffered a [theft of $130 million in user funds](https://rekt.news/cream-rekt-2/) due to an Oracle vulnerability. +- In May 2022, Mirror Protocol, a synthetic asset platform on the Terra blockchain, suffered a [theft of $115 million in user funds](https://rekt.news/mirror-rekt/) due to an Oracle vulnerability. +- In October 2022, Mango Market, a decentralized lending platform on the Solana blockchain, suffered a [theft of $115 million in user funds](https://rekt.news/mango-markets-rekt/) due to an Oracle vulnerability. ## Vulnerability Example @@ -116,7 +116,7 @@ These 4 steps can be completed in a single transaction. ### Reproduce on Foundry -We will use Foundry to reproduce the manipulation attack on the oracle because it is fast and allows us to create a local fork of the mainnet for testing. If you are not familiar with Foundry, you can read [WTF Solidity Tools T07: Foundry](https://github.com/AmazingAng/WTF-Solidity/blob/main/Topics/Tools/TOOL07_Foundry/readme.md). +We will use Foundry to reproduce the manipulation attack on the Oracle because it is fast and allows us to create a local fork of the mainnet for testing. If you are not familiar with Foundry, you can read [WTF Solidity Tools T07: Foundry](https://github.com/AmazingAng/WTF-Solidity/blob/main/Topics/Tools/TOOL07_Foundry/readme.md). 1. After installing Foundry, start a new project and install the OpenZeppelin library by running the following command in the command line: diff --git a/Languages/en/S16_NFTReentrancy_en/readme.md b/Languages/en/S16_NFTReentrancy_en/readme.md index dea93a089..fc4a34f10 100644 --- a/Languages/en/S16_NFTReentrancy_en/readme.md +++ b/Languages/en/S16_NFTReentrancy_en/readme.md @@ -41,7 +41,7 @@ Now let's learn an example of an NFT contract with a reentrancy vulnerability. T ### Vulnerable Contract -The `NFTReentrancy` contract inherits from the `ERC721` contract. It has two main state variables: `totalSupply` to track the total supply of NFTs and `mintedAddress` to keep track of addresses that have already minted to prevent a user from minting multiple times. It has two main functions: +The `NFTReentrancy` contract inherits from the `ERC721` contract. It has two main state variables: `totalSupply` to track the total supply of NFTs and `mintedAddress` to keep track of addresses that have already been minted to prevent a user from minting multiple times. It has two main functions: - Constructor: Initializes the name and symbol of the `ERC721` NFT. - `mint()`: Mint function where each user can mint one NFT for free. **Note: This function has a reentrancy vulnerability!**