前言
使用 truffle部署合约,并练习ethers库。
之前一直是使用web3js,今天看到一个源码使用了ethers,看了之后感觉比web3js方便很多。
web3js 与 ethers对比
连接到以太坊
1 2 3 4
| var Web3 = require('web3'); var web3 = new Web3('http://localhost:8545');
var ethers = require('ethers'); const url = "http://127.0.0.1:8545"; const provider = new ethers.providers.JsonRpcProvider(url);
|
签名对象
在ethers中,签名者是以太坊账户的抽象。它可用于对消息和交易进行签名,并将签名的交易发送到以太坊网络。
在 web3 中,可以使用一个帐户来签署消息和交易。
1 2 3 4 5 6
| const account = web3.eth.accounts.create();
const signer = ethers.Wallet.createRandom();
const signer = provider.getSigner();
|
使用私钥生成账号对象生成调用的方法不同,不过使用上大同小异。
1 2 3 4 5
| const signer = web3.eth.accounts.privateKeyToAccount(private_key)
const signer = new ethers.Wallet(private_key);
|
账号签名
1 2 3 4
| signature = web3.eth.accounts.sign('Some data', privateKey)
signature = await signer.signMessage('Some data')
|
合约调用
只读方法
1 2 3 4 5 6 7 8 9
| const contract = new this.web3.eth.Contract(abi, contract_address) const token_blance = await contract.methods.balanceOf(wallet_address).call() const blance = this.web3.utils.fromWei(token_blance, 'ether')
const daiContract = new ethers.Contract(daiAddress, daiAbi, provider); const res = await daiContract.balanceOf(myaddress).toString()
|
上述方法中使用web3js需要去下载相应的ABI,比如你可以去etherscan下载,而在ethers中,你可以直接传入方法生成daiAbi
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const daiAbi = [ "function name() view returns (string)", "function symbol() view returns (string)",
"function balanceOf(address) view returns (uint)",
"function transfer(address to, uint amount)",
"event Transfer(address indexed from, address indexed to, uint amount)" ]; const daiContract = new ethers.Contract(daiAddress, daiAbi, provider);
|
实践目标
1.使用truffle部署一个合约
2.使用truffle console 进行交互
3.使用ethers进行合约交互练习
安装环境
1 2 3 4 5
| yarn global add truffle yarn install ethers # 或者 npm install -g truffle npm install ethers
|
编写合约
实现一个最简单的合约
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| // SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.0;
/** * @title Storage * @dev Store & retrieve value in a variable */ contract Storage {
uint256 number;
/** * @dev Store value in variable * @param num value to store */ function store(uint256 num) public { number = num; }
/** * @dev Return value * @return value of 'number' */ function retrieve() public view returns (uint256){ return number; } }
|
1 2 3 4
| # 编译 truffle compile # 部署 truffle migrate
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| Starting migrations... ====================== > Network name: 'development' > Network id: 1 > Block gas limit: 6721975 (0x6691b7)
1_initial_migration.js ======================
Replacing 'Migrations' ---------------------- > transaction hash: 0x67c58fd2401c5bc506591f30b9566be6e8226c8b09a8125a511224cfa5029f7f > Blocks: 0 Seconds: 0 > contract address: 0x25A6E016CB92D46fe8cE3f74D4F93b6439F6Cc89 > block number: 14820726 > block timestamp: 1653184639 > account: 0x4BC9E31c338C402Aa2590E7008a879B5a66A8568 > balance: 99.995114 > gas used: 244300 (0x3ba4c) > gas price: 20 gwei > value sent: 0 ETH > total cost: 0.004886 ETH
> Saving migration to chain. > Saving artifacts ------------------------------------- > Total cost: 0.004886 ETH
2_deploy_contracts.js =====================
Replacing 'Storage' ------------------- > transaction hash: 0x45ae44d9c9730485b0208dbbb0d1116398f9d562931024fc9757e5b603160cc1 > Blocks: 0 Seconds: 0 > contract address: 0xFe87778700B9dda2B5FD5fb7895120C33a331E69 > block number: 14820728 > block timestamp: 1653184640 > account: 0x4BC9E31c338C402Aa2590E7008a879B5a66A8568 > balance: 99.9918876 > gas used: 118807 (0x1d017) > gas price: 20 gwei > value sent: 0 ETH > total cost: 0.00237614 ETH
> Saving migration to chain. > Saving artifacts ------------------------------------- > Total cost: 0.00237614 ETH
Summary ======= > Total deployments: 2 > Final cost: 0.00726214 ETH
|
部署完成之后,我们可以使用 truffle console
进行交互
1 2 3 4 5
| let ins = await Storage.deployed() await ins.store(7) let n2 = await ins.retrieve() n2 # BN { negative: 0, words: [ 7, <1 empty item> ], length: 1, red: null }
|
所以上述合约就只有2个方法
一个read方法:retrieve
一个write方法:store
所以通过 truffle 可以直接跟他进行交互
代码实现的功能:调用storage合约,将number修改为10,并且读取一次number的值。
ethers可以直接根据方法名生成abi,比web3js方便很多。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| const { ethers } = require("ethers");
const provider = new ethers.providers.JsonRpcProvider("http://127.0.0.1:8545");
(async () => { const num = await provider.getBlockNumber(); console.log(num); const singer = new ethers.Wallet( "private_key" ); const myaddress = singer.address; console.log(myaddress); const signature = await singer.signMessage("some data"); console.log(signature); const contractAddress = "0xFe87778700B9dda2B5FD5fb7895120C33a331E69";
const storageAbi = [ "function retrieve() view returns (uint256)",
"function store(uint256 num)", ];
const storageContract = new ethers.Contract( contractAddress, storageAbi, provider.getSigner() ); const res = await storageContract.store(10); console.log(res);
const res2 = await storageContract.retrieve(); console.log(res2.toString()); })();
|
综上所述,对比web3js,ethers封装了更方便的api接口,能简化一些调用流程。
参考
Ethers Getting Started