Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gas estimation for CREATE opcodes with l64 rule gives incorrect results. #8

Open
jnaviask opened this issue Jan 13, 2021 · 1 comment

Comments

@jnaviask
Copy link

jnaviask commented Jan 13, 2021

I've been benchmarking gas usage and was having trouble with a contract that makes a CREATE call internally -- the gas estimation came out far higher than expected. The results I was getting were similar to here: polkadot-evm/frontier#252 (comment)

And to clarify, by l64 I mean the protocol defined here, to pass gas into subcontracts: ethereum/EIPs#150

Investigation shows the following cost occurring in the gasometer at l64 time:

2021-01-13 15:26:24.970  TRACE        http.worker20 evm:Running opcode: Err(Create), Pre gas-left: 4294945964    
2021-01-13 15:26:24.970  TRACE        http.worker20 evm:Opcode costs: memory_gas: 36, gas_cost: 32000, total used gas: 231    
2021-01-13 15:26:24.970  TRACE        http.worker20 evm:Recording l64 cost: 67108030    
2021-01-13 15:26:24.971  TRACE        http.worker20 evm:Running opcode: Ok(Push(1)), Pre gas-left: 4227805934    

I note that the l64 cost is approximately equal to the amount of gas remaining / 64. My suspicion is that, because the gasometer runs the code with a MAX_U256 starting gas, the l64 calls are being improperly estimated when compared with the amount of starting gas used in practice. Note that this starting gas comes from the following line in frontier: https://github.com/paritytech/frontier/blob/master/client/rpc/src/eth.rs#L760, but should theoretically be unneeded for the purposes of estimation.


If useful, here is the entire contract I've been using for testing, specifically the spawn() call on the CreateContract.

As a quick point of comparison, the gas estimate I get with EIP-150 enabled is 67227213, but if I set call_l64_after_gas: false in the config, I instead get 119183 -- much closer if not exactly the amount of gas used when the call is actually executed.

pragma solidity ^0.5.0;

contract SubContract {
  constructor() public payable { }
  function getAddress() external view returns (address ownAddress) {
    return address(this);
  }

  function getValue() external view returns (uint) {
    return address(this).balance;
  }
}

contract CreateContract {
  address public deployed;

  constructor() public { }

  function spawn() external returns (SubContract subAddress) {
    SubContract result = new SubContract();
    deployed = address(result);
    return result;
  }

  function spawnWithValue() external payable returns (SubContract subAddress) {
    SubContract result = (new SubContract).value(msg.value)();
    deployed = address(result);
    return result;
  }
}
@crystalin
Copy link
Contributor

@sorpaas This is what I think is happening:

See https://github.com/rust-blockchain/evm/blob/master/src/executor/stack/mod.rs#L322 where the 64th is recorded as a cost.

Do you have an idea how to solve it ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants