本文环境:
区块链:以太坊POA联盟链;
出块节点数:3;
操作系统:windows 64;
节点版本:Geth1.9.14;
node版本:v10.14.0
参考文档:https://web3js.readthedocs.io/en/v1.2.8/
目录
2.7 transactionConfirmationBlocks
3.6 methods.myMethod.estimateGas
3.7 methods.myMethod.encodeABI
web3.eth.Contract对象让你可以轻松地与以太坊区块链上的智能合约进行交互。 当你创建一个新的合约对象时,只需要指定相应的智能合约 json 接口, web3 就会自动将所有的调用转换为基于 RPC 的底层 ABI 调用。
这使得你可以像 JavaScript 对象一样与智能合约进行交互。
一、new contract
new web3.eth.Contract(jsonInterface[, address][, options])
创建新的合约实例,并在其json interface对象中定义所有的方法和事件。
参数
-
jsonInterface
-Object
: 所要实例化合约的 json 接口 -
address
-String
(可选): 要调用的智能合约地址 -
options
-Object
(可选): 合约配置选项。 其中某些选项被用作合约调用和交易的回调:
-
from
-String
: 交易发送方地址 -
gasPrice
-String
: 为交易指定的 gas 价格,以 wei 为单位 -
gas
-Number
: 交易可用的最大 gas 量(gas limit)。 -
data
-String
: 合约字节码。当合约被 :ref:`部署 <contract-deploy>`时需要使用。
返回值
Object
: 带有所有方法和事件的合约实例
子
//官方示例
var myContract = new web3.eth.Contract([...], '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe', {
from: '0x1234567890123456789012345678901234567891', // 默认交易发送地址
gasPrice: '20000000000' // 以 wei 为单位的默认 gas 价格,当前价格为 20 gwei
});
二、属性
2.1 defaultAccount
web3.eth.Contract.defaultAccount
contract.defaultAccount // 合约实例上的默认账户
如果下面这些方法没有指定 "from"
属性,默认账户地址就会被用作默认的 "from"
属性:
- web3.eth.sendTransaction()
- web3.eth.call()
- new web3.eth.Contract() -> myContract.methods.myMethod().call()
- new web3.eth.Contract() -> myContract.methods.myMethod().send()
属性
String
- 20 字节: 任意以太坊地址。 你应该在你的节点或 keystore 中拥有该地址的私钥。 (默认值为 undefined
)
例子
web3.eth.defaultAccount;
> undefined
// 设置默认账户
web3.eth.defaultAccount = '0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe';
2.2 defaultBlock
web3.eth.Contract.defaultBlock
contract.defaultBlock // 在合约实例上
默认块在一些特定方法上使用。你可以通过传入 defaultBlock 作为最后一个参数来覆盖它。 默认值为 “latest”。
属性
默认块参数的可能取值如下:
-
Number|BN|BigNumber
: 区块号 -
"genesis"
-String
: 创世块 -
"latest"
-String
: 最新块(也就是当前链头块) -
"pending"
-String
: 正在挖的块(包括 pending 状态交易) -
"earliest"
-String
: 创世块
默认值为 "latest"
例子
contract.defaultBlock;
> "latest"
// 设置默认块
contract.defaultBlock = 231;
2.3 defaultHardfork
contract.defaultHardfork
本地签名交易时用的默认硬分叉属性
属性
默认硬分叉属性的可能取值如下:
-
"chainstart"
-String
-
"homestead"
-String
-
"dao"
-String
-
"tangerineWhistle"
-String
-
"spuriousDragon"
-String
-
"byzantium"
-String
-
"constantinople"
-String
-
"petersburg"
-String
-
"istanbul"
-String
默认值为 "petersburg"
例子
contract.defaultHardfork;
> "petersburg"
// 设置默认硬分叉
contract.defaultHardfork = 'istanbul';
2.4 defaultChain
contract.defaultChain
默认链属性是本地签名交易的时候用的
属性
默认链属性可以是一下列表中之一:
-
"mainnet"
-String
-
"goerli"
-String
-
"kovan"
-String
-
"rinkeby"
-String
-
"ropsten"
-String
默认值为 "mainnet"
例子
contract.defaultChain;
> "mainnet"
// 设置默认链
contract.defaultChain = 'goerli';
2.5 defaultCommon
contract.defaultCommon
默认通用属性是本地签名交易的时候用的
属性
默认通用属性包含如下所示的 Common
对象:
-
customChain
-Object
: 自定义链属性
-
name
-string
: (可选) 链名字 -
networkId
-number
: 自定义链的网络 Id -
chainId
-number
: 自定义链的链 Id
-
baseChain
-string
: (可选)mainnet
,goerli
,kovan
,rinkeby
, orropsten
-
hardfork
-string
: (可选)chainstart
,homestead
,dao
,tangerineWhistle
,spuriousDragon
,byzantium
,constantinople
,petersburg
, oristanbul
默认值为 undefined
。
例子
contract.defaultCommon;
> {customChain: {name: 'custom-network', chainId: 1, networkId: 1}, baseChain: 'mainnet', hardfork: 'petersburg'}
// 设置默认通用值
contract.defaultCommon = {customChain: {name: 'custom-network', chainId: 1, networkId: 1}, baseChain: 'mainnet', hardfork: 'petersburg'};
2.6 transactionBlockTimeout
web3.eth.Contract.transcationBlockTimeout
contract.transactionBlockTimeout // 在合约实例上
transactionBlockTimeout
会被用在基于套接字的连接上。该属性定义了直到第一次确认发生它应该等待的区块数。 这意味着当超时发生时,PromiEvent 会拒绝并显示超时错误。
返回值
-
number
: transactionBlockTimeout 当前设定的值 (默认值: 50)
2.7 transactionConfirmationBlocks
web3.eth.Contract.transactionConfirmationBlocks
contract.transactionConfirmationBlocks // 在合约实例上
定义了确认交易所需要的区块确认数。
返回值
-
number
: transactionConfirmationBlocks 当前设定的值 (默认值: 24)
2.8 transactionPollingTimeout
web3.eth.Contract.transactionPollingTimeout
contract.transactionPollingTimeout // 在合约实例上
transactionPollingTimeout
将通过 HTTP 连接使用。 这个选项定义了 Web3 等待确认交易被网络挖出的收据的秒数。注意:当此种超时发生时,交易可能仍未完成。
返回值
-
number
: transactionPollingTimeout 当前设定的值 (默认值: 750)
2.9 handleRevert
web3.eth.Contract.handleRevert
contract.handleRevert // 在合约实例上
handleRevert`选项属性默认值为`false
,如果在 :ref:`send <contract-send>`或者 :ref:`call <contract-call>`合约方法时启用,将返回回退原因字符串。
注解
回退原因字符串和签名是存在于返回错误的属性中的。
返回值
-
boolean
:handleRevert
的当前值 (默认值: false)
2.10 选项属性
myContract.options
合约实例的选项属性 对象
。from
、 gas
和 ``gasPrice``作为发送交易时的备用值使用。
属性
Object
- 选项属性:
-
address
-String
: 合约的部署地址。 -
jsonInterface
-Array
: 合同的 json 接口。 -
data
-String
: 合约字节码。 部署合约时使用。 -
from
-String
: 交易发起方地址。 -
gasPrice
-String
: 用于交易的 gas 价格。以 wei 为单位。 -
gas
-Number
: 可用于该交易的 gas 用量上限 (gas limit)。 -
handleRevert
-Boolean
: 如果这里不设置,将使用 Eth 模块提供的默认值。 -
transactionBlockTimeout
-Number
: 如果这里不设置,将使用 Eth 模块提供的默认值。 -
transactionConfirmationBlocks
-Number
: 如果这里不设置,将使用 Eth 模块提供的默认值。 -
transactionPollingTimeout
-Number
: 如果这里不设置,将使用 Eth 模块提供的默认值。 -
chain
-Number
: 如果这里不设置,将使用 Eth 模块提供的默认值。 -
hardfork
-Number
: 如果这里不设置,将使用 Eth 模块提供的默认值。 -
common
-Number
: 如果这里不设置,将使用 Eth 模块提供的默认值。
例子
myContract.options;
> {
address: '0x1234567890123456789012345678901234567891',
jsonInterface: [...],
from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe',
gasPrice: '10000000000000',
gas: 1000000
}
myContract.options.from = '0x1234567890123456789012345678901234567891'; // 默认交易发送方地址
myContract.options.gasPrice = '20000000000000'; // 默认 gas 价格,以 wei 为单位
myContract.options.gas = 5000000; // 5M gas 作为备用值
2.11 options.address
myContract.options.address
用于本合约实例的地址。 所有通过 web3.js 从这个合约生成的交易都将包含这个地址作为 “to” 地址(也就是交易接收方地址)。
地址将以小写的方式保存。
属性
-
address
-String|null
: 本合约的地址, 如果未设置其值为null
。
例子
myContract.options.address;
> '0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae'
// 设置新地址
myContract.options.address = '0x1234FFDD...';
2.12 options.jsonInterface
myContract.options.jsonInterface
从合约的ABI派生出来的json接口对象。
属性
-
jsonInterface
-Array
: 当前合约的json接口。重设该接口会导致合约实例方法和事件的重新生成。
例子
myContract.options.jsonInterface;
> [{
"type":"function",
"name":"foo",
"inputs": [{"name":"a","type":"uint256"}],
"outputs": [{"name":"b","type":"address"}]
},{
"type":"event",
"name":"Event",
"inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"bytes32","indexed":false}],
}]
// 设置新的接口
myContract.options.jsonInterface = [...];
三、方法
3.1 clone
myContract.clone()
克隆当前合约实例。
例子
var contract1 = new eth.Contract(abi, address, {gasPrice: '12345678', from: fromAddress});
var contract2 = contract1.clone();
contract2.options.address = address2;
(contract1.options.address !== contract2.options.address);
> true
3.2 deploy
myContract.deploy(options)
调用此函数将合约部署到区块链上。 成功部署后 promise 对象会被解析为新的合约实例。
参数
-
options
-Object
: 用于合约部署的选项。
-
data
-String
: 合约字节码 -
arguments
-Array
(可选): 在部署合约时传递给构造函数的参数。
返回值
Object
: 交易对象:
-
Array
- 参数: 之前传递给方法的参数。它们是可以被改变的。 -
Function
- send: 用来部署合约。promise 会被解析为合约实例而不是交易收据。 -
Function
- estimateGas: 估算部署合约所需要的 gas 用量。 -
Function
- encodeABI: 编码由合约数据和构造函数参数构成的合约部署 ABI。
关于这些方法的更多详情,参见下面的文档。
例子
myContract.deploy({
data: '0x12345...',
arguments: [123, 'My String']
})
.send({
from: '0x1234567890123456789012345678901234567891',
gas: 1500000,
gasPrice: '30000000000000'
}, function(error, transactionHash){ ... })
.on('error', function(error){ ... })
.on('transactionHash', function(transactionHash){ ... })
.on('receipt', function(receipt){
console.log(receipt.contractAddress) // 包含新合约地址
})
.on('confirmation', function(confirmationNumber, receipt){ ... })
.then(function(newContractInstance){
console.log(newContractInstance.options.address) // 带有新合约地址的合约实例
});
//数据已经设置为合约本身的选项
myContract.options.data = '0x12345...';
myContract.deploy({
arguments: [123, 'My String']
})
.send({
from: '0x1234567890123456789012345678901234567891',
gas: 1500000,
gasPrice: '30000000000000'
})
.then(function(newContractInstance){
console.log(newContractInstance.options.address) // 具有新合同地址的合约实例
});
// 只是编码
myContract.deploy({
data: '0x12345...',
arguments: [123, 'My String']
})
.encodeABI();
> '0x12345...0000012345678765432'
// gas 估算
myContract.deploy({
data: '0x12345...',
arguments: [123, 'My String']
})
.estimateGas(function(err, gas){
console.log(gas);
});
本文实例1:使用代码部署智能合约
//本文示例,实际部署了一个erc20合约,用于本文测试
var Web3= require('web3');
var web3= new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
var initialAmount = 1000000; /* var of type uint256 here */
var tokenName = "kongfuziToken"; /* var of type string here */
var decimalUnits = 18; /* var of type uint8 here */
var tokenSymbol = "KFZT"; /* var of type string here */
var tokentestContract = new web3.eth.Contract([{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","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":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"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":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initialAmount","type":"uint256"},{"name":"tokenName","type":"string"},{"name":"decimalUnits","type":"uint8"},{"name":"tokenSymbol","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}]);
var tokentest = tokentestContract.deploy({
data: '0x60806040523480156200001157600080fd5b506040516200137338038062001373833981018060405281019080805190602001909291908051820192919060200180519060200190929190805182019291905050506200007a848360ff16600a0a620001c66401000000000262001042176401000000009004565b600081905550600054600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055503373ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6000546040518082815260200191505060405180910390a382600190805190602001906200014692919062000208565b5081600260006101000a81548160ff021916908360ff16021790555080600390805190602001906200017a92919062000208565b5033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050620002b7565b6000806000841415620001dd576000915062000201565b8284029050828482811515620001ef57fe5b04141515620001fd57600080fd5b8091505b5092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200024b57805160ff19168380011785556200027c565b828001600101855582156200027c579182015b828111156200027b5782518255916020019190600101906200025e565b5b5090506200028b91906200028f565b5090565b620002b491905b80821115620002b057600081600090555060010162000296565b5090565b90565b6110ac80620002c76000396000f3006080604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b4578063095ea7b31461014457806318160ddd146101a957806323b872dd146101d4578063313ce5671461025957806341c0e1b51461028a57806370a08231146102a15780638da5cb5b146102f857806395d89b411461034f578063a9059cbb146103df578063dd62ed3e14610444575b600080fd5b3480156100c057600080fd5b506100c96104bb565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101095780820151818401526020810190506100ee565b50505050905090810190601f1680156101365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015057600080fd5b5061018f600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610559565b604051808215151515815260200191505060405180910390f35b3480156101b557600080fd5b506101be61064b565b6040518082815260200191505060405180910390f35b3480156101e057600080fd5b5061023f600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610651565b604051808215151515815260200191505060405180910390f35b34801561026557600080fd5b5061026e610acf565b604051808260ff1660ff16815260200191505060405180910390f35b34801561029657600080fd5b5061029f610ae2565b005b3480156102ad57600080fd5b506102e2600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b79565b6040518082815260200191505060405180910390f35b34801561030457600080fd5b5061030d610bc2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561035b57600080fd5b50610364610be8565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103a4578082015181840152602081019050610389565b50505050905090810190601f1680156103d15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103eb57600080fd5b5061042a600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610c86565b604051808215151515815260200191505060405180910390f35b34801561045057600080fd5b506104a5600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610f72565b6040518082815260200191505060405180910390f35b60018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156105515780601f1061052657610100808354040283529160200191610551565b820191906000526020600020905b81548152906001019060200180831161053457829003601f168201915b505050505081565b600081600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60005481565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415151561068e57600080fd5b8373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141515156106c957600080fd5b600082101515156106d957600080fd5b600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115151561072757600080fd5b600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482111515156107b257600080fd5b600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054011015151561084157600080fd5b61088a600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205483610ff9565b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610916600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205483611015565b600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506109df600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205483610ff9565b600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b600260009054906101000a900460ff1681565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610b3e57600080fd5b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b6000600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60038054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610c7e5780601f10610c5357610100808354040283529160200191610c7e565b820191906000526020600020905b815481529060010190602001808311610c6157829003601f168201915b505050505081565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614151515610cc357600080fd5b3373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614151515610cfe57600080fd5b60008210151515610d0e57600080fd5b81600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610d5c57600080fd5b600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540110151515610deb57600080fd5b610e34600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205483610ff9565b600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610ec0600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205483611015565b600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a36001905092915050565b6000600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600082821115151561100a57600080fd5b818303905092915050565b600080828401905083811015801561102d5750828110155b151561103857600080fd5b8091505092915050565b60008060008414156110575760009150611079565b828402905082848281151561106857fe5b0414151561107557600080fd5b8091505b50929150505600a165627a7a72305820360d57956695d80a16337257760d883f19b65df7ef14137b17cbc8d21f722ef20029',
arguments: [initialAmount, tokenName, decimalUnits, tokenSymbol]
})
.send({
from: "0x38D8B866a1ABeBcA20AFC004622F5355EeFEB568",
gas: '5700000'
}, function(error, transactionHash){
console.log(error, transactionHash)
})
.on('receipt', function(receipt){
console.log("receipt.contractAddress :" + receipt.contractAddress); // 包含新合约地址
console.log(receipt)
})
.then(function(newContractInstance){
console.log("newContractInstance.options.address :" + newContractInstance.options.address) // 带有新合约地址的合约实例
});
/*
null '0xa63dd8dc8b3b1de2f7e1276a92dc71665684660b3f97d2d6a299659de2f88b6f'
receipt.contractAddress :0xb43938511C10A242dce4f5C110c54fBB51f5bd28
{ blockHash:
'0x7f8d2898026aa7a0665f6460becc930c1a2afc55e5b323b5013c114eb3a6c14d',
blockNumber: 278509,
contractAddress: '0xb43938511C10A242dce4f5C110c54fBB51f5bd28',
cumulativeGasUsed: 1114009,
from: '0x38d8b866a1abebca20afc004622f5355eefeb568',
gasUsed: 1114009,
logsBloom:
'0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000008000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000200000042000000000000000000000000000000000000000000000000000420000010000000000000000000000000000000000000000000000000000000000000',
status: true,
to: null,
transactionHash:
'0xa63dd8dc8b3b1de2f7e1276a92dc71665684660b3f97d2d6a299659de2f88b6f',
transactionIndex: 0,
events:
{ Transfer:
{ address: '0xb43938511C10A242dce4f5C110c54fBB51f5bd28',
blockNumber: 278509,
transactionHash:
'0xa63dd8dc8b3b1de2f7e1276a92dc71665684660b3f97d2d6a299659de2f88b6f',
transactionIndex: 0,
blockHash:
'0x7f8d2898026aa7a0665f6460becc930c1a2afc55e5b323b5013c114eb3a6c14d',
logIndex: 0,
removed: false,
id: 'log_d01b6181',
returnValues: [Result],
event: 'Transfer',
signature:
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
raw: [Object] } } }
newContractInstance.options.address :0xb43938511C10A242dce4f5C110c54fBB51f5bd28
*/
注意:
不同版本web3.js带来的API变化问题。请检查你的web3.js版本:
如果version<1.0.0,使用:
new web3.eth.contract(studentFactoryArtifact,address); // 注意区分contract大小写
如果version>1.0.0,使用:
new web3.eth.Contract(studentFactoryArtifact,address); // 注意区分Contract大小写
3.3 methods
myContract.methods.myMethod([param1[, param2[, ...]]])
为指定方法创建一个交易对象, 可以被用来 called, send, estimated.
该智能合约的方法可以通过下面几种方式得到:
- 方法名:
myContract.methods.myMethod(123)
- 带参数的方法名:
myContract.methods['myMethod(uint256)'](123)
- 方法签名:
myContract.methods['0x58cf5f10'](123)
这样可以调用与 JavaScript 合约对象名称相同但参数不同的函数。
返回值
Object
: 交易对象:
-
Array
- 参数: 之前传递给方法的参数。它们是可以被改变的。 -
Function
- call: 将在不发送交易的情况下调用该“常量”方法并在 EVM 中执行其智能合约方法(无法更改智能合约状态)。 -
Function
- send: 用来向合约发送交易并执行其方法(可以更改智能合约状态)。 -
Function
- estimateGas: 将估算在链上执行该方法时所要消耗的 gas。 -
Function
- encodeABI: 对合于方法进行 ABI 编码。得到的编码可以通过交易去 send,可以直接 call,也可以作为参数传给另外一个智能合约方法。
关于这些方法的更多详情,参见下面的文档。
例子
// 对一个方法发起 call 调用
myContract.methods.myMethod(123).call({from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'}, function(error, result){
...
});
// 或者发生交易并使用 promise
myContract.methods.myMethod(123).send({from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'})
.then(function(receipt){
// receipt can also be a new contract instance, when coming from a "contract.deploy({...}).send()"
});
// 或者发送交易并使用事件
myContract.methods.myMethod(123).send({from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'})
.on('transactionHash', function(hash){
...
})
.on('receipt', function(receipt){
...
})
.on('confirmation', function(confirmationNumber, receipt){
...
})
.on('error', function(error, receipt) {
...
});
3.4 methods.myMethod.call
myContract.methods.myMethod([param1[, param2[, ...]]]).call(options[, callback])
将在不发送交易的情况下调用该“常量”方法并在 EVM 中执行其智能合约方法。注意此种调用方式无法改变智能合约状态。
参数
-
options
-Object
(可选): 用于发起调用的选项。
-
from
-String
(可选): 调用“交易”的发起方地址。 -
gasPrice
-String
(可选): 用于该调用“交易”的 gas 价格。以 wei 为计量单位。 -
gas
-Number
(可选): 用于该调用“交易”的 gas 用量上限 (gas limit)。
-
callback
-Function
(可选): 回调函数,回调时将以智能合约方法执行结果作为第二个参数,以错误对象作为第一个参数。
返回值
-
Promise
返回Mixed
: 智能合约方法返回值。 如果只返回一个值,则按原样返回。如果有多个返回值,则作为一个带有属性和索引的对象返回。
例子
// 使用回调
myContract.methods.myMethod(123).call({from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'}, function(error, result){
...
});
// 使用 promise
myContract.methods.myMethod(123).call({from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'})
.then(function(result){
...
});
// 多返回值:
// Solidity
contract MyContract {
function myFunction() returns(uint256 myNumber, string myString) {
return (23456, "Hello!%");
}
}
// web3.js
var MyContract = new web3.eth.Contract(abi, address);
MyContract.methods.myFunction().call()
.then(console.log);
> Result {
myNumber: '23456',
myString: 'Hello!%',
0: '23456', // 这里这些是作为属性名称时的备用值
1: 'Hello!%'
}
// 单参数返回:
// Solidity
contract MyContract {
function myFunction() returns(string myString) {
return "Hello!%";
}
}
// web3.js
var MyContract = new web3.eth.Contract(abi, address);
MyContract.methods.myFunction().call()
.then(console.log);
> "Hello!%"
本文实例2:调用智能合约“常量”方法,不改变状态
var Web3= require('web3');
var web3= new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
var contractAddress = "0xb43938511C10A242dce4f5C110c54fBB51f5bd28"; //智能合约地址
var accountsAddress = "0x38D8B866a1ABeBcA20AFC004622F5355EeFEB568";
var contractAbi = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","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":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"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":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initialAmount","type":"uint256"},{"name":"tokenName","type":"string"},{"name":"decimalUnits","type":"uint8"},{"name":"tokenSymbol","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}];
var myContract = new web3.eth.Contract(contractAbi,contractAddress);
myContract.methods.totalSupply().call().then(function(result){
console.log("totalSupply:",result);
});
myContract.methods.name().call().then(function(result){
console.log("name:",result);
});
myContract.methods.decimals().call().then(function(result){
console.log("decimals:",result);
});
myContract.methods.symbol().call().then(function(result){
console.log("symbol:",result);
});
myContract.methods.owner().call().then(function(result){
console.log("owner:",result);
});
myContract.methods.balanceOf(accountsAddress).call().then(function(result){
console.log("result1:",result);
console.log("result2:",JSON.stringify(result));
});
/*
totalSupply: 1000000000000000000000000
decimals: 18
name: kongfuziToken
symbol: KFZT
owner: 0x38D8B866a1ABeBcA20AFC004622F5355EeFEB568
result1: 1000000000000000000000000
result2: "1000000000000000000000000"
*/
3.5 methods.myMethod.send
myContract.methods.myMethod([param1[, param2[, ...]]]).send(options[, callback])
向合约发送交易来执行其方法。注意这会改变合约状态。
参数
-
options
-Object
: 用来发送交易的选项。
-
from
-String
: 交易发送方地址。 -
gasPrice
-String
(可选): 用于该交易的 gas 价格,以 wei 为单位。 -
gas
-Number
(可选): 该交易 gas 用量上限 (gas limit)。 -
value
- ``Number|String|BN|BigNumber``(可选): 交易转账金额,以 wei 为单位。
-
callback
-Function
(可选): 回调函数,触发时其第二个参数为交易哈希,第一个参数为错误对象。
返回值
回调 将返回 32 字节的交易哈希值。
PromiEvent
: 一个 整合了事件发生器 <promiEvent> promise. 当收到交易*收据*时会被解析, 当该``send()``调用是从``someContract.deploy()``发出时,promise 会解析为*新合约地址*。重设该接口会导致合约实例方法和事件的重新生成。 此外也存在下面这些事件:
-
"transactionHash"
返回String
: 发送交易且得到交易哈希值后立即触发。 -
"receipt"
返回Object
: 当收到交易*收据*时触发。合约收据带有的不是``logs``,而是以事件名称为健,以事件本身为属性值的``events``。 关于返回事件对象的详情,参见 getPastEvents 返回值 。 -
"confirmation"
返回Number
,Object
: 从区块被挖到的第一个区块确认开始,每次确认都会触发,直到第 24 次确认。触发时第一个参数为收到的确认数,第二个参数为收到交易收据。 -
"error"
返回Error
和Object|undefined
: 交易发送过程中出错时触发。如果交易被网络拒绝且带有交易收据,第二个参数就是该交易收据。
例子
// 使用回调
myContract.methods.myMethod(123).send({from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'}, function(error, transactionHash){
...
});
// 使用 promise
myContract.methods.myMethod(123).send({from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'})
.then(function(receipt){
// 当这个 receipt 对象来自于 "contract.deploy({...}).send()" 这么个调用时,它也可以是一个新合约实例
});
// 使用事件触发器
myContract.methods.myMethod(123).send({from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'})
.on('transactionHash', function(hash){
...
})
.on('confirmation', function(confirmationNumber, receipt){
...
})
.on('receipt', function(receipt){
// receipt 相关例子
console.log(receipt);
> {
"transactionHash": "0x9fc76417374aa880d4449a1f7f31ec597f00b1f6f3dd2d66f4c9c6c445836d8b",
"transactionIndex": 0,
"blockHash": "0xef95f2f1ed3ca60b048b4bf67cde2195961e0bba6f70bcbea9a2c4e133e34b46",
"blockNumber": 3,
"contractAddress": "0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe",
"cumulativeGasUsed": 314159,
"gasUsed": 30234,
"events": {
"MyEvent": {
returnValues: {
myIndexedParam: 20,
myOtherIndexedParam: '0x123456789...',
myNonIndexParam: 'My String'
},
raw: {
data: '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385',
topics: ['0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7', '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385']
},
event: 'MyEvent',
signature: '0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7',
logIndex: 0,
transactionIndex: 0,
transactionHash: '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385',
blockHash: '0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7',
blockNumber: 1234,
address: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'
},
"MyOtherEvent": {
...
},
"MyMultipleEvent":[{...}, {...}] // 如果同一事件有多个,则它们将被组装到数组中
}
}
})
.on('error', function(error, receipt) { // 如果交易被网络拒绝并带有交易收据,则第二个参数将是交易收据。
...
});
本文实例3:调用智能合约方法,改变状态
var Web3= require('web3');
var web3= new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
var contractAddress = "0xb43938511C10A242dce4f5C110c54fBB51f5bd28"; //智能合约地址
var accountsAddress = "0x38D8B866a1ABeBcA20AFC004622F5355EeFEB568";
var contractAbi = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","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":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"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":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initialAmount","type":"uint256"},{"name":"tokenName","type":"string"},{"name":"decimalUnits","type":"uint8"},{"name":"tokenSymbol","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}];
var myContract = new web3.eth.Contract(contractAbi,contractAddress);
// 使用promise
// personal.unlockAccount(eth.accounts[1],password,0)
var toAddress = "0xDa25997b15a6BeA86116942B8Ab69a5620D82284";
myContract.methods.transfer(toAddress,1230000000000).send({from: accountsAddress})
.then(function(receipt){
console.log("receipt:",receipt);
});
/*
receipt: { blockHash:
'0xbec129bb90df90619a19a064826d7baab7d84fd2f4c58a7a767d2e858c5b0c15',
blockNumber: 301107,
contractAddress: null,
cumulativeGasUsed: 54019,
from: '0x38d8b866a1abebca20afc004622f5355eefeb568',
gasUsed: 54019,
logsBloom:
'0x00000000000000000010000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000200000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000200000042000000000000000000000000000000000000000000000000000400000010000000000000000000000000000000000000000000000000000000000000',
status: true,
to: '0xb43938511c10a242dce4f5c110c54fbb51f5bd28',
transactionHash:
'0x5f8850cbc8c21b7b10917777a4c9ebd5cbb0a2e5370d108edb767d0ca44576f1',
transactionIndex: 0,
events:
{ Transfer:
{ address: '0xb43938511C10A242dce4f5C110c54fBB51f5bd28',
blockNumber: 301107,
transactionHash:
'0x5f8850cbc8c21b7b10917777a4c9ebd5cbb0a2e5370d108edb767d0ca44576f1',
transactionIndex: 0,
blockHash:
'0xbec129bb90df90619a19a064826d7baab7d84fd2f4c58a7a767d2e858c5b0c15',
logIndex: 0,
removed: false,
id: 'log_d82a25b4',
returnValues: [Result],
event: 'Transfer',
signature:
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
raw: [Object] } } }
*/
3.6 methods.myMethod.estimateGas
myContract.methods.myMethod([param1[, param2[, ...]]]).estimateGas(options[, callback])
通过在 EVM 中执行方法来估算链上执行是需要的 gas 用量。 由于彼时合约状态的不同,当前估算的 gas 用量和随后通过真实交易所得到的实际 gas 用量可能会有所出入。
参数
-
options
-Object
(可选): 用于调用的选项。
-
from
-String
(可选): 交易发起方地址。 -
gas
-Number
(可选): 交易 gas 用量上限 (gas limit)。设置特定的值有助于检测 gas 耗尽相关错误,gas 耗尽时会返回相同的值。 -
value
- ``Number|String|BN|BigNumber``(可选): 交易转账金额,以 wei 为单位。
-
callback
-Function
(可选): 回调函数,触发时其第二个参数为 gas 估算量,第一个参数为错误对象。
返回值
-
Promise
返回Number
: 估算的 gas 用量
例子
// 使用回调
myContract.methods.myMethod(123).estimateGas({gas: 5000000}, function(error, gasAmount){
if(gasAmount == 5000000)
console.log('Method ran out of gas');
});
// 使用 promise
myContract.methods.myMethod(123).estimateGas({from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'})
.then(function(gasAmount){
...
})
.catch(function(error){
...
});
本文实例4:估算智能合约方法gas用量
var Web3= require('web3');
var web3= new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
var contractAddress = "0xb43938511C10A242dce4f5C110c54fBB51f5bd28"; //智能合约地址
var accountsAddress = "0x38D8B866a1ABeBcA20AFC004622F5355EeFEB568";
var contractAbi = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","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":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"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":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initialAmount","type":"uint256"},{"name":"tokenName","type":"string"},{"name":"decimalUnits","type":"uint8"},{"name":"tokenSymbol","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}];
var myContract = new web3.eth.Contract(contractAbi,contractAddress);
var toAddress = "0xDa25997b15a6BeA86116942B8Ab69a5620D82284";
// 使用 promise
// personal.unlockAccount(eth.accounts[1],password,0)
myContract.methods.transfer(toAddress,1230000000000).estimateGas({from: accountsAddress})
.then(function(gasAmount){
console.log("gasAmount:",gasAmount);
})
.catch(function(error){
console.log("error:",error);
});
/*
gasAmount: 39019
*/
3.7 methods.myMethod.encodeABI
myContract.methods.myMethod([param1[, param2[, ...]]]).encodeABI()
为指定的合约方法进行 ABI 编码,可用于发送交易、调用方法或向另一个合约方法传递参数。
返回值
-
String
: 编码后的 ABI 字节码,可用于交易发送或方法调用。
例子
myContract.methods.myMethod(123).encodeABI();
> '0x58cf5f1000000000000000000000000000000000000000000000000000000000000007B'
本文实例5:对智能合约方法进行 ABI 编码
var Web3= require('web3');
var web3= new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
var contractAddress = "0xb43938511C10A242dce4f5C110c54fBB51f5bd28"; //智能合约地址
var accountsAddress = "0x38D8B866a1ABeBcA20AFC004622F5355EeFEB568";
var contractAbi = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","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":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"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":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initialAmount","type":"uint256"},{"name":"tokenName","type":"string"},{"name":"decimalUnits","type":"uint8"},{"name":"tokenSymbol","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}];
var myContract = new web3.eth.Contract(contractAbi,contractAddress);
var toAddress = "0xDa25997b15a6BeA86116942B8Ab69a5620D82284";
console.log(myContract.methods.transfer(toAddress,1230000000000).encodeABI());
/*
0xa9059cbb000000000000000000000000da25997b15a6bea86116942b8ab69a5620d822840000000000000000000000000000000000000000000000000000011e61b68c00
*/
四、事件
4.1 once
myContract.once(event[, options], callback)
订阅一个事件并在第一次事件触发或错误发生后立即取消订阅。一个事件仅触发一次。
参数
-
event
-String
: 要订阅的合约事件名, 或者用"allEvents"
来订阅所有事件。 -
options
-Object
(可选): 用于部署的选项。
-
filter
-Object
(可选): 按索引参数过滤事件, 例如{filter: {myNumber: [12,13]}}
表示 “myNumber” 为 12 或 13 的所有事件。 -
topics
-Array
(可选): 手动设置事件过滤器的主题。如果提供了过滤器属性和事件签名,则不会自动设置(topic [0])
-
callback
-Function
: 回调函数,触发时把*事件*对象作为第二个参数,错误作为第一个参数。 关于详细事件结构,参见 getPastEvents 返回值 。
例子
myContract.once('MyEvent', {
filter: {myIndexedParam: [20,23], myOtherIndexedParam: '0x123456789...'}, // 使用数组表示 或:比如 20 或 23。
fromBlock: 0
}, function(error, event){ console.log(event); });
// 事件输入的例子
> {
returnValues: {
myIndexedParam: 20,
myOtherIndexedParam: '0x123456789...',
myNonIndexParam: 'My String'
},
raw: {
data: '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385',
topics: ['0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7', '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385']
},
event: 'MyEvent',
signature: '0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7',
logIndex: 0,
transactionIndex: 0,
transactionHash: '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385',
blockHash: '0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7',
blockNumber: 1234,
address: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'
}
4.2 events
myContract.events.MyEvent([options][, callback])
订阅指定的合约事件
参数
-
options
-Object
(可选): 用于部署的选项。
-
filter
-Object
(可选): 按索引参数过滤事件, 例如{filter: {myNumber: [12,13]}}
表示 “myNumber” 为 12 或 13 的所有事件。 -
fromBlock
-Number|String|BN|BigNumber
(可选): 读取从该编号开始的区块中的事件(大于或等于该区块号)。 也可以使用预先定义的区块号,比如"latest"
,"earlist"
,"pending"
,"genesis"
等。 -
topics
-Array
(可选): 手动设置事件过滤器的主题。如果提供了过滤器属性和事件签名,则不会自动设置(topic [0])。
-
callback
-Function
(可选): 回调函数,触发时把*事件*对象作为第二个参数,错误作为第一个参数。
返回值
EventEmitter
: 该事件发生器有以下事件:
-
"data"
返回Object
: 接收到新传入的事件时触发,参数为事件对象。 -
"changed"
返回Object
: 当事件从区块链上移除时触发。 该事件带有额外属性"removed: true"
。 -
"error"
返回Object
: 当订阅中出现错误时触发。 -
"connected"
返回String
: 当订阅成功连接时触发一次。返回订阅 id。
返回的事件 “对象” 结构如下:
-
event
-String
: 事件名称。 -
signature
-String|Null
: 事件签名,如果是匿名事件,其值为null
。 -
address
-String
: 该事件的发源地地址。 -
returnValues
-Object
: 事件返回值, 比如{myVar: 1, myVar2: '0x234...'}
. -
logIndex
-Number
: 事件在区块中的索引位置。 -
transactionIndex
-Number
: 事件所在交易在区块中的索引位置。 -
transactionHash
32 Bytes -String
: 事件所在交易的哈希值。 -
blockHash
32 Bytes -String
: 事件所在区块链的哈希值。区块处于 pending 状态时其值为null
。 -
blockNumber
-Number
: 事件所在区块的区块号。 区块处于 pending 状态时其值为null
。 -
raw.data
-String
: 包含未索引的日志参数。 -
raw.topics
-Array
: 最大可保存 4 个 32 字节长的主题数组,主题 1-3 包含事件的索引参数。
例子
myContract.events.MyEvent({
filter: {myIndexedParam: [20,23], myOtherIndexedParam: '0x123456789...'}, // 使用数组表示 或:如 20 或 23。
fromBlock: 0
}, function(error, event){ console.log(event); })
.on("connected", function(subscriptionId){
console.log(subscriptionId);
})
.on('data', function(event){
console.log(event); // 与上述可选的回调结果相同
})
.on('changed', function(event){
// 从本地数据库中删除事件
})
.on('error', function(error, receipt) { // 如果交易被网络拒绝并带有交易收据,第二个参数将是交易收据。
...
});
// 事件输出例子
> {
returnValues: {
myIndexedParam: 20,
myOtherIndexedParam: '0x123456789...',
myNonIndexParam: 'My String'
},
raw: {
data: '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385',
topics: ['0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7', '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385']
},
event: 'MyEvent',
signature: '0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7',
logIndex: 0,
transactionIndex: 0,
transactionHash: '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385',
blockHash: '0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7',
blockNumber: 1234,
address: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'
}
4.3 events.allEvents
myContract.events.allEvents([options][, callback])
和 事件 相同,只是会接收合约的所有事件。 过滤属性可以选择性地过滤这些事件。
4.4 getPastEvents
myContract.getPastEvents(event[, options][, callback])
读取合约历史事件。
参数
-
event
-String
: 合约事件名,或者用"allEvents"
读取所有事件。 -
options
-Object
(可选): 用于部署的选项。
-
filter
-Object
(可选): 按索引参数过滤事件, 例如{filter: {myNumber: [12,13]}}
表示 “myNumber” 为 12 或 13 的所有事件。 -
fromBlock
-Number|String|BN|BigNumber
(可选): 读取从该编号开始的区块中的历史事件(大于或等于该区块号)。 也可以使用预先定义的区块编号,比如"latest"
,"earlist"
,"pending"
,"genesis"
。 -
toBlock
-Number|String|BN|BigNumber
(可选): 读取截止到该编号的区块中的历史事件(小于或等于该区块号)(默认值为 “latest”)。 也可以使用预先定义的区块编号,比如"latest"
,"earlist"
,"pending"
,"genesis"
。 -
topics
-Array
(可选): 用来手动设置事件过滤器的主题。如果设置了 filter 属性和事件签名,则不会自动设置(topic [0])。
-
callback
-Function
(可选): 回调函数,触发时其第一个参数为错误对象,第二个参数为历史事件日志数组。
返回值
-
Promise
返回Array
: 满足给定事件或过滤条件的历史事件对象数组。 - 对于返回的事件对象结构,参见 getPastEvents 返回值。
例子
myContract.getPastEvents('MyEvent', {
filter: {myIndexedParam: [20,23], myOtherIndexedParam: '0x123456789...'}, // 使用数组表示 或:如 20 或 23。
fromBlock: 0,
toBlock: 'latest'
}, function(error, events){ console.log(events); })
.then(function(events){
console.log(events) // 与上述可选回调结果相同
});
> [{
returnValues: {
myIndexedParam: 20,
myOtherIndexedParam: '0x123456789...',
myNonIndexParam: 'My String'
},
raw: {
data: '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385',
topics: ['0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7', '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385']
},
event: 'MyEvent',
signature: '0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7',
logIndex: 0,
transactionIndex: 0,
transactionHash: '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385',
blockHash: '0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7',
blockNumber: 1234,
address: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'
},{
...
}]
四、本文智能合约源码
请注意:本合约仅用于测试。
pragma solidity ^0.4.18;
/**
* Math operations with safety checks
*/
contract SafeMath {
function safeMul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
function safeDiv(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0);
uint256 c = a / b;
require(a == b * c + a % b);
return c;
}
function safeSub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
return a - b;
}
function safeAdd(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c>=a && c>=b);
return c;
}
}
contract Token is SafeMath{
function balanceOf(address _owner) public constant returns (uint256 balance);
function transfer(address _to, uint256 _value) public returns (bool success);
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
function approve(address _spender, uint256 _value) public returns (bool success);
function allowance(address _owner, address _spender) public constant returns (uint256 remaining);
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
contract TokenTEST is Token {
uint256 public totalSupply;
string public name;
uint8 public decimals;
string public symbol;
address public owner;
/* This creates an array with all balances */
mapping (address => uint256) balances;
mapping (address => mapping (address => uint256)) allowed;
function TokenTEST(uint256 initialAmount, string tokenName, uint8 decimalUnits, string tokenSymbol) public {
totalSupply = SafeMath.safeMul(initialAmount , 10 ** uint256(decimalUnits));
balances[msg.sender] = totalSupply;
Transfer(address(0), msg.sender, totalSupply);
name = tokenName;
decimals = decimalUnits;
symbol = tokenSymbol;
owner = msg.sender;
}
/* Send tokens */
function transfer(address _to, uint256 _value) public returns (bool success) {
require(_to != address(0));
require(_to != msg.sender);
require(_value >= 0);
require(balances[msg.sender] >= _value);
require(balances[_to] + _value >= balances[_to]);
balances[msg.sender] = SafeMath.safeSub(balances[msg.sender], _value); // Subtract from the sender
balances[_to] = SafeMath.safeAdd(balances[_to], _value);
Transfer(msg.sender, _to, _value);
return true;
}
/* A contract attempts to get the tokens */
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
require(_to != address(0));
require(_to != _from);
require(_value >= 0);
require(_value <= balances[_from]); // Check if the sender has enough
require(_value <= allowed[_from][msg.sender]); // Check allowance
require(balances[_to] + _value >= balances[_to]); // Check for overflows
balances[_from] = SafeMath.safeSub(balances[_from], _value); // Subtract from the sender
balances[_to] = SafeMath.safeAdd(balances[_to], _value); // Add the same to the recipient
allowed[_from][msg.sender] = SafeMath.safeSub(allowed[_from][msg.sender], _value);
Transfer(_from, _to, _value);
return true;
}
function balanceOf(address _owner) public constant returns (uint256 balance) {
return balances[_owner];
}
/* Allow another contract to spend some tokens in your behalf */
function approve(address _spender, uint256 _value) public returns (bool success) {
//require((_value == 0) || (allowed[msg.sender][_spender] == 0));
allowed[msg.sender][_spender] = _value;
Approval(msg.sender, _spender, _value);
return true;
}
function allowance(address _owner, address _spender) public constant returns (uint256 remaining) {
return allowed[_owner][_spender];
}
// only owner can kill
function kill() {
require(msg.sender == owner);
selfdestruct(owner);
}
}