如何解决为什么我不能在 Solidity 中更改合约状态?
我在测试中遇到问题,似乎表明 solidity 无法更改合约存储变量的值。
这是在 JavaScript 中的测试:
const Mystery = artifacts.require ("Mystery");
contract ("Mystery",async accounts => {
it ("Incrementing performs as intended",async () => {
const subject = await Mystery.deployed ();
const firstValue = (await subject.returnAndIncrement.call ()).toNumber ();
const secondValue = (await subject.returnAndIncrement.call ()).toNumber ();
const thirdValue = (await subject.returnAndIncrement.call ()).toNumber ();
assert.equal (
[firstValue,secondValue,thirdValue],[100,101,102]
);
});
});
pragma solidity >=0.4.22 <0.9.0;
contract Mystery {
uint32 private currentValue = 100;
function returnAndIncrement () public returns (uint32 value) {
value = currentValue;
currentValue = currentValue + 1;
return value;
}
}
这里是测试运行器输出的相关部分:
Contract: Mystery
1) Incrementing performs as intended
> No events were emitted
0 passing (993ms)
1 failing
1) Contract: Mystery
Incrementing performs as intended:
AssertionError: expected [ 100,100,100 ] to equal [ 100,102 ]
+ expected - actual
[
100
- 100
- 100
+ 101
+ 102
]
at Context.it (test/TestMystery.js:12:16)
at process._tickCallback (internal/process/next_tick.js:68:7)
我的第一个想法是存在某种竞争条件:在它们中的任何一个有机会增加初始值之前,所有三个调用都在获取初始值。但是我的阅读表明以太坊将操作序列化,因此您无法在单个合约中进行竞争。此外,我尝试在对 returnAndIncrement()
的调用之间插入 5 秒的暂停,以试图打破任何现有的比赛,但对结果没有影响。
我的第二个想法是我的测试配置存在根本性的错误,所以不管实际发生了什么,我都只是得到零。所以我从 100 而不是 0 开始 currentValue
,如上所示;这不是问题。
我的第三个想法是,当我认为我正在将 currentValue
的值复制到 value
中时,我实际上在做的是使 value
成为对 { 值的引用{1}},所以当我增加 currentValue
时,我也在增加 currentValue
。但如果是这样的话,我会得到 value
而不是 [101,102,103]
。
解决方法
要更改智能合约的状态,您需要发送交易而不是调用。
变化:
subject.returnAndIncrement.call ()
致:
subject.returnAndIncrement.send({..}) // you can pass options such gas,account ..
有关详细信息,请查看 web3js doc
但是send交易的返回值并不是你要找的值,你可能需要查看日志才能得到值;
,你的赋值有点混乱,阅读代码注释:
uint32 private currentValue = 100;
function returnAndIncrement () public returns (uint32 value) {
// 1. memory variable `value` is now 100
value = currentValue;
// 2. storage variable `currentValue` is now 101
currentValue = currentValue + 1;
// 3. you're returning the `value` from memory (which has value 100)
return value;
}
根据上下文猜测,您可能希望从存储中返回递增的值。
最简单的方法是:
uint32 private currentValue = 100;
function returnAndIncrement () public returns (uint32) {
currentValue++;
return currentValue;
}
编辑:或者一点 Solidity 魔法。 :) 这实际上具有稍微便宜的 gas 成本(28432 与上面示例中的 29284 相对),因为对(昂贵的)存储的访问较少。
uint32 private currentValue = 100;
function returnAndIncrement () public returns (uint32 value) {
value = ++currentValue;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。