I am running f
:
contract Test {
function f() {
f();
}
}
which produces VM Exception: invalid opcode
in browser-solidity. Is that a bug or expected behavior?
Seems to be a bug in the ethereumjs-vm that browser-solidity uses via universal-dapp.js.
runCode.js has odd code...
function iterateVm (done) {
if (runState.stack.length > 1024) {
return done(ERROR.INVALID_OPCODE)
}
...because the stack length is different from the depth, which is checked against the 1024 (value of fees.stackLimit.v) in opFns.js:
// increment the runState.depth
callOptions.depth = runState.depth + 1
if (runState.depth >= fees.stackLimit.v ...
If the stack length check is correct, it could at least return a different that would avoid confusing the depth limit error with an invalid opcode.
Note: the following code is an internal function call that's "translated into simple jumps inside the EVM". This means that the stack depth will not increase.
contract Test {
function f() {
f();
}
}
An external function call is needed to increase the stack depth, use this.f()
. Explicitly labelling the function as external
(or public
) also improves clarity.
contract Test {
function f() external {
this.f();
}
}
Furthermore, the EIP150 hardfork has made breaching the stack depth practically impossible (since all gas would be exhausted first):
Supersede the "hard limit" max call stack depth with a softer limit, where creating a deep call tower would require an exponentially growing amount of gas. This completely removes call stack depth limit attacks as a category of issue that contract developers should have to worry about...
contract Test {
function f() {
f();
}
}
it will provoke an infinite recursive call. So it is not a solidity browser bug.
try something like :
contract C {
function g(uint a) returns (uint ret) { return f(); }
function f() returns (uint ret) { return g(7) + f(); }
}
These function calls are translated into simple jumps inside the EVM.
Edit : the error is generated by a stack-length of 1024 so the compiler could no more jump to the destination (every f() call performs a Jump to Jumpdest).
74 JUMPDEST
75 PUSH 50
77 PUSH 4a
79 JUMP
every recursive call (..=>97=>74=>97...) 0X50 is added to the stack until we reach the stake limit length then the error jumps out. This error will be fired while the contract has enough remaining gas (so no outOfGas exception).
outOfGas
or stackDepth
exception. Why invalid opcode
? A simple jump shouldnt be an invalid opcode.
Commented
Nov 5, 2016 at 23:30