I now understand how a wallet or web3 call can determine if a transaction will succeed or fails.
The answer was buried in the Vitalik Buterin's blog post about Merkling in Ethereum.
If you want to query ethereum for -
"Pretend to run this transaction on this contract. What would the output be?"
Ethereum uses three different types of Merkle trees-
For responding to the above query , ethereum uses the state tree by constructing a Merkle state transition proof.
To Quote Vitalik -
Essentially, it is a proof which make the claim “if you run
transaction T on the state with root S, the result will be a state
with root S', with log L and output O” (“output” exists as a concept
in Ethereum because every transaction is a function call; it is not
To compute the proof, the server locally creates a fake block, sets
the state to S, and pretends to be a light client while applying the
transaction. That is, if the process of applying the transaction
requires the client to determine the balance of an account, the light
client makes a balance query. If the light client needs to check a
particular item in the storage of a particular contract, the light
client makes a query for that, and so on. The server “responds” to all
of its own queries correctly, but keeps track of all the data that it
sends back. The server then sends the client the combined data from
all of these requests as a proof. The client then undertakes the exact
same procedure, but using the provided proof as its database; if its
result is the same as what the server claims, then the client accepts
So, how does an Ethereum wallet know that your transaction is going to fail?
It applies the state transition mechanism your function call either fell short of gas or threw an error or failed a required condition.