Defi部署教程 Compound部署 搭建去中心化借貸銀行

本文環(huán)境
操作系統(tǒng):maxOS 10.15.6
科學上網(wǎng)
公鏈網(wǎng)絡:BSC Testnet
測試工具:Remix IDE笑旺、MetaMask
合約源碼:https://github.com/compound-finance/compound-protocol.git

在 remix 進行編譯部署時,勾選啟用優(yōu)化鸟蟹。

Compound中含有的合約代碼量很大建钥,文件數(shù)量30+熊经,一開始筆者也忍不住打了退堂鼓镐依。然而學習就是一個從難到易的過程槐壳,只有花時間去努力學習务唐,才能慢慢理解它的結構和細節(jié),最終會贊美Compound團隊提供的優(yōu)秀代碼枫笛,優(yōu)秀方案来农!
下圖是網(wǎng)上找的Compound合約結構圖,以饗讀者崇堰。在部署前沃于,先梳理清楚各個合約之間的關系涩咖,并將其分組,梳理出各個模塊檩互,及初始化參數(shù)。

Compound 合約結構

一咨演、COMP 模塊

激勵資產合約,可以使用標準 ERC20 合約闸昨。
因為 Comptroller 中會使用到 COMP 的地址,因此我們最先部署 COMP 合約薄风,得到合約地址: 0x1fe7FF222D59B6648D640090046661313A1CF0a2饵较。
部署完成后,到合約 ComptrollerG7.sol (或者計劃使用的 Comptroller 合約)進行配置,更改為自己的 COMP 合約地址遭赂。
也可以直接使用Comp.sol部署 compound自帶的COMP token合約循诉,修改一下name,symbol撇他,totalSupply等茄猫。

     /**
     * @notice Return the address of the COMP token
     * @return The address of COMP
     */
    function getCompAddress() public view returns (address) {
        return 0x1fe7FF222D59B6648D640090046661313A1CF0a2;
    }

二、comptroller 模塊

在compound設計中困肩,unitroller 是代理合約划纽,comptroller 是邏輯實現(xiàn)合約,通過 delegatecall 來實現(xiàn)遠程合約調用锌畸。

2.1 部署 Unitroller.sol

使用 account1 賬號進行部署勇劣,成功:

contract address: 0x268e3eF4380DA46e55B77a6263810910722a875E

2.2 部署 ComptrollerG7.sol

使用 account1 賬號進行部署;成功:

contract address: 0x67006E2110119Abfd40b2A743A85b4d3bF8967b9

三、priceOracle 模塊

3.1 部署 SimplePriceOracle.sol

使用 account1 賬號進行部署

contract address: 0x5991199a9aB1801A229a2E49a042471eDE997a21

四潭枣、綁定與設置

4.1 代理綁定

  • 第一步: 在 Unitroller.sol 合約調用 _setPendingImplementation;
    參數(shù) address newPendingImplementation比默,這里設置為 ComptrollerG7.sol 地址

  • 第二步: 在 ComptrollerG7.sol 合約調用 _become,
    參數(shù) Unitroller unitroller,這里設置為 Unitroller.sol 地址

代理綁定卸耘,第一步轉移所有權退敦,第二步新的 Comptroller 接受所有權,這樣就可以防止意外地升級到無效的合約;
備注:設置完成后對外提供 Comptroller 合約地址時蚣抗, 提供的是 Unitroller 合約地址侈百。

以下步驟,請 unitrollerProxy = ComptrollerG7(address(unitroller));
at Address unitrollerAddr得到unitrollerProxy合約翰铡,名字還是ComptrollerG7

4.2 設置 closeFactor

在 ComptrollerG7.sol 合約調用 _setCloseFactor钝域,
參數(shù) uint newCloseFactorMantissa,這里設置為 50%锭魔,即:0.5 * 1 ^18 = 500000000000000000

4.3 設置 liquidationIncentiveMantissa

