Commit b1c90b74 authored by Kelvin Fichter's avatar Kelvin Fichter

Got EM tests updated to latest framework

parent 82390b3a
......@@ -487,8 +487,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
bytes memory _returndata
)
{
console.log("ovmCALL to");
console.logAddress(_address);
// CALL updates the CALLER and ADDRESS.
MessageContext memory nextMessageContext = messageContext;
nextMessageContext.ovmCALLER = nextMessageContext.ovmADDRESS;
......@@ -729,9 +727,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
override
public
{
console.log("in safecreate with nuisance gas:");
console.log(messageRecord.nuisanceGasLeft);
// Since this function is public, anyone can attempt to directly call it. We need to make
// sure that the OVM_ExecutionManager itself is the only party that can actually try to
// call this function.
......@@ -773,7 +768,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
// left over since contract calls can only be passed 63/64ths of total gas, so we need to
// explicitly handle this case here.
if (ethAddress == address(0)) {
console.log("detected the create exception");
_revertWithFlag(RevertFlag.CREATE_EXCEPTION);
}
......@@ -820,8 +814,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
address _created
)
{
console.log("createContract with addy");
console.logAddress(_contractAddress);
// We always update the nonce of the creating account, even if the creation fails.
_setAccountNonce(ovmADDRESS(), 1);
......@@ -876,8 +868,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
bytes memory _returndata
)
{
console.log("_callContract with nuisance gas:");
console.log(messageRecord.nuisanceGasLeft);
return _handleExternalInteraction(
_nextMessageContext,
_gasLimit,
......@@ -910,8 +900,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
bytes memory _returndata
)
{
console.log("starting _handleExternalInteraction with gasLeft");
console.log(gasleft());
// We need to switch over to our next message context for the duration of this call.
MessageContext memory prevMessageContext = messageContext;
_switchMessageContext(prevMessageContext, _nextMessageContext);
......@@ -948,9 +936,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
bytes memory returndataFromFlag
) = _decodeRevertData(returndata);
console.log("unsuccessfull safecreate with nuisance gas left post-revert:");
console.log(nuisanceGasLeftPostRevert);
// INVALID_STATE_ACCESS is the only flag that triggers an immediate abort of the
// parent EVM message. This behavior is necessary because INVALID_STATE_ACCESS must
// halt any further transaction execution that could impact the execution result.
......@@ -1175,7 +1160,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
)
internal
{
console.log("checking account load");
// See `_checkContractStorageLoad` for more information.
if (gasleft() < MIN_GAS_FOR_INVALID_STATE_ACCESS) {
_revertWithFlag(RevertFlag.OUT_OF_GAS);
......@@ -1195,14 +1179,10 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
// If we hadn't already loaded the account, then we'll need to charge "nuisance gas" based
// on the size of the contract code.
if (_wasAccountAlreadyLoaded == false) {
console.log("was not already loaded");
_useNuisanceGas(
(Lib_EthUtils.getCodeSize(_getAccountEthAddress(_address)) * NUISANCE_GAS_PER_CONTRACT_BYTE) + MIN_NUISANCE_GAS_PER_CONTRACT
);
console.log("got code size:");
console.log(Lib_EthUtils.getCodeSize(_getAccountEthAddress(_address)));
}
console.log("was already loaded");
}
/**
......@@ -1386,8 +1366,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
}
// ABI decode the incoming data.
console.log("raw revert data:");
console.logBytes(_revertdata);
return abi.decode(_revertdata, (RevertFlag, uint256, uint256, bytes));
}
......@@ -1436,7 +1414,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
)
internal
{
console.log("reverting with no info other than flag");
_revertWithFlag(_flag, bytes(''));
}
......@@ -1474,8 +1451,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
)
internal
{
console.log("using nuisance gas of amount:");
console.log(_amount);
// Essentially the same as a standard OUT_OF_GAS, except we also retain a record of the gas
// refund to be given at the end of the transaction.
if (messageRecord.nuisanceGasLeft < _amount) {
......@@ -1680,8 +1655,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
)
internal
{
console.log("setting number to:");
console.log(_transaction.number);
transactionContext.ovmTIMESTAMP = _transaction.timestamp;
transactionContext.ovmNUMBER = _transaction.number;
transactionContext.ovmTXGASLIMIT = _transaction.gasLimit;
......
......@@ -376,10 +376,7 @@ contract OVM_StateManager is iOVM_StateManager {
// storage because writing to zero when the actual value is nonzero causes a gas
// discrepancy. Could be moved into a new `putVerifiedContractStorage` function, or
// something along those lines.
if (
verifiedContractStorage[_contract][_key] == false
&& accounts[_contract].isFresh == false
) {
if (verifiedContractStorage[_contract][_key] == false) {
verifiedContractStorage[_contract][_key] = true;
}
}
......@@ -401,6 +398,15 @@ contract OVM_StateManager is iOVM_StateManager {
bytes32 _value
)
{
// Storage XOR system doesn't work for newly created contracts that haven't set this
// storage slot value yet.
if (
verifiedContractStorage[_contract][_key] == false
&& accounts[_contract].isFresh
) {
return bytes32(0);
}
// See `putContractStorage` for more information about the XOR here.
return contractStorage[_contract][_key] ^ STORAGE_XOR_VALUE;
}
......
......@@ -10,9 +10,24 @@ import { Lib_RLPReader } from "../rlp/Lib_RLPReader.sol";
*/
library Lib_OVMCodec {
/*******************
* Data Structures *
*******************/
/*********
* Enums *
*********/
enum EOASignatureType {
ETH_SIGNED_MESSAGE,
NATIVE_TRANSACTON
}
enum QueueOrigin {
SEQUENCER_QUEUE,
L1TOL2_QUEUE
}
/***********
* Structs *
***********/
struct Account {
uint256 nonce;
......@@ -43,11 +58,6 @@ library Lib_OVMCodec {
bytes32[] siblings;
}
enum QueueOrigin {
SEQUENCER_QUEUE,
L1TOL2_QUEUE
}
struct Transaction {
uint256 timestamp;
uint256 number;
......@@ -78,11 +88,6 @@ library Lib_OVMCodec {
bytes data;
}
enum EOASignatureType {
ETH_SIGNED_MESSAGE,
NATIVE_TRANSACTON
}
/*********************************************
* Internal Functions: Encoding and Decoding *
......
# Execution Managager Integration/State Tests
## General notes
- run everything below with invalid state accesses automatically and assert invalid state access handled in ALL cases
- run everything below through a state manager proxy which consumes a different amount of gas and check that the **OVM** gas values are not different
## Test Cases
- CALL-types
- for all: call an undeployed contract and make sure it errors or whatevs (or maybe that's just a unit test)
ALL DONE - ovmCALL
- -> ovmCALLER
- -> ovmADDRESS
- -> SLOAD
- -> SSTORE
- -> CREATE/2
ALL DONE - ovmSTATICCALL
- -> ovmCALLER
- -> ovmADDRESS
- -> SLOAD
- -> SSTORE (fail)
- -> CREATE/2 (fail)
- -> ovmCALL -> ovmSSTORE
- -> ovmCALL -> ovmCREATE
- -> ovmSTATICCALL -> RETURN -> SSTORE (fails)
- ovmDELEGATECALL
DONE - -> ovmCALLER
DONE - -> ovmADDRESS
DONE - -> SLOAD
DONE - -> SSTORE
DONE - -> CREATE/2
DONE - -> ovmDELEGATECALL -> ovmCALLER
DONE - -> ovmDELEGATECALL -> ovmADDRESS
DONE - -> ovmDELEGATECALL -> ovmCREATE
- Code-related
- TODO: fill this in
- CREATE-types
- do we just duplicate these exactly for CREATE and CREATE2? Probably
DONE - ovmCREATE -> success -> ovmEXTCODE{SIZE,HASH,COPY}
DONE - ovmCREATE -> fail (ovmREVERT, NOT out of gas/invalid jump) -> ovmEXTCODE{SIZE,HASH,COPY}
- ovmCREATE -> fail -> ovmCALL what was attempted to be created (fail)
- ovmCREATE -> ovmCREATE (during constructor) -> success -> success (check right address for inner deployment)
DONE - ovmCREATE -> ovmCALL(in constructor) -> ovmSSTORE, return -> ovmREVERT (deployment fails, storage not modified, but state access gas correctly increased)
DONE - ovmCREATE -> INVALID -> returns 0 address
- ovmCREATE -> ovmCREATE (during constructor) -> success -> fail (outer contract)
- "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
- CREATE collisions: TODO fill in what this needs
- 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)
- ovmCREATE -> ovmCALL(in constructor) -> ovmSSTORE, return -> ovmREVERT (deployment fails, storage not modified, but state access gas correctly increased)
- 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
- ovmCALL(gas) -> ovmCREATE, ovmSSTORE(max times), ovmREVERT -> ovmSSTORE fails (max allocated in reverting CREATE)
- ovmCALL(gas) -> ovmCREATE -> ovmCREATE ovmSSTORE(max times), ovmREVERT -> deploy -> ovmSSTORE fails (propogates through a failed CREATE inside a successful CREATE
- ovmCALL(gas) -> ovmCREATE -> ovmCREATE, ovmSLOAD(max times), inner deploy success -> outer deploy fail -> ovmSSTORE fails (propogates through a successful create inside a failed create)
- ovmCREATE -> ovmCALL, ovmSSTORE (max), return -> ovmSSTORE fails
- ovmCREATE -> ovmCALL(gas/2) -> ovmCREATE, out of gas, call reverts (as if out of gas) -> ovmSSTORE (success in constructor)
- Explicit invalid state access tests
- CALL -> CALL, ISA
- CALL -> CALL, CALL, ISA
DONE - CREATE -> CREATE, ISA
- CREATE -> CREATE -> CREATE ISA
DONE - CREATE -> CALL, ISA
DONE - CALL -> CREATE, ISA
- CALL -> CREATE -> CALL, ISA
- CREATE -> CALL -> CREATE, ISA
\ No newline at end of file
......@@ -20,6 +20,7 @@
"@types/mocha": "^8.0.3",
"@types/node": "^14.6.0",
"assert": "^2.0.0",
"buffer-xor": "^2.0.2",
"chai": "^4.2.0",
"ethereum-waffle": "3.0.0",
"ethers": "5.0.0",
......
......@@ -192,7 +192,7 @@ const test_nuisanceGas: TestDefinition = {
// This is because there is natural gas consumption between the ovmCALL(GAS/2) and ovmCREATE, which allots nuisance gas via _getNuisanceGasLimit.
// This means that the ovmCREATE exception, DOES consumes all nuisance gas allotted, but that allotment
// is less than the full OVM_TX_GAS_LIMIT / 2 which is alloted to the parent ovmCALL.
nuisanceGasLeft: 4603714,
nuisanceGasLeft: 4531286,
},
},
},
......
......@@ -37,6 +37,11 @@ const test_ovmCALL: TestDefinition = {
ethAddress: '0x' + '00'.repeat(20),
},
},
verifiedContractStorage: {
$DUMMY_OVM_ADDRESS_1: {
[NON_NULL_BYTES32]: true
}
}
},
},
parameters: [
......
......@@ -11,11 +11,12 @@ import {
VERIFIED_EMPTY_CONTRACT_HASH,
DUMMY_BYTECODE_BYTELEN,
DUMMY_BYTECODE_HASH,
getStorageXOR
} from '../../../../helpers'
const CREATED_CONTRACT_1 = '0xa1c4ba6fe56bda6db9df39bf45dbfc3cd104bd6f'
const CREATED_CONTRACT_1 = '0x2bda4a99d5be88609d23b1e4ab5d1d34fb1c2feb'
const CREATED_CONTRACT_2 = '0x2bda4a99d5be88609d23b1e4ab5d1d34fb1c2feb'
const NESTED_CREATED_CONTRACT = '0xb99a3d1d1e3f0bd867570da4776221c1b0b74ea3'
const NESTED_CREATED_CONTRACT = '0xcb964b3f4162a0d4f5c997b40e19da5a546bc36f'
const DUMMY_REVERT_DATA =
'0xdeadbeef1e5420deadbeef1e5420deadbeef1e5420deadbeef1e5420deadbeef1e5420'
......@@ -53,7 +54,15 @@ const test_ovmCREATE: TestDefinition = {
ethAddress: '0x' + '00'.repeat(20),
},
},
contractStorage: {
$DUMMY_OVM_ADDRESS_2: {
[NULL_BYTES32]: getStorageXOR(NULL_BYTES32),
},
},
verifiedContractStorage: {
$DUMMY_OVM_ADDRESS_1: {
[NON_NULL_BYTES32]: true,
},
$DUMMY_OVM_ADDRESS_2: {
[NULL_BYTES32]: true,
},
......
......@@ -51,6 +51,11 @@ const test_ovmDELEGATECALL: TestDefinition = {
ethAddress: '0x' + '00'.repeat(20),
},
},
verifiedContractStorage: {
$DUMMY_OVM_ADDRESS_1: {
[NON_NULL_BYTES32]: true
}
}
},
},
parameters: [
......
/* Internal Imports */
import {
runExecutionManagerTest,
ExecutionManagerTestRunner,
TestDefinition,
OVM_TX_GAS_LIMIT,
NULL_BYTES32,
NON_NULL_BYTES32,
REVERT_FLAGS,
DUMMY_BYTECODE,
} from '../../../../helpers'
const test_ovmREVERT: TestDefinition = {
name: 'basic ovmREVERT unit tests',
name: 'Basic tests for ovmREVERT',
preState: {
ExecutionManager: {
ovmStateManager: '$OVM_STATE_MANAGER',
......@@ -31,34 +29,30 @@ const test_ovmREVERT: TestDefinition = {
},
parameters: [
{
name: 'ovmREVERT inside ovmCALL should cause EM to revert',
parameters: [
{
name: 'ovmCALL => ovmREVERT',
steps: [
{
functionName: 'ovmCALL',
functionParams: [
OVM_TX_GAS_LIMIT / 2,
'$DUMMY_OVM_ADDRESS_1',
[
functionParams: {
gasLimit: OVM_TX_GAS_LIMIT / 2,
target: '$DUMMY_OVM_ADDRESS_1',
subSteps: [
{
functionName: 'ovmREVERT',
functionParams: ['0xdeadbeef'],
revertData: '0xdeadbeef',
expectedReturnStatus: false,
expectedReturnValues: [
REVERT_FLAGS.INTENTIONAL_REVERT,
'0xdeadbeef',
OVM_TX_GAS_LIMIT / 2,
0,
],
expectedReturnValue: {
flag: REVERT_FLAGS.INTENTIONAL_REVERT,
data: '0xdeadbeef',
nuisanceGasLeft: OVM_TX_GAS_LIMIT / 2,
ovmGasRefund: 0,
},
],
],
expectedReturnStatus: true,
expectedReturnValues: [],
},
],
},
expectedReturnStatus: false,
expectedReturnValue: '0xdeadbeef'
},
],
},
// TODO: fix this. only way to do it is manually set up and call ovmREVERT directly inside a context which mirrors that during creation.
......@@ -103,4 +97,5 @@ const test_ovmREVERT: TestDefinition = {
],
}
runExecutionManagerTest(test_ovmREVERT)
const runner = new ExecutionManagerTestRunner()
runner.run(test_ovmREVERT)
/* Internal Imports */
import {
runExecutionManagerTest,
ExecutionManagerTestRunner,
TestDefinition,
OVM_TX_GAS_LIMIT,
NULL_BYTES32,
NON_NULL_BYTES32,
REVERT_FLAGS,
DUMMY_BYTECODE,
getStorageXOR,
} from '../../../../helpers'
const test_ovmSLOAD: TestDefinition = {
name:
'External storage manipulation during initcode subcalls should correctly NOT be persisted if ovmREVERTed',
name: 'Basic tests for ovmSLOAD',
preState: {
ExecutionManager: {
ovmStateManager: '$OVM_STATE_MANAGER',
......@@ -32,6 +30,11 @@ const test_ovmSLOAD: TestDefinition = {
ethAddress: '$OVM_CALL_HELPER',
},
},
contractStorage: {
$DUMMY_OVM_ADDRESS_1: {
[NON_NULL_BYTES32]: getStorageXOR(NULL_BYTES32),
},
},
verifiedContractStorage: {
$DUMMY_OVM_ADDRESS_1: {
[NON_NULL_BYTES32]: true,
......@@ -41,27 +44,30 @@ const test_ovmSLOAD: TestDefinition = {
},
parameters: [
{
name: 'ovmCALL => ovmSLOAD',
steps: [
{
functionName: 'ovmCALL',
functionParams: [
OVM_TX_GAS_LIMIT,
'$DUMMY_OVM_ADDRESS_1',
[
functionParams: {
gasLimit: OVM_TX_GAS_LIMIT,
target: '$DUMMY_OVM_ADDRESS_1',
subSteps: [
{
functionName: 'ovmSLOAD',
functionParams: [NON_NULL_BYTES32],
functionParams: {
key: NON_NULL_BYTES32
},
expectedReturnStatus: true,
expectedReturnValues: [NULL_BYTES32],
expectedReturnValue: NULL_BYTES32,
},
],
],
},
expectedReturnStatus: true,
expectedReturnValues: [],
},
],
},
],
}
runExecutionManagerTest(test_ovmSLOAD)
const runner = new ExecutionManagerTestRunner()
runner.run(test_ovmSLOAD)
/* Internal Imports */
import {
runExecutionManagerTest,
ExecutionManagerTestRunner,
TestDefinition,
OVM_TX_GAS_LIMIT,
NULL_BYTES32,
NON_NULL_BYTES32,
REVERT_FLAGS,
DUMMY_BYTECODE,
getStorageXOR,
} from '../../../../helpers'
const test_ovmSTATICCALL: TestDefinition = {
name: 'Basic checks on staticcall',
name: 'Basic tests for ovmSTATICCALL',
preState: {
ExecutionManager: {
ovmStateManager: '$OVM_STATE_MANAGER',
......@@ -30,9 +31,24 @@ const test_ovmSTATICCALL: TestDefinition = {
codeHash: NON_NULL_BYTES32,
ethAddress: '$OVM_CALL_HELPER',
},
$DUMMY_OVM_ADDRESS_3: {
codeHash: NON_NULL_BYTES32,
ethAddress: '$OVM_CALL_HELPER',
},
},
contractStorage: {
$DUMMY_OVM_ADDRESS_1: {
[NON_NULL_BYTES32]: getStorageXOR(NULL_BYTES32),
},
$DUMMY_OVM_ADDRESS_3: {
[NON_NULL_BYTES32]: getStorageXOR(NULL_BYTES32),
},
},
verifiedContractStorage: {
$DUMMY_OVM_ADDRESS_2: {
$DUMMY_OVM_ADDRESS_1: {
[NON_NULL_BYTES32]: true,
},
$DUMMY_OVM_ADDRESS_3: {
[NON_NULL_BYTES32]: true,
},
},
......@@ -40,255 +56,285 @@ const test_ovmSTATICCALL: TestDefinition = {
},
parameters: [
{
name: 'ovmSTATICCALL => ovmSSTORE',
steps: [
{
functionName: 'ovmCALL',
functionParams: [
OVM_TX_GAS_LIMIT,
'$DUMMY_OVM_ADDRESS_1',
[
{
functionName: 'ovmSTATICCALL',
functionParams: [
OVM_TX_GAS_LIMIT / 2,
'$DUMMY_OVM_ADDRESS_2',
[
functionParams: {
gasLimit: OVM_TX_GAS_LIMIT / 2,
target: '$DUMMY_OVM_ADDRESS_1',
subSteps: [
{
functionName: 'ovmSSTORE',
functionParams: [NULL_BYTES32, NULL_BYTES32],
expectedReturnStatus: false,
expectedReturnValues: [
REVERT_FLAGS.STATIC_VIOLATION,
'0x',
OVM_TX_GAS_LIMIT / 2,
0,
],
functionParams: {
key: NULL_BYTES32,
value: NULL_BYTES32
},
{
functionName: 'ovmCREATE',
functionParams: [DUMMY_BYTECODE, false, []],
expectedReturnStatus: false,
expectedReturnValues: [
REVERT_FLAGS.STATIC_VIOLATION,
'0x',
OVM_TX_GAS_LIMIT / 2,
0,
],
expectedReturnValue: {
flag: REVERT_FLAGS.STATIC_VIOLATION,
nuisanceGasLeft: OVM_TX_GAS_LIMIT / 2
}
}
]
},
expectedReturnStatus: false
}
]
},
{
name: 'ovmSTATICCALL => ovmSLOAD',
steps: [
{
functionName: 'ovmSTATICCALL',
functionParams: {
gasLimit: OVM_TX_GAS_LIMIT / 2,
target: '$DUMMY_OVM_ADDRESS_1',
subSteps: [
{
functionName: 'ovmSLOAD',
functionParams: [NON_NULL_BYTES32],
expectedReturnStatus: true,
expectedReturnValues: [NULL_BYTES32],
functionParams: {
key: NON_NULL_BYTES32,
},
{
functionName: 'ovmCALLER',
functionParams: [],
expectedReturnStatus: true,
expectedReturnValues: ['$DUMMY_OVM_ADDRESS_1'],
expectedReturnValue: NULL_BYTES32
}
]
},
{
functionName: 'ovmADDRESS',
functionParams: [],
expectedReturnStatus: true,
expectedReturnValues: ['$DUMMY_OVM_ADDRESS_2'],
expectedReturnStatus: true
}
]
},
],
],
expectedReturnStatus: true,
expectedReturnValues: [],
{
name: 'ovmSTATICCALL => ovmCREATE',
steps: [
{
functionName: 'ovmSTATICCALL',
functionParams: {
gasLimit: OVM_TX_GAS_LIMIT / 2,
target: '$DUMMY_OVM_ADDRESS_1',
subSteps: [
{
functionName: 'ovmCREATE',
functionParams: {
bytecode: DUMMY_BYTECODE,
},
],
],
expectedReturnStatus: true,
expectedReturnValues: [],
expectedReturnStatus: false,
expectedReturnValue: {
flag: REVERT_FLAGS.STATIC_VIOLATION,
nuisanceGasLeft: OVM_TX_GAS_LIMIT / 2
}
}
]
},
],
expectedReturnStatus: false
}
]
},
{
name: 'ovmCALL(ADDRESS_1) => ovmSTATICCALL(ADDRESS_2) => ovmCALLER',
steps: [
{
functionName: 'ovmCALL',
functionParams: [
OVM_TX_GAS_LIMIT,
'$DUMMY_OVM_ADDRESS_1',
[
functionParams: {
gasLimit: OVM_TX_GAS_LIMIT / 2,
target: '$DUMMY_OVM_ADDRESS_1',
subSteps: [
{
functionName: 'ovmSTATICCALL',
functionParams: [
OVM_TX_GAS_LIMIT,
'$DUMMY_OVM_ADDRESS_2',
[
{
functionName: 'ovmCALL',
functionParams: [
OVM_TX_GAS_LIMIT,
'$DUMMY_OVM_ADDRESS_2',
[
functionParams: {
gasLimit: OVM_TX_GAS_LIMIT / 2,
target: '$DUMMY_OVM_ADDRESS_2',
subSteps: [
{
functionName: 'ovmSLOAD',
functionParams: [NON_NULL_BYTES32],
expectedReturnStatus: true,
expectedReturnValues: [NULL_BYTES32],
functionName: 'ovmCALLER',
expectedReturnValue: '$DUMMY_OVM_ADDRESS_1'
}
]
},
{
functionName: 'ovmSSTORE',
functionParams: [NULL_BYTES32, NULL_BYTES32],
expectedReturnStatus: false,
expectedReturnValues: [
REVERT_FLAGS.STATIC_VIOLATION,
'0x',
867484476,
2906,
],
expectedReturnStatus: true
}
]
},
{
functionName: 'ovmCREATE',
functionParams: [DUMMY_BYTECODE, false, []],
expectedReturnStatus: false,
expectedReturnValues: [
REVERT_FLAGS.STATIC_VIOLATION,
'0x',
867484476,
2906,
],
},
],
],
expectedReturnStatus: true,
expectedReturnValues: [],
expectedReturnStatus: true
}
]
},
],
],
expectedReturnStatus: true,
expectedReturnValues: [],
{
name: 'ovmCALL(ADDRESS_1) => ovmSTATICCALL(ADDRESS_2) => ovmADDRESS',
steps: [
{
functionName: 'ovmCALL',
functionParams: {
gasLimit: OVM_TX_GAS_LIMIT / 2,
target: '$DUMMY_OVM_ADDRESS_1',
subSteps: [
{
functionName: 'ovmSTATICCALL',
functionParams: {
gasLimit: OVM_TX_GAS_LIMIT / 2,
target: '$DUMMY_OVM_ADDRESS_2',
subSteps: [
{
functionName: 'ovmADDRESS',
expectedReturnValue: '$DUMMY_OVM_ADDRESS_2'
}
]
},
],
],
expectedReturnStatus: true,
expectedReturnValues: [],
expectedReturnStatus: true
}
]
},
],
expectedReturnStatus: true
}
]
},
{
name: 'ovmCALL(ADDRESS_1) => ovmSTATICCALL(ADDRESS_2) => ovmCALL(ADDRESS_3) => ovmSSTORE',
steps: [
{
functionName: 'ovmCALL',
functionParams: [
OVM_TX_GAS_LIMIT,
'$DUMMY_OVM_ADDRESS_1',
[
functionParams: {
gasLimit: OVM_TX_GAS_LIMIT,
target: '$DUMMY_OVM_ADDRESS_1',
subSteps: [
{
functionName: 'ovmSTATICCALL',
functionParams: [
OVM_TX_GAS_LIMIT / 2,
'$DUMMY_OVM_ADDRESS_2',
[
functionParams: {
gasLimit: OVM_TX_GAS_LIMIT,
target: '$DUMMY_OVM_ADDRESS_2',
subSteps: [
{
functionName: 'ovmSTATICCALL',
functionParams: [
OVM_TX_GAS_LIMIT,
'$DUMMY_OVM_ADDRESS_2',
[],
],
expectedReturnStatus: true,
expectedReturnValues: [],
},
functionName: 'ovmCALL',
functionParams: {
gasLimit: OVM_TX_GAS_LIMIT / 2,
target: '$DUMMY_OVM_ADDRESS_3',
subSteps: [
{
functionName: 'ovmSSTORE',
functionParams: [NULL_BYTES32, NULL_BYTES32],
functionParams: {
key: NULL_BYTES32,
value: NULL_BYTES32
},
expectedReturnStatus: false,
expectedReturnValues: [
REVERT_FLAGS.STATIC_VIOLATION,
'0x',
OVM_TX_GAS_LIMIT / 2,
33806,
],
},
],
],
expectedReturnStatus: true,
expectedReturnValues: [],
expectedReturnValue: {
flag: REVERT_FLAGS.STATIC_VIOLATION,
nuisanceGasLeft: OVM_TX_GAS_LIMIT / 2
}
}
]
},
],
],
expectedReturnStatus: true,
expectedReturnValues: [],
expectedReturnStatus: false,
expectedReturnValue: {
flag: REVERT_FLAGS.STATIC_VIOLATION,
nuisanceGasLeft: OVM_TX_GAS_LIMIT / 2
}
}
]
},
],
expectedReturnStatus: false
}
]
},
expectedReturnStatus: true
}
]
},
{
name: 'ovmCALL(ADDRESS_1) => ovmSTATICCALL(ADDRESS_2) => ovmCALL(ADDRESS_3) => ovmSLOAD',
steps: [
{
functionName: 'ovmCALL',
functionParams: [
OVM_TX_GAS_LIMIT,
'$DUMMY_OVM_ADDRESS_1',
[
{
functionName: 'ovmSTATICCALLToRevert',
functionParams: [
OVM_TX_GAS_LIMIT / 2,
'$DUMMY_OVM_ADDRESS_2',
[
REVERT_FLAGS.STATIC_VIOLATION,
'0x',
OVM_TX_GAS_LIMIT / 2,
0,
],
],
expectedReturnStatus: true,
expectedReturnValues: [false, '0x'],
functionParams: {
gasLimit: OVM_TX_GAS_LIMIT / 2,
target: '$DUMMY_OVM_ADDRESS_1',
subSteps: [
{
functionName: 'ovmSTATICCALL',
functionParams: {
gasLimit: OVM_TX_GAS_LIMIT / 2,
target: '$DUMMY_OVM_ADDRESS_2',
subSteps: [
{
functionName: 'ovmCALL',
functionParams: {
gasLimit: OVM_TX_GAS_LIMIT / 2,
target: '$DUMMY_OVM_ADDRESS_3',
subSteps: [
{
functionName: 'ovmSLOAD',
functionParams: {
key: NON_NULL_BYTES32,
},
],
],
expectedReturnStatus: true,
expectedReturnValues: [],
expectedReturnValue: NULL_BYTES32
}
]
},
],
expectedReturnStatus: true
}
]
},
expectedReturnStatus: true
}
]
},
expectedReturnStatus: true
}
]
},
{
name: 'ovmCALL(ADDRESS_1) => ovmSTATICCALL(ADDRESS_2) => ovmCALL(ADDRESS_3) => ovmCREATE',
steps: [
{
functionName: 'ovmCALL',
functionParams: [
OVM_TX_GAS_LIMIT,
'$DUMMY_OVM_ADDRESS_1',
[
functionParams: {
gasLimit: OVM_TX_GAS_LIMIT,
target: '$DUMMY_OVM_ADDRESS_1',
subSteps: [
{
functionName: 'ovmSTATICCALL',
functionParams: [
OVM_TX_GAS_LIMIT,
'$DUMMY_OVM_ADDRESS_1',
[
{
functionName: 'ovmSTATICCALLToRevert',
functionParams: [
OVM_TX_GAS_LIMIT / 2,
'$DUMMY_OVM_ADDRESS_2',
[
REVERT_FLAGS.STATIC_VIOLATION,
'0x',
OVM_TX_GAS_LIMIT / 2,
0,
],
],
expectedReturnStatus: true,
expectedReturnValues: [false, '0x'],
},
],
],
expectedReturnStatus: true,
expectedReturnValues: [],
},
],
],
expectedReturnStatus: true,
expectedReturnValues: [],
functionParams: {
gasLimit: OVM_TX_GAS_LIMIT,
target: '$DUMMY_OVM_ADDRESS_2',
subSteps: [
{
functionName: 'ovmCALL',
functionParams: {
gasLimit: OVM_TX_GAS_LIMIT / 2,
target: '$DUMMY_OVM_ADDRESS_3',
subSteps: [
{
functionName: 'ovmCREATE',
functionParams: {
bytecode: DUMMY_BYTECODE
},
],
expectedReturnStatus: false,
expectedReturnValue: {
flag: REVERT_FLAGS.STATIC_VIOLATION,
nuisanceGasLeft: OVM_TX_GAS_LIMIT / 2
}
}
]
},
],
expectedReturnStatus: false,
expectedReturnValue: {
flag: REVERT_FLAGS.STATIC_VIOLATION,
nuisanceGasLeft: OVM_TX_GAS_LIMIT / 2
}
}
]
},
expectedReturnStatus: false
}
]
},
expectedReturnStatus: true
}
]
},
]
}
runExecutionManagerTest(test_ovmSTATICCALL)
const runner = new ExecutionManagerTestRunner()
runner.run(test_ovmSTATICCALL)
/* External Imports */
import { ethers } from 'ethers'
import { defaultAccounts } from 'ethereum-waffle'
import xor from 'buffer-xor'
/* Internal Imports */
import { makeHexString, makeAddress } from './utils'
import { makeHexString, makeAddress, fromHexString, toHexString } from './utils'
export const DEFAULT_ACCOUNTS = defaultAccounts
export const DEFAULT_ACCOUNTS_BUIDLER = defaultAccounts.map((account) => {
......@@ -34,3 +35,8 @@ export const NUISANCE_GAS_COSTS = {
// TODO: get this exported/imported somehow in a way that we can do math on it. unfortunately using require('.....artifacts/contract.json') is erroring...
export const Helper_TestRunner_BYTELEN = 3654
export const STORAGE_XOR = '0xfeedfacecafebeeffeedfacecafebeeffeedfacecafebeeffeedfacecafebeef'
export const getStorageXOR = (key: string): string => {
return toHexString(xor(fromHexString(key), fromHexString(STORAGE_XOR)))
}
......@@ -199,7 +199,7 @@ const setContractStorage = async (
const slots = getStorageSlots(layout, obj)
for (const slot of slots) {
contract.__setStorageSlot(slot.hash, slot.value)
await contract.__setStorageSlot(slot.hash, slot.value)
}
}
......@@ -216,7 +216,7 @@ const checkContractStorage = async (
const slots = getStorageSlots(layout, obj)
for (const slot of slots) {
const value = contract.__getStorageSlot(slot.hash)
const value = await contract.__getStorageSlot(slot.hash)
if (value !== slot.value) {
throw new Error(
......
......@@ -27,7 +27,7 @@ import {
isTestStep_EXTCODECOPY,
isTestStep_REVERT,
} from './test.types'
import { encodeRevertData } from '../codec'
import { encodeRevertData, REVERT_FLAGS } from '../codec'
import { getModifiableStorageFactory } from '../storage'
import {
OVM_TX_GAS_LIMIT,
......@@ -263,6 +263,12 @@ export class ExecutionManagerTestRunner {
return false
} else if (isTestStep_Context(step)) {
return true
} else if (isTestStep_CALL(step)) {
if (isRevertFlagError(step.expectedReturnValue) && (step.expectedReturnValue.flag === REVERT_FLAGS.INVALID_STATE_ACCESS || step.expectedReturnValue.flag === REVERT_FLAGS.STATIC_VIOLATION)) {
return step.expectedReturnStatus
} else {
return true
}
} else {
return step.expectedReturnStatus
}
......@@ -329,10 +335,6 @@ export class ExecutionManagerTestRunner {
return '0x'
}
if (isTestStep_REVERT(step)) {
return step.expectedReturnValue || '0x'
}
if (isRevertFlagError(step.expectedReturnValue)) {
return encodeRevertData(
step.expectedReturnValue.flag,
......@@ -342,6 +344,10 @@ export class ExecutionManagerTestRunner {
)
}
if (isTestStep_REVERT(step)) {
return step.expectedReturnValue || '0x'
}
let returnData: any[] = []
if (isTestStep_CALL(step)) {
if (step.expectedReturnValue === '0x00') {
......
......@@ -34,7 +34,7 @@ interface TestStep_REVERT {
functionName: 'ovmREVERT'
revertData?: string
expectedReturnStatus: boolean
expectedReturnValue?: string
expectedReturnValue?: string | RevertFlagError
}
interface TestStep_EXTCODESIZE {
......@@ -174,6 +174,7 @@ export const isTestStep_Context = (
): step is TestStep_Context => {
return [
'ovmCALLER',
'ovmNUMBER',
'ovmADDRESS',
'ovmL1TXORIGIN',
'ovmTIMESTAMP',
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -2018,7 +2018,7 @@ buffer-xor@^1.0.3:
resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=
buffer-xor@^2.0.1:
buffer-xor@^2.0.1, buffer-xor@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-2.0.2.tgz#34f7c64f04c777a1f8aac5e661273bb9dd320289"
integrity sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ==
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment