3.读取合约信息
目标:
- 了解什么是 Contract 、EVM字节码
- 如何创建Contract实例,两种创建 contract 实例的方法
- 读取链上合约信息
- 认识以太坊浏览器
contract 类
在ethers
中,Contract
类是部署在以太坊网络上的合约(EVM
字节码)的抽象,通过它,开发者可以非常容易的对合约进行读取call
和交易transcation
并可以获得交易的结果和事件。以太坊强大的地方正是合约,所以对于合约的操作要熟练掌握。
创建Contract
变量(实例)
Contract
对象分为两类,只读和可读写。只读Contract
只能读取链上合约信息,执行call
操作,即调用合约中view
和pure
的函数,而不能执行交易transaction
。
- 只读合约
只读Contract
:参数分别是合约地址,合约abi
和provider
变量(只读)
const contract = new ethers.Contract(`address`, `abi`, `provider`);
- 可读写合约
可读写Contract
:参数分别是合约地址,合约abi
和signer
变量。Signer
签名者是ethers
中的另一个类,用于签名交易,之后我们会讲到。
const contract = new ethers.Contract(`address`, `abi`, `signer`);
代码
- 创建 provider 实例
const provider = new ethers.providers.JsonRpcProvider(mainNetWork);
- 创建 contract 实例
- 直接输入合约
abi
。你可以从remix
的编译页面中复制,在本地编译合约时生成的artifact
文件夹的json
文件中得到,或者从etherscan
开源合约的代码页面得到
// 1.1 创建合约实例
// 方法1. 直接输入合约abi
const addressWETH = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' // WETH Contract
const abi = '[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"guy","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Withdrawal","type":"event"}]'
const contractWETH = new ethers.Contract(addressWETH,abi, provider)
- 由于
abi
可读性太差,ethers
创新的引入了Human-Readable Abi
(人类可读abi)。开发者可以通过function signature
和event signature
来写abi
// 方法2.
const abiERC20 = [
"function transfer(address, uint) returns (bool)",
"function name() view returns (string)",
"function symbol() view returns (string)",
"function totalSupply() view returns (uint256)",
"function balanceOf(address) view returns (uint)",
];
const addressDAI = '0x6B175474E89094C44Da98b954EedeAC495271d0F' // DAI Contract
const contractDAI = new ethers.Contract(addressDAI, abiERC20, provider)
- 读取合约相关信息
// 2. 读取合约信息
const contractWETHName = await contractWETH.name()
const symbolWETH = await contractWETH.symbol()
const totalSupply = await contractWETH.totalSupply()
console.log('WETH的合约名字', contractWETHName)
console.log('WETH的合约代号', symbolWETH)
console.log('WETH的目前总供给量', )
// 调用合约中的函数
const balanceWETH = await contractWETH.balanceOf('vitalik.eth')
console.log('vitalik.eth 的持仓', ethers.utils.formatEther(balanceWETH))
console.log('-------------------------')
const contractDAIName = await contractDAI.name()
const contractDAISymbol = await contractDAI.symbol()
const contractDAITotalSupply = await contractDAI.totalSupply()
console.log('DAI合约的名字',contractDAIName)
console.log('DAI合约的代号',contractDAISymbol)
console.log('DAI合约的目前总供给量',ethers.utils.formatEther(contractDAITotalSupply))
// 调用合约中的函数
const balanceDAI = await contractDAI.balanceOf('vitalik.eth')
console.log('vitalik.eth 的持仓', ethers.utils.formatEther(balanceDAI))