在 ComptrollerG7.sol 合約調用 _setLiquidationIncentive例证,
參數(shù) uint newLiquidationIncentiveMantissa,設置流動性激勵為 8%迷捧,參數(shù)值就是1.08 * 1 ^ 18 = 1080000000000000000

4.4 設置 oracle

在 ComptrollerG7.sol 合約調用 _setPriceOracle织咧,
參數(shù) PriceOracle newOracle胀葱,這里設置為 SimplePriceOracle.sol 地址:0x5991199a9aB1801A229a2E49a042471eDE997a21

五、interestRate 模塊

拐點利率模型

5.1 部署 JumpRateModelV2.sol

部署時參數(shù):

  • uint baseRatePerYear, 實際設置為 0
  • uint multiplierPerYear, 實際設置 7%, 即 0.07 * 10 ^ 18 = 70000000000000000
  • uint jumpMultiplierPerYear, 實際設置 3, 即 3 * 10 ^ 18 = 3000000000000000000
  • uint kink_, 實際設置 75%, 即 0.75 * 10 ^ 18 = 750000000000000000
  • address owner_, 實際設置 msg.sender

使用 account1 賬號進行部署笙蒙,成功:

contract address: 0x8A517DA790929D2aC3527210f9472E2822424180

備注: 部署后, 參數(shù)都可以用 updateJumpRateModel 方法進行修改;

5.2 部署另一個 JumpRateModelV2.sol

如果是測試抵屿,只需要部署一個就可以了,使用erc20的捅位,
因為 cToken 跟 JumpRateModelV2 需要一一對應的關系轧葛,因此再次部署該合約,用于后面分別與 CErc20Delegator.sol 和 CEther.sol 對應.
部署時參數(shù)跟5.1節(jié)相同;
使用 account1 賬號進行部署艇搀,成功:

contract address: 0x0cca4ccD1ED542B5D7F3Ebbcf49D92DCB0a8D04e

六尿扯、CToken 模塊(ERC20)

6.1 部署 ERC20Token.sol

部署一個標準 ERC20 代幣,作為基礎資產用于測試焰雕,
例子:使用 account1 賬號進行部署usdt合約衷笋,成功:

contract address:  0xBEA207ec294BCe7a866C3a598195A61Bb7E8D599

6.2 部署 CErc20Delegate.sol

此合約給支持代理的 cToken 合約使用,不支持代理的 cToken 不需要使用這個合約;
所有 ERC20 基礎資產的 CToken 采用委托代理模式淀散,所以我們先部署一個實現(xiàn)合約:
使用 account1 賬號進行部署右莱,成功:

contract address: 0xc176eD65274b2a2d422126d597Be715fc97d2e98

6.3 部署 CErc20Delegator.sol

此合約即為與代幣類型(ERC20)的標的資產對應的 cToken 合約;
部署時參數(shù):

  • address underlying_, erc20標的資產地址蚜锨,見6.1節(jié)
  • ComptrollerInterface comptroller_, ComptrollerG7.sol 合約地址档插,見2.2節(jié)
  • InterestRateModel interestRateModel_, JumpRateModelV2合約地址,見5.1節(jié)
  • uint initialExchangeRateMantissa_, 初始匯率亚再,按 1:1 設置郭膛,比列見備注說明,本文 1 * 10 ^ 18 = 100000000000000000
  • string memory name_, cToken 的 name COMPOUND USD
  • string memory symbol_, cToken 的 symbol cUSD
  • uint8 decimals_, cToken 的 decimals, 設為 18
  • address payable admin_, 應該是時間鎖定合約地址氛悬,此處設為 msg.sender
  • address implementation_, CErc20Delegate 合約地址则剃,見6.2節(jié)
  • bytes memory becomeImplementationData, 額外初始數(shù)據(jù),此處填入0x;即無數(shù)據(jù)

備注:initialExchangeRateMantissa_ = 1 * 10 ^ (18 + underlyingDecimals - cTokenDecimals)

