A bug on opcode CALL
chenjiaweiprimeledger opened this issue · 2 comments
When I executed ethereumj with a solidity program, I found that the requred gas is greater than left gas, throwing an exception.
org.ethereum.vm.VM#step
DataWord gasLeft = program.getGas().clone();
gasLeft.sub(new DataWord(gasCost));
adjustedCallGas = **blockchainConfig.getCallGas(op, callGasWord, gasLeft)**;
gasCost += adjustedCallGas.longValueSafe();
for example:
program.getGas()=100
gasCost=40
callGasWord comes from stack, it is 100 when call is contract call, and 0 when call is transfer. transfer is OK, but for contract call callGasWord is 100, gasLeft is 60, blockchainConfig.getCallGas will throw the exception.
The input is
gasLeft = 100; // gas left for the rest of the program execution
callGas = 100; // amount of gas that underlying call should be supplied with
The steps are
gasLeft = 100 - 40; // gasLeft is reduced by 40gas, the CALL price
if (callGas > gasLeft) throw; // program throws, cause there is not enough gas to supply underlying call
Isn't it a correct behavior?
The input is
gasLeft = 100; // gas left for the rest of the program execution callGas = 100; // amount of gas that underlying call should be supplied with
The steps are
gasLeft = 100 - 40; // gasLeft is reduced by 40gas, the CALL price if (callGas > gasLeft) throw; // program throws, cause there is not enough gas to supply underlying call
Isn't it a correct behavior?
It's a correct behavior, but not a correct logic.
Comment on BlockchainConfig.getCallGas()
says:
Calculates available gas to be passed for callee Since EIP150
But i'm afraid it's not implemented in AbstractConfig.getCallGas()
, try this:
public DataWord getCallGas(OpCode op, DataWord requestedGas, DataWord availableGas) throws Program.OutOfGasException {
// modify to apply eip150
// if (requestedGas.compareTo(availableGas) > 0) {
// throw Program.Exception.notEnoughOpGas(op, requestedGas, availableGas);
// }
// return requestedGas;
return availableGas.sub(availableGas.div(DataWord.of(64)));
}