This is really a two part question.
First, the only way I can get the error message thrown by a Smart Contract require
statement is to call the function first with a call
rather than a send
. send
does not return the message thrown by a failed require
statement whereas call
does.
Example. In Solidity I might have the following:
require (org._isUser(_user),'Error: User not registered');
In my React frontend I want to be able to display 'Error: User not registered'.
My function call in React is as follows:
async function createPO(e) {
e.preventDefault()
const poeacct = e.target.elements[0].value
const ponumber = e.target.elements[1].value
const podate = e.target.elements[2].value
let callOK = true
try {
await contract2.methods
.createOrder('0xd2c4895e24095f23277df168f94a6c035813fe5d', poeacct, ponumber, podate)
.call({ from: accounts[0] })
} catch (err) {
callOK = false
setMess(err.message)
console.log(err)
}
if (callOK) {
await contract2.methods
.createOrder('0xd2c4895e24095f23277df168f94a6c035813fe5d', poeacct, ponumber, podate)
.send({ from: accounts[0] })
setpouAcct(pouacct)
setpoeAcct(poeacct)
setpoNumber(ponumber)
setpoDate(podate)
setMess('Transaction successful')
}
}
This works but it's kind of klugey so I'm wondering if there's a better way.
Second. The error returned by the 'catch' in the Web3 call is JSON but there's a prefix:
Error: [object Object]
{
"message": "VM Exception while processing transaction: revert Error: Order already exists",
"code": -32000,
"data": {
"0x270bb8ddea630f3fc42a4f6196d7710cc50779a34994fd534a8ce139976b0ef5": {
"error": "revert",
"program_counter": 21219,
"return": "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001b4572726f723a204f7264657220616c7265616479206578697374730000000000",
"reason": "Error: Order already exists"
}
The Error: [object Object]
prefix prevents me from parsing out the 'reason:' node. If I remove the prefix manually (i.e. hard code it) it works.
I've tried substring
,slice
and JSON.parse etc. but I can't find a solution.
Best Answer
Similar to JuliSmz answer, but I wasn't comfortable with the magic 56 character string position as I was worried it would be brittle. I wrote this little function which takes the error object returned by the
catch