使用 account1 賬號進行部署如捅,成功:

contract address: 0x209C9b6a0Ec37b91d0758514070A8439B14B9B3c

七棍现、CToken 模塊(ETH)

7.1 部署 CEther.sol

此合約即為與主幣類型(ETH)對應的 cToken 合約,
部署時參數(shù):

  • ComptrollerInterface comptroller_, unitroller合約地址镜遣,見2.1節(jié)
  • InterestRateModel interestRateModel_, JumpRateModelV2合約地址己肮,見5.2節(jié)
  • uint initialExchangeRateMantissa_, 初始匯率,按 1:1 設置悲关,本文 1 * 10 ^ 18 = 100000000000000000
  • string memory name_, cToken 的 name COMPOUND ETHER
  • string memory symbol_, cToken 的 symbol cETH
  • uint8 decimals_, cToken 的 decimals谎僻,設為 18
  • address payable admin_, 設為 msg.sender

使用 account1 賬號進行部署,成功:

contract address: 0xf3feeab27E8B8b71ED92040be19E5aA80baf9B01

八寓辱、設置市場價格

在SimplePriceOracle.sol合約里調用setUnderlyingPrice:

8.1設置cUSD的價格:

CToken cToken艘绍, CErc20Delegator.sol 地址
uint underlyingPriceMantissa, 1 * 10 ^ 18 = 1000000000000000000
使用 account1 賬號進行cUSD價格設置操作秫筏,成功

8.2設置cETH的價格:

CToken cToken诱鞠, CEther.sol 地址
uint underlyingPriceMantissa挎挖, 2000 * 10 ^ 18 = 2000000000000000000000
使用 account1 賬號進行cETH價格設置操作,成功

九航夺、CToken 配置

9.1 設置 ReserveFactor

設置保證金系數(shù)

9.1.1 在 CErc20Delegator.sol 調用合約方法 _setReserveFactor:

設置時參數(shù):

  • uint newReserveFactorMantissa , 新的保證金系數(shù), 本文 0.1 * 10 ^ 18 = 100000000000000000

9.1.2 在 CEther.sol 調用合約方法 _setReserveFactor:

設置時參數(shù):

  • uint newReserveFactorMantissa , 新的保證金系數(shù), 本文 0.2 * 10 ^ 18 = 200000000000000000

9.2 CToken 加入市場

在 ComptrollerG7.sol 調用合約方法 _supportMarket:
設置時參數(shù):

  • CToken cToken, CErc20Delegator.sol 或 CEther.sol 地址

本文操作兩次肋乍,將前面部署的 CErc20Delegator.sol 和 CEther.sol 均加入;
使用 account1 賬號進行操作

9.3 設置 CollateralFactor

設置抵押率;
在 ComptrollerG7.sol 調用合約方法 _setCollateralFactor:
設置時參數(shù):

  • CToken cToken, CErc20Delegator.sol 地址
  • uint newCollateralFactorMantissa, 抵押率,本文使用 0.6 * 10 ^ 18 = 600000000000000000

使用 account1 賬號進行操作,成功

Remix部署完合約以后敷存,如下圖:

部署的合約

十墓造、COMP獎勵

用戶存和借cToken都會有獎勵,如果cToken市場設置了compSpeed锚烦。
compSpeed: 整數(shù)觅闽,表示協(xié)議將COMP分配給市場供應商或借款人的速率。價值是分配給市場的每個區(qū)塊的COMP(單位:wei)涮俄。 請注意蛉拙,并非每個市場都向其參與者分發(fā)了COMP〕骨祝可以設置成0孕锄。速度表明市場供應商或借款人獲得了多少紅利,因此將這個數(shù)字翻一番苞尝,可以顯示市場供應商和借款人獲得的紅利之和畸肆。
//代碼示例實現(xiàn)了讀取每個以太坊區(qū)塊分配到單個市場的COMP量。

    /**
     * @notice Set COMP speed for a single market
     * @param cToken The market whose COMP speed to update
     * @param compSpeed New COMP speed for market
     */
    function _setCompSpeed(CToken cToken, uint compSpeed) public {
        require(adminOrInitializing(), "only admin can set comp speed");
        setCompSpeedInternal(cToken, compSpeed);
    }

owner才可以設置
參數(shù)

  • cToken 相應的市場cToken地址
  • compSpeed 價值是分配給市場的每個區(qū)塊的COMP(單位:wei)
    這個方法不執(zhí)行宙址,默認為0轴脐,不分發(fā)comp

計算compspeed:需要翻倍計算

const cTokenAddress = '0xabc...';
const comptroller = new web3.eth.Contract(comptrollerAbi, comptrollerAddress);
let compSpeed = await comptroller.methods.compSpeeds(cTokenAddress).call();
compSpeed = compSpeed / 1e18;
// COMP issued to suppliers OR borrowers
const compSpeedPerDay = compSpeed * 4 * 60 * 24;
// COMP issued to suppliers AND borrowers
const compSpeedPerDayTotal = compSpeedPerDay * 2;

十一 提取(Claim COMP)

每個 Compound 用戶都會為他們提供給協(xié)議或從協(xié)議中借用的每個區(qū)塊累積COMP抡砂。用戶可以隨時調用Comptroller的 claimComp 方法大咱,將累積的COMP轉移到他們的地址。
合約方法:

// Claim all the COMP accrued by holder in all markets
function claimComp(address holder) public
// Claim all the COMP accrued by holder in specific markets
function claimComp(address holder, CToken[] memory cTokens) public
// Claim all the COMP accrued by specific holders in specific markets for their supplies and/or borrows
function claimComp(address[] memory holders, CToken[] memory cTokens, bool borrowers, bool suppliers) public

可以使用claimComp()方法提取個人的comp獎勵

const comptroller = new web3.eth.Contract(comptrollerAbi, comptrollerAddress);
await comptroller.methods.claimComp("0x1234...").send({ from: sender });

測試模塊

前面我們部署了comptroller合約注益,現(xiàn)在我們需要寫一部分測試碴巾,看具體的合約邏輯執(zhí)行。在最小可運行的compound合約中丑搔,我們部署了抵押usd厦瓢,以及compound鑄造出來的token:cUSD. 并部署了cUSD實際調用的邏輯cErc20Delegate, 然后cUSD的借貸模型中采用的是JumpRateModelV2,對應的審計合約是comptrollerG7.

下面我們分別就compound中低匙,最核心的用戶交互邏輯來編寫5個測試旷痕,簡單驗證邏輯可行性。

1顽冶、存 mint

用戶向compound中存款的邏輯是:用戶向compound中存入USD代幣, compound根據(jù)當前的匯率算出鑄造的cUSD代幣數(shù)量欺抗,將對應的cUSD代幣轉賬給用戶。

用戶函數(shù):enterMarkets

用戶的地址中對應用戶的所有資產列表强重,當計算一個用戶的所有流動性時绞呈。在借貸一種資產前贸人,一個或者多種資產必須被提供給compound以用作抵押。在借貸發(fā)生前佃声,任何借貸出的資產必須通過這種方式添加進入compound中艺智。該函數(shù)的返回值是一個列表,即該用戶的所有資產列表圾亏。
在 ComptrollerG7.sol 調用合約方法 enterMarkets:
參數(shù):cTokens: [
"0x209C9b6a0Ec37b91d0758514070A8439B14B9B3c", // cUSD 地址
"0xf3feeab27E8B8b71ED92040be19E5aA80baf9B01" // cETH 地址
]

