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 { ...@@ -487,8 +487,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
bytes memory _returndata bytes memory _returndata
) )
{ {
console.log("ovmCALL to");
console.logAddress(_address);
// CALL updates the CALLER and ADDRESS. // CALL updates the CALLER and ADDRESS.
MessageContext memory nextMessageContext = messageContext; MessageContext memory nextMessageContext = messageContext;
nextMessageContext.ovmCALLER = nextMessageContext.ovmADDRESS; nextMessageContext.ovmCALLER = nextMessageContext.ovmADDRESS;
...@@ -729,9 +727,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager { ...@@ -729,9 +727,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
override override
public 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 // 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 // sure that the OVM_ExecutionManager itself is the only party that can actually try to
// call this function. // call this function.
...@@ -773,7 +768,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager { ...@@ -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 // left over since contract calls can only be passed 63/64ths of total gas, so we need to
// explicitly handle this case here. // explicitly handle this case here.
if (ethAddress == address(0)) { if (ethAddress == address(0)) {
console.log("detected the create exception");
_revertWithFlag(RevertFlag.CREATE_EXCEPTION); _revertWithFlag(RevertFlag.CREATE_EXCEPTION);
} }
...@@ -820,8 +814,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager { ...@@ -820,8 +814,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
address _created address _created
) )
{ {
console.log("createContract with addy");
console.logAddress(_contractAddress);
// We always update the nonce of the creating account, even if the creation fails. // We always update the nonce of the creating account, even if the creation fails.
_setAccountNonce(ovmADDRESS(), 1); _setAccountNonce(ovmADDRESS(), 1);
...@@ -876,8 +868,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager { ...@@ -876,8 +868,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
bytes memory _returndata bytes memory _returndata
) )
{ {
console.log("_callContract with nuisance gas:");
console.log(messageRecord.nuisanceGasLeft);
return _handleExternalInteraction( return _handleExternalInteraction(
_nextMessageContext, _nextMessageContext,
_gasLimit, _gasLimit,
...@@ -910,8 +900,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager { ...@@ -910,8 +900,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
bytes memory _returndata 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. // We need to switch over to our next message context for the duration of this call.
MessageContext memory prevMessageContext = messageContext; MessageContext memory prevMessageContext = messageContext;
_switchMessageContext(prevMessageContext, _nextMessageContext); _switchMessageContext(prevMessageContext, _nextMessageContext);
...@@ -948,9 +936,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager { ...@@ -948,9 +936,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
bytes memory returndataFromFlag bytes memory returndataFromFlag
) = _decodeRevertData(returndata); ) = _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 // 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 // parent EVM message. This behavior is necessary because INVALID_STATE_ACCESS must
// halt any further transaction execution that could impact the execution result. // halt any further transaction execution that could impact the execution result.
...@@ -1175,7 +1160,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager { ...@@ -1175,7 +1160,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
) )
internal internal
{ {
console.log("checking account load");
// See `_checkContractStorageLoad` for more information. // See `_checkContractStorageLoad` for more information.
if (gasleft() < MIN_GAS_FOR_INVALID_STATE_ACCESS) { if (gasleft() < MIN_GAS_FOR_INVALID_STATE_ACCESS) {
_revertWithFlag(RevertFlag.OUT_OF_GAS); _revertWithFlag(RevertFlag.OUT_OF_GAS);
...@@ -1195,14 +1179,10 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager { ...@@ -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 // If we hadn't already loaded the account, then we'll need to charge "nuisance gas" based
// on the size of the contract code. // on the size of the contract code.
if (_wasAccountAlreadyLoaded == false) { if (_wasAccountAlreadyLoaded == false) {
console.log("was not already loaded");
_useNuisanceGas( _useNuisanceGas(
(Lib_EthUtils.getCodeSize(_getAccountEthAddress(_address)) * NUISANCE_GAS_PER_CONTRACT_BYTE) + MIN_NUISANCE_GAS_PER_CONTRACT (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 { ...@@ -1386,8 +1366,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
} }
// ABI decode the incoming data. // ABI decode the incoming data.
console.log("raw revert data:");
console.logBytes(_revertdata);
return abi.decode(_revertdata, (RevertFlag, uint256, uint256, bytes)); return abi.decode(_revertdata, (RevertFlag, uint256, uint256, bytes));
} }
...@@ -1436,7 +1414,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager { ...@@ -1436,7 +1414,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
) )
internal internal
{ {
console.log("reverting with no info other than flag");
_revertWithFlag(_flag, bytes('')); _revertWithFlag(_flag, bytes(''));
} }
...@@ -1474,8 +1451,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager { ...@@ -1474,8 +1451,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
) )
internal 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 // 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. // refund to be given at the end of the transaction.
if (messageRecord.nuisanceGasLeft < _amount) { if (messageRecord.nuisanceGasLeft < _amount) {
...@@ -1680,8 +1655,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager { ...@@ -1680,8 +1655,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager {
) )
internal internal
{ {
console.log("setting number to:");
console.log(_transaction.number);
transactionContext.ovmTIMESTAMP = _transaction.timestamp; transactionContext.ovmTIMESTAMP = _transaction.timestamp;
transactionContext.ovmNUMBER = _transaction.number; transactionContext.ovmNUMBER = _transaction.number;
transactionContext.ovmTXGASLIMIT = _transaction.gasLimit; transactionContext.ovmTXGASLIMIT = _transaction.gasLimit;
......
...@@ -376,10 +376,7 @@ contract OVM_StateManager is iOVM_StateManager { ...@@ -376,10 +376,7 @@ contract OVM_StateManager is iOVM_StateManager {
// storage because writing to zero when the actual value is nonzero causes a gas // storage because writing to zero when the actual value is nonzero causes a gas
// discrepancy. Could be moved into a new `putVerifiedContractStorage` function, or // discrepancy. Could be moved into a new `putVerifiedContractStorage` function, or
// something along those lines. // something along those lines.
if ( if (verifiedContractStorage[_contract][_key] == false) {
verifiedContractStorage[_contract][_key] == false
&& accounts[_contract].isFresh == false
) {
verifiedContractStorage[_contract][_key] = true; verifiedContractStorage[_contract][_key] = true;
} }
} }
...@@ -401,6 +398,15 @@ contract OVM_StateManager is iOVM_StateManager { ...@@ -401,6 +398,15 @@ contract OVM_StateManager is iOVM_StateManager {
bytes32 _value 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. // See `putContractStorage` for more information about the XOR here.
return contractStorage[_contract][_key] ^ STORAGE_XOR_VALUE; return contractStorage[_contract][_key] ^ STORAGE_XOR_VALUE;
} }
......
...@@ -10,9 +10,24 @@ import { Lib_RLPReader } from "../rlp/Lib_RLPReader.sol"; ...@@ -10,9 +10,24 @@ import { Lib_RLPReader } from "../rlp/Lib_RLPReader.sol";
*/ */
library Lib_OVMCodec { library Lib_OVMCodec {
/******************* /*********
* Data Structures * * Enums *
*******************/ *********/
enum EOASignatureType {
ETH_SIGNED_MESSAGE,
NATIVE_TRANSACTON
}
enum QueueOrigin {
SEQUENCER_QUEUE,
L1TOL2_QUEUE
}
/***********
* Structs *
***********/
struct Account { struct Account {
uint256 nonce; uint256 nonce;
...@@ -43,11 +58,6 @@ library Lib_OVMCodec { ...@@ -43,11 +58,6 @@ library Lib_OVMCodec {
bytes32[] siblings; bytes32[] siblings;
} }
enum QueueOrigin {
SEQUENCER_QUEUE,
L1TOL2_QUEUE
}
struct Transaction { struct Transaction {
uint256 timestamp; uint256 timestamp;
uint256 number; uint256 number;
...@@ -78,11 +88,6 @@ library Lib_OVMCodec { ...@@ -78,11 +88,6 @@ library Lib_OVMCodec {
bytes data; bytes data;
} }
enum EOASignatureType {
ETH_SIGNED_MESSAGE,
NATIVE_TRANSACTON
}
/********************************************* /*********************************************
* Internal Functions: Encoding and Decoding * * 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 @@ ...@@ -20,6 +20,7 @@
"@types/mocha": "^8.0.3", "@types/mocha": "^8.0.3",
"@types/node": "^14.6.0", "@types/node": "^14.6.0",
"assert": "^2.0.0", "assert": "^2.0.0",
"buffer-xor": "^2.0.2",
"chai": "^4.2.0", "chai": "^4.2.0",
"ethereum-waffle": "3.0.0", "ethereum-waffle": "3.0.0",
"ethers": "5.0.0", "ethers": "5.0.0",
......
...@@ -192,7 +192,7 @@ const test_nuisanceGas: TestDefinition = { ...@@ -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 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 // 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. // 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 = { ...@@ -37,6 +37,11 @@ const test_ovmCALL: TestDefinition = {
ethAddress: '0x' + '00'.repeat(20), ethAddress: '0x' + '00'.repeat(20),
}, },
}, },
verifiedContractStorage: {
$DUMMY_OVM_ADDRESS_1: {
[NON_NULL_BYTES32]: true
}
}
}, },
}, },
parameters: [ parameters: [
......
...@@ -11,11 +11,12 @@ import { ...@@ -11,11 +11,12 @@ import {
VERIFIED_EMPTY_CONTRACT_HASH, VERIFIED_EMPTY_CONTRACT_HASH,
DUMMY_BYTECODE_BYTELEN, DUMMY_BYTECODE_BYTELEN,
DUMMY_BYTECODE_HASH, DUMMY_BYTECODE_HASH,
getStorageXOR
} from '../../../../helpers' } from '../../../../helpers'
const CREATED_CONTRACT_1 = '0xa1c4ba6fe56bda6db9df39bf45dbfc3cd104bd6f' const CREATED_CONTRACT_1 = '0x2bda4a99d5be88609d23b1e4ab5d1d34fb1c2feb'
const CREATED_CONTRACT_2 = '0x2bda4a99d5be88609d23b1e4ab5d1d34fb1c2feb' const CREATED_CONTRACT_2 = '0x2bda4a99d5be88609d23b1e4ab5d1d34fb1c2feb'
const NESTED_CREATED_CONTRACT = '0xb99a3d1d1e3f0bd867570da4776221c1b0b74ea3' const NESTED_CREATED_CONTRACT = '0xcb964b3f4162a0d4f5c997b40e19da5a546bc36f'
const DUMMY_REVERT_DATA = const DUMMY_REVERT_DATA =
'0xdeadbeef1e5420deadbeef1e5420deadbeef1e5420deadbeef1e5420deadbeef1e5420' '0xdeadbeef1e5420deadbeef1e5420deadbeef1e5420deadbeef1e5420deadbeef1e5420'
...@@ -53,7 +54,15 @@ const test_ovmCREATE: TestDefinition = { ...@@ -53,7 +54,15 @@ const test_ovmCREATE: TestDefinition = {
ethAddress: '0x' + '00'.repeat(20), ethAddress: '0x' + '00'.repeat(20),
}, },
}, },
contractStorage: {
$DUMMY_OVM_ADDRESS_2: {
[NULL_BYTES32]: getStorageXOR(NULL_BYTES32),
},
},
verifiedContractStorage: { verifiedContractStorage: {
$DUMMY_OVM_ADDRESS_1: {
[NON_NULL_BYTES32]: true,
},
$DUMMY_OVM_ADDRESS_2: { $DUMMY_OVM_ADDRESS_2: {
[NULL_BYTES32]: true, [NULL_BYTES32]: true,
}, },
......
...@@ -51,6 +51,11 @@ const test_ovmDELEGATECALL: TestDefinition = { ...@@ -51,6 +51,11 @@ const test_ovmDELEGATECALL: TestDefinition = {
ethAddress: '0x' + '00'.repeat(20), ethAddress: '0x' + '00'.repeat(20),
}, },
}, },
verifiedContractStorage: {
$DUMMY_OVM_ADDRESS_1: {
[NON_NULL_BYTES32]: true
}
}
}, },
}, },
parameters: [ parameters: [
......
/* Internal Imports */ /* Internal Imports */
import { import {
runExecutionManagerTest, ExecutionManagerTestRunner,
TestDefinition, TestDefinition,
OVM_TX_GAS_LIMIT, OVM_TX_GAS_LIMIT,
NULL_BYTES32,
NON_NULL_BYTES32, NON_NULL_BYTES32,
REVERT_FLAGS, REVERT_FLAGS,
DUMMY_BYTECODE,
} from '../../../../helpers' } from '../../../../helpers'
const test_ovmREVERT: TestDefinition = { const test_ovmREVERT: TestDefinition = {
name: 'basic ovmREVERT unit tests', name: 'Basic tests for ovmREVERT',
preState: { preState: {
ExecutionManager: { ExecutionManager: {
ovmStateManager: '$OVM_STATE_MANAGER', ovmStateManager: '$OVM_STATE_MANAGER',
...@@ -31,34 +29,30 @@ const test_ovmREVERT: TestDefinition = { ...@@ -31,34 +29,30 @@ const test_ovmREVERT: TestDefinition = {
}, },
parameters: [ parameters: [
{ {
name: 'ovmREVERT inside ovmCALL should cause EM to revert', name: 'ovmCALL => ovmREVERT',
parameters: [
{
steps: [ steps: [
{ {
functionName: 'ovmCALL', functionName: 'ovmCALL',
functionParams: [ functionParams: {
OVM_TX_GAS_LIMIT / 2, gasLimit: OVM_TX_GAS_LIMIT / 2,
'$DUMMY_OVM_ADDRESS_1', target: '$DUMMY_OVM_ADDRESS_1',
[ subSteps: [
{ {
functionName: 'ovmREVERT', functionName: 'ovmREVERT',
functionParams: ['0xdeadbeef'], revertData: '0xdeadbeef',
expectedReturnStatus: false, expectedReturnStatus: false,
expectedReturnValues: [ expectedReturnValue: {
REVERT_FLAGS.INTENTIONAL_REVERT, flag: REVERT_FLAGS.INTENTIONAL_REVERT,
'0xdeadbeef', data: '0xdeadbeef',
OVM_TX_GAS_LIMIT / 2, nuisanceGasLeft: OVM_TX_GAS_LIMIT / 2,
0, 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. // 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 = { ...@@ -103,4 +97,5 @@ const test_ovmREVERT: TestDefinition = {
], ],
} }
runExecutionManagerTest(test_ovmREVERT) const runner = new ExecutionManagerTestRunner()
runner.run(test_ovmREVERT)
/* Internal Imports */ /* Internal Imports */
import { import {
runExecutionManagerTest, ExecutionManagerTestRunner,
TestDefinition, TestDefinition,
OVM_TX_GAS_LIMIT, OVM_TX_GAS_LIMIT,
NULL_BYTES32, NULL_BYTES32,
NON_NULL_BYTES32, NON_NULL_BYTES32,
REVERT_FLAGS, getStorageXOR,
DUMMY_BYTECODE,
} from '../../../../helpers' } from '../../../../helpers'
const test_ovmSLOAD: TestDefinition = { const test_ovmSLOAD: TestDefinition = {
name: name: 'Basic tests for ovmSLOAD',
'External storage manipulation during initcode subcalls should correctly NOT be persisted if ovmREVERTed',
preState: { preState: {
ExecutionManager: { ExecutionManager: {
ovmStateManager: '$OVM_STATE_MANAGER', ovmStateManager: '$OVM_STATE_MANAGER',
...@@ -32,6 +30,11 @@ const test_ovmSLOAD: TestDefinition = { ...@@ -32,6 +30,11 @@ const test_ovmSLOAD: TestDefinition = {
ethAddress: '$OVM_CALL_HELPER', ethAddress: '$OVM_CALL_HELPER',
}, },
}, },
contractStorage: {
$DUMMY_OVM_ADDRESS_1: {
[NON_NULL_BYTES32]: getStorageXOR(NULL_BYTES32),
},
},
verifiedContractStorage: { verifiedContractStorage: {
$DUMMY_OVM_ADDRESS_1: { $DUMMY_OVM_ADDRESS_1: {
[NON_NULL_BYTES32]: true, [NON_NULL_BYTES32]: true,
...@@ -41,27 +44,30 @@ const test_ovmSLOAD: TestDefinition = { ...@@ -41,27 +44,30 @@ const test_ovmSLOAD: TestDefinition = {
}, },
parameters: [ parameters: [
{ {
name: 'ovmCALL => ovmSLOAD',
steps: [ steps: [
{ {
functionName: 'ovmCALL', functionName: 'ovmCALL',
functionParams: [ functionParams: {
OVM_TX_GAS_LIMIT, gasLimit: OVM_TX_GAS_LIMIT,
'$DUMMY_OVM_ADDRESS_1', target: '$DUMMY_OVM_ADDRESS_1',
[ subSteps: [
{ {
functionName: 'ovmSLOAD', functionName: 'ovmSLOAD',
functionParams: [NON_NULL_BYTES32], functionParams: {
key: NON_NULL_BYTES32
},
expectedReturnStatus: true, expectedReturnStatus: true,
expectedReturnValues: [NULL_BYTES32], expectedReturnValue: NULL_BYTES32,
}, },
], ],
], },
expectedReturnStatus: true, expectedReturnStatus: true,
expectedReturnValues: [],
}, },
], ],
}, },
], ],
} }
runExecutionManagerTest(test_ovmSLOAD) const runner = new ExecutionManagerTestRunner()
runner.run(test_ovmSLOAD)
/* External Imports */ /* External Imports */
import { ethers } from 'ethers' import { ethers } from 'ethers'
import { defaultAccounts } from 'ethereum-waffle' import { defaultAccounts } from 'ethereum-waffle'
import xor from 'buffer-xor'
/* Internal Imports */ /* Internal Imports */
import { makeHexString, makeAddress } from './utils' import { makeHexString, makeAddress, fromHexString, toHexString } from './utils'
export const DEFAULT_ACCOUNTS = defaultAccounts export const DEFAULT_ACCOUNTS = defaultAccounts
export const DEFAULT_ACCOUNTS_BUIDLER = defaultAccounts.map((account) => { export const DEFAULT_ACCOUNTS_BUIDLER = defaultAccounts.map((account) => {
...@@ -34,3 +35,8 @@ export const NUISANCE_GAS_COSTS = { ...@@ -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... // 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 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 ( ...@@ -199,7 +199,7 @@ const setContractStorage = async (
const slots = getStorageSlots(layout, obj) const slots = getStorageSlots(layout, obj)
for (const slot of slots) { 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 ( ...@@ -216,7 +216,7 @@ const checkContractStorage = async (
const slots = getStorageSlots(layout, obj) const slots = getStorageSlots(layout, obj)
for (const slot of slots) { for (const slot of slots) {
const value = contract.__getStorageSlot(slot.hash) const value = await contract.__getStorageSlot(slot.hash)
if (value !== slot.value) { if (value !== slot.value) {
throw new Error( throw new Error(
......
...@@ -27,7 +27,7 @@ import { ...@@ -27,7 +27,7 @@ import {
isTestStep_EXTCODECOPY, isTestStep_EXTCODECOPY,
isTestStep_REVERT, isTestStep_REVERT,
} from './test.types' } from './test.types'
import { encodeRevertData } from '../codec' import { encodeRevertData, REVERT_FLAGS } from '../codec'
import { getModifiableStorageFactory } from '../storage' import { getModifiableStorageFactory } from '../storage'
import { import {
OVM_TX_GAS_LIMIT, OVM_TX_GAS_LIMIT,
...@@ -263,6 +263,12 @@ export class ExecutionManagerTestRunner { ...@@ -263,6 +263,12 @@ export class ExecutionManagerTestRunner {
return false return false
} else if (isTestStep_Context(step)) { } else if (isTestStep_Context(step)) {
return true 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 { } else {
return step.expectedReturnStatus return step.expectedReturnStatus
} }
...@@ -329,10 +335,6 @@ export class ExecutionManagerTestRunner { ...@@ -329,10 +335,6 @@ export class ExecutionManagerTestRunner {
return '0x' return '0x'
} }
if (isTestStep_REVERT(step)) {
return step.expectedReturnValue || '0x'
}
if (isRevertFlagError(step.expectedReturnValue)) { if (isRevertFlagError(step.expectedReturnValue)) {
return encodeRevertData( return encodeRevertData(
step.expectedReturnValue.flag, step.expectedReturnValue.flag,
...@@ -342,6 +344,10 @@ export class ExecutionManagerTestRunner { ...@@ -342,6 +344,10 @@ export class ExecutionManagerTestRunner {
) )
} }
if (isTestStep_REVERT(step)) {
return step.expectedReturnValue || '0x'
}
let returnData: any[] = [] let returnData: any[] = []
if (isTestStep_CALL(step)) { if (isTestStep_CALL(step)) {
if (step.expectedReturnValue === '0x00') { if (step.expectedReturnValue === '0x00') {
......
...@@ -34,7 +34,7 @@ interface TestStep_REVERT { ...@@ -34,7 +34,7 @@ interface TestStep_REVERT {
functionName: 'ovmREVERT' functionName: 'ovmREVERT'
revertData?: string revertData?: string
expectedReturnStatus: boolean expectedReturnStatus: boolean
expectedReturnValue?: string expectedReturnValue?: string | RevertFlagError
} }
interface TestStep_EXTCODESIZE { interface TestStep_EXTCODESIZE {
...@@ -174,6 +174,7 @@ export const isTestStep_Context = ( ...@@ -174,6 +174,7 @@ export const isTestStep_Context = (
): step is TestStep_Context => { ): step is TestStep_Context => {
return [ return [
'ovmCALLER', 'ovmCALLER',
'ovmNUMBER',
'ovmADDRESS', 'ovmADDRESS',
'ovmL1TXORIGIN', 'ovmL1TXORIGIN',
'ovmTIMESTAMP', 'ovmTIMESTAMP',
......
This diff is collapsed.
...@@ -2018,7 +2018,7 @@ buffer-xor@^1.0.3: ...@@ -2018,7 +2018,7 @@ buffer-xor@^1.0.3:
resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=
buffer-xor@^2.0.1: buffer-xor@^2.0.1, buffer-xor@^2.0.2:
version "2.0.2" version "2.0.2"
resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-2.0.2.tgz#34f7c64f04c777a1f8aac5e661273bb9dd320289" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-2.0.2.tgz#34f7c64f04c777a1f8aac5e661273bb9dd320289"
integrity sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ== 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