How to detect a transaction that will fail in web3js - ethereum

I've just recently finished working on a rather complex contract with the Remix IDE. I'm now attaching web3 to the frontend but when I call functions that should fail, they still go through on Metamask.
When testing my contract in Remix, I would often click on and call certain functions that had require statements that I knew would fail just to confirm that the contract state was recorded correctly. Remix didn't send the transaction to metamask and instead output an error message and I would like to handle the transaction error on my own as well.
How can I check my contract call to see whether it will fail. Must I use the method that predicts gas and detect it that way and if so how? My current code is below:
contract.callFunction(function(error, result) {
if (!error) alert(result);
else alert(error);
}
The above code catches rejecting the metamask confirmation as an error but transactions that should fail go through to metamask with an insanely high gas limit set. The function callFunction is in the contract and takes no parameters but does have an effect on the blockchain so it requires the transaction. The first line of the function is "require(state == 1);" and I have the contract set to state 2 currently so I'm expecting the transaction to fail, I just want to detect it failing.

In order to find out whether the transaction will fail we do have to call estimateGas() and attach a callback function. I assumed we'd have to check the gas estimate returned in order to predict whether it would fail but the process is made rather easy. Here's the full code I ended up with to successfully run a function while catching the two most common error cases.
contract.nextState.estimateGas(function(error, result) {
if (!error) {
contract.nextState(function(error, result) {
if (!error) {
alert("This is my value: " + result);
} else {
if (error.message.indexOf("User denied") != -1) {
alert("You rejected the transaction on Metamask!");
} else {
alert(error);
}
}
});
} else {
alert("This function cannot be run at this time.");
}
});
[EDIT] I'm coming back after the fact to help clear up information for those with a similar question. All of the information discussed below references the following link.
After creating a contract object, you can access any variable or function through using it's name. You can also access these members through array notation which is useful when the name of the variable or function isn't known at the time the code is written.
contract.foobar == contract["foobar"]
Once you have a function object (contract.foobar) you can use either call, send, or estimateGas. After first giving the function the parameters it needs (call it like any other function) you then use either call, send, or estimateGas on the returned object while providing options and a callback function.
This callback function takes 2 parameters. The first is the error which will be undefined if there was no error, and the second will be the result of the call, send, or estimateGas. Call and Send will both return the result of the function while estimateGas always returns a number showing how much gas is estimated to be necessary.

Related

Contract functionA call contract functionB ,and functionA can storage value

I have a problem about handle function value.
likes the title ..
I already know contract's function call other contract's function depend on:
addr.call(abi.encodeWithSignature("function(parameter_type)", parameter ));
but what if I want to handle the function's value(ex:bool) temporarily (memory) for condition .
I had seen abi.encodePacked() , but I don't even know what parameter feedback to me (compile error , different parameter type), that I can't even storage it .
Some articles write it only for bytes, uint , but I only want to do condition(bool).
You don't need to do that .call unless you want to preserve the msg.sender.
If the msg.sender does not matter for you, I recommend you to look at interfaces. Now, what you have to do, is to create an interface with the functionB definition of that you want to call, and then call it.
Example:
(some deployed contract)
contract MySecondContract {
function functionB() public returns(bool) {
return true;
}
}
(get the deployed contract address and use it in your code like)
interface IMySecondContract {
function functionB() external returns(bool);
}
contract MyFirstContract {
function functionA() public returns(bool) {
bool result = IMySecondContract(MySecondContract-address-here).functionB();
return result;
}
}
If you do want to keep using .call, here you can see that the .call method returns two values.
Something like
(bool success, bytes myReturn) = addr.call(...);
and then this, might work.
Something else that might help is this new way of debugging.

Where in the ECMAScript specification is the return value from the await expression indicated?

I recently tried to figure out how promises works in ECMAScript. Most interested in the construction of AwaitExpression. In my opinion, it is the most incomprehensible and rather complicated in the specification.
Let me give some code:
/// Promise
var promiseA = new Promise((resolve, reject) => {
setTimeout(() => resolve("Done!"), 10000)
});
/// Async/Await
(async function(){
var result = await promiseA;
console.log(result); /// Output: "Done!"
})();
/// Promise.prototype.then
promiseA.then(function (result){
console.log(result); /// Output: "Done!"
});
For me, as I said above, AwaitExpression is incomprehensible, I do not understand where the return of the value from promise is going. But I understand where the value from [[PromiseResult]] comes from and how the value [[PromiseResult]] from .then is passed into the argument to the callback function.
And there are some steps that unfortunately are not clear to me from Await ():
Remove asyncContext from the execution context stack and restore the execution context that is at the top of the execution context
stack as the running execution context.
Set the code evaluation state of asyncContext such that when evaluation is resumed with a Completion completion, the following
steps of the algorithm that invoked Await will be performed, with
completion available.
Return.
NOTE: This returns to the evaluation of the operation that had most previously resumed evaluation of asyncContext.
And part of the actions from the Await Fulfilled Functions is still not quite clear:
Resume the suspended evaluation of asyncContext using NormalCompletion(value) as the result of the operation that suspended
it.
Assert: When we reach this step, asyncContext has already been removed from the execution context stack and prevContext is the
currently running execution context.
Return undefined.
P.S How Promise and .then are executed is clear to me, you can take this into account when explaining AwaitExpression.
I think the critical thing to keep in mind when reading this is that the spec is free to start and stop execution of a given function right in the middle. When that happens, the function literally stops exactly where it is, but the spec steps keep going.
Given your example
(async function(){
var result = await promiseA;
console.log(result); /// Output: "Done!"
})();
in spec terms, this functions becomes:
Call the async function [[Call]]
Do the normal prep work that function has
OrdinaryCallEvaluateBody
EvaluateBody for async functions
Create the promise that gets returned by the async function
AsyncFunctionStart
Initialize the promise object that gets returned
Mark the execution context such that, when it fully completes, it will fulfill or reject the promise.
Start executing the steps of the function, one at a time
Eventually we get to the await and do:
Using the awaited promise, set it up so that the async function will resume execution when the promise finishes. (Step 2-9)
"pop the execution context" which marks what step we were in the function, so that it can be started again later. (Step 10 in your quote)
Set a flag on the execution context saying "the function is suspended, when it resumes, you will get the result of a promise, please resume the function as if the promise result was the completion value of the 'await'. (Step 11)
Return. (Step 12).
Return the promise for the async fn result.
The core thing to understand, is that Step 12 is not returning into the async function, because it was suspended. It is returning to AsyncFunctionStart, which then returns to EvaluateBody, which then returns the Promise result of the async function.
Then, later when the promiseA fulfills (due to the work of step 2-9 earlier)
Set the async function as the active execution context again (Step 5 of "Await Fulfilled Functions")
Resume execution with the result of the promise as the "completion" (Step 6). Because of the flags set on Step 11, this uses the completion value as the result of the await, and picks up execution of the async function until it returns, or awaits again.
Assert that the async function has finished some work for now (Step 7)
Return. (Step 8)
It's the part
using NormalCompletion(value) as the result of the operation that suspended it.
from the text you quoted. It will resume the execution of the async function, and make the await expression have the value as the result. Compare the yield operation and the generator next() method for reference.

Error when interacting with smart contract

I deployed following contract in remix.ethereum
0x932FC462d97e23E9fe8d5a1F085d9D611B892666
and hooked it up to my UI at
https://tewkenbak.github.io/tewken/ (this is a contract for testing)
Following things happened
1) in remix.ethereum i wasnt able to compile the contract - no errors
2) i was able to deploy the contract to the mainnet
3) the contract doesnt give me any errors when interacting with it at
https://etherscan.io/address/0x932fc462d97e23e9fe8d5a1f085d9d611b892666#writeContract
4) when I try to interact with contract through my UI - above link i get following Error
the same time I get NO error message in the console
UPDATE
I just checked your source code, looks like you gave the wrong method name here and some other places:
if (walletMode === 'metamask') {
contract.buy(masternode, {
value: convertEthToWei(amount)
}, function (e, r) {
console.log(e, r)
})
}
there is no buy function in the contract.
You gave the wrong abi, since there is no function named buy in your smart contract.

