From 9fccd02b82c86038a43b9c0d1c4418facfac3c0f Mon Sep 17 00:00:00 2001 From: Mosamorphing <121625762+Mosamorphing@users.noreply.github.com> Date: Mon, 18 Mar 2024 20:23:06 +0100 Subject: [PATCH 01/15] Update readme.md --- Languages/en/41_WETH_en/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Languages/en/41_WETH_en/readme.md b/Languages/en/41_WETH_en/readme.md index 334d1431..1a7506e8 100644 --- a/Languages/en/41_WETH_en/readme.md +++ b/Languages/en/41_WETH_en/readme.md @@ -107,7 +107,7 @@ Deploy the `WETH` contract as shown in the image. ### 2. Execute `deposit` to deposit `1 ETH`, and check the `WETH` balance -Execute `deposit` function to deposit `1 ETH`, and check the `WETH` balance. +Execute the `deposit` function to deposit `1 ETH`, and check the `WETH` balance. ![WETH](./img/41-3.jpg) From 1e03a98854b2048a27c9dd1ccd1146a5ce98d025 Mon Sep 17 00:00:00 2001 From: Mosamorphing <121625762+Mosamorphing@users.noreply.github.com> Date: Mon, 18 Mar 2024 20:28:21 +0100 Subject: [PATCH 02/15] Update readme.md --- Languages/en/42_PaymentSplit_en/readme.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Languages/en/42_PaymentSplit_en/readme.md b/Languages/en/42_PaymentSplit_en/readme.md index 3aabb03e..13dbb270 100644 --- a/Languages/en/42_PaymentSplit_en/readme.md +++ b/Languages/en/42_PaymentSplit_en/readme.md @@ -17,7 +17,7 @@ All codes and tutorials are open-sourced on Github: [github.com/AmazingAng/WTFSo --- -In this lecture, we'll introduce the payment splitting contract, which allows the transfer of `ETH` to a group of accounts according to their respective weights for payment splitting purposes. The code section is a simplification of the PaymentSplitter contract provided by the OpenZeppelin library, which can be found on [Github](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/finance/PaymentSplitter.sol). +In this lecture, we'll introduce the payment-splitting contract, which allows the transfer of `ETH` to a group of accounts according to their respective weights for payment-splitting purposes. The code section is a simplification of the PaymentSplitter contract provided by the OpenZeppelin library, which can be found on [Github](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/finance/PaymentSplitter.sol). ## Payment Split @@ -30,9 +30,9 @@ Payment split is the act of dividing money according to a certain ratio. In real The Payment Split contract (`PaymentSplit`) has the following features: 1. When creating the contract, the beneficiaries `payees` and their share `shares` are predetermined. -2. The shares can be equal or in any other proportions. -3. From all the ETH that the contract receives, each beneficiary is able to withdraw the amount proportional to their allocated share. -4. The Payment Split contract follows the `Pull Payment` pattern, where payments are not automatically transferred to the account, but are kept in the contract. Beneficiaries trigger the actual transfer by calling the `release()` function. +2. The shares can be equal or in any other proportion. +3. From all the ETH that the contract receives, each beneficiary can withdraw the amount proportional to their allocated share. +4. The Payment Split contract follows the `Pull Payment` pattern, where payments are not automatically transferred to the account but are kept in the contract. Beneficiaries trigger the actual transfer by calling the `release()` function. ```solidity // SPDX-License-Identifier: MIT @@ -62,7 +62,7 @@ There are a total of `3` events in the Splitter Contract: ### State Variables -There are `5` state variables in the revenue splitting contract, used to record beneficiary addresses, shares, and paid out `ETH`: +There are `5` state variables in the revenue-splitting contract, used to record beneficiary addresses, shares, and paid-out `ETH`: - `totalShares`: Total shares, which is the sum of `shares`. - `totalReleased`: The amount of `ETH` paid out from the revenue splitting contract to beneficiaries, which is the sum of `released`. @@ -81,7 +81,7 @@ There are `5` state variables in the revenue splitting contract, used to record ### Functions -There are `6` functions in the revenue sharing contract: +There are `6` functions in the revenue-sharing contract: - Constructor: initializes the beneficiary array `_payees` and the revenue sharing array `_shares`, where the length of both arrays must not be 0 and their lengths must be equal. Elements of the \_shares array must be greater than 0, and the addresses in the \_payees array can't be the zero address and can't have a duplicate address. - `receive()`: callback function, releases the `PaymentReceived` event when the revenue sharing contract receives `ETH`. @@ -203,7 +203,7 @@ In the constructor, enter two beneficiary addresses with shares of `1` and `3`. ![Viewing the second beneficiary](./img/42-4.png) -### 3. Call `release` function to claim `ETH` +### 3. Call the `release` function to claim `ETH` ![Calling the release function](./img/42-5.png) @@ -213,4 +213,4 @@ In the constructor, enter two beneficiary addresses with shares of `1` and `3`. ## Summary -In this lecture, we introduced the revenue sharing contract. In the world of blockchain, `Code is Law`, we can write the proportion that each person should receive in the smart contract beforehand. After receiving revenue, the smart contract will handle revenue sharing to avoid the issue of "unequal distribution of shares" afterwards. +In this lecture, we introduced the revenue-sharing contract. In the world of blockchain, `Code is Law`, we can write the proportion that each person should receive in the smart contract beforehand. After receiving revenue, the smart contract will handle revenue sharing to avoid the issue of "unequal distribution of shares" afterwards. From 659ee04720108352041f4fc464eb60d26ebb94a5 Mon Sep 17 00:00:00 2001 From: Mosamorphing <121625762+Mosamorphing@users.noreply.github.com> Date: Mon, 18 Mar 2024 20:30:24 +0100 Subject: [PATCH 03/15] Update readme.md --- Languages/en/43_TokenVesting_en/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Languages/en/43_TokenVesting_en/readme.md b/Languages/en/43_TokenVesting_en/readme.md index 87dec330..3cd2f3a8 100644 --- a/Languages/en/43_TokenVesting_en/readme.md +++ b/Languages/en/43_TokenVesting_en/readme.md @@ -150,4 +150,4 @@ There are `3` functions in the LinearVesting contract. ## Summary -A large amount of token unlocking in the short term can cause huge pressure on the token price, while agreed-upon token ownership terms can alleviate selling pressure and prevent the team and capital parties from exiting too early. In this lesson, we introduced token ownership terms and wrote a contract for linear release of ERC20 tokens. +A large amount of token unlocking in the short term can cause huge pressure on the token price, while agreed-upon token ownership terms can alleviate selling pressure and prevent the team and capital parties from exiting too early. In this lesson, we introduced token ownership terms and wrote a contract for the linear release of ERC20 tokens. From cc316bce12f7c4af32851c7efa76cf74d4f6ef18 Mon Sep 17 00:00:00 2001 From: Mosamorphing <121625762+Mosamorphing@users.noreply.github.com> Date: Mon, 18 Mar 2024 20:33:51 +0100 Subject: [PATCH 04/15] Update readme.md --- Languages/en/44_TokenLocker_en/readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Languages/en/44_TokenLocker_en/readme.md b/Languages/en/44_TokenLocker_en/readme.md index 673ef2d1..f3f37f84 100644 --- a/Languages/en/44_TokenLocker_en/readme.md +++ b/Languages/en/44_TokenLocker_en/readme.md @@ -13,7 +13,7 @@ Feel free to follow me on Twitter: [@0xAA_Science](https://twitter.com/0xAA_Scie You are also welcome to join the WTF Scientists community and find information on how to join the WeChat group: [link](https://discord.gg/5akcruXrsk) -All of the code and tutorials are open source and can be found on Github (I will provide a course certification for 1024 stars and a community NFT for 2048 stars): [github.com/AmazingAng/WTFSolidity](https://github.com/AmazingAng/WTFSolidity) +All of the code and tutorials are open source and can be found on GitHub (I will provide a course certification for 1024 stars and a community NFT for 2048 stars): [github.com/AmazingAng/WTFSolidity](https://github.com/AmazingAng/WTFSolidity) --- @@ -23,7 +23,7 @@ A Token Lock is a simple time-based smart contract that allows one to lock a num ### What are LP Tokens? -In decentralized exchanges (DEX), users trade tokens, such as in the case of Uniswap. Unlike centralized exchanges (CEX), decentralized exchanges use Automated Market Maker (AMM) mechanisms. Users or projects provide a liquidity pool, so that other users can buy and sell tokens instantly. To compensate the user or project for providing the liquidity pool, the DEX will mint corresponding LP tokens, which represent their contribution and entitle them to transaction fees. +In decentralized exchanges (DEX), users trade tokens, such as in the case of Uniswap. Unlike centralized exchanges (CEX), decentralized exchanges use Automated Market Maker (AMM) mechanisms. Users or projects provide a liquidity pool so that other users can buy and sell tokens instantly. To compensate the user or project for providing the liquidity pool, the DEX will mint corresponding LP tokens, which represent their contribution and entitle them to transaction fees. ### Why Lock Liquidity? From 068e8c08e7476f9dbc5619fc09fb2134000f948e Mon Sep 17 00:00:00 2001 From: Mosamorphing <121625762+Mosamorphing@users.noreply.github.com> Date: Mon, 18 Mar 2024 20:36:59 +0100 Subject: [PATCH 05/15] Update readme.md --- Languages/en/46_ProxyContract_en/readme.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Languages/en/46_ProxyContract_en/readme.md b/Languages/en/46_ProxyContract_en/readme.md index f4f25057..2459c9d4 100644 --- a/Languages/en/46_ProxyContract_en/readme.md +++ b/Languages/en/46_ProxyContract_en/readme.md @@ -31,7 +31,7 @@ Is there a way to modify or upgrade the contract after it is deployed? The answe ![Proxy Pattern](./img/46-1.png) -The proxy pattern separates contract data and logic, and saves them in different contracts. Taking the simple proxy contract in the above figure as an example, the data (state variable) is stored in the proxy contract, and the logic (function) is stored in another logic contract. The proxy contract (Proxy) delegates the function call to the logic contract (Implementation) through `delegatecall`, and then returns the final result to the caller(Caller). +The proxy pattern separates contract data and logic and saves them in different contracts. Taking the simple proxy contract in the above figure as an example, the data (state variable) is stored in the proxy contract, and the logic (function) is stored in another logic contract. The proxy contract (Proxy) delegates the function call to the logic contract (Implementation) through `delegatecall`, and then returns the final result to the caller(Caller). The proxy pattern has two main benefits: 1. Upgradeable: When we need to upgrade the logic of the contract, we only need to point the proxy contract to a new logic contract. @@ -77,8 +77,8 @@ The fallback function of `Proxy` delegates external calls to the `Logic` contrac ```solidity /** -* @dev fallback function, delegates invocations of current contract to `implementation` contract -* with inline assembly, it gives fallback function a return value +* @dev fallback function, delegates invocations of the current contract to `implementation` contract +* with inline assembly, it gives the fallback function a return value */ fallback() external payable { address _implementation = implementation; @@ -87,7 +87,7 @@ fallback() external payable { // the parameters of opcode calldatacopy: start position of memory, start position of calldata, length of calldata calldatacopy(0, 0, calldatasize()) - // use delegatecall to call implementation contract + // use delegatecall to call the implementation contract // the parameters of opcode delegatecall: gas, target contract address, start position of input memory, length of input memory, start position of output memory, length of output memory // set start position of output memory and length of output memory to 0 // delegatecall returns 1 if success, 0 if fail @@ -199,4 +199,4 @@ The question we left for everyone earlier was: why does a call to `increment()` In the next lesson, we will introduce upgradeable proxy contracts. -Although the proxy contract is very powerful, it is prone to bugs. When using it, you'd better directly copy the template contract from [OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/proxy). \ No newline at end of file +Although the proxy contract is very powerful, it is prone to bugs. When using it, you'd better directly copy the template contract from [OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/proxy). From afcaf25feda4fa8c7d6df95a0c1d7fe8a02521b4 Mon Sep 17 00:00:00 2001 From: Mosamorphing <121625762+Mosamorphing@users.noreply.github.com> Date: Mon, 18 Mar 2024 20:40:18 +0100 Subject: [PATCH 06/15] Update readme.md --- Languages/en/47_Upgrade_en/readme.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Languages/en/47_Upgrade_en/readme.md b/Languages/en/47_Upgrade_en/readme.md index 70fe7dbc..d4d3e355 100644 --- a/Languages/en/47_Upgrade_en/readme.md +++ b/Languages/en/47_Upgrade_en/readme.md @@ -44,14 +44,14 @@ It contains `3` functions: - Constructor: Initializes admin and logic contract addresses. - `fallback()`: Callback function, delegates the call to the logic contract. -- `upgrade()`: Upgrade function, changes the logic contract's address, can only be called by `admin`. +- `upgrade()`: The upgrade function, changes the logic contract's address, and can only be called by `admin`. ```solidity // SPDX-License-Identifier: MIT // wtf.academy pragma solidity ^0.8.4; -// simple upgradeable contract, the admin could change the logic contract's address by calling upgrade function, thus change the contract logic +// simple upgradeable contract, the admin could change the logic contract's address by calling the upgrade function, thus changing the contract logic // FOR TEACHING PURPOSE ONLY, DO NOT USE IN PRODUCTION contract SimpleUpgrade { // logic contract's address @@ -60,7 +60,7 @@ contract SimpleUpgrade { // admin address address public admin; - // string variable, could be changed by logic contract's function + // string variable, could be changed by the logic contract's function string public words; // constructor, initializing admin address and logic contract's address @@ -74,7 +74,7 @@ contract SimpleUpgrade { (bool success, bytes memory data) = implementation.delegatecall(msg.data); } - // upgrade function, changes the logic contract's address, can only by called by admin + // upgrade function, changes the logic contract's address, can only be called by admin function upgrade(address newImplementation) external { require(msg.sender == admin); implementation = newImplementation; @@ -109,7 +109,7 @@ This logic contract contains `3` state variables, consistent with the proxy cont ```solidity // Logic Contract 2 contract Logic2 { - // State variables consistent with proxy contract to prevent slot collisions + // State variables consistent with a proxy contract to prevent slot collisions address public implementation; address public admin; // String that can be changed through the function of the logic contract @@ -142,4 +142,4 @@ contract Logic2 { ## Summary -In this lesson, we introduced a simple upgradeable contract. It is a proxy contract that can change the logic contract and adds upgrade functionality to immutable smart contracts. However, this contract has a problem of selector conflict and poses security risks. Later, we will introduce the upgradeable contract standards that solve this vulnerability: Transparent Proxy and UUPS. \ No newline at end of file +In this lesson, we introduced a simple upgradeable contract. It is a proxy contract that can change the logic contract and add upgrade functionality to immutable smart contracts. However, this contract has a problem of selector conflict and poses security risks. Later, we will introduce the upgradeable contract standards that solve this vulnerability: Transparent Proxy and UUPS. From 03a6dcb74cd00481beaf0b6e462b1a31b9119c36 Mon Sep 17 00:00:00 2001 From: Mosamorphing <121625762+Mosamorphing@users.noreply.github.com> Date: Mon, 18 Mar 2024 20:43:45 +0100 Subject: [PATCH 07/15] Update readme.md --- Languages/en/48_TransparentProxy_en/readme.md | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Languages/en/48_TransparentProxy_en/readme.md b/Languages/en/48_TransparentProxy_en/readme.md index 04cf0d40..4559e387 100644 --- a/Languages/en/48_TransparentProxy_en/readme.md +++ b/Languages/en/48_TransparentProxy_en/readme.md @@ -23,7 +23,7 @@ In this lesson, we will introduce the selector clash issue in proxy contracts, a ## Selector Clash -In smart contracts, a function selector is the hash of a function signature's first 4 bytes. For example, the selector of function `mint(address account)` is `bytes4(keccak256("mint(address)"))`, which is `0x6a627842`. More about function selectors see [WTF Solidity Tutorial #29: Function Selectors](https://github.com/AmazingAng/WTFSolidity/blob/main/Languages/en/29_Selector_en/readme.md). +In smart contracts, a function selector is the hash of a function signature's first 4 bytes. For example, the selector of function `mint(address account)` is `bytes4(keccak256("mint(address)"))`, which is `0x6a627842`. For more about function selectors see [WTF Solidity Tutorial #29: Function Selectors](https://github.com/AmazingAng/WTFSolidity/blob/main/Languages/en/29_Selector_en/readme.md). Because a function selector has only 4 bytes, its range is very small. Therefore, two different functions may have the same selector, such as the following two functions: @@ -46,7 +46,7 @@ Currently, there are two upgradeable contract standards that solve this problem: The logic of the transparent proxy is very simple: admin may mistakenly call the upgradable functions of the proxy contract when calling the functions of the logic contract because of the "selector clash". Restricting the admin's privileges can solve the conflict: - The admin becomes a tool person and can only upgrade the contract by calling the upgradable function of the proxy contract, without calling the fallback function to call the logic contract. -- Other users cannot call upgradable function, but can call functions of the logic contract. +- Other users cannot call the upgradable function but can call functions of the logic contract. ### Proxy Contract @@ -102,13 +102,13 @@ The new and old logic contracts here are the same as in [Lecture 47](https://git ```solidity // old logic contract contract Logic1 { - // state variable should be the same as proxy contract, in case of slot clash + // state variable should be the same as a proxy contract, in case of slot clash address public implementation; address public admin; - // string variable, can be modified by calling loginc contract's function + // string variable, can be modified by calling the logic contract's function string public words; - // to change state variable in proxy contract, selector 0xc2985578 + //To change state variable in proxy contract, selector 0xc2985578 function foo() public{ words = "old"; } @@ -116,13 +116,13 @@ contract Logic1 { // new logic contract contract Logic2 { - // state variable should be the same as proxy contract, in case of slot clash + // state variable should be the same as a proxy contract, in case of slot clash address public implementation; address public admin; - // string variable, can be modified by calling loginc contract's function + // string variable, can be modified by calling the logic contract's function string public words; - // to change state variable in proxy contract, selector 0xc2985578 + //To change state variable in proxy contract, selector 0xc2985578 function foo() public{ words = "new"; } @@ -152,6 +152,6 @@ contract Logic2 { ## Summary -In this lesson, we introduced the "selector clash" in proxy contracts and how to avoid this problem using transparent proxy. The logic of transparent proxy is simple, solving the "selector clash" problem by restricting the admin's access to the logic contract. However, it has a drawback that every time a user calls a function, there is an additional check for whether or not the caller is the admin, which consumes more gas. Nevertheless, transparent proxy are still the solution chosen by most project teams. +In this lesson, we introduced the "selector clash" in proxy contracts and how to avoid this problem using a transparent proxy. The logic of transparent proxy is simple, solving the "selector clash" problem by restricting the admin's access to the logic contract. However, it has a drawback; every time a user calls a function, there is an additional check for whether or not the caller is the admin, which consumes more gas. Nevertheless, transparent proxies are still the solution chosen by most project teams. -In the next lesson, we will introduce the general Universal Upgradeable Proxy Standard (UUPS), which is more complex but consumes less gas. \ No newline at end of file +In the next lesson, we will introduce the general Universal Upgradeable Proxy Standard (UUPS), which is more complex but consumes less gas. From b2252e409b67d0b9ce0e1bb081781c907ba42095 Mon Sep 17 00:00:00 2001 From: Mosamorphing <121625762+Mosamorphing@users.noreply.github.com> Date: Mon, 18 Mar 2024 20:49:49 +0100 Subject: [PATCH 08/15] Update readme.md --- Languages/en/49_UUPS_en/readme.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Languages/en/49_UUPS_en/readme.md b/Languages/en/49_UUPS_en/readme.md index 1b1ecb4c..0c579cc2 100644 --- a/Languages/en/49_UUPS_en/readme.md +++ b/Languages/en/49_UUPS_en/readme.md @@ -33,21 +33,21 @@ The following table summarizes the differences between regular upgradeable contr ## UUPS contract -First, let's review [WTF Solidity Minimalist Tutorial Lesson 23: Delegatecall](https://github.com/AmazingAng/WTFSolidity/blob/main/Languages/en/23_Delegatecall_en/readme.md). If user A `delegatecall`s contract C (logic contract) through contract B (proxy contract), the context is still the context of contract B, and `msg.sender` is still user A rather than contract B. Therefore, the UUPS contract can place the upgrade function in the logical contract and check whether the caller is admin. +First, let's review [WTF Solidity Minimalist Tutorial Lesson 23: Delegatecall](https://github.com/AmazingAng/WTFSolidity/blob/main/Languages/en/23_Delegatecall_en/readme.md). If user A `delegatecall`s contract C (logic contract) through contract B (proxy contract), the context is still the context of contract B, and `msg.sender` is still user A rather than contract B. Therefore, the UUPS contract can place the upgrade function in the logical contract and check whether the caller is an admin. ![delegatecall](./img/49-2.png) ### UUPS proxy contract -The UUPS proxy contract looks like an unupgradable proxy contract and is very simple because the upgrade function is placed in the logic contract. It contains three variables: +The UUPS proxy contract looks like an un-upgradable proxy contract and is very simple because the upgrade function is placed in the logic contract. It contains three variables: - `implementation`: address of the logic contract. - `admin`: address of the admin. -- `words`: string that can be changed by functions in the logic contract. +- `words`: a string that can be changed by functions in the logic contract. It contains `2` functions: - Constructor: initializes the admin and logic contract address. -- `fallback()`: callback function that delegates the call to the logic contract. +- `fallback()`: a callback function that delegates the call to the logic contract. ```solidity contract UUPSProxy { @@ -146,4 +146,4 @@ contract UUPS2{ ![demo](./img/49-8.png) Summary: -In this lesson, we introduced another solution to the "selector clash" in proxy contracts: UUPS. Unlike transparent proxies, UUPS places upgrade functions in the logic contract, making "selector clash" unable to pass compilation. Compared to transparent proxies, UUPS is more gas-efficient but also more complex. \ No newline at end of file +In this lesson, we introduced another solution to the "selector clash" in proxy contracts: UUPS. Unlike transparent proxies, UUPS places upgrade functions in the logic contract, making "selector clash" unable to pass compilation. Compared to transparent proxies, UUPS is more gas-efficient but also more complex. From 6adedfded53a8e9a92ae25caaf767ebe1218d1f0 Mon Sep 17 00:00:00 2001 From: Mosamorphing <121625762+Mosamorphing@users.noreply.github.com> Date: Mon, 18 Mar 2024 21:16:07 +0100 Subject: [PATCH 09/15] Update readme.md --- Languages/en/50_MultisigWallet_en/readme.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Languages/en/50_MultisigWallet_en/readme.md b/Languages/en/50_MultisigWallet_en/readme.md index 3dd2f01c..ae84c79c 100644 --- a/Languages/en/50_MultisigWallet_en/readme.md +++ b/Languages/en/50_MultisigWallet_en/readme.md @@ -26,7 +26,7 @@ Vitalik once said that a multisig wallet is safer than a hardware wallet ([tweet ## Multisig Wallet -A multisig wallet is an electronic wallet where transactions require authorization from multiple private key holders (multisig owners) before they can be executed. For example, if a wallet is managed by three multisig owners, each transaction requires authorization from at least two of them. Multisig wallets can prevent single point failure (loss of private keys, individual misbehavior), have greater decentralized characteristics, and provide increased security. It is used by many DAOs. +A multisig wallet is an electronic wallet where transactions require authorization from multiple private key holders (multisig owners) before they can be executed. For example, if a wallet is managed by three multisig owners, each transaction requires authorization from at least two of them. Multisig wallets can prevent single-point failure (loss of private keys, individual misbehavior), have greater decentralized characteristics, and provide increased security. It is used by many DAOs. Gnosis Safe is the most popular multisig wallet on Ethereum, managing nearly $40 billion in assets. The contract has undergone auditing and practical testing, supports multiple chains (Ethereum, BSC, Polygon, etc.), and provides comprehensive DAPP support. For more information, you can read the [Gnosis Safe tutorial](https://peopledao.mirror.xyz/nFCBXda8B5ZxQVqSbbDOn2frFDpTxNVtdqVBXGIjj0s) I wrote in December 2021. @@ -101,7 +101,7 @@ The `MultisigWallet` contract has `6` functions: } ``` -2. `_setupOwners()`: Called by the constructor during contract deployment to initialize the `owners`, `isOwner`, `ownerCount`, `threshold` state variables. The passed-in parameters must have a threshold greater than or equal to `1` and less than or equal to the number of multisignature owners. The multisignature addresses cannot be the zero address and cannot be duplicated. +2. `_setupOwners()`: Called by the constructor during contract deployment to initialize the `owners`, `isOwner`, `ownerCount`, and `threshold` state variables. The passed-in parameters must have a threshold greater than or equal to `1` and less than or equal to the number of multisignature owners. The multisignature addresses cannot be the zero addresses and cannot be duplicated. ```solidity /// @dev Initialize owners, isOwner, ownerCount, threshold @@ -130,7 +130,7 @@ function _setupOwners(address[] memory _owners, uint256 _threshold) internal { 3. `execTransaction()`: After collecting enough multisig signatures, it verifies the signatures and executes the transaction. The parameters passed in include the target address `to`, the amount of Ethereum sent `value`, the data `data`, and the packaged signatures `signatures`. The packaged signature is the signature of the transaction hash collected by the multisig parties, packaged into a [bytes] data in the order of the multisig owners' addresses from small to large. This step calls `encodeTransactionData()` to encode the transaction and calls `checkSignatures()` to verify the validity of the signatures and whether the number of signatures reaches the execution threshold. ```solidity -/// @dev After collecting enough signatures from the multisig, execute transaction +/// @dev After collecting enough signatures from the multisig, execute the transaction /// @param to Target contract address /// @param value msg.value, ether paid /// @param data calldata @@ -305,4 +305,4 @@ Transaction hash: 0xb43ad6901230f2c59c3f7ef027c9a372f199661c61beeec49ef5a774231f In this lesson, we introduced the concept of a multisig wallet and wrote a minimal implementation of a multisig wallet contract, which is less than 150 lines of code. -I have had many opportunities to work with multisig wallets. In 2021, I learned about Gnosis Safe and wrote a tutorial on its usage in both Chinese and English because of the creation of the national treasury by PeopleDAO. Afterwards, I was lucky enough to maintain the assets of three treasury multisig wallets and now I am deeply involved in governing Safes as a guardian. I hope that everyone's assets will be even more secure. \ No newline at end of file +I have had many opportunities to work with multisig wallets. In 2021, I learned about Gnosis Safe and wrote a tutorial on its usage in both Chinese and English because of the creation of the national treasury by PeopleDAO. Afterwards, I was lucky enough to maintain the assets of three treasury multisig wallets and now I am deeply involved in governing Safes as a guardian. I hope that everyone's assets will be even more secure. From c10b2af18fa874fc8cd9ba4546a41cef13b52774 Mon Sep 17 00:00:00 2001 From: Mosamorphing <121625762+Mosamorphing@users.noreply.github.com> Date: Mon, 18 Mar 2024 21:19:08 +0100 Subject: [PATCH 10/15] Update readme.md --- Languages/en/51_ERC4626_en/readme.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Languages/en/51_ERC4626_en/readme.md b/Languages/en/51_ERC4626_en/readme.md index 1561cf88..2b16049f 100644 --- a/Languages/en/51_ERC4626_en/readme.md +++ b/Languages/en/51_ERC4626_en/readme.md @@ -21,7 +21,7 @@ All code and tutorials are open source on GitHub: [github.com/AmazingAng/WTFSoli ----- -We often say that DeFi is like LEGO blocks, where you can create new protocols by combining multiple protocols. However, due to the lack of standards in DeFi, its composability is severely affected. ERC4626 extends the ERC20 token standard and aims to standardize yield vaults. In this talk, we will introduce the new generation DeFi standard - ERC4626 and write a simple vault contract. The teaching code reference comes from the ERC4626 contract in openzeppelin and solmate and is for teaching purposes only. +We often say that DeFi is like LEGO blocks, where you can create new protocols by combining multiple protocols. However, due to the lack of standards in DeFi, its composability is severely affected. ERC4626 extends the ERC20 token standard and aims to standardize yield vaults. In this talk, we will introduce the new generation DeFi standard - ERC4626 and write a simple vault contract. The teaching code reference comes from the ERC4626 contract in Openzeppelin and Solmate and is for teaching purposes only. ## Vault @@ -47,12 +47,12 @@ In summary, the importance of ERC4626 for DeFi is no less than that of ERC721 fo ### Key Points of ERC4626 -The ERC4626 standard mainly implements the following logics: +The ERC4626 standard mainly implements the following logic: 1. ERC20: ERC4626 inherits ERC20, and the vault shares are represented by ERC20 tokens: users deposit specific ERC20 underlying assets (such as WETH) into the vault, and the contract mints a specific number of vault share tokens for them; When users withdraw underlying assets from the vault, the corresponding number of vault share tokens will be destroyed. The `asset()` function returns the token address of the vault's underlying asset. -2. Deposit logic: allows users to deposit underlying assets and mint corresponding number of vault shares. Related functions are `deposit()` and `mint()`. The `deposit(uint assets, address receiver)` function allows users to deposit `assets` units of assets and mint corresponding number of vault shares to `receiver` address. `mint(uint shares, address receiver)` is similar, except that it takes the minted vault shares as a parameter. -3. Withdrawal logic: allows users to destroy vault share tokens and withdraw corresponding number of underlying assets from the vault. Related functions are `withdraw()` and `redeem()`, the former taking the amount of underlying assets to be withdrawn as a parameter, and the latter taking the number of destroyed vault share tokens as a parameter. -4. Accounting and limit logic: other functions in the ERC4626 standard are for asset accounting in the vault, deposit and withdrawal limits, and the number of underlying assets and vault shares for deposit and withdrawal. +2. Deposit logic: allows users to deposit underlying assets and mint the corresponding number of vault shares. Related functions are `deposit()` and `mint()`. The `deposit(uint assets, address receiver)` function allows users to deposit `assets` units of assets and mint the corresponding number of vault shares to the `receiver` address. `mint(uint shares, address receiver)` is similar, except that it takes the minted vault shares as a parameter. +3. Withdrawal logic: allows users to destroy vault share tokens and withdraw the corresponding number of underlying assets from the vault. Related functions are `withdraw()` and `redeem()`, the former taking the amount of underlying assets to be withdrawn as a parameter, and the latter taking the number of destroyed vault share tokens as a parameter. +4. Accounting and limit logic: other functions in the ERC4626 standard are for asset accounting in the vault, deposit and withdrawal limits and the number of underlying assets and vault shares for deposit and withdrawal. ### IERC4626 Interface Contract @@ -485,4 +485,4 @@ contract ERC4626 is ERC20, IERC4626 { ## Summary -In this lesson, we introduced the ERC4626 tokenized vault standard and wrote a simple vault contract that converts underlying assets to 1:1 vault share tokens. The ERC4626 standard improves the liquidity and composability of DeFi and it will gradually become more popular in the future. What applications would you build with ERC4626? \ No newline at end of file +In this lesson, we introduced the ERC4626 tokenized vault standard and wrote a simple vault contract that converts underlying assets to 1:1 vault share tokens. The ERC4626 standard improves the liquidity and composability of DeFi and it will gradually become more popular in the future. What applications would you build with ERC4626? From 360e58c2832555f7af90d5df1fe37348c7d93474 Mon Sep 17 00:00:00 2001 From: Mosamorphing <121625762+Mosamorphing@users.noreply.github.com> Date: Mon, 18 Mar 2024 21:25:48 +0100 Subject: [PATCH 11/15] Update readme.md --- Languages/en/52_EIP712_en/readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Languages/en/52_EIP712_en/readme.md b/Languages/en/52_EIP712_en/readme.md index 93ada4e4..bea8e523 100644 --- a/Languages/en/52_EIP712_en/readme.md +++ b/Languages/en/52_EIP712_en/readme.md @@ -96,7 +96,7 @@ Next is the `EIP712Storage` contract part, which needs to verify the signature a 1. `EIP712DOMAIN_TYPEHASH`: The type hash of `EIP712Domain`, which is a constant. 2. `STORAGE_TYPEHASH`: The type hash of `Storage`, which is a constant. -3. `DOMAIN_SEPARATOR`: This is the unique value of each domain (Dapp) mixed in the signature, consisting of `EIP712DOMAIN_TYPEHASH` and `EIP712Domain` (name, version, chainId, verifyingContract), initialized in `constructor()` . +3. `DOMAIN_SEPARATOR`: This is the unique value of each domain (Dapp) mixed in the signature, consisting of `EIP712DOMAIN_TYPEHASH` and `EIP712Domain` (name, version, chainId, verifyingContract), initialized in `constructor()`. 4. `number`: The state variable that stores the value in the contract can be modified by the `permitStore()` method. 5. `owner`: Contract owner, initialized in `constructor()`, and verify the validity of the signature in the `permitStore()` method. @@ -104,7 +104,7 @@ In addition, the `EIP712Storage` contract has `3` functions. 1. Constructor: Initialize `DOMAIN_SEPARATOR` and `owner`. 2. `retrieve()`: Read the value of `number`. -3. `permitStore`: Verify the EIP712 signature and modify the value of `number`. First, it breaks the signature into `r`, `s`, `v`. The signed message text `digest` is then spelled out using `DOMAIN_SEPARATOR`, `STORAGE_TYPEHASH`, the caller address, and the `_num` parameter entered. Finally, use the `recover()` method of `ECDSA` to recover the signer's address. If the signature is valid, update the value of `number`. +3. `permitStore`: Verify the EIP712 signature and modify the value of `number`. First, it breaks the signature into `r`, `s`, and `v`. The signed message text `digest` is then spelt out using `DOMAIN_SEPARATOR`, `STORAGE_TYPEHASH`, the caller address, and the `_num` parameter entered. Finally, use the `recover()` method of `ECDSA` to recover the signer's address. If the signature is valid, update the value of `number`. ```solidity // SPDX-License-Identifier: MIT From 501ba8ca941c95409815b8053302c5e83312ae6a Mon Sep 17 00:00:00 2001 From: Mosamorphing <121625762+Mosamorphing@users.noreply.github.com> Date: Mon, 18 Mar 2024 21:27:42 +0100 Subject: [PATCH 12/15] Update readme.md --- Languages/en/53_ERC20Permit/readme.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Languages/en/53_ERC20Permit/readme.md b/Languages/en/53_ERC20Permit/readme.md index 80556f6b..9fcbabd5 100644 --- a/Languages/en/53_ERC20Permit/readme.md +++ b/Languages/en/53_ERC20Permit/readme.md @@ -23,7 +23,7 @@ In this lecture, we introduce an extension of ERC20 tokens, ERC20Permit, which s ## ERC20 -We introduced ERC20, the most popular token standard in Ethereum, in [Lecture 31](https://github.com/WTFAcademy/WTF-Solidity/blob/main/Languages/en/31_ERC20_en/readme.md). One of the main reasons for its popularity is that the two functions `approve` and `transferFrom` are used together, so that tokens can not only be transferred between externally owned accounts (EOA), but can also be used by other contracts. +We introduced ERC20, the most popular token standard in Ethereum, in [Lecture 31](https://github.com/WTFAcademy/WTF-Solidity/blob/main/Languages/en/31_ERC20_en/readme.md). One of the main reasons for its popularity is that the two functions `approve` and `transferFrom` are used together so that tokens can not only be transferred between externally owned accounts (EOA) but can also be used by other contracts. However, the `approve` function of ERC20 is restricted to be called only by the token owner, which means that all initial operations of `ERC20` tokens must be performed by `EOA`. For example, if user A uses `USDT` to exchange `ETH` on a decentralized exchange, two transactions must be completed: in the first step, user A calls `approve` to authorize `USDT` to the contract, and in the second step, user A calls `approve` to authorize `USDT` to the contract. Contracts are exchanged. Very cumbersome, and users must hold `ETH` to pay for the gas of the transaction. @@ -42,7 +42,7 @@ EIP-2612 proposes ERC20Permit, which extends the ERC20 standard by adding a `per First, let us study the interface contract of ERC20Permit, which defines 3 functions: -- `permit()`: Authorize the ERC20 token balance of `owenr` to `spender` according to the signature of `owner`, and the amount is `value`. Require: +- `permit()`: Authorize the ERC20 token balance of `owner` to `spender` according to the signature of `owner`, and the amount is `value`. Require: - `spender` cannot be a zero address. - `deadline` must be a timestamp in the future. @@ -63,7 +63,7 @@ pragma solidity ^0.8.0; */ interface IERC20Permit { /** - * @dev Authorizes `owenr`’s ERC20 balance to `spender` based on the owner’s signature, the amount is `value` + * @dev Authorizes `owner`’s ERC20 balance to `spender` based on the owner’s signature, the amount is `value` */ function permit( address owner, @@ -98,7 +98,7 @@ Next, let us write a simple ERC20Permit contract, which implements all interface The contract contains 5 functions: - Constructor: Initialize the `name` and `symbol` of the token. -- **`permit()`**: The core function of ERC20Permit, which implements the `permit()` of IERC20Permit. It first checks whether the signature has expired, then restores the signed message using `_PERMIT_TYPEHASH`, `owner`, `spender`, `value`, `nonce`, `deadline` and verifies whether the signature is valid. If the signature is valid, the `_approve()` function of ERC20 is called to perform the authorization operation. +- **`permit()`**: The core function of ERC20Permit, which implements the `permit()` of IERC20Permit. It first checks whether the signature has expired, then restores the signed message using `_PERMIT_TYPEHASH`, `owner`, `spender`, `value`, `nonce`, and `deadline` and verifies whether the signature is valid. If the signature is valid, the `_approve()` function of ERC20 is called to perform the authorization operation. - `nonces()`: Implements the `nonces()` function of IERC20Permit. - `DOMAIN_SEPARATOR()`: Implements the `DOMAIN_SEPARATOR()` function of IERC20Permit. - `_useNonce()`: A function that consumes `nonce`, returns the user's current `nonce`, and increases it by 1. @@ -183,7 +183,7 @@ contract ERC20Permit is ERC20, IERC20Permit, EIP712 { 1. Deploy the `ERC20Permit` contract and set both `name` and `symbol` to `WTFPermit`. -2. Run `signERC20Permit.html` and change the `Contract Address` to the deployed `ERC20Permit` contract address. Other information is given below. Then click the `Connect Metamask` and `Sign Permit` buttons in sequence to sign, and obtain `r`, `s`, `v` for contract verification. To sign, use the wallet that deploys the contract, such as the Remix test wallet: +2. Run `signERC20Permit.html` and change the `Contract Address` to the deployed `ERC20Permit` contract address. Other information is given below. Then click the `Connect Metamask` and `Sign Permit` buttons in sequence to sign, and obtain `r`, `s`, and `v` for contract verification. To sign, use the wallet that deploys the contract, such as the Remix test wallet: ```js owner: 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4 spender: 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2 From f2c8bc8fde72e1e1100fa903ad4a3468659e21e3 Mon Sep 17 00:00:00 2001 From: Mosamorphing <121625762+Mosamorphing@users.noreply.github.com> Date: Mon, 18 Mar 2024 21:29:30 +0100 Subject: [PATCH 13/15] Update readme.md --- Languages/en/54_CrossChainBridge/readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Languages/en/54_CrossChainBridge/readme.md b/Languages/en/54_CrossChainBridge/readme.md index 5304e1d9..fb22b36a 100644 --- a/Languages/en/54_CrossChainBridge/readme.md +++ b/Languages/en/54_CrossChainBridge/readme.md @@ -31,7 +31,7 @@ At the same time, cross-chain bridges are not natively supported by the blockcha There are three main types of cross-chain bridges: -- **Burn/Mint**: Destroy (burn) tokens on the source chain, and then create (mint) the same number of tokens on the target chain. The advantage of this method is that the total supply of tokens remains unchanged, but the cross-chain bridge needs to have the permission to mint the tokens, which is suitable for project parties to build their own cross-chain bridges. +- **Burn/Mint**: Destroy (burn) tokens on the source chain, and then create (mint) the same number of tokens on the target chain. The advantage of this method is that the total supply of tokens remains unchanged, but the cross-chain bridge needs to have permission to mint the tokens, which is suitable for project parties to build their own cross-chain bridges. ![](./img/54-1.png) @@ -195,4 +195,4 @@ main(); ## Summary -In this lecture, we introduced the cross-chain bridge, which allows digital assets and information to be moved between two or more blockchains, making it convenient for users to operate assets on multiple chains. At the same time, it also carries great risks. Attacks on cross-chain bridges in the past two years have caused more than **2 billion US dollars** in user asset losses. In this tutorial, we build a simple cross-chain bridge and implement ERC20 token transfer between Goerli testnet and Sepolia testnet. I believe that through this tutorial, you will have a deeper understanding of cross-chain bridges. +In this lecture, we introduced the cross-chain bridge, which allows digital assets and information to be moved between two or more blockchains, making it convenient for users to operate assets on multiple chains. At the same time, it also carries great risks. Attacks on cross-chain bridges in the past two years have caused more than **2 billion US dollars** in user asset losses. In this tutorial, we build a simple cross-chain bridge and implement ERC20 token transfer between the Goerli testnet and the Sepolia testnet. I believe that through this tutorial, you will have a deeper understanding of cross-chain bridges. From 4c6337c19ac572f6c173a4c267b081c9dca7f43e Mon Sep 17 00:00:00 2001 From: Mosamorphing <121625762+Mosamorphing@users.noreply.github.com> Date: Mon, 18 Mar 2024 21:32:38 +0100 Subject: [PATCH 14/15] Update readme.md --- Languages/en/56_DEX/readme.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Languages/en/56_DEX/readme.md b/Languages/en/56_DEX/readme.md index 3869dd6d..427451b3 100644 --- a/Languages/en/56_DEX/readme.md +++ b/Languages/en/56_DEX/readme.md @@ -21,7 +21,7 @@ In this lecture, we will introduce the Constant Product Automated Market Maker ( ## Automatic market maker -An Automated Market Maker (AMM) is an algorithm, or a smart contract that runs on the blockchain, which allows decentralized transactions between digital assets. The introduction of AMM has created a new trading method that does not require traditional buyers and sellers to match orders. Instead, a liquidity pool is created through a preset mathematical formula (such as a constant product formula), allowing users to trade at any time. Trading. +An Automated Market Maker (AMM) is an algorithm or a smart contract that runs on the blockchain, which allows decentralized transactions between digital assets. The introduction of AMM has created a new trading method that does not require traditional buyers and sellers to match orders. Instead, a liquidity pool is created through a preset mathematical formula (such as a constant product formula), allowing users to trade at any time. Trading. ![](./img/56-1.png) @@ -33,9 +33,9 @@ The Constant Sum Automated Market Maker (CSAMM) is the simplest automated market $$k=x+y$$ -where $k$ is a constant. That is, the sum of the quantities of colas and dollars in the market remains the same before and after the trade. For example, there are 10 bottles of Coke and $10 in the market. At this time, $k=20$, and the price of Coke is $1/bottle. I was thirsty and wanted to exchange my $2 for a Coke. The total number of dollars in the post-trade market becomes 12. According to the constraint $k=20$, there are 8 bottles of Coke in the post-trade market at a price of $1/bottle. I got 2 bottles of coke in the deal for $1/bottle. +where $k$ is a constant. That is, the sum of the quantities of colas and dollars in the market remains the same before and after the trade. For example, there are 10 bottles of Coke and $10 in the market. At this time, $k=20$, and the price of Coke is $1/bottle. I was thirsty and wanted to exchange my $2 for a Coke. The total number of dollars in the post-trade market becomes 12. According to the constraint $k=20$, there are 8 bottles of Coke in the post-trade market at a price of $1/bottle. I got 2 bottles of Coke in the deal for $1/bottle. -The advantage of CSAMM is that it can ensure that the relative price of tokens remains unchanged. This is very important in stable currency exchange. Everyone hopes that 1 USDT can always be exchanged for 1 USDC. But its shortcomings are also obvious. Its liquidity is easily exhausted: I only need $10 to exhaust the liquidity of Coke in the market, and other users who want to drink Coke will not be able to trade. +The advantage of CSAMM is that it can ensure that the relative price of tokens remains unchanged. This is very important in a stable currency exchange. Everyone hopes that 1 USDT can always be exchanged for 1 USDC. But its shortcomings are also obvious. Its liquidity is easily exhausted: I only need $10 to exhaust the liquidity of Coke in the market, and other users who want to drink Coke will not be able to trade. Below we introduce the constant product automatic market maker with "unlimited" liquidity. @@ -55,7 +55,7 @@ Next, let us build a minimalist decentralized exchange based on CPAMM. Next, we use smart contracts to write a decentralized exchange `SimpleSwap` to support users to trade a pair of tokens. -`SimpleSwap` inherits the ERC20 token standard and facilitates recording of liquidity provided by liquidity providers. In the constructor, we specify a pair of token addresses `token0` and `token1`. The exchange only supports this pair of tokens. `reserve0` and `reserve1` record the reserve amount of tokens in the contract. +`SimpleSwap` inherits the ERC20 token standard and facilitates the recording of liquidity provided by liquidity providers. In the constructor, we specify a pair of token addresses `token0` and `token1`. The exchange only supports this pair of tokens. `reserve0` and `reserve1` record the reserve amount of tokens in the contract. ```solidity contract SimpleSwap is ERC20 { From 9b44b43d9c3af70c15bba8b3883eb26d41ee7940 Mon Sep 17 00:00:00 2001 From: Mosamorphing <121625762+Mosamorphing@users.noreply.github.com> Date: Mon, 18 Mar 2024 21:42:20 +0100 Subject: [PATCH 15/15] Update readme.md --- Languages/en/57_Flashloan/readme.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Languages/en/57_Flashloan/readme.md b/Languages/en/57_Flashloan/readme.md index aea5783e..97cbfe49 100644 --- a/Languages/en/57_Flashloan/readme.md +++ b/Languages/en/57_Flashloan/readme.md @@ -26,9 +26,9 @@ You must have heard the term “flash loan attack”, but what is a flash loan? The first time you heard about "flash loan" must be in Web3, because Web2 does not have this thing. Flashloan is a DeFi innovation that allows users to lend and quickly return funds in one transaction without providing any collateral. -Imagine that you suddenly find an arbitrage opportunity in the market, but you need to prepare 1 million U of funds to complete the arbitrage. In Web2, you go to the bank to apply for a loan, which requires approval, and you may miss the arbitrage opportunity. In addition, if the arbitrage fails, you not only have to pay interest, but also need to return the lost principal. +Imagine that you suddenly find an arbitrage opportunity in the market, but you need to prepare 1 million U of funds to complete the arbitrage. In Web2, you go to the bank to apply for a loan, which requires approval, and you may miss the arbitrage opportunity. In addition, if the arbitrage fails, you not only have to pay interest but also need to return the lost principal. -In Web3, you can obtain funds through flash loans on the DeFI platform (Uniswap, AAVE, Dodo). You can borrow 1 million u tokens without guarantee, perform on-chain arbitrage, and finally return the loan and interest. . +In Web3, you can obtain funds through flash loans on the DeFI platform (Uniswap, AAVE, Dodo). You can borrow 1 million U tokens without guarantee, perform on-chain arbitrage, and finally return the loan and interest. Flash loans take advantage of the atomicity of Ethereum transactions: a transaction (including all operations within it) is either fully executed or not executed at all. If a user attempts to use a flash loan and does not return the funds in the same transaction, the entire transaction will fail and be rolled back as if it never happened. Therefore, the DeFi platform does not need to worry about the borrower not being able to repay the loan, because if it is not repaid, it means that the money has not been loaned out; at the same time, the borrower does not need to worry about the arbitrage being unsuccessful, because if the arbitrage is unsuccessful, the repayment will not be repaid, and It means that the loan was unsuccessful. @@ -46,7 +46,7 @@ Below, we introduce how to implement flash loan contracts in Uniswap V2, Uniswap function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock { // Other logic... - // Optimistically send tokens to the to address + // Optimistically send tokens to the address if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); @@ -182,7 +182,7 @@ function testFlashloan() public { } ``` -In the test contract, we tested the cases of sufficient and insufficient handling fees respectively. You can use the following command line to test after installing Foundry (you can change the RPC to other Ethereum RPC): +In the test contract, we tested the cases of sufficient and insufficient handling fees respectively. You can use the following command line to test after installing Foundry (you can change the RPC to another Ethereum RPC): ```shell FORK_URL=https://singapore.rpc.blxrbdn.com @@ -202,7 +202,7 @@ function flash( ) external override lock noDelegateCall { // Other logic... -// Optimistically send tokens to the to address +// Optimistically send tokens to the address if (amount0 > 0) TransferHelper.safeTransfer(token0, recipient, amount0); if (amount1 > 0) TransferHelper.safeTransfer(token1, recipient, amount1); @@ -339,7 +339,7 @@ function testFlashloan() public { // If the handling fee is insufficient, it will be reverted. function testFlashloanFail() public { - //Exchange weth and transfer it to the flashloan contract to use it as handling fee + //Exchange weth and transfer it to the flashloan contract to use it as a handling fee weth.deposit{value: 1e18}(); weth.transfer(address(flashloan), 1e17); // Flash loan loan amount @@ -360,7 +360,7 @@ forge test --fork-url $FORK_URL --match-path test/UniswapV3Flashloan.t.sol -vv ### 3. AAVE V3 Flash Loan -AAVE is a decentralized lending platform. Its [Pool contract](https://github.com/aave/aave-v3-core/blob/master/contracts/protocol/pool/Pool.sol#L424) passes `flashLoan The two functions ()` and `flashLoanSimple()` support single-asset and multi-asset flash loans. Here, we only use `flashLoan()` to implement flash loan of a single asset (`WETH`). +AAVE is a decentralized lending platform. Its [Pool contract](https://github.com/aave/aave-v3-core/blob/master/contracts/protocol/pool/Pool.sol#L424) passes `flashLoan The two functions ()` and `flashLoanSimple()` support single-asset and multi-asset flash loans. Here, we only use `flashLoan()` to implement a flash loan of a single asset (`WETH`). Next, we complete the flash loan contract `AaveV3Flashloan.sol`. We let it inherit `IFlashLoanSimpleReceiver` and write the core logic of flash loan in the callback function `executeOperation`. @@ -481,7 +481,7 @@ function testFlashloan() public { } ``` -In the test contract, we tested the cases of sufficient and insufficient handling fees respectively. You can use the following command line to test after installing Foundry (you can change the RPC to other Ethereum RPC): +In the test contract, we tested the cases of sufficient and insufficient handling fees respectively. You can use the following command line to test after installing Foundry (you can change the RPC to another Ethereum RPC): ```shell FORK_URL=https://singapore.rpc.blxrbdn.com