ComptrollerG7(address(unitroller)).enterMarkets(addrs);
//此時alice調用enterMarkets后十拣,全局變量accountAssets[alice] = cToken[cUni], markets[cWALKER]={true, 60%,{alice:true},false}
//alice 調用cWALKER的mint方法
WALKER.approve(address(cWALKER),uint(-1));
cWALKER.mint(200000000000000000000); //200
// 200000000000000000000/1000000000000000000  //1:1
cWALKER.balanceOf(alice) =  200000000000000000000; //200
cWALKER.totalSupply() = 200000000000000000000
cWALKER.getCash() = 200000000000000000000
cWALKER.supplyRatePerBlock() = 0 //此時沒有借款志鹃,利用率為0
ComptrollerG7(address(unitroller)).getAccountLiquidity(alice) = 120000000000000000000 = 200000000000000000000 * 0.6 // 120 用戶流動性:為UnderlyingToken * 0.6 * price 
mint

2夭问、借 borrow

借幣邏輯是:用戶在compound中有多種cToken資產,記錄在accountAssets中曹铃。然后用戶向compound借出一定量的usd資產缰趋,同時增加用戶的負債額度。compound在接受用戶的借款請求時陕见,首先會檢查cToken有沒有上市秘血,再檢查用戶是否enterMarket,然后根據(jù)現(xiàn)在的預言機報價檢查用戶的賬戶流動性评甜。

//alice 在compound中存入了200000000000000000000的WALKER代幣灰粮,獲得了200000000000000000000的cWALKER代幣
//alice 向compound提出借款50000000000000000000的WALKER代幣
cWALKER.borrow(50000000000000000000);//50
cWALKER.totalBorrows() = 50000000000000000000;//50
cWALKER.getCash() == 150000000000000000000 = 200000000000000000000 - 50000000000000000000//150
cWALKER.supplyRatePerBlock = 2219685438
cWALKER.exchangeRateStored() = 1000000000000000000
cWALKER.borrowRatePerBlock() = 11098427194
利用率:utilization = cWALKER.supplyRatePerBlock / cWALKER.borrowRatePerBlock * (1- 0.25) = 
cWALKER.borrowIndex() = 1000000000000000000
cWALKER.accrualBlockNumber() =  18301817
borrow

3、還 repay

repay操作是borrow的逆操作蜕着,可以通過repayBorrow償還自己的貸款谋竖,repayBorrowBehalf代為償還他人貸款红柱,其具體邏輯是用戶批準cToken合約使用其underlying token承匣,先調用accuralInterest計算目前利率指數(shù)和對全部借貸額計息,然后調用comptroller.repayBorrowAllowed函數(shù)檢查是否可以償還锤悄,最后調用repayBorrowFresh償還韧骗。

WALKER.approve(cWALKER, 50000000000000000000);
cWALKER.repayBorrow(50000000000000000000);
cWALKER.totalBorrows() = 129296676810100;
cWALKER.getCash() = 200000000000000000000;//200
cWALKER.supplyRatePerBlock = 0
cWALKER.exchangeRateStored() = 1000000517186707240
cWALKER.borrowRatePerBlock() = 28699
利用率:utilization = cWALKER.supplyRatePerBlock / cWALKER.borrowRatePerBlock * (1- 0.25) = 
cWALKER.borrowIndex() = 1000002585933536202
cWALKER.accrualBlockNumber() =  18302050
repay

4、取 redeem

redeem是mint的逆運算零聚,但在實際邏輯中袍暴,增加了一個檢查賬戶虛擬流動性的一項。用戶可以調用redeem來償還給定數(shù)量的cToken隶症,或者調用redeemUnderlying來償還某數(shù)量的cToken得到給定數(shù)量的underlying Token. redeem操作的步驟是用戶批準cUSD合約使用用戶的cUSD代幣政模,然后調用accuralInterest函數(shù),來計算最新的利率指數(shù)Index蚂会,并對totalBorrows計息淋样。再然后是調用comptroller.redeemAllowed函數(shù),計算用戶的虛擬流動性胁住,看是否用戶有足夠的流動性來取走token趁猴。最后是redeemFresh函數(shù)根據(jù)要取走的數(shù)值刊咳,更新accountBorrow中的數(shù)值和totalBorrows。

