diff --git a/basic/07-hardhat/README.md b/basic/07-hardhat/README.md index 95c20544a..9608a233f 100644 --- a/basic/07-hardhat/README.md +++ b/basic/07-hardhat/README.md @@ -20,6 +20,11 @@ Hardhat Runner 是与 Hardhat 交互的 CLI 命令,是一个可扩展的任务 ## 项目结构和配置 hardhat +```sh +npm install --save-dev hardhat // 安装hardhat +npx hardhat // 创建hardhat项目 +``` + ### 项目结构 一个标准的使用 hardhat 构建的项目通常是这样的: diff --git a/basic/39-Ethlend/README.md b/basic/39-Ethlend/README.md deleted file mode 100644 index fa5bb06fd..000000000 --- a/basic/39-Ethlend/README.md +++ /dev/null @@ -1,5 +0,0 @@ -## ETHLend - -## 参考链接 - -- github 仓库地址: https://github.com/ETHLend/Microstaking/blob/master/contracts/StakingContract.sol diff --git a/basic/39-Ethlend/images/flow_chart.png b/basic/39-Ethlend/images/flow_chart.png deleted file mode 100644 index 18d511230..000000000 Binary files a/basic/39-Ethlend/images/flow_chart.png and /dev/null differ diff --git a/basic/39-Multicall/.gitignore b/basic/39-Multicall/.gitignore new file mode 100644 index 000000000..36077f288 --- /dev/null +++ b/basic/39-Multicall/.gitignore @@ -0,0 +1,9 @@ +node_modules +.env +coverage +coverage.json +typechain + +#Hardhat files +cache +artifacts diff --git a/basic/39-Multicall/README.md b/basic/39-Multicall/README.md new file mode 100644 index 000000000..00a70b10f --- /dev/null +++ b/basic/39-Multicall/README.md @@ -0,0 +1,21 @@ +# Multicall + +Multicall aggregates results from multiple contract **constant function calls**. + +This reduces the number of separate JSON RPC requests that need to be sent (especially useful if using remote nodes like Infura), while also providing the guarantee that all values returned are from the same block (like an atomic read) and returning the block number the values are from (giving them important context so that results from old blocks can be ignored if they're from an out-of-date node). + +This smart contract is intended to be used with **Multicall.js** in front-end dapps. + + +## Multicall.js + project url: https://github.com/makerdao/multicall.js + - Get the return value(s) of multiple smart contract function calls in a single call + - Guarantee that all values are from the same block + - Use watchers to poll for multiple blockchain state variables/functions + - Get updates when a watcher detects state has changed + - Results from out of sync nodes are automatically ignored + - Get new block updates + + +## 参考链接 +- github 仓库地址: https://github.com/ETHLend/Microstaking/blob/master/contracts/StakingContract.sol diff --git a/basic/39-Multicall/contracts/Multicall.sol b/basic/39-Multicall/contracts/Multicall.sol new file mode 100644 index 000000000..08db3dd34 --- /dev/null +++ b/basic/39-Multicall/contracts/Multicall.sol @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: MIT + + +pragma solidity ^0.8.0; + +/// @title Multicall - Aggregate results from multiple read-only function calls +/// @author Michael Elliot +/// @author Joshua Levine +/// @author Nick Johnson + +contract Multicall { + struct Call { + address target; + bytes callData; + } + struct Result { + bool success; + bytes returnData; + } + + function aggregate(Call[] memory calls) public returns (uint256 blockNumber, bytes[] memory returnData) { + blockNumber = block.number; + returnData = new bytes[](calls.length); + for(uint256 i = 0; i < calls.length; i++) { + (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData); + require(success, "Multicall aggregate: call failed"); + returnData[i] = ret; + } + } + function blockAndAggregate(Call[] memory calls) public returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) { + (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls); + } + function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) { + blockHash = blockhash(blockNumber); + } + function getBlockNumber() public view returns (uint256 blockNumber) { + blockNumber = block.number; + } + function getCurrentBlockCoinbase() public view returns (address coinbase) { + coinbase = block.coinbase; + } + function getCurrentBlockDifficulty() public view returns (uint256 difficulty) { + difficulty = block.difficulty; + } + function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) { + gaslimit = block.gaslimit; + } + function getCurrentBlockTimestamp() public view returns (uint256 timestamp) { + timestamp = block.timestamp; + } + function getEthBalance(address addr) public view returns (uint256 balance) { + balance = addr.balance; + } + function getLastBlockHash() public view returns (bytes32 blockHash) { + blockHash = blockhash(block.number - 1); + } + function tryAggregate(bool requireSuccess, Call[] memory calls) public returns (Result[] memory returnData) { + returnData = new Result[](calls.length); + for(uint256 i = 0; i < calls.length; i++) { + (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData); + + if (requireSuccess) { + require(success, "Multicall2 aggregate: call failed"); + } + + returnData[i] = Result(success, ret); + } + } + function tryBlockAndAggregate(bool requireSuccess, Call[] memory calls) public returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) { + blockNumber = block.number; + blockHash = blockhash(block.number); + returnData = tryAggregate(requireSuccess, calls); + } +} \ No newline at end of file diff --git a/basic/39-Multicall/hardhat.config.js b/basic/39-Multicall/hardhat.config.js new file mode 100644 index 000000000..cfeed5580 --- /dev/null +++ b/basic/39-Multicall/hardhat.config.js @@ -0,0 +1,21 @@ +require("@nomiclabs/hardhat-waffle"); + +// This is a sample Hardhat task. To learn how to create your own go to +// https://hardhat.org/guides/create-task.html +task("accounts", "Prints the list of accounts", async (taskArgs, hre) => { + const accounts = await hre.ethers.getSigners(); + + for (const account of accounts) { + console.log(account.address); + } +}); + +// You need to export an object to set up your config +// Go to https://hardhat.org/config/ to learn more + +/** + * @type import('hardhat/config').HardhatUserConfig + */ +module.exports = { + solidity: "0.8.4", +}; diff --git a/basic/39-Multicall/package.json b/basic/39-Multicall/package.json new file mode 100644 index 000000000..227090f9a --- /dev/null +++ b/basic/39-Multicall/package.json @@ -0,0 +1,12 @@ +{ + "name": "hardhat-project", + "devDependencies": { + "@nomiclabs/hardhat-ethers": "^2.0.3", + "@nomiclabs/hardhat-waffle": "^2.0.1", + "chai": "^4.3.4", + "ethereum-waffle": "^3.4.0", + "ethers": "^5.5.2", + "hardhat": "^2.8.0", + "@makerdao/multicall": "0.12.0" + } +} diff --git a/basic/39-Multicall/scripts/sample-script.js b/basic/39-Multicall/scripts/sample-script.js new file mode 100644 index 000000000..90cd8197e --- /dev/null +++ b/basic/39-Multicall/scripts/sample-script.js @@ -0,0 +1,32 @@ +// We require the Hardhat Runtime Environment explicitly here. This is optional +// but useful for running the script in a standalone fashion through `node