Skip to content

Commit

Permalink
add multicall task
Browse files Browse the repository at this point in the history
  • Loading branch information
liberhe committed Jan 5, 2022
1 parent cc5850e commit 451ab81
Show file tree
Hide file tree
Showing 15 changed files with 243 additions and 6 deletions.
5 changes: 5 additions & 0 deletions basic/07-hardhat/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ Hardhat Runner 是与 Hardhat 交互的 CLI 命令,是一个可扩展的任务

## 项目结构和配置 hardhat

```sh
npm install --save-dev hardhat // 安装hardhat
npx hardhat // 创建hardhat项目
```

### 项目结构

一个标准的使用 hardhat 构建的项目通常是这样的:
Expand Down
5 changes: 0 additions & 5 deletions basic/39-Ethlend/README.md

This file was deleted.

Binary file removed basic/39-Ethlend/images/flow_chart.png
Binary file not shown.
9 changes: 9 additions & 0 deletions basic/39-Multicall/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
node_modules
.env
coverage
coverage.json
typechain

#Hardhat files
cache
artifacts
21 changes: 21 additions & 0 deletions basic/39-Multicall/README.md
Original file line number Diff line number Diff line change
@@ -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
74 changes: 74 additions & 0 deletions basic/39-Multicall/contracts/Multicall.sol
Original file line number Diff line number Diff line change
@@ -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 <[email protected]>
/// @author Joshua Levine <[email protected]>
/// @author Nick Johnson <[email protected]>

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);
}
}
21 changes: 21 additions & 0 deletions basic/39-Multicall/hardhat.config.js
Original file line number Diff line number Diff line change
@@ -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",
};
12 changes: 12 additions & 0 deletions basic/39-Multicall/package.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
32 changes: 32 additions & 0 deletions basic/39-Multicall/scripts/sample-script.js
Original file line number Diff line number Diff line change
@@ -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 <script>`.
//
// When running the script with `npx hardhat run <script>` you'll find the Hardhat
// Runtime Environment's members available in the global scope.
const hre = require("hardhat");

async function main() {
// Hardhat always runs the compile task when running scripts with its command
// line interface.
//
// If this script is run directly using `node` you may want to call compile
// manually to make sure everything is compiled
// await hre.run('compile');

// We get the contract to deploy
const Greeter = await hre.ethers.getContractFactory("Greeter");
const greeter = await Greeter.deploy("Hello, Hardhat!");

await greeter.deployed();

console.log("Greeter deployed to:", greeter.address);
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
19 changes: 19 additions & 0 deletions basic/39-Multicall/test/sample-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const { expect } = require("chai");
const { ethers } = require("hardhat");

describe("Greeter", function () {
it("Should return the new greeting once it's changed", async function () {
const Greeter = await ethers.getContractFactory("Greeter");
const greeter = await Greeter.deploy("Hello, world!");
await greeter.deployed();

expect(await greeter.greet()).to.equal("Hello, world!");

const setGreetingTx = await greeter.setGreeting("Hola, mundo!");

// wait until the transaction is mined
await setGreetingTx.wait();

expect(await greeter.greet()).to.equal("Hola, mundo!");
});
});
6 changes: 6 additions & 0 deletions defi/Euler/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Euler Protocol

## 原理
euler 白皮书: https://docs.euler.finance/getting-started/white-paper

## 参考链接
2 changes: 1 addition & 1 deletion defi/Perpetual-V1/clearningHouse.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ positionNotional = positonSize * price

unrealizedPnlForLongPosition = positionNotional - openNotional

badDebt = ealizedPnl + realizedFundingPayment + margin;
badDebt = realizedPnl + realizedFundingPayment + margin;

仓位数据结构
```
Expand Down
Binary file added defi/stablecoin/RAI/img/不可能三角.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 33 additions & 0 deletions defi/stablecoin/RAI/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# RAI

## 背景
由 Reflexer Labs 开发、由 ETH 支持的稳定资产 RAI 是一种降低或延迟资产波动性的方案,以便为其它 DeFi 协议提供这类低波动性的资产作为基础的标的资产。
RAI 是一种仅由 ETH 支持的稳定资产,与其他由央行发行的稳定币不同的是,RAI 依靠算法来维持价格的稳定,而无需与美元等外部价格挂钩,主打的特点是治理最小化,在尽可能少的人为干预下工作,这也是为什么创始团队 Reflexer Labs 把 RAI 称为金钱之神。
格里芬困境::即为了保证全球主要结算货币(美元)的充足性,不得「印出」超本国需求的美元;但由于货币超发,难以保证本国通货膨胀处于正常水平,在确保国际资金充足的情况下,实际上是伤害了本国的利益。

## 原理
RAI 在很多方面与 DAI 相似,是 MCD 系统的硬分叉。
RAI 有一个任意设定的初始目标价格(发行时初始目标价格为 3.14 美元),只要市场价格与目标价格不同,RAI 就会通过算法调整利率——也就是「赎回率」(redblockquoteption rate)以应对价格变化。当赎回率调整时,人们就会选择铸造或销毁他们的 RAI,通过改变代币供应量,RAI 价格也就能保持稳定了。

用户收到的 RAI 单位数取决于目标价格,但价值不取决于目标价格。例如,假设 RAI 的最小抵押比率为 145%,用户存入了 1 ETH,1 ETH = $100 USD。用户可以提取价值高达 69 美元的 RAI。如果 RAI = 1 美元的目标价,那么价值 69 美元的 RAI 将相当于 69 RAI。如果目标价为 RAI = 3 美元,那么价值 69 美元的 RAI 将只有 23 RAI。因此,RAI 的目标价格可以理解为系统内债务的价格。
当 RAI 的市场价格等于其目标价格时,可以说 RAI 到达了均衡模式。当 RAI 的均衡被扰动时,控制器设定反向市场利率,具体说根据目标价格与市场价格的相对差来确定利率。

在 MakerDAO,向 DAI 的贷款人收取稳定费(stability fee)。如果稳定费是 3%,你借了 100DAI,那么一年后你就欠了 103DAI。MakerDAO 促进稳定性的方法之一是,当 DAI 的价格下降时,让 MKR 持有人投票增加稳定费,借贷人到期需要偿还更多的 DAI,这意味借款人需要在市场中买更多的 DAI 以偿还贷款(总体贷款美元计价不变),这就将 DAI 的价格推回到 1 美元的固定汇率。

RAI 的利率更有趣。例如,如果 RAI 的市场价格从均衡点下跌了 10%,而 RAI 调节机制的反应就是设置 x%/天的利率,那么 RAI 实际上是将目标价格提高了 x%/天。对 RAI 借款人来说,由于将债务重新定价为更高的成本,这与直接向他们收取利率具有同样的影响,这也将促使其买入更多的 RAI 以偿还 RAI 贷款(但实际锚定美元成本不变)。RAI 的这种机制鼓励借款人偿还债务 (为此他们需要购买 RAI),这有助于 RAI 恢复平衡。

ETH 杠杆需求上升→ 质押并卖出 RAI → RAI 价格下降;(质押出 RAI,并用 RAI 买入 ETH)
RAI 需求上升→购买 RAI → RAI 价格上升。


## 技术解析
技术文档:https://docs.reflexer.finance/
medium :https://medium.com/reflexer-labs/stability-without-pegs-8c6a1cbc7fbd


## 参考链接
- Ameen Soleimani 详细解释了RAI如何解决稳定币特里芬困境: https://zhuanlan.zhihu.com/p/358193948
- Reflexer:不同于稳定币的另一原生加密稳定资产RAI: https://zhuanlan.zhihu.com/p/352154160
- 一文读懂新型算法稳定币三杰Fei、Float、Reflexer: https://www.blockvalue.com/blockchain/20210323845831.html
- 看Reflexer如何将PID控制理论应用于加密货币: https://xw.qq.com/partner/hwbrowser/20210412A0AYVE/20210412A0AYVE00?ADTAG=hwb&pgv_ref=hwb&appid=hwbrowser&ctype=news
- Advanced DeFi Management: https://defisaver.com/
10 changes: 10 additions & 0 deletions defi/stablecoin/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# 算法稳定币
- Ampleforth(AMPL)
- Empty Set Dollar(ESD)
- Basis Cash(BAC/BAS)
- Frax(FRAX/FXS)



## 参考链接
https://www.blockvalue.com/blockchain/20210323845831.html

0 comments on commit 451ab81

Please sign in to comment.