How can I access the value in c?
the number is not only what is contained inside c
but the whole BigNumber notation, which is accessible with a f.toString()
How can I save object f to a javascript variable?
f.toString()
will give you a string, which can be saved into a variable. Same as you can keep it inside the BigNumber
object and use the .toString
to access to a readable value
Since I am saving an array of arrays, can I get the length of the Promise object?
this question doesn't make sense given the answers above, that kind of structure is the internal representation of the number stored into the BigNumber
object
TLDR;
Similar to this issue here , use .call
after the function name. Then it works out!
const newLimit = await contract.setAllowance.call(kid1, value); // the .call() is the fix
Edit: (adding more details in the line of @GoodVibration's comments)
setAllowance
is a non-constant call, which means it modifies contract state in some way. constant
was used in older solidity code, which in modern versions are indicated via view
(only reads state) or pure
(no read from, or write to contract state).
When we invoke such a non-constant method, we will only get the transaction response as the return value, irrespective of what return value we might have coded in (in this case, uint256
). Thus, we have two options:
- use
.call
: this sort of "evaluates" the code inside the method, but not cause a transaction to happen, and thus no state change will be persisted. A test case to help explain things better:
it("will set allowance limits to non-zero within the scope of the method", async () => {
try {
const value = web3.utils.toWei("0.2");
// https://ethereum.stackexchange.com/a/90342/22522
const newLimit = await contract.setAllowance.call(accounts[1], value);
assert.equal(value, newLimit); // we get a return value
} catch (err) {
console.log("error:\n", err);
assert(false);
}
});
it("proves that above call does not persist state change", async () => {
const allowance = await contract.getAllowance(kid1);
assert.equal(allowance, 0); // allowance did not change at all!!
});
- Invoke the method, and use Events for testing: when we write
await contract.method(... args)
, that method
is actually invoked, transaction goes through mining, and events are fired. While this is great, it will always return a Tx object as response, and not the return type you coded. As such you need to assert on the events that gets fired. something like this:
// smart contract
event AllowanceChange(address user, uint256 oldLimit, string delta, uint256 newLimit);
...
function setAllowance(address user, uint256 amount) external onlyOwner nonReentrant returns (uint256) {
allowance[user] = amount;
emit AllowanceChange(user, amount, "set", allowance[user]);
return allowance[user];
}
// Truffle JS Test
const value = web3.utils.toWei("0.2");
const result = await contract.setAllowance(accounts[1], value);
truffleAssert.eventEmitted(
result,
"AllowanceLimitChange",
(ev) => ev.newLimit.toString() === value,
"Allowance Change event should be triggered"
);
Best Answer
Well, I spent the day to figure it out.
To correct this behavior, it is necessary to define the method of interaction with the function. This works well after adding a “call” to a function. Solution in js code: