从 JavaScript 调用智能合约
在本教程中,我们将了解如何从 JavaScript 调用智能合约函数。首先是读取智能合约的状态(例如,ERC-20 持有者的余额),然后我们将通过进行代币转账来修改区块链的状态。你应该已经熟悉设置 JS 环境以与区块链进行交互。
在这个示例中,我们将使用 DAI 代币,出于测试目的,我们将使用 ganache-cli 分叉区块链,并解锁一个已经拥有大量 DAI 的地址:
ganache-cli -f https://mainnet.infura.io/v3/[YOUR INFURA KEY] -d -i 66 1 --unlock 0x4d10ae710Bd8D1C31bd7465c8CBC3add6F279E81
要与智能合约进行交互,我们需要它的地址和 ABI:
const ERC20TransferABI = [
{
constant: false,
inputs: [
{
name: "_to",
type: "address",
},
{
name: "_value",
type: "uint256",
},
],
name: "transfer",
outputs: [
{
name: "",
type: "bool",
},
],
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",
},
]
const DAI_ADDRESS = "0x6b175474e89094c44da98b954eedeac495271d0f"
对于这个项目,我们精简了完整的 ERC-20 ABI,只保留了 balanceOf 和 transfer 函数,但你可以在这里找到完整的 ERC-20 ABI (opens in a new tab)。
然后我们需要实例化我们的智能合约:
const web3 = new Web3("http://localhost:8545")
const daiToken = new web3.eth.Contract(ERC20TransferABI, DAI_ADDRESS)
我们还将设置两个地址:
- 接收转账的地址,以及
- 我们已经解锁的发送转账的地址:
const senderAddress = "0x4d10ae710Bd8D1C31bd7465c8CBC3add6F279E81"
const receiverAddress = "0x19dE91Af973F404EDF5B4c093983a7c6E3EC8ccE"
在下一部分中,我们将调用 balanceOf 函数来检索这两个地址当前持有的代币数量。
调用 (Call):从智能合约读取值
第一个示例将调用一个“常量 (constant)”方法,并在 EVM 中执行其智能合约方法,而无需发送任何交易。为此,我们将读取一个地址的 ERC-20 余额。阅读我们关于 ERC-20 代币的文章。
你可以通过以下方式访问你为其提供了 ABI 的已实例化智能合约方法:yourContract.methods.methodname。通过使用 call 函数,你将收到执行该函数的结果。
daiToken.methods.balanceOf(senderAddress).call(function (err, res) {
if (err) {
console.log("An error occurred", err)
return
}
console.log("The balance is: ", res)
})
请记住,DAI ERC-20 有 18 位小数,这意味着你需要去掉 18 个零才能获得正确的金额。由于 JavaScript 无法处理大数值,因此 uint256 将作为字符串返回。如果你不确定如何在 JS 中处理大数,请查看我们关于 bignumber.js 的教程 (opens in a new tab)。
发送 (Send):向智能合约函数发送交易
对于第二个示例,我们将调用 DAI 智能合约的转账 (transfer) 函数,向我们的第二个地址发送 10 个 DAI。转账函数接受两个参数:接收者地址和要转账的代币数量:
daiToken.methods
.transfer(receiverAddress, "100000000000000000000")
.send({ from: senderAddress }, function (err, res) {
if (err) {
console.log("An error occurred", err)
return
}
console.log("Hash of the transaction: " + res)
})
调用函数会返回将被打包到区块链中的交易哈希。在以太坊上,交易哈希是可预测的——这就是为什么我们可以在交易执行之前获取它的哈希(在此处了解哈希是如何计算的 (opens in a new tab))。
由于该函数仅将交易提交到区块链,因此在知道它何时被打包并包含在区块链中之前,我们无法看到结果。在下一个教程中,我们将学习如何通过知道交易的哈希来等待其在区块链上执行 (opens in a new tab)。
页面最后更新: 2026年3月3日