Web3js 调用和 truffle 调用行为不同
Posted
技术标签:
【中文标题】Web3js 调用和 truffle 调用行为不同【英文标题】:Web3js invocation and truffle invocation behaving differently 【发布时间】:2021-02-28 08:20:39 【问题描述】:我有一份看起来像这样的合同 -
contract Calculator
uint public result;
constructor() public
result = 777; //note the initial value
function add(uint a, uint b) public returns (uint, address)
result = a + b;
return (result, msg.sender);
当我在 truffle 上调用函数时,我得到了正确的交易 -
truffle(development)> await calculator.add(5,11)
tx: '0xa66e94bb28810bb2a861c97ee149718afa599d47b7b1c6e55743ea657fdeef56',
receipt:
transactionHash: '0xa66e94bb28810bb2a861c97ee149718afa599d47b7b1c6e55743ea657fdeef56',
transactionIndex: 0,
blockHash: '0x6ae4e3ce65f1e177c419306a50662ed46f40c729a6a18ede028b07e63dd12f61',
blockNumber: 6,
from: '0x5d88950b52f89ad66906fc263e8c35ddacff04d4',
to: '0x7c8beb382c70cbf12b41fd4e5d74cfee53fdc391',
gasUsed: 26074,
cumulativeGasUsed: 26074,
contractAddress: null,
logs: [ [Object] ],
status: true,
logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000200000000000000000000000000000000000000',
rawLogs: [ [Object] ]
,
logs: [
logIndex: 0,
transactionIndex: 0,
transactionHash: '0xa66e94bb28810bb2a861c97ee149718afa599d47b7b1c6e55743ea657fdeef56',
blockHash: '0x6ae4e3ce65f1e177c419306a50662ed46f40c729a6a18ede028b07e63dd12f61',
blockNumber: 6,
address: '0x7C8beb382C70CbF12b41fd4e5d74CfEe53FDc391',
type: 'mined',
id: 'log_28a5e84f',
event: 'Added',
args: [Result]
]
我正在像这样使用 Web3js 调用相同的函数 -
const Web3 = require("web3");
const CalculatorContract = require("../build/contracts/Calculator.json");
let web3 = new Web3(new Web3.providers.WebsocketProvider("ws://127.0.0.1:7545"));
async sendTransaction ()
let accounts = await web3.eth.getAccounts();
let contractAddress = "0x7C8beb382C70CbF12b41fd4e5d74CfEe53FDc391";
let calculatorContract = new web3.eth.Contract(CalculatorContract.abi, contractAddress);
console.log("Calculator adding: ", await calculatorContract.methods.add(11, 88).call(
from: '0x38e3614A5Cf95f0DBb858D9E3752Ac477DA70ccD'
));
console.log("Calculator result: ", await calculatorContract.methods.result().call());
当我调用上述函数时,我会得到这样的输出 -
Calculator adding: Result 0: '99', 1: '0x5d88950b52F89AD66906fC263E8C35DdacFf04D4'
Calculator result: 777 //why 777? the last invocation should rewrite 777 to 99
现在我的问题是 -
-
为什么 truffle 调用正在创建事务,但 Web3js 调用没有创建任何事务?我怎样才能使它们的行为相同?
使用 truffle 调用时(我的意思是返回事务时),如何获取方法调用的返回值?
软件版本:
truffle(development)> truffle version
Truffle v5.1.51 (core: 5.1.51)
Solidity v0.5.16 (solc-js)
Node v15.1.0
Web3.js v1.2.9
Ganache: 2.5.4
Nodejs: v15.1.0
Web3js: ^1.3.0
【问题讨论】:
【参考方案1】:Web3.js 合约对象与 Truffle 合约对象不同。结构略有不同,当然,因为都是无类型的 javascript,你不知道输入或输出函数会有什么。
Historically, Ethereum transactions did not have return values。 Web3.js 行为早于这次,可能不支持直接返回交易值。但是 EIP 1288 记录了返回值如何通过 getTransactionReceipt()
和 receipt
对象获得。
要让 Web3.js 修改 EVM 状态,您需要使用 send()
而不是 call()
。这是另一个弱类型问题,因为不应混淆视图和编写函数。
试试:
console.log("Calculator adding: ", await calculatorContract.methods.add(11, 88).send(
from: '0x38e3614A5Cf95f0DBb858D9E3752Ac477DA70ccD'
));
解决 Truffle 和 Web3.js 之间的差异。解决行为差异的最简单方法是根本不使用 Truffle 工件,而是在任何地方使用 Web3.js 合约。
附言。我推荐 OpenZeppelin SDK (Node.js / TypeScript) 而不是 Truffle。使用 TypeScript 输入更加理智,也可以用作前端和后端代码中的 Web3.js 替代品。或者使用 Python 和 Web3.py 甚至更好,因为如果您能负担得起切换语言的费用,它们会为您的问题中的猜谜游戏留下更少的空间。
【讨论】:
感谢您的评论。但是让我们把松露放在一边,我仍然很困惑为什么从 web3js 调用add(11, 88)
并没有持久化结果?我的意思是如果我调用result()
(这是一个为result
公共变量自动生成的getter函数),它返回默认值777,而不是99。关于SDK和语言,在我的web3代码中,我没有使用任何松露相关库。它唯一的 web3js。而且我不是 Python 人,而是 Java 和 Nodejs 人。
非常感谢。不是send()
是低级方法,linksuggested
是要避免,而是建议使用transfer()
?
你把事情搞混了。当您的问题在 JavaScript 中时,您指的是 Solidity 文档。它们是两种不同的编程语言和两种不同的运行时环境。以上是关于Web3js 调用和 truffle 调用行为不同的主要内容,如果未能解决你的问题,请参考以下文章
使用 web3js 和 galanche 调用具有价值的以太坊智能合约
使用 Trezor(硬件钱包)将签名交易发送到 Ropsten 或 Truffle 开发网络