Ethereum web3js method call fail

I have a simple solidity smart contract with method like:
function foo(uint a) public {
b = bytes32(1);
emit Event(a, b);
emit Event2(a, b);
}
(full code is here: https://remix.ethereum.org/#optimize=false&version=soljson-v0.4.25+commit.59dbf8f1.js)
and invoke it using web3.js code :
contract = testContract.at('xxxAddress')
// contract.foo(6); // Failed, Why?
//Success
contract.foo.sendTransaction(6, {from: eth.accounts[1]},function(error, result) {
console.log("Got err:", error, ", result: ", result)
}
);
but, why straightforward contract.foo(6) failed? Can any expert explain it?
The call to a function that modifies the blockchain needs to send as a transaction since it requires gas to run. This is why you need to send a transaction and not just call the function. You can find more about it here.

why do i need 2 parameters for callback?

i have a simlple asynchronious reader in a node-script reading firefox-json-bookmarks.
when i remove the first parameter (err) in the callback function, i got an error.
what is the reason? And why is err different from e?
app.js
var fs = require('fs'), obj;
fs.readFile(__dirname + '/bookmarks.json', 'utf8', handleFile);
function handleFile( err, data ) { // why is the first parameter needed?
try {
obj = JSON.parse( JSON.stringify(data) );
console.log(obj);
} catch (e) {
console.log(e);
//console.log(err);
}
}
Each time you call a function, that function is pushed onto a stack of functions known as the call stack. When that function returns a value, it is popped off the stack. The call stack describes where you are in your program and how you got there.
Synchronous Code
Imagine the call stack through out the course of this program.
function a() { return b() }
function b() { return c() }
function c() { throw new Error() }
a();
First, a is called, so we add it to the stack.
[ a ]
Then a calls b, so we add that to the stack too.
[ a, b ]
Then b calls c.
[ a, b, c ]
Then c throws an error. At this point, the debugger can tell you that c was the function that threw the error and that you ended up at c, via a then b. This works fine for regular synchronous code, like JSON.parse.
Asynchronous Code
Asynchronous code continues to run after the function has returned. For instance:
function a() {
setTimeout(function() { console.log(2); }, 10000);
return 1;
}
If you call a, then it will be pushed onto the call stack, then return 1 and be popped off the call stack. About 10 seconds later 2 will be printed into the console.
What would happen if the timeout did this instead?
function a() {
setTimeout(function() { throw new Error(); }, 10000);
return 1;
}
The error would be thrown, but the call stack would be empty. As you can imagine, this isn't very useful for developers.
This is also a problem if we want to return a value asynchronously. By the time the async stuff happens (timeout, read/write, network etc), the function has already returned.
Instead, we can use a form of what's known as Continuation-Passing Style, mostly referred to as callbacks. As well as calling our asynchronous function, we also pass it function (a continuation), which we ask it to run when it has finished. Remember, this can be after the function has returned a value!
In Node.js, these callbacks serve two purposes:
Errors
If an error occurs whilst doing the asynchronous work, standard practice is to call the callback with the error as the first argument. You'll often see the following code.
foo.doAsyncBar(function(err, baz) {
if(err) throw err;
// do something with baz
});
By passing the error the callback rather than throwing it, we are able to make our own decisions about how best to handle it. We can just throw it, as shown above, or we can handle it in a more graceful way.
Return
Hopefully, the function won't error, in which case, the general practice is to pass null as the first argument to the callback. This lets the developer writing the handling code know that the function didn't error and that the return value is in one of the next arguments.
For a more in depth article on Node.js error handling, see Joyent's Production Practices document for Errors.