5儡司、清算 liquidity

發(fā)生清算的一種典型情況是娱挨,用戶enterMarkets了兩個market,分別是cUni和cUSDT資金池捕犬。然后用戶在cUni池中跷坝,存入Uni獲得一定的cUni。用戶憑借cUni在cUSDT資金池中借貸出USDT碉碉。然而探孝,由于Uni的價格波動,導致Uni/USDT的價格突然下跌誉裆,此時用戶放置在cUni池中的cUni的總價值小于了借出的USDT的價值顿颅,從而觸發(fā)外部清算者進行清算。

清算過程整體分為兩部分:第一部分是repayBorrower部分足丢,代為償還underlying token粱腻,另一部分是seize部分,即將被清算者的cToken及獎勵金一起獎勵給清算者斩跌。由于清算涉及到兩種cToken,故在清算的第一步是分別調用兩種cToken的accural Interest函數(shù)绍些,計算各自最新的利率指數(shù)Index,并計算含息債務總額耀鸦。然后調用comptroller.liquidateBorrowAllowed函數(shù)柬批,計算被清算賬戶的流動性,如果被清算賬戶的流動性為正袖订,則不允許清算氮帐,如果被清算賬戶的流動性為負,并驗算單筆交易的清算量不能超過被清算賬戶的最大可清算量洛姑,則允許清算上沐。具體清算時,要求清算者不能是被清算者自己楞艾,然后計算轉給被清算者的cToken數(shù)量参咙。

在執(zhí)行轉賬cToken到清算者之前,需調用comptroller.seizeAllowed函數(shù)硫眯,作用是驗證調用seize函數(shù)的msg.sender和address(this)的comptroller保持一致蕴侧。然后將清算者的賬戶余額加上seizeTokens,被清算者的余額減去seizeTokens两入。在完成seize部分后净宵,函數(shù)跳轉到repayBorrow部分,代為償還underlying token。
具體清算的概念塘娶,可以看清算概述归斤,比較詳細簡單。

前端調用的方法

CErc20Delegator.sol是給普通erc20用的刁岸,CEther.sol是給鏈的主幣用的脏里,基礎的都是cToken。
里面的mint虹曙,redeem迫横,redeemUnderlying,borrow酝碳,repayBorrow矾踱,repayBorrowBehalf都類似的。

    /**
     * @notice Sender supplies assets into the market and receives cTokens in exchange
     * @dev Accrues interest whether or not the operation succeeds, unless reverted
     * @param mintAmount The amount of the underlying asset to supply
     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
     */
    function mint(uint mintAmount) external returns (uint) {
        bytes memory data = delegateToImplementation(abi.encodeWithSignature("mint(uint256)", mintAmount));
        return abi.decode(data, (uint));
    }
    /**
     * @notice Sender redeems cTokens in exchange for the underlying asset
     * @dev Accrues interest whether or not the operation succeeds, unless reverted
     * @param redeemTokens The number of cTokens to redeem into underlying 將被贖回的cToken的數(shù)量
     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
     * redeem 方法將指定數(shù)量的 cToken 轉換為標的資產疏哗,并將其返還給用戶呛讲。收到的標的數(shù)量等于贖回的 cToken 數(shù)量乘以當前匯率。
     * 贖回額必須小于用戶的賬戶流動性和市場可用的流動性返奉。
     */
    function redeem(uint redeemTokens) external returns (uint) {
        return redeemInternal(redeemTokens);
    }

    /**
     * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset
     * @dev Accrues interest whether or not the operation succeeds, unless reverted
     * @param redeemAmount The amount of underlying to redeem 將被贖回的標的的資產數(shù)量
     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
     * redeem underlying 方法將 cToken兌換成指定數(shù)量的標的資產贝搁,并返回給用戶。贖回的 cToken的數(shù)量等于收到的標的數(shù)量除以當前匯率芽偏。
     * 贖回額必須小于用戶的賬戶流動性和市場可用的流動性雷逆。
     */
    function redeemUnderlying(uint redeemAmount) external returns (uint) {
        return redeemUnderlyingInternal(redeemAmount);
    }

    /**
      * @notice Sender borrows assets from the protocol to their own address
      * @param borrowAmount The amount of the underlying asset to borrow
      * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
      * borrow 方法將協(xié)議中的標的資產轉移給用戶,并創(chuàng)建一個借款余額污尉,根據(jù)該資產的借款利率開始累積利息膀哲。
      * 借款額必須小于用戶的賬戶流動性和市場可用的流動性。
      */
    function borrow(uint borrowAmount) external returns (uint) {
        return borrowInternal(borrowAmount);
    }

    /**
     * @notice Sender repays their own borrow
     * @dev Reverts upon any failure
     * repay 方法將標的資產轉移到協(xié)議中被碗,并減少用戶的借款余額某宪。
     */
    function repayBorrow() external payable {
        (uint err,) = repayBorrowInternal(msg.value);
        requireNoError(err, "repayBorrow failed");
    }

    /**
     * @notice Sender repays a borrow belonging to borrower
     * @dev Reverts upon any failure
     * @param borrower the account with the debt being payed off
     */
    function repayBorrowBehalf(address borrower) external payable {
        (uint err,) = repayBorrowBehalfInternal(borrower, msg.value);
        requireNoError(err, "repayBorrowBehalf failed");
    }

在 ComptrollerG7.sol 調用合約方法 enterMarkets:

參數(shù):cTokens: [
"0x209C9b6a0Ec37b91d0758514070A8439B14B9B3c", // cUSD 地址
"0xf3feeab27E8B8b71ED92040be19E5aA80baf9B01" // cETH 地址
]

ComptrollerG7(address(unitroller)).enterMarkets(addrs);

參考:

  1. 第108篇 Compound 簡單部署
  2. Compound 合約部署
  3. 清算概述
  4. Compound學習
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蛮放,隨后出現(xiàn)的幾起案子缩抡,更是在濱河造成了極大的恐慌,老刑警劉巖包颁,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異压真,居然都是意外死亡娩嚼,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進店門滴肿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來岳悟,“玉大人,你說我怎么就攤上這事」笊伲” “怎么了呵俏?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長滔灶。 經(jīng)常有香客問我普碎,道長,這世上最難降的妖魔是什么录平? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任麻车,我火速辦了婚禮,結果婚禮上斗这,老公的妹妹穿的比我還像新娘动猬。我一直安慰自己,他們只是感情好表箭,可當我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布赁咙。 她就那樣靜靜地躺著,像睡著了一般免钻。 火紅的嫁衣襯著肌膚如雪序目。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天伯襟,我揣著相機與錄音猿涨,去河邊找鬼。 笑死姆怪,一個胖子當著我的面吹牛叛赚,可吹牛的內容都是我干的。 我是一名探鬼主播稽揭,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼俺附,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了溪掀?” 一聲冷哼從身側響起事镣,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎揪胃,沒想到半個月后璃哟,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡喊递,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年随闪,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片骚勘。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡铐伴,死狀恐怖撮奏,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情当宴,我是刑警寧澤畜吊,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站户矢,受9級特大地震影響玲献,放射性物質發(fā)生泄漏。R本人自食惡果不足惜逗嫡,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一青自、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧驱证,春花似錦延窜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至伙单,卻和暖如春获高,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背吻育。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工念秧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人布疼。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓摊趾,卻偏偏與公主長得像,于是被迫代替她去往敵國和親游两。 傳聞我的和親對象是個殘疾皇子砾层,可洞房花燭夜當晚...
    茶點故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內容