Error: VM Exception while processing transaction: revert
Error: VM Exception while processing transaction: invalid opcode
Error: VM Exception while processing transaction: out of gas
I got this error! What do I do????
Unfortunately, this error is incredibly generic and unhelpful. You have two options:
Panic
Don't Panic
out of gas
errors!You're either not sending enough gas or are hitting the block gas limit. Estimate your gas requirement with estimateGas()
. If it's about equal to the block gas limit, it either requires too much gas to fit in a block or is using up all of the gas you provide it because of an error, which we can debug below.
Does your contract just need too much gas to deploy? Try splitting your deployment into multiple transactions.
If you're using solc directly, use the --optimize --runs=1
parameters via the docs.
If you're using truffle, configure the optimizer in truffle.js
with solc: { optimizer: { enabled: true, runs: 200 } }
Are you using a helper library like web3.js or a library like truffle that uses web3.js? Each individual call may have a self-imposed gas limit on it; make sure your truffle.js
config sets a gas limit vaguely equal to the chain you're deploying to.
Using a library like web3.js directly? It may not be estimating gas for you at all. Try the brute force approach below to see if that's the issue.
If you're running on a test net, you can employ the "brute force" approach of "just send as much gas as possible" and see if that was your issue. Try myContract.myMethod(..., { gas: 8000000 })
and see if it works. If it does, your gas estimation or gas limit is definitely wrong somewhere. If that didn't fix your problem, you're either going above the block gas limit or running into one of the problems below.
Are you using hella strings? Honestly you might just be using too much gas; strings can be silenty very expensive.
"revert" or "invalid opcode"
You're probably failing a require()
block in the code path executed by your constructor. Make sure all of your input arguments are absolutely correct!
Deploying a crowdsale? Make sure your opening and closing times pass the required checks. Your start time needs to be at least a few blocks ahead of when you deploy, otherwise you'll fail the require(openingTime > block.timestamp)
condition because the time your contract is actually deployed is pretty random.
You could also be running into authorization issues, discussed below.
"revert"
The bad news is that literally anything could have gone wrong here. All it means is that a REVERT
opcode was issued somewhere along the way. No, you don't get a stack trace. Using truffle or web3.js? No, you don't get to know which transaction caused the issue, since those are handled asynchronously and the stack traces have 0 context and are completely useless. Oh, you're using truffle? You get a special, minified, entirely garbage stack trace that is of no use to anyone in the conceivable universe.
The good news is that it was probably a require()
block somewhere, so you can start tracking that down.
If you're running a suite of transactions and don't know which transaction caused the error, either step-though each rpc call as it happens or do the 'ole printf
debugging approach where you put console.log('1.')
in between each rpc call, allowing you to see which one fails.
Now that you've narrowed down which call is the problem, mentally evaluate the code, given the inputs you're sending to the contract. Go over things like:
You can check to see how much gas was consumed to estimate where in the code path your transaction failed. Only used ~21,000 gas? You probably hit a modifier like onlyOwner
that stopped your transaction in its tracks.
You can also just start commenting-out code that might be the problem and see when the execution actually succeeds! Binary search is your friend here 😉.
Are you working with ether or tokens? You may have mixed up your units somewhere. Unless there's a specific reason, all storage and math relating to currencies should be done in the smallest amount of that currency. This means your contract should only accept wei in its arguments. If you're doing token math, you might have mixed up 1 TKNbit
with 1 TKN
. A TKNbit
is the smallest unit of your token; if your decimals are 18, 1 TKN = 10^18 TKNbits
.
Well first, if you can't solve this one yourself you probably shouldn't be working on a crowdsale. don't @ me
That said, let's debug it! Is the buyTokens()
function failing? Your problem is probably one of these:
MintableToken
or it does not pass hasMintingPermission
RefundVault
"invalid opcode"
You're not any better off with this error, so consider taking "Option 1: Panic" above. This error means that an invlid opcode was produced in your contract, and the EVM has no idea what to do with it. So it bails, and it bails hard.
This error could be from an assert()
failure within your code path; check those first.
Make sure you're not accessing an array out-of-bounds! If you're using dynamically sized arrays, a common mistake is to myArray[newIndex] = value
before you've manually allocated that space by doing myArray.length++
. Using myArray.push(value)
does this behind the scenes.
Well, the only thing someone else is going to do is look over your code and do the exact same thing we went through above, but a second pair of eyes is always helpful.
If you're going to ask for help in a forum, you must include your entire source code, including the script by which you call your contracts. Don't cherry-pick things you think are the problem; just post the code!
And for the love of all that is holy, don't just say "please help???" and never respond to questions from community members asking for clarification.
Yup! In solidity 0.4.22, the ability to specify an error message was added. It looks like require(something, "something didn't happen!")
.
For now, this extra return information isn't really supported by tooling like web3.js and friends. So, uh, just sit tight there, yeah? Or maybe open a PR against your favorite libraries!
Also, follow the EIP 1066: Status Codes as it develops.