require(_calldatasToEMInDeployed.length == _returnDataForCodeContractInDeployed.length, "Invalid behavior requested for mock code contract: mismatch between number of calldata batches and returndata for post-deployment behavior.");
// Note: this function is the only way that the opcodes REVERT, CALLER, EXTCODESIZE, ADDRESS can appear in a code contract which passes SafetyChecker.isBytecodeSafe().
// The static analysis enforces that the EXACT functionality below is implemented by comparing to a reference bytestring.
function doSafeExecutionManagerCall(argOff, argLen, retOffset, retLen) {
let success := call(gas(), caller(), 0, argOff, argLen, retOffset, retLen)
- "creator" does ovmCREATE -> invalid jumpdest -> creator out-of-gasses (or at least, appears to--really it will revert with no data, so there will be some gas left)
- "creator" does ovmCREATE -> initcode does ovmCREATE -> invalid jumpdest -> creator out-of-gasses (or at least, appears to--really it will revert with no data, so there will be some gas left) AKA same as above but nested CREATEs
- OVM gas metering
- do everything for both queue origins/flip flopped roles:
- blocks transactions whose gas limit would put the cumulative gas over the max for the current epoch
- starts a new epoch and allows tx through if the above would have held true, but new epoch has begun
- allows transaction through queue B even if queue A cumulative gas would have blocked it
- out of gas
- ovmCALL -> [ovmCALL(gas()/2) -> out of gas] -> SSTORE (does not out of gas parent)
- State access limiting logic
- ovmCALL(gas()/2) -> ovmCALL(gas()) -> out of gas -> return(someVal) -> SSTORE(someVal)
- this one shows that if a subcall out-of-gasses, but you do not do any further state accesses, then you can still return, and if your parent has a bigger allocation left, they can still ovmSSTORE
- ovmSSTORE, repeated max times, ovmCALL(gas()) -> ovmSSTORE -> fails (even though max gas allotment was given, the parent already used them up)
- ovmCALL(gas/2) -> ovmCREATE, out of gas -> SSTORE succeeds
- ovmCALL(gas) -> ovmCREATE, out of gas -> SSTORE fails
- ovmCALL(gas) -> ovmCREATE, ovmREVERT (in init) -> SSTORE succeeds