You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.
I've asked for help in the Truffle Gitter before filing this issue.
Issue
If a view fails require() with a reason, the reason isn't available in the error. In other words, in a catch(err) block, err.reason is always undefined if a view failed. If the Solidity code passed a reason in the require() that failed, then err.reason should be the reason from Solidity.
Steps to Reproduce
Create a Solidity smart contract with a view.
Have a statement of the form require(cond, "ThisShouldFail") in the view.
In JS, call the view inside a try / catch block. Use view arguments such that cond evaluates to false.
In the catch(err) block, err.reason is undefined.
Here's an example:
$ truffle test
Compiling your contracts...
===========================
> Compiling ./contracts/Migrations.sol
> Compiling ./contracts/ReasonTest.sol
Contract: ReasonTest
current_value(): <BN: 5>
Fail require() in a transaction:
err.reason: TooSmall
Fail require() in a view:
err.reason: undefined
✓ Demonstrate the bug (89ms)
1 passing (106ms)
$ cat contracts/ReasonTest.sol
pragma solidity >=0.4.21 <0.6.0;
/**
* A simple smart contract that holds a value which decreases by 10.
*/
contract ReasonTest
{
uint public value;
constructor(uint initial_value) public
{
value = initial_value;
}
function current_value() public view
returns (uint)
{
return value;
}
function next_value() public view
returns (uint)
{
require( value >= 10, "TooSmall" );
return value-10;
}
function update_value() public
returns (uint)
{
require( value >= 10, "TooSmall" );
value -= 10;
return value;
}
}
$ cat test/reason.js
const ReasonTest = artifacts.require("ReasonTest");
contract("ReasonTest", function(accounts)
{
it( "Demonstrate the bug",
async function()
{
let instance = await ReasonTest.deployed();
// Print out current_value(), we see it's smaller than 10, so require(value <= 10) should fail
console.log("current_value():", await instance.current_value());
// When require() fails in a transaction, we get err.reason as expected (in Truffle 5)
console.log("Fail require() in a transaction:");
try
{
await instance.update_value();
}
catch(err)
{
console.log("err.reason:", err.reason);
}
// When require() fails in a view, err.reason is not available
console.log("Fail require() in a view:");
try
{
await instance.next_value();
}
catch(err)
{
console.log("err.reason:", err.reason);
}
});
});
Expected Behavior
Output of above-given files should be:
Fail require() in a transaction:
err.reason: TooSmall
Fail require() in a view:
err.reason: TooSmall
Actual Results
Output actually is:
Fail require() in a transaction:
err.reason: TooSmall
Fail require() in a view:
err.reason: undefined
Environment
I think only Truffle version is relevant to this situation. It is:
@theoretical2019 Yes thanks again for such a good report! I found the bug, for calls Truffle was not getting the reason. I'll open up a PR for this and hopefully we'll get it released next week!
@theoretical2019 So we figured out what was going on with this issue. So it turns out that for sends, Truffle receives the status of the transaction through the receipt data I believe. This is how Truffle can tell whether it was successful or reverted. With calls (which would occur in the situation where a function declared view) there is no status information and thus Truffle won't be able to tell if it "fails" a requires conditions. We decided it might be dangerous to not replicate this behavior and so decided to leave it as it is for now.
Check out the conversation in the closed PR above (PR #2340) if you would like to see what was discussed. Thanks again for opening this though!
Issue
If a view fails
require()
with a reason, the reason isn't available in the error. In other words, in acatch(err)
block,err.reason
is alwaysundefined
if a view failed. If the Solidity code passed a reason in therequire()
that failed, thenerr.reason
should be the reason from Solidity.Steps to Reproduce
require(cond, "ThisShouldFail")
in the view.try
/catch
block. Use view arguments such thatcond
evaluates tofalse
.catch(err)
block,err.reason
isundefined
.Here's an example:
Expected Behavior
Output of above-given files should be:
Actual Results
Output actually is:
Environment
I think only Truffle version is relevant to this situation. It is:
I'm using Truffle's built-in Ethereum environment (no external Geth / Parity / Ganache / etc.)
Here's details of the external environment just in case it matters:
The text was updated successfully, but these errors were encountered: