Commit 3e81548f authored by Kelvin Fichter's avatar Kelvin Fichter

Linted files

parent 8575b629
import { usePlugin, BuidlerConfig } from '@nomiclabs/buidler/config' import { usePlugin, BuidlerConfig } from '@nomiclabs/buidler/config'
import { import { DEFAULT_ACCOUNTS_BUIDLER, GAS_LIMIT } from './test/helpers/constants'
DEFAULT_ACCOUNTS_BUIDLER,
GAS_LIMIT,
} from './test/helpers/constants'
usePlugin('@nomiclabs/buidler-ethers') usePlugin('@nomiclabs/buidler-ethers')
usePlugin('@nomiclabs/buidler-waffle') usePlugin('@nomiclabs/buidler-waffle')
...@@ -21,7 +18,7 @@ const config: BuidlerConfig = { ...@@ -21,7 +18,7 @@ const config: BuidlerConfig = {
timeout: 50000, timeout: 50000,
}, },
solc: { solc: {
version: "0.7.0", version: '0.7.0',
optimizer: { enabled: true, runs: 200 }, optimizer: { enabled: true, runs: 200 },
}, },
} }
......
...@@ -8,13 +8,13 @@ ...@@ -8,13 +8,13 @@
## Test Cases ## Test Cases
- CALL-types - CALL-types
- for all: call an undeployed contract and make sure it errors or whatevs (or maybe that's just a unit test) - for all: call an undeployed contract and make sure it errors or whatevs (or maybe that's just a unit test)
- ovmCALL ALL DONE - ovmCALL
- -> ovmCALLER - -> ovmCALLER
- -> ovmADDRESS - -> ovmADDRESS
- -> SLOAD - -> SLOAD
- -> SSTORE - -> SSTORE
- -> CREATE/2 - -> CREATE/2
- ovmSTATICCALL ALL DONE - ovmSTATICCALL
- -> ovmCALLER - -> ovmCALLER
- -> ovmADDRESS - -> ovmADDRESS
- -> SLOAD - -> SLOAD
...@@ -22,27 +22,31 @@ ...@@ -22,27 +22,31 @@
- -> CREATE/2 (fail) - -> CREATE/2 (fail)
- -> ovmCALL -> ovmSSTORE - -> ovmCALL -> ovmSSTORE
- -> ovmCALL -> ovmCREATE - -> ovmCALL -> ovmCREATE
- -> ovmSTATICCALL -> RETURN -> SLOAD (fails) - -> ovmSTATICCALL -> RETURN -> SSTORE (fails)
- ovmDELEGATECALL - ovmDELEGATECALL
- -> ovmCALLER DONE - -> ovmCALLER
- -> ovmADDRESS DONE - -> ovmADDRESS
- -> SLOAD DONE - -> SLOAD
- -> SSTORE DONE - -> SSTORE
- -> CREATE/2 DONE - -> CREATE/2
- -> ovmDELEGATECALL -> ovmCALLER DONE - -> ovmDELEGATECALL -> ovmCALLER
- -> ovmDELEGATECALL -> ovmADDRESS DONE - -> ovmDELEGATECALL -> ovmADDRESS
DONE - -> ovmDELEGATECALL -> ovmCREATE
- Code-related - Code-related
- TODO: fill this in
- CREATE-types - CREATE-types
- do we just duplicate these exactly for CREATE and CREATE2? Probably - do we just duplicate these exactly for CREATE and CREATE2? Probably
- ovmCREATE -> success -> ovmEXTCODE{SIZE,HASH,COPY} DONE - ovmCREATE -> success -> ovmEXTCODE{SIZE,HASH,COPY}
- ovmCREATE -> fail (ovmREVERT, NOT out of gas/invalid jump) -> 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 -> fail -> ovmCALL what was attempted to be created (fail)
- ovmCREATE -> ovmCREATE (during constructor) -> success -> success (check right address for inner deployment) - ovmCREATE -> ovmCREATE (during constructor) -> success -> success (check right address for inner deployment)
- ovmCREATE -> ovmCALL(in constructor) -> ovmSSTORE, return -> ovmREVERT (deployment fails, storage not modified, but state access gas correctly increased) 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) - 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 -> 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 - "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 - OVM gas metering
- do everything for both queue origins/flip flopped roles: - do everything for both queue origins/flip flopped roles:
...@@ -52,6 +56,7 @@ ...@@ -52,6 +56,7 @@
- out of gas - out of gas
- ovmCALL -> [ovmCALL(gas()/2) -> out of gas] -> SSTORE (does not out of gas parent) - 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 - State access limiting logic
...@@ -70,9 +75,9 @@ ...@@ -70,9 +75,9 @@
- Explicit invalid state access tests - Explicit invalid state access tests
- CALL -> CALL, ISA - CALL -> CALL, ISA
- CALL -> CALL, CALL, ISA - CALL -> CALL, CALL, ISA
- CREATE -> CREATE, ISA DONE - CREATE -> CREATE, ISA
- CREATE -> CREATE -> CREATE ISA - CREATE -> CREATE -> CREATE ISA
- CREATE -> CALL, ISA DONE - CREATE -> CALL, ISA
- CALL -> CREATE, ISA DONE - CALL -> CREATE, ISA
- CALL -> CREATE -> CALL, ISA - CALL -> CREATE -> CALL, ISA
- CREATE -> CALL -> CREATE, ISA - CREATE -> CALL -> CREATE, ISA
\ No newline at end of file
...@@ -7,7 +7,9 @@ ...@@ -7,7 +7,9 @@
"build": "yarn run build:contracts", "build": "yarn run build:contracts",
"build:contracts": "buidler compile", "build:contracts": "buidler compile",
"test": "yarn run test:contracts", "test": "yarn run test:contracts",
"test:contracts": "buidler test \"test/contracts/OVM/execution/OVM_ExecutionManager/ovmSTATICCALL.spec.ts\"" "test:contracts": "buidler test \"test/contracts/OVM/execution/OVM_ExecutionManager/ovmSTATICCALL.spec.ts\"",
"lint": "tslint --format stylish --project .",
"fix": "prettier --config prettier-config.json --write \"buidler.config.ts\" \"{src,test}/**/*.ts\""
}, },
"devDependencies": { "devDependencies": {
"@nomiclabs/buidler": "^1.4.4", "@nomiclabs/buidler": "^1.4.4",
...@@ -23,7 +25,12 @@ ...@@ -23,7 +25,12 @@
"fs-extra": "^9.0.1", "fs-extra": "^9.0.1",
"lodash": "^4.17.20", "lodash": "^4.17.20",
"mocha": "^8.1.1", "mocha": "^8.1.1",
"prettier": "^2.1.2",
"ts-node": "^9.0.0", "ts-node": "^9.0.0",
"tslint": "^6.1.3",
"tslint-config-prettier": "^1.18.0",
"tslint-no-focused-test": "^0.5.0",
"tslint-plugin-prettier": "^2.3.0",
"typescript": "^4.0.2" "typescript": "^4.0.2"
} }
} }
{
"$schema": "http://json.schemastore.org/prettierrc",
"trailingComma": "es5",
"tabWidth": 2,
"semi": false,
"singleQuote": true,
"arrowParens": "always"
}
/* tslint:disable:no-empty */
import { expect } from '../../../setup' import { expect } from '../../../setup'
describe('OVM_ECDSAContractAccount', () => { describe('OVM_ECDSAContractAccount', () => {
describe('execute', () => { describe('execute', () => {
describe('when provided an invalid signature', () => { describe('when provided an invalid signature', () => {
it('should revert', async () => { it('should revert', async () => {})
})
}) })
describe('when provided a valid signature', () => { describe('when provided a valid signature', () => {
describe('when provided an invalid nonce', () => { describe('when provided an invalid nonce', () => {
it('should revert', async () => { it('should revert', async () => {})
})
}) })
describe('when provided a valid nonce', () => { describe('when provided a valid nonce', () => {
describe('when executing ovmCREATE', () => { describe('when executing ovmCREATE', () => {
it('should return the address of the created contract', async () => { it('should return the address of the created contract', async () => {})
})
}) })
describe('when executing ovmCALL', () => { describe('when executing ovmCALL', () => {
it('should return the result of the call', async () => { it('should return the result of the call', async () => {})
})
}) })
}) })
}) })
......
...@@ -12,7 +12,7 @@ import { ...@@ -12,7 +12,7 @@ import {
setProxyTarget, setProxyTarget,
NON_NULL_BYTES32, NON_NULL_BYTES32,
FORCE_INCLUSION_PERIOD_SECONDS, FORCE_INCLUSION_PERIOD_SECONDS,
ZERO_ADDRESS ZERO_ADDRESS,
} from '../../../helpers' } from '../../../helpers'
const getEthTime = async (): Promise<number> => { const getEthTime = async (): Promise<number> => {
...@@ -85,10 +85,10 @@ describe('OVM_CanonicalTransactionChain', () => { ...@@ -85,10 +85,10 @@ describe('OVM_CanonicalTransactionChain', () => {
const timestamp = await getEthTime() const timestamp = await getEthTime()
Mock__OVM_L1ToL2TransactionQueue.setReturnValues('peek', [ Mock__OVM_L1ToL2TransactionQueue.setReturnValues('peek', [
{ {
timestamp: timestamp, timestamp,
batchRoot: NON_NULL_BYTES32, batchRoot: NON_NULL_BYTES32,
isL1ToL2Batch: true isL1ToL2Batch: true,
} },
]) ])
await setEthTime(timestamp + FORCE_INCLUSION_PERIOD_SECONDS / 2) await setEthTime(timestamp + FORCE_INCLUSION_PERIOD_SECONDS / 2)
}) })
...@@ -96,7 +96,9 @@ describe('OVM_CanonicalTransactionChain', () => { ...@@ -96,7 +96,9 @@ describe('OVM_CanonicalTransactionChain', () => {
it('should revert', async () => { it('should revert', async () => {
await expect( await expect(
OVM_CanonicalTransactionChain.appendQueueBatch() OVM_CanonicalTransactionChain.appendQueueBatch()
).to.be.revertedWith('Cannot append until the inclusion delay period has elapsed.') ).to.be.revertedWith(
'Cannot append until the inclusion delay period has elapsed.'
)
}) })
}) })
...@@ -105,25 +107,24 @@ describe('OVM_CanonicalTransactionChain', () => { ...@@ -105,25 +107,24 @@ describe('OVM_CanonicalTransactionChain', () => {
const timestamp = await getEthTime() const timestamp = await getEthTime()
Mock__OVM_L1ToL2TransactionQueue.setReturnValues('peek', [ Mock__OVM_L1ToL2TransactionQueue.setReturnValues('peek', [
{ {
timestamp: timestamp, timestamp,
batchRoot: NON_NULL_BYTES32, batchRoot: NON_NULL_BYTES32,
isL1ToL2Batch: true isL1ToL2Batch: true,
} },
]) ])
Mock__OVM_L1ToL2TransactionQueue.setReturnValues('dequeue', [ Mock__OVM_L1ToL2TransactionQueue.setReturnValues('dequeue', [
{ {
timestamp: timestamp, timestamp,
batchRoot: NON_NULL_BYTES32, batchRoot: NON_NULL_BYTES32,
isL1ToL2Batch: true isL1ToL2Batch: true,
} },
]) ])
await setEthTime(timestamp + FORCE_INCLUSION_PERIOD_SECONDS) await setEthTime(timestamp + FORCE_INCLUSION_PERIOD_SECONDS)
}) })
it('should append the top element of the queue and attempt to dequeue', async () => { it('should append the top element of the queue and attempt to dequeue', async () => {
await expect( await expect(OVM_CanonicalTransactionChain.appendQueueBatch()).to.not
OVM_CanonicalTransactionChain.appendQueueBatch() .be.reverted
).to.not.be.reverted
// TODO: Check that the batch root was inserted. // TODO: Check that the batch root was inserted.
...@@ -138,28 +139,19 @@ describe('OVM_CanonicalTransactionChain', () => { ...@@ -138,28 +139,19 @@ describe('OVM_CanonicalTransactionChain', () => {
describe('appendSequencerBatch()', () => { describe('appendSequencerBatch()', () => {
describe('when the sender is not the sequencer', () => { describe('when the sender is not the sequencer', () => {
before(async () => { before(async () => {
await Proxy_Manager.setProxy( await Proxy_Manager.setProxy('Sequencer', ZERO_ADDRESS)
'Sequencer',
ZERO_ADDRESS
)
}) })
it('should revert', async () => { it('should revert', async () => {
await expect( await expect(
OVM_CanonicalTransactionChain.appendSequencerBatch( OVM_CanonicalTransactionChain.appendSequencerBatch([], 0)
[],
0
)
).to.be.revertedWith('Function can only be called by the Sequencer.') ).to.be.revertedWith('Function can only be called by the Sequencer.')
}) })
}) })
describe('when the sender is the sequencer', () => { describe('when the sender is the sequencer', () => {
before(async () => { before(async () => {
await Proxy_Manager.setProxy( await Proxy_Manager.setProxy('Sequencer', await signer.getAddress())
'Sequencer',
await signer.getAddress()
)
}) })
describe('when the given batch is empty', () => { describe('when the given batch is empty', () => {
...@@ -167,10 +159,7 @@ describe('OVM_CanonicalTransactionChain', () => { ...@@ -167,10 +159,7 @@ describe('OVM_CanonicalTransactionChain', () => {
it('should revert', async () => { it('should revert', async () => {
await expect( await expect(
OVM_CanonicalTransactionChain.appendSequencerBatch( OVM_CanonicalTransactionChain.appendSequencerBatch(batch, 0)
batch,
0
)
).to.be.revertedWith('Cannot submit an empty batch.') ).to.be.revertedWith('Cannot submit an empty batch.')
}) })
}) })
...@@ -179,7 +168,7 @@ describe('OVM_CanonicalTransactionChain', () => { ...@@ -179,7 +168,7 @@ describe('OVM_CanonicalTransactionChain', () => {
const batch = [NON_NULL_BYTES32] const batch = [NON_NULL_BYTES32]
describe('when the timestamp is not greater than the previous OVM timestamp', () => { describe('when the timestamp is not greater than the previous OVM timestamp', () => {
const timestamp = 0; const timestamp = 0
it('should revert', async () => { it('should revert', async () => {
await expect( await expect(
...@@ -187,12 +176,14 @@ describe('OVM_CanonicalTransactionChain', () => { ...@@ -187,12 +176,14 @@ describe('OVM_CanonicalTransactionChain', () => {
batch, batch,
timestamp timestamp
) )
).to.be.revertedWith('Batch timestamp must be later than the last OVM timestamp.') ).to.be.revertedWith(
'Batch timestamp must be later than the last OVM timestamp.'
)
}) })
}) })
describe('when the timestamp is greater than the previous OVM timestamp', () => { describe('when the timestamp is greater than the previous OVM timestamp', () => {
const timestamp = 1000; const timestamp = 1000
describe('when the queue is not empty', () => { describe('when the queue is not empty', () => {
before(() => { before(() => {
...@@ -205,8 +196,8 @@ describe('OVM_CanonicalTransactionChain', () => { ...@@ -205,8 +196,8 @@ describe('OVM_CanonicalTransactionChain', () => {
{ {
timestamp: timestamp / 2, timestamp: timestamp / 2,
batchRoot: NON_NULL_BYTES32, batchRoot: NON_NULL_BYTES32,
isL1ToL2Batch: true isL1ToL2Batch: true,
} },
]) ])
}) })
...@@ -216,7 +207,9 @@ describe('OVM_CanonicalTransactionChain', () => { ...@@ -216,7 +207,9 @@ describe('OVM_CanonicalTransactionChain', () => {
batch, batch,
timestamp timestamp
) )
).to.be.revertedWith('Older queue batches must be processed before a newer sequencer batch.') ).to.be.revertedWith(
'Older queue batches must be processed before a newer sequencer batch.'
)
}) })
}) })
...@@ -224,10 +217,10 @@ describe('OVM_CanonicalTransactionChain', () => { ...@@ -224,10 +217,10 @@ describe('OVM_CanonicalTransactionChain', () => {
before(() => { before(() => {
Mock__OVM_L1ToL2TransactionQueue.setReturnValues('peek', [ Mock__OVM_L1ToL2TransactionQueue.setReturnValues('peek', [
{ {
timestamp: timestamp, timestamp,
batchRoot: NON_NULL_BYTES32, batchRoot: NON_NULL_BYTES32,
isL1ToL2Batch: true isL1ToL2Batch: true,
} },
]) ])
}) })
...@@ -268,9 +261,9 @@ describe('OVM_CanonicalTransactionChain', () => { ...@@ -268,9 +261,9 @@ describe('OVM_CanonicalTransactionChain', () => {
describe('getTotalElements()', () => { describe('getTotalElements()', () => {
describe('when no batch elements have been inserted', () => { describe('when no batch elements have been inserted', () => {
it('should return zero', async () => { it('should return zero', async () => {
expect( expect(await OVM_CanonicalTransactionChain.getTotalElements()).to.equal(
await OVM_CanonicalTransactionChain.getTotalElements() 0
).to.equal(0) )
}) })
}) })
...@@ -284,9 +277,9 @@ describe('OVM_CanonicalTransactionChain', () => { ...@@ -284,9 +277,9 @@ describe('OVM_CanonicalTransactionChain', () => {
}) })
it('should return the number of inserted batch elements', async () => { it('should return the number of inserted batch elements', async () => {
expect( expect(await OVM_CanonicalTransactionChain.getTotalElements()).to.equal(
await OVM_CanonicalTransactionChain.getTotalElements() 1
).to.equal(1) )
}) })
}) })
...@@ -294,16 +287,13 @@ describe('OVM_CanonicalTransactionChain', () => { ...@@ -294,16 +287,13 @@ describe('OVM_CanonicalTransactionChain', () => {
const batch = Array(64).fill(NON_NULL_BYTES32) const batch = Array(64).fill(NON_NULL_BYTES32)
beforeEach(async () => { beforeEach(async () => {
Mock__OVM_L1ToL2TransactionQueue.setReturnValues('size', [0]) Mock__OVM_L1ToL2TransactionQueue.setReturnValues('size', [0])
await OVM_CanonicalTransactionChain.appendSequencerBatch( await OVM_CanonicalTransactionChain.appendSequencerBatch(batch, 1000)
batch,
1000
)
}) })
it('should return the number of inserted batch elements', async () => { it('should return the number of inserted batch elements', async () => {
expect( expect(await OVM_CanonicalTransactionChain.getTotalElements()).to.equal(
await OVM_CanonicalTransactionChain.getTotalElements() 64
).to.equal(64) )
}) })
}) })
...@@ -311,20 +301,14 @@ describe('OVM_CanonicalTransactionChain', () => { ...@@ -311,20 +301,14 @@ describe('OVM_CanonicalTransactionChain', () => {
const batch = Array(32).fill(NON_NULL_BYTES32) const batch = Array(32).fill(NON_NULL_BYTES32)
beforeEach(async () => { beforeEach(async () => {
Mock__OVM_L1ToL2TransactionQueue.setReturnValues('size', [0]) Mock__OVM_L1ToL2TransactionQueue.setReturnValues('size', [0])
await OVM_CanonicalTransactionChain.appendSequencerBatch( await OVM_CanonicalTransactionChain.appendSequencerBatch(batch, 1000)
batch, await OVM_CanonicalTransactionChain.appendSequencerBatch(batch, 2000)
1000
)
await OVM_CanonicalTransactionChain.appendSequencerBatch(
batch,
2000
)
}) })
it('should return the number of inserted batch elements', async () => { it('should return the number of inserted batch elements', async () => {
expect( expect(await OVM_CanonicalTransactionChain.getTotalElements()).to.equal(
await OVM_CanonicalTransactionChain.getTotalElements() 64
).to.equal(64) )
}) })
}) })
}) })
...@@ -332,9 +316,9 @@ describe('OVM_CanonicalTransactionChain', () => { ...@@ -332,9 +316,9 @@ describe('OVM_CanonicalTransactionChain', () => {
describe('getTotalBatches()', () => { describe('getTotalBatches()', () => {
describe('when no batches have been inserted', () => { describe('when no batches have been inserted', () => {
it('should return zero', async () => { it('should return zero', async () => {
expect( expect(await OVM_CanonicalTransactionChain.getTotalBatches()).to.equal(
await OVM_CanonicalTransactionChain.getTotalBatches() 0
).to.equal(0) )
}) })
}) })
...@@ -348,9 +332,9 @@ describe('OVM_CanonicalTransactionChain', () => { ...@@ -348,9 +332,9 @@ describe('OVM_CanonicalTransactionChain', () => {
}) })
it('should return the number of inserted batch elements', async () => { it('should return the number of inserted batch elements', async () => {
expect( expect(await OVM_CanonicalTransactionChain.getTotalBatches()).to.equal(
await OVM_CanonicalTransactionChain.getTotalBatches() 1
).to.equal(1) )
}) })
}) })
...@@ -366,9 +350,9 @@ describe('OVM_CanonicalTransactionChain', () => { ...@@ -366,9 +350,9 @@ describe('OVM_CanonicalTransactionChain', () => {
}) })
it('should return the number of inserted batch elements', async () => { it('should return the number of inserted batch elements', async () => {
expect( expect(await OVM_CanonicalTransactionChain.getTotalBatches()).to.equal(
await OVM_CanonicalTransactionChain.getTotalBatches() 8
).to.equal(8) )
}) })
}) })
}) })
......
...@@ -11,7 +11,7 @@ import { ...@@ -11,7 +11,7 @@ import {
getMockContract, getMockContract,
setProxyTarget, setProxyTarget,
NON_NULL_BYTES32, NON_NULL_BYTES32,
ZERO_ADDRESS ZERO_ADDRESS,
} from '../../../helpers' } from '../../../helpers'
describe('OVM_StateCommitmentChain', () => { describe('OVM_StateCommitmentChain', () => {
...@@ -55,7 +55,7 @@ describe('OVM_StateCommitmentChain', () => { ...@@ -55,7 +55,7 @@ describe('OVM_StateCommitmentChain', () => {
describe('appendStateBatch', () => { describe('appendStateBatch', () => {
describe('when the provided batch is empty', () => { describe('when the provided batch is empty', () => {
const batch = [] const batch = []
it('should revert', async () => { it('should revert', async () => {
await expect( await expect(
OVM_StateCommitmentChain.appendStateBatch(batch) OVM_StateCommitmentChain.appendStateBatch(batch)
...@@ -68,25 +68,32 @@ describe('OVM_StateCommitmentChain', () => { ...@@ -68,25 +68,32 @@ describe('OVM_StateCommitmentChain', () => {
describe('when submitting more elements than present in the OVM_CanonicalTransactionChain', () => { describe('when submitting more elements than present in the OVM_CanonicalTransactionChain', () => {
before(() => { before(() => {
Mock__OVM_CanonicalTransactionChain.setReturnValues('getTotalElements', [batch.length - 1]) Mock__OVM_CanonicalTransactionChain.setReturnValues(
'getTotalElements',
[batch.length - 1]
)
}) })
it('should revert', async () => { it('should revert', async () => {
await expect( await expect(
OVM_StateCommitmentChain.appendStateBatch(batch) OVM_StateCommitmentChain.appendStateBatch(batch)
).to.be.revertedWith('Number of state roots cannot exceed the number of canonical transactions.') ).to.be.revertedWith(
'Number of state roots cannot exceed the number of canonical transactions.'
)
}) })
}) })
describe('when not submitting more elements than present in the OVM_CanonicalTransactionChain', () => { describe('when not submitting more elements than present in the OVM_CanonicalTransactionChain', () => {
before(() => { before(() => {
Mock__OVM_CanonicalTransactionChain.setReturnValues('getTotalElements', [batch.length]) Mock__OVM_CanonicalTransactionChain.setReturnValues(
'getTotalElements',
[batch.length]
)
}) })
it('should append the state batch', async () => { it('should append the state batch', async () => {
await expect( await expect(OVM_StateCommitmentChain.appendStateBatch(batch)).to.not
OVM_StateCommitmentChain.appendStateBatch(batch) .be.reverted
).to.not.be.reverted
// TODO: Check for correct insertion. // TODO: Check for correct insertion.
}) })
...@@ -102,26 +109,27 @@ describe('OVM_StateCommitmentChain', () => { ...@@ -102,26 +109,27 @@ describe('OVM_StateCommitmentChain', () => {
batchRoot: NON_NULL_BYTES32, batchRoot: NON_NULL_BYTES32,
batchSize: 0, batchSize: 0,
prevTotalElements: 0, prevTotalElements: 0,
extraData: '0x' extraData: '0x',
} }
beforeEach(async () => { beforeEach(async () => {
Mock__OVM_CanonicalTransactionChain.setReturnValues('getTotalElements', [batch.length]) Mock__OVM_CanonicalTransactionChain.setReturnValues('getTotalElements', [
batch.length,
])
await OVM_StateCommitmentChain.appendStateBatch(batch) await OVM_StateCommitmentChain.appendStateBatch(batch)
}) })
describe('when the sender is not the OVM_FraudVerifier', () => { describe('when the sender is not the OVM_FraudVerifier', () => {
before(async () => { before(async () => {
await Proxy_Manager.setProxy( await Proxy_Manager.setProxy('OVM_FraudVerifier', ZERO_ADDRESS)
'OVM_FraudVerifier',
ZERO_ADDRESS
)
}) })
it('should revert', async () => { it('should revert', async () => {
await expect( await expect(
OVM_StateCommitmentChain.deleteStateBatch(batchHeader) OVM_StateCommitmentChain.deleteStateBatch(batchHeader)
).to.be.revertedWith('State batches can only be deleted by the OVM_FraudVerifier.') ).to.be.revertedWith(
'State batches can only be deleted by the OVM_FraudVerifier.'
)
}) })
}) })
...@@ -138,7 +146,7 @@ describe('OVM_StateCommitmentChain', () => { ...@@ -138,7 +146,7 @@ describe('OVM_StateCommitmentChain', () => {
await expect( await expect(
OVM_StateCommitmentChain.deleteStateBatch({ OVM_StateCommitmentChain.deleteStateBatch({
...batchHeader, ...batchHeader,
batchIndex: 1 batchIndex: 1,
}) })
).to.be.revertedWith('Invalid batch index.') ).to.be.revertedWith('Invalid batch index.')
}) })
...@@ -150,7 +158,7 @@ describe('OVM_StateCommitmentChain', () => { ...@@ -150,7 +158,7 @@ describe('OVM_StateCommitmentChain', () => {
await expect( await expect(
OVM_StateCommitmentChain.deleteStateBatch({ OVM_StateCommitmentChain.deleteStateBatch({
...batchHeader, ...batchHeader,
extraData: '0x1234' extraData: '0x1234',
}) })
).to.be.revertedWith('Invalid batch header.') ).to.be.revertedWith('Invalid batch header.')
}) })
...@@ -158,9 +166,8 @@ describe('OVM_StateCommitmentChain', () => { ...@@ -158,9 +166,8 @@ describe('OVM_StateCommitmentChain', () => {
describe('when the provided batch header is valid', () => { describe('when the provided batch header is valid', () => {
it('should remove the batch and all following batches', async () => { it('should remove the batch and all following batches', async () => {
await expect( await expect(OVM_StateCommitmentChain.deleteStateBatch(batchHeader))
OVM_StateCommitmentChain.deleteStateBatch(batchHeader) .to.not.be.reverted
).to.not.be.reverted
// TODO: Check that it deleted the batches. // TODO: Check that it deleted the batches.
}) })
...@@ -172,52 +179,53 @@ describe('OVM_StateCommitmentChain', () => { ...@@ -172,52 +179,53 @@ describe('OVM_StateCommitmentChain', () => {
describe('getTotalElements', () => { describe('getTotalElements', () => {
describe('when no batch elements have been inserted', () => { describe('when no batch elements have been inserted', () => {
it('should return zero', async () => { it('should return zero', async () => {
expect( expect(await OVM_StateCommitmentChain.getTotalElements()).to.equal(0)
await OVM_StateCommitmentChain.getTotalElements()
).to.equal(0)
}) })
}) })
describe('when one batch element has been inserted', () => { describe('when one batch element has been inserted', () => {
beforeEach(async () => { beforeEach(async () => {
const batch = [NON_NULL_BYTES32] const batch = [NON_NULL_BYTES32]
Mock__OVM_CanonicalTransactionChain.setReturnValues('getTotalElements', [batch.length]) Mock__OVM_CanonicalTransactionChain.setReturnValues(
'getTotalElements',
[batch.length]
)
await OVM_StateCommitmentChain.appendStateBatch(batch) await OVM_StateCommitmentChain.appendStateBatch(batch)
}) })
it('should return the number of inserted batch elements', async () => { it('should return the number of inserted batch elements', async () => {
expect( expect(await OVM_StateCommitmentChain.getTotalElements()).to.equal(1)
await OVM_StateCommitmentChain.getTotalElements()
).to.equal(1)
}) })
}) })
describe('when 64 batch elements have been inserted in one batch', () => { describe('when 64 batch elements have been inserted in one batch', () => {
beforeEach(async () => { beforeEach(async () => {
const batch = Array(64).fill(NON_NULL_BYTES32) const batch = Array(64).fill(NON_NULL_BYTES32)
Mock__OVM_CanonicalTransactionChain.setReturnValues('getTotalElements', [batch.length]) Mock__OVM_CanonicalTransactionChain.setReturnValues(
'getTotalElements',
[batch.length]
)
await OVM_StateCommitmentChain.appendStateBatch(batch) await OVM_StateCommitmentChain.appendStateBatch(batch)
}) })
it('should return the number of inserted batch elements', async () => { it('should return the number of inserted batch elements', async () => {
expect( expect(await OVM_StateCommitmentChain.getTotalElements()).to.equal(64)
await OVM_StateCommitmentChain.getTotalElements()
).to.equal(64)
}) })
}) })
describe('when 32 batch elements have been inserted in each of two batches', () => { describe('when 32 batch elements have been inserted in each of two batches', () => {
beforeEach(async () => { beforeEach(async () => {
const batch = Array(32).fill(NON_NULL_BYTES32) const batch = Array(32).fill(NON_NULL_BYTES32)
Mock__OVM_CanonicalTransactionChain.setReturnValues('getTotalElements', [batch.length * 2]) Mock__OVM_CanonicalTransactionChain.setReturnValues(
'getTotalElements',
[batch.length * 2]
)
await OVM_StateCommitmentChain.appendStateBatch(batch) await OVM_StateCommitmentChain.appendStateBatch(batch)
await OVM_StateCommitmentChain.appendStateBatch(batch) await OVM_StateCommitmentChain.appendStateBatch(batch)
}) })
it('should return the number of inserted batch elements', async () => { it('should return the number of inserted batch elements', async () => {
expect( expect(await OVM_StateCommitmentChain.getTotalElements()).to.equal(64)
await OVM_StateCommitmentChain.getTotalElements()
).to.equal(64)
}) })
}) })
}) })
...@@ -225,39 +233,39 @@ describe('OVM_StateCommitmentChain', () => { ...@@ -225,39 +233,39 @@ describe('OVM_StateCommitmentChain', () => {
describe('getTotalBatches()', () => { describe('getTotalBatches()', () => {
describe('when no batches have been inserted', () => { describe('when no batches have been inserted', () => {
it('should return zero', async () => { it('should return zero', async () => {
expect( expect(await OVM_StateCommitmentChain.getTotalBatches()).to.equal(0)
await OVM_StateCommitmentChain.getTotalBatches()
).to.equal(0)
}) })
}) })
describe('when one batch has been inserted', () => { describe('when one batch has been inserted', () => {
beforeEach(async () => { beforeEach(async () => {
const batch = [NON_NULL_BYTES32] const batch = [NON_NULL_BYTES32]
Mock__OVM_CanonicalTransactionChain.setReturnValues('getTotalElements', [batch.length]) Mock__OVM_CanonicalTransactionChain.setReturnValues(
'getTotalElements',
[batch.length]
)
await OVM_StateCommitmentChain.appendStateBatch(batch) await OVM_StateCommitmentChain.appendStateBatch(batch)
}) })
it('should return the number of inserted batch elements', async () => { it('should return the number of inserted batch elements', async () => {
expect( expect(await OVM_StateCommitmentChain.getTotalBatches()).to.equal(1)
await OVM_StateCommitmentChain.getTotalBatches()
).to.equal(1)
}) })
}) })
describe('when 8 batches have been inserted', () => { describe('when 8 batches have been inserted', () => {
beforeEach(async () => { beforeEach(async () => {
const batch = [NON_NULL_BYTES32] const batch = [NON_NULL_BYTES32]
Mock__OVM_CanonicalTransactionChain.setReturnValues('getTotalElements', [batch.length * 8]) Mock__OVM_CanonicalTransactionChain.setReturnValues(
'getTotalElements',
[batch.length * 8]
)
for (let i = 0; i < 8; i++) { for (let i = 0; i < 8; i++) {
await OVM_StateCommitmentChain.appendStateBatch(batch) await OVM_StateCommitmentChain.appendStateBatch(batch)
} }
}) })
it('should return the number of inserted batch elements', async () => { it('should return the number of inserted batch elements', async () => {
expect( expect(await OVM_StateCommitmentChain.getTotalBatches()).to.equal(8)
await OVM_StateCommitmentChain.getTotalBatches()
).to.equal(8)
}) })
}) })
}) })
...@@ -275,4 +283,4 @@ describe('OVM_StateCommitmentChain', () => { ...@@ -275,4 +283,4 @@ describe('OVM_StateCommitmentChain', () => {
// TODO // TODO
}) })
}) })
}) })
\ No newline at end of file
...@@ -6,60 +6,60 @@ import { ...@@ -6,60 +6,60 @@ import {
NULL_BYTES32, NULL_BYTES32,
NON_NULL_BYTES32, NON_NULL_BYTES32,
REVERT_FLAGS, REVERT_FLAGS,
DUMMY_BYTECODE DUMMY_BYTECODE,
} from '../../../../helpers' } from '../../../../helpers'
const test_ovmREVERT: TestDefinition = { const test_ovmREVERT: TestDefinition = {
name: "basic ovmREVERT unit tests", name: 'basic ovmREVERT unit tests',
preState: { preState: {
ExecutionManager: { ExecutionManager: {
ovmStateManager: "$OVM_STATE_MANAGER", ovmStateManager: '$OVM_STATE_MANAGER',
ovmSafetyChecker: "$OVM_SAFETY_CHECKER", ovmSafetyChecker: '$OVM_SAFETY_CHECKER',
messageRecord: { messageRecord: {
nuisanceGasLeft: GAS_LIMIT nuisanceGasLeft: GAS_LIMIT,
} },
}, },
StateManager: { StateManager: {
owner: "$OVM_EXECUTION_MANAGER", owner: '$OVM_EXECUTION_MANAGER',
accounts: { accounts: {
"$DUMMY_OVM_ADDRESS_1": { $DUMMY_OVM_ADDRESS_1: {
codeHash: NON_NULL_BYTES32, codeHash: NON_NULL_BYTES32,
ethAddress: "$OVM_CALL_HELPER" ethAddress: '$OVM_CALL_HELPER',
}, },
} },
} },
}, },
parameters: [ parameters: [
{ {
name: "ovmREVERT inside ovmCALL should cause EM to revert", name: 'ovmREVERT inside ovmCALL should cause EM to revert',
parameters: [ parameters: [
{ {
steps: [ steps: [
{ {
functionName: "ovmCALL", functionName: 'ovmCALL',
functionParams: [ functionParams: [
GAS_LIMIT / 2, GAS_LIMIT / 2,
"$DUMMY_OVM_ADDRESS_1", '$DUMMY_OVM_ADDRESS_1',
[ [
{ {
functionName: "ovmREVERT", functionName: 'ovmREVERT',
functionParams: [ "0xdeadbeef" ], functionParams: ['0xdeadbeef'],
expectedReturnStatus: false, expectedReturnStatus: false,
expectedReturnValues: [ expectedReturnValues: [
REVERT_FLAGS.INTENTIONAL_REVERT, REVERT_FLAGS.INTENTIONAL_REVERT,
"0xdeadbeef", '0xdeadbeef',
GAS_LIMIT / 2, GAS_LIMIT / 2,
0 0,
] ],
} },
] ],
], ],
expectedReturnStatus: true, expectedReturnStatus: true,
expectedReturnValues: [] expectedReturnValues: [],
} },
] ],
} },
] ],
}, },
// 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.
// { // {
...@@ -100,7 +100,7 @@ const test_ovmREVERT: TestDefinition = { ...@@ -100,7 +100,7 @@ const test_ovmREVERT: TestDefinition = {
// } // }
// ] // ]
// } // }
] ],
} }
runExecutionManagerTest(test_ovmREVERT) runExecutionManagerTest(test_ovmREVERT)
...@@ -6,37 +6,38 @@ import { ...@@ -6,37 +6,38 @@ import {
NULL_BYTES32, NULL_BYTES32,
NON_NULL_BYTES32, NON_NULL_BYTES32,
REVERT_FLAGS, REVERT_FLAGS,
DUMMY_BYTECODE DUMMY_BYTECODE,
} from '../../../../helpers' } from '../../../../helpers'
const test_ovmSLOAD: TestDefinition = { const test_ovmSLOAD: TestDefinition = {
name: "External storage manipulation during initcode subcalls should correctly NOT be persisted if ovmREVERTed", name:
'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',
ovmSafetyChecker: "$OVM_SAFETY_CHECKER", ovmSafetyChecker: '$OVM_SAFETY_CHECKER',
messageRecord: { messageRecord: {
nuisanceGasLeft: GAS_LIMIT nuisanceGasLeft: GAS_LIMIT,
} },
}, },
StateManager: { StateManager: {
owner: "$OVM_EXECUTION_MANAGER", owner: '$OVM_EXECUTION_MANAGER',
accounts: { accounts: {
"$DUMMY_OVM_ADDRESS_1": { $DUMMY_OVM_ADDRESS_1: {
codeHash: NON_NULL_BYTES32, codeHash: NON_NULL_BYTES32,
ethAddress: "$OVM_CALL_HELPER" ethAddress: '$OVM_CALL_HELPER',
}, },
"$DUMMY_OVM_ADDRESS_2": { $DUMMY_OVM_ADDRESS_2: {
codeHash: NON_NULL_BYTES32, codeHash: NON_NULL_BYTES32,
ethAddress: "$OVM_CALL_HELPER" ethAddress: '$OVM_CALL_HELPER',
}, },
}, },
verifiedContractStorage: { verifiedContractStorage: {
"$DUMMY_OVM_ADDRESS_1": { $DUMMY_OVM_ADDRESS_1: {
[NON_NULL_BYTES32]: true [NON_NULL_BYTES32]: true,
} },
} },
} },
}, },
parameters: [ parameters: [
{ {
...@@ -45,22 +46,22 @@ const test_ovmSLOAD: TestDefinition = { ...@@ -45,22 +46,22 @@ const test_ovmSLOAD: TestDefinition = {
functionName: 'ovmCALL', functionName: 'ovmCALL',
functionParams: [ functionParams: [
GAS_LIMIT, GAS_LIMIT,
"$DUMMY_OVM_ADDRESS_1", '$DUMMY_OVM_ADDRESS_1',
[ [
{ {
functionName: 'ovmSLOAD', functionName: 'ovmSLOAD',
functionParams: [NON_NULL_BYTES32], functionParams: [NON_NULL_BYTES32],
expectedReturnStatus: true, expectedReturnStatus: true,
expectedReturnValues: [NULL_BYTES32] expectedReturnValues: [NULL_BYTES32],
}, },
] ],
], ],
expectedReturnStatus: true, expectedReturnStatus: true,
expectedReturnValues: [] expectedReturnValues: [],
} },
] ],
} },
] ],
} }
runExecutionManagerTest(test_ovmSLOAD) runExecutionManagerTest(test_ovmSLOAD)
...@@ -21,9 +21,9 @@ describe('OVM_SafetyChecker', () => { ...@@ -21,9 +21,9 @@ describe('OVM_SafetyChecker', () => {
for (const testName of Object.keys(SAFETY_CHECKER_TEST_JSON)) { for (const testName of Object.keys(SAFETY_CHECKER_TEST_JSON)) {
const test = SAFETY_CHECKER_TEST_JSON[testName] const test = SAFETY_CHECKER_TEST_JSON[testName]
it(`should correctly classify: ${testName}`, async () => { it(`should correctly classify: ${testName}`, async () => {
expect( expect(await OVM_SafetyChecker.isBytecodeSafe(test.in)).to.equal(
await OVM_SafetyChecker.isBytecodeSafe(test.in) test.out
).to.equal(test.out) )
}) })
} }
}) })
......
...@@ -5,11 +5,7 @@ import { ethers } from '@nomiclabs/buidler' ...@@ -5,11 +5,7 @@ import { ethers } from '@nomiclabs/buidler'
import { Contract, ContractFactory } from 'ethers' import { Contract, ContractFactory } from 'ethers'
/* Internal Imports */ /* Internal Imports */
import { import { DUMMY_ACCOUNTS, DUMMY_BYTES32, toOVMAccount } from '../../../helpers'
DUMMY_ACCOUNTS,
DUMMY_BYTES32,
toOVMAccount
} from '../../../helpers'
describe('OVM_StateManager', () => { describe('OVM_StateManager', () => {
let Factory__OVM_StateManager: ContractFactory let Factory__OVM_StateManager: ContractFactory
...@@ -58,7 +54,9 @@ describe('OVM_StateManager', () => { ...@@ -58,7 +54,9 @@ describe('OVM_StateManager', () => {
expect( expect(
toOVMAccount( toOVMAccount(
await OVM_StateManager.callStatic.getAccount(DUMMY_ACCOUNTS[0].address) await OVM_StateManager.callStatic.getAccount(
DUMMY_ACCOUNTS[0].address
)
) )
).to.deep.equal(DUMMY_ACCOUNTS[0].data) ).to.deep.equal(DUMMY_ACCOUNTS[0].data)
}) })
...@@ -76,7 +74,9 @@ describe('OVM_StateManager', () => { ...@@ -76,7 +74,9 @@ describe('OVM_StateManager', () => {
expect( expect(
toOVMAccount( toOVMAccount(
await OVM_StateManager.callStatic.getAccount(DUMMY_ACCOUNTS[0].address) await OVM_StateManager.callStatic.getAccount(
DUMMY_ACCOUNTS[0].address
)
) )
).to.deep.equal(DUMMY_ACCOUNTS[1].data) ).to.deep.equal(DUMMY_ACCOUNTS[1].data)
}) })
...@@ -107,7 +107,7 @@ describe('OVM_StateManager', () => { ...@@ -107,7 +107,7 @@ describe('OVM_StateManager', () => {
OVM_StateManager.putContractStorage( OVM_StateManager.putContractStorage(
DUMMY_ACCOUNTS[0].address, DUMMY_ACCOUNTS[0].address,
DUMMY_BYTES32[0], DUMMY_BYTES32[0],
DUMMY_BYTES32[1], DUMMY_BYTES32[1]
) )
).to.not.be.reverted ).to.not.be.reverted
}) })
...@@ -116,14 +116,14 @@ describe('OVM_StateManager', () => { ...@@ -116,14 +116,14 @@ describe('OVM_StateManager', () => {
await OVM_StateManager.putContractStorage( await OVM_StateManager.putContractStorage(
DUMMY_ACCOUNTS[0].address, DUMMY_ACCOUNTS[0].address,
DUMMY_BYTES32[0], DUMMY_BYTES32[0],
DUMMY_BYTES32[1], DUMMY_BYTES32[1]
) )
await expect( await expect(
OVM_StateManager.putContractStorage( OVM_StateManager.putContractStorage(
DUMMY_ACCOUNTS[0].address, DUMMY_ACCOUNTS[0].address,
DUMMY_BYTES32[0], DUMMY_BYTES32[0],
DUMMY_BYTES32[2], DUMMY_BYTES32[2]
) )
).to.not.be.reverted ).to.not.be.reverted
}) })
...@@ -134,7 +134,7 @@ describe('OVM_StateManager', () => { ...@@ -134,7 +134,7 @@ describe('OVM_StateManager', () => {
await OVM_StateManager.putContractStorage( await OVM_StateManager.putContractStorage(
DUMMY_ACCOUNTS[0].address, DUMMY_ACCOUNTS[0].address,
DUMMY_BYTES32[0], DUMMY_BYTES32[0],
DUMMY_BYTES32[1], DUMMY_BYTES32[1]
) )
expect( expect(
...@@ -149,13 +149,13 @@ describe('OVM_StateManager', () => { ...@@ -149,13 +149,13 @@ describe('OVM_StateManager', () => {
await OVM_StateManager.putContractStorage( await OVM_StateManager.putContractStorage(
DUMMY_ACCOUNTS[0].address, DUMMY_ACCOUNTS[0].address,
DUMMY_BYTES32[0], DUMMY_BYTES32[0],
DUMMY_BYTES32[1], DUMMY_BYTES32[1]
) )
await OVM_StateManager.putContractStorage( await OVM_StateManager.putContractStorage(
DUMMY_ACCOUNTS[0].address, DUMMY_ACCOUNTS[0].address,
DUMMY_BYTES32[0], DUMMY_BYTES32[0],
DUMMY_BYTES32[2], DUMMY_BYTES32[2]
) )
expect( expect(
......
...@@ -5,9 +5,7 @@ import { ethers } from '@nomiclabs/buidler' ...@@ -5,9 +5,7 @@ import { ethers } from '@nomiclabs/buidler'
import { Contract, ContractFactory, Signer } from 'ethers' import { Contract, ContractFactory, Signer } from 'ethers'
/* Internal Imports */ /* Internal Imports */
import { import { getProxyManager, ZERO_ADDRESS, NULL_BYTES32 } from '../../../helpers'
getProxyManager, ZERO_ADDRESS, NULL_BYTES32
} from '../../../helpers'
const parseQueueElement = (result: any[]): any => { const parseQueueElement = (result: any[]): any => {
return { return {
...@@ -57,13 +55,15 @@ describe('OVM_L1ToL2TransactionQueue', () => { ...@@ -57,13 +55,15 @@ describe('OVM_L1ToL2TransactionQueue', () => {
describe('enqueue()', () => { describe('enqueue()', () => {
it('should allow users to enqueue an element', async () => { it('should allow users to enqueue an element', async () => {
const [element] = makeQueueElements(1) const [element] = makeQueueElements(1)
await expect(OVM_L1ToL2TransactionQueue.enqueue(element)).to.not.be.reverted await expect(OVM_L1ToL2TransactionQueue.enqueue(element)).to.not.be
.reverted
}) })
it('should allow users to enqueue more than one element', async () => { it('should allow users to enqueue more than one element', async () => {
const elements = makeQueueElements(10) const elements = makeQueueElements(10)
for (let i = 0; i < elements.length; i++) { for (const element of elements) {
await expect(OVM_L1ToL2TransactionQueue.enqueue(elements[i])).to.not.be.reverted await expect(OVM_L1ToL2TransactionQueue.enqueue(element)).to.not.be
.reverted
} }
}) })
}) })
...@@ -78,10 +78,12 @@ describe('OVM_L1ToL2TransactionQueue', () => { ...@@ -78,10 +78,12 @@ describe('OVM_L1ToL2TransactionQueue', () => {
}) })
it('should revert', async () => { it('should revert', async () => {
await expect(OVM_L1ToL2TransactionQueue.dequeue()).to.be.revertedWith('Sender is not allowed to enqueue.') await expect(OVM_L1ToL2TransactionQueue.dequeue()).to.be.revertedWith(
'Sender is not allowed to enqueue.'
)
}) })
}) })
describe('when the sender is the OVM_CanonicalTransactionChain', () => { describe('when the sender is the OVM_CanonicalTransactionChain', () => {
before(async () => { before(async () => {
await Proxy_Manager.setProxy( await Proxy_Manager.setProxy(
...@@ -91,7 +93,9 @@ describe('OVM_L1ToL2TransactionQueue', () => { ...@@ -91,7 +93,9 @@ describe('OVM_L1ToL2TransactionQueue', () => {
}) })
it('should revert if the queue is empty', async () => { it('should revert if the queue is empty', async () => {
await expect(OVM_L1ToL2TransactionQueue.dequeue()).to.be.revertedWith('Queue is empty.') await expect(OVM_L1ToL2TransactionQueue.dequeue()).to.be.revertedWith(
'Queue is empty.'
)
}) })
it('should allow users to dequeue an element', async () => { it('should allow users to dequeue an element', async () => {
...@@ -102,10 +106,10 @@ describe('OVM_L1ToL2TransactionQueue', () => { ...@@ -102,10 +106,10 @@ describe('OVM_L1ToL2TransactionQueue', () => {
it('should allow users to dequeue more than one element', async () => { it('should allow users to dequeue more than one element', async () => {
const elements = makeQueueElements(10) const elements = makeQueueElements(10)
for (let i = 0; i < elements.length; i++) { for (const element of elements) {
await OVM_L1ToL2TransactionQueue.enqueue(elements[i]) await OVM_L1ToL2TransactionQueue.enqueue(element)
} }
for (let i = 0; i < elements.length; i++) { for (const element of elements) {
await expect(OVM_L1ToL2TransactionQueue.dequeue()).to.not.be.reverted await expect(OVM_L1ToL2TransactionQueue.dequeue()).to.not.be.reverted
} }
}) })
...@@ -136,8 +140,8 @@ describe('OVM_L1ToL2TransactionQueue', () => { ...@@ -136,8 +140,8 @@ describe('OVM_L1ToL2TransactionQueue', () => {
it('should decrease when elements are dequeued', async () => { it('should decrease when elements are dequeued', async () => {
const elements = makeQueueElements(10) const elements = makeQueueElements(10)
for (let i = 0; i < elements.length; i++) { for (const element of elements) {
await OVM_L1ToL2TransactionQueue.enqueue(elements[i]) await OVM_L1ToL2TransactionQueue.enqueue(element)
} }
for (let i = 0; i < elements.length; i++) { for (let i = 0; i < elements.length; i++) {
await OVM_L1ToL2TransactionQueue.dequeue() await OVM_L1ToL2TransactionQueue.dequeue()
...@@ -156,7 +160,9 @@ describe('OVM_L1ToL2TransactionQueue', () => { ...@@ -156,7 +160,9 @@ describe('OVM_L1ToL2TransactionQueue', () => {
}) })
it('should revert when the queue is empty', async () => { it('should revert when the queue is empty', async () => {
await expect(OVM_L1ToL2TransactionQueue.peek()).to.be.revertedWith('Queue is empty.') await expect(OVM_L1ToL2TransactionQueue.peek()).to.be.revertedWith(
'Queue is empty.'
)
}) })
it('should return the front element if only one exists', async () => { it('should return the front element if only one exists', async () => {
...@@ -168,8 +174,8 @@ describe('OVM_L1ToL2TransactionQueue', () => { ...@@ -168,8 +174,8 @@ describe('OVM_L1ToL2TransactionQueue', () => {
it('should return the front if more than one exists', async () => { it('should return the front if more than one exists', async () => {
const elements = makeQueueElements(10) const elements = makeQueueElements(10)
for (let i = 0; i < elements.length; i++) { for (const element of elements) {
await OVM_L1ToL2TransactionQueue.enqueue(elements[i]) await OVM_L1ToL2TransactionQueue.enqueue(element)
const front = await OVM_L1ToL2TransactionQueue.peek() const front = await OVM_L1ToL2TransactionQueue.peek()
expect(parseQueueElement(front)).to.deep.equal(elements[0]) expect(parseQueueElement(front)).to.deep.equal(elements[0])
} }
...@@ -177,8 +183,8 @@ describe('OVM_L1ToL2TransactionQueue', () => { ...@@ -177,8 +183,8 @@ describe('OVM_L1ToL2TransactionQueue', () => {
it('should return the new front when elements are dequeued', async () => { it('should return the new front when elements are dequeued', async () => {
const elements = makeQueueElements(10) const elements = makeQueueElements(10)
for (let i = 0; i < elements.length; i++) { for (const element of elements) {
await OVM_L1ToL2TransactionQueue.enqueue(elements[i]) await OVM_L1ToL2TransactionQueue.enqueue(elements)
} }
for (let i = 0; i < elements.length - 1; i++) { for (let i = 0; i < elements.length - 1; i++) {
const front = await OVM_L1ToL2TransactionQueue.peek() const front = await OVM_L1ToL2TransactionQueue.peek()
......
...@@ -5,19 +5,27 @@ import { ethers } from '@nomiclabs/buidler' ...@@ -5,19 +5,27 @@ import { ethers } from '@nomiclabs/buidler'
import { ContractFactory, Contract, Signer, BigNumber } from 'ethers' import { ContractFactory, Contract, Signer, BigNumber } from 'ethers'
/* Internal Imports */ /* Internal Imports */
import { getProxyManager, getMockContract, MockContract, ZERO_ADDRESS, NULL_BYTES32, NON_NULL_BYTES32, setProxyTarget} from '../../../helpers' import {
getProxyManager,
getMockContract,
MockContract,
ZERO_ADDRESS,
NULL_BYTES32,
NON_NULL_BYTES32,
setProxyTarget,
} from '../../../helpers'
const DUMMY_BATCH_HEADER = { const DUMMY_BATCH_HEADER = {
batchIndex: 0, batchIndex: 0,
batchRoot: NULL_BYTES32, batchRoot: NULL_BYTES32,
batchSize: 0, batchSize: 0,
prevTotalElements: 0, prevTotalElements: 0,
extraData: NULL_BYTES32 extraData: NULL_BYTES32,
} }
const DUMMY_BATCH_PROOF = { const DUMMY_BATCH_PROOF = {
index: 0, index: 0,
siblings: [NULL_BYTES32] siblings: [NULL_BYTES32],
} }
const DUMMY_OVM_TRANSACTION = { const DUMMY_OVM_TRANSACTION = {
...@@ -27,7 +35,7 @@ const DUMMY_OVM_TRANSACTION = { ...@@ -27,7 +35,7 @@ const DUMMY_OVM_TRANSACTION = {
origin: ZERO_ADDRESS, origin: ZERO_ADDRESS,
msgSender: ZERO_ADDRESS, msgSender: ZERO_ADDRESS,
gasLimit: 0, gasLimit: 0,
data: NULL_BYTES32 data: NULL_BYTES32,
} }
describe('OVM_FraudVerifier', () => { describe('OVM_FraudVerifier', () => {
...@@ -44,7 +52,7 @@ describe('OVM_FraudVerifier', () => { ...@@ -44,7 +52,7 @@ describe('OVM_FraudVerifier', () => {
Mock__OVM_StateCommitmentChain = await getMockContract( Mock__OVM_StateCommitmentChain = await getMockContract(
await ethers.getContractFactory('OVM_StateCommitmentChain') await ethers.getContractFactory('OVM_StateCommitmentChain')
) )
Mock__OVM_CanonicalTransactionChain = await getMockContract( Mock__OVM_CanonicalTransactionChain = await getMockContract(
await ethers.getContractFactory('OVM_CanonicalTransactionChain') await ethers.getContractFactory('OVM_CanonicalTransactionChain')
) )
...@@ -82,18 +90,22 @@ describe('OVM_FraudVerifier', () => { ...@@ -82,18 +90,22 @@ describe('OVM_FraudVerifier', () => {
) )
Mock__OVM_StateTransitionerFactory.setReturnValues('create', [ Mock__OVM_StateTransitionerFactory.setReturnValues('create', [
Mock__OVM_StateTransitioner.address Mock__OVM_StateTransitioner.address,
]) ])
}) })
let Factory__OVM_FraudVerifier: ContractFactory let Factory__OVM_FraudVerifier: ContractFactory
before(async () => { before(async () => {
Factory__OVM_FraudVerifier = await ethers.getContractFactory('OVM_FraudVerifier') Factory__OVM_FraudVerifier = await ethers.getContractFactory(
'OVM_FraudVerifier'
)
}) })
let OVM_FraudVerifier: Contract let OVM_FraudVerifier: Contract
beforeEach(async () => { beforeEach(async () => {
OVM_FraudVerifier = await Factory__OVM_FraudVerifier.deploy(Proxy_Manager.address) OVM_FraudVerifier = await Factory__OVM_FraudVerifier.deploy(
Proxy_Manager.address
)
}) })
describe('initializeFraudVerification', () => { describe('initializeFraudVerification', () => {
...@@ -123,7 +135,9 @@ describe('OVM_FraudVerifier', () => { ...@@ -123,7 +135,9 @@ describe('OVM_FraudVerifier', () => {
describe('when provided an invalid transaction inclusion proof', () => { describe('when provided an invalid transaction inclusion proof', () => {
before(() => { before(() => {
Mock__OVM_CanonicalTransactionChain.setReturnValues('verifyElement', [false]) Mock__OVM_CanonicalTransactionChain.setReturnValues('verifyElement', [
false,
])
}) })
it('should revert', async () => { it('should revert', async () => {
...@@ -142,12 +156,14 @@ describe('OVM_FraudVerifier', () => { ...@@ -142,12 +156,14 @@ describe('OVM_FraudVerifier', () => {
describe('when provided a valid transaction inclusion proof', () => { describe('when provided a valid transaction inclusion proof', () => {
before(() => { before(() => {
Mock__OVM_CanonicalTransactionChain.setReturnValues('verifyElement', [true]) Mock__OVM_CanonicalTransactionChain.setReturnValues('verifyElement', [
true,
])
}) })
it('should deploy a new state transitioner', async () => { it('should deploy a new state transitioner', async () => {
await expect( await expect(
OVM_FraudVerifier.initializeFraudVerification( OVM_FraudVerifier.initializeFraudVerification(
NULL_BYTES32, NULL_BYTES32,
DUMMY_BATCH_HEADER, DUMMY_BATCH_HEADER,
DUMMY_BATCH_PROOF, DUMMY_BATCH_PROOF,
...@@ -165,11 +181,12 @@ describe('OVM_FraudVerifier', () => { ...@@ -165,11 +181,12 @@ describe('OVM_FraudVerifier', () => {
}) })
}) })
describe('finalizeFraudVerification', () => { describe('finalizeFraudVerification', () => {
beforeEach(async () => { beforeEach(async () => {
Mock__OVM_StateCommitmentChain.setReturnValues('verifyElement', [true]) Mock__OVM_StateCommitmentChain.setReturnValues('verifyElement', [true])
Mock__OVM_CanonicalTransactionChain.setReturnValues('verifyElement', [true]) Mock__OVM_CanonicalTransactionChain.setReturnValues('verifyElement', [
true,
])
await OVM_FraudVerifier.initializeFraudVerification( await OVM_FraudVerifier.initializeFraudVerification(
NULL_BYTES32, NULL_BYTES32,
DUMMY_BATCH_HEADER, DUMMY_BATCH_HEADER,
...@@ -195,7 +212,9 @@ describe('OVM_FraudVerifier', () => { ...@@ -195,7 +212,9 @@ describe('OVM_FraudVerifier', () => {
DUMMY_BATCH_HEADER, DUMMY_BATCH_HEADER,
DUMMY_BATCH_PROOF DUMMY_BATCH_PROOF
) )
).to.be.revertedWith('State transition process must be completed prior to finalization.') ).to.be.revertedWith(
'State transition process must be completed prior to finalization.'
)
}) })
}) })
...@@ -207,7 +226,7 @@ describe('OVM_FraudVerifier', () => { ...@@ -207,7 +226,7 @@ describe('OVM_FraudVerifier', () => {
describe('when provided an invalid post-state root index', () => { describe('when provided an invalid post-state root index', () => {
const batchProof = { const batchProof = {
...DUMMY_BATCH_PROOF, ...DUMMY_BATCH_PROOF,
index: DUMMY_BATCH_PROOF.index + 2 index: DUMMY_BATCH_PROOF.index + 2,
} }
it('should revert', async () => { it('should revert', async () => {
...@@ -227,12 +246,14 @@ describe('OVM_FraudVerifier', () => { ...@@ -227,12 +246,14 @@ describe('OVM_FraudVerifier', () => {
describe('when provided a valid post-state root index', () => { describe('when provided a valid post-state root index', () => {
const batchProof = { const batchProof = {
...DUMMY_BATCH_PROOF, ...DUMMY_BATCH_PROOF,
index: DUMMY_BATCH_PROOF.index + 1 index: DUMMY_BATCH_PROOF.index + 1,
} }
describe('when provided an invalid pre-state root inclusion proof', () => { describe('when provided an invalid pre-state root inclusion proof', () => {
beforeEach(() => { beforeEach(() => {
Mock__OVM_StateCommitmentChain.setReturnValues('verifyElement', [false]) Mock__OVM_StateCommitmentChain.setReturnValues('verifyElement', [
false,
])
}) })
it('should revert', async () => { it('should revert', async () => {
...@@ -251,14 +272,19 @@ describe('OVM_FraudVerifier', () => { ...@@ -251,14 +272,19 @@ describe('OVM_FraudVerifier', () => {
describe('when provided a valid pre-state root inclusion proof', () => { describe('when provided a valid pre-state root inclusion proof', () => {
before(() => { before(() => {
Mock__OVM_StateCommitmentChain.setReturnValues('verifyElement', [true]) Mock__OVM_StateCommitmentChain.setReturnValues('verifyElement', [
true,
])
}) })
describe('when provided an invalid post-state root inclusion proof', () => { describe('when provided an invalid post-state root inclusion proof', () => {
beforeEach(() => { beforeEach(() => {
Mock__OVM_StateCommitmentChain.setReturnValues('verifyElement', (stateRoot: string, ...args: any) => { Mock__OVM_StateCommitmentChain.setReturnValues(
return [stateRoot !== NON_NULL_BYTES32] 'verifyElement',
}) (stateRoot: string, ...args: any) => {
return [stateRoot !== NON_NULL_BYTES32]
}
)
}) })
it('should revert', async () => { it('should revert', async () => {
...@@ -277,12 +303,17 @@ describe('OVM_FraudVerifier', () => { ...@@ -277,12 +303,17 @@ describe('OVM_FraudVerifier', () => {
describe('when provided a valid post-state root inclusion proof', () => { describe('when provided a valid post-state root inclusion proof', () => {
before(() => { before(() => {
Mock__OVM_StateCommitmentChain.setReturnValues('verifyElement', [true]) Mock__OVM_StateCommitmentChain.setReturnValues('verifyElement', [
true,
])
}) })
describe('when the provided post-state root does not differ from the computed one', () => { describe('when the provided post-state root does not differ from the computed one', () => {
before(() => { before(() => {
Mock__OVM_StateTransitioner.setReturnValues('getPostStateRoot', [NON_NULL_BYTES32]) Mock__OVM_StateTransitioner.setReturnValues(
'getPostStateRoot',
[NON_NULL_BYTES32]
)
}) })
it('should revert', async () => { it('should revert', async () => {
...@@ -295,13 +326,18 @@ describe('OVM_FraudVerifier', () => { ...@@ -295,13 +326,18 @@ describe('OVM_FraudVerifier', () => {
DUMMY_BATCH_HEADER, DUMMY_BATCH_HEADER,
batchProof batchProof
) )
).to.be.revertedWith('State transition has not been proven fraudulent.') ).to.be.revertedWith(
'State transition has not been proven fraudulent.'
)
}) })
}) })
describe('when the provided post-state root differs from the computed one', () => { describe('when the provided post-state root differs from the computed one', () => {
before(() => { before(() => {
Mock__OVM_StateTransitioner.setReturnValues('getPostStateRoot', [NULL_BYTES32]) Mock__OVM_StateTransitioner.setReturnValues(
'getPostStateRoot',
[NULL_BYTES32]
)
}) })
it('should succeed and attempt to delete a state batch', async () => { it('should succeed and attempt to delete a state batch', async () => {
...@@ -313,12 +349,19 @@ describe('OVM_FraudVerifier', () => { ...@@ -313,12 +349,19 @@ describe('OVM_FraudVerifier', () => {
DUMMY_BATCH_HEADER, DUMMY_BATCH_HEADER,
batchProof batchProof
) )
expect( expect(
Mock__OVM_StateCommitmentChain.getCallData('deleteStateBatch', 0) Mock__OVM_StateCommitmentChain.getCallData(
).to.deep.equal([Object.values(DUMMY_BATCH_HEADER).map((value) => { 'deleteStateBatch',
return Number.isInteger(value) ? BigNumber.from(value) : value 0
})]) )
).to.deep.equal([
Object.values(DUMMY_BATCH_HEADER).map((value) => {
return Number.isInteger(value)
? BigNumber.from(value)
: value
}),
])
}) })
}) })
}) })
......
/* tslint:disable:no-empty */
import { expect } from '../../../setup' import { expect } from '../../../setup'
describe('OVM_StateTransitioner', () => { describe('OVM_StateTransitioner', () => {
describe('proveContractState', () => { describe('proveContractState', () => {
describe('when provided an invalid code hash', () => { describe('when provided an invalid code hash', () => {
it('should revert', async () => { it('should revert', async () => {})
})
}) })
describe('when provided a valid code hash', () => { describe('when provided a valid code hash', () => {
describe('when provided an invalid account inclusion proof', () => { describe('when provided an invalid account inclusion proof', () => {
it('should revert', async () => { it('should revert', async () => {})
})
}) })
describe('when provided a valid account inclusion proof', () => { describe('when provided a valid account inclusion proof', () => {})
})
}) })
}) })
describe('proveStorageSlot', () => { describe('proveStorageSlot', () => {
describe('when the corresponding account is not proven', () => { describe('when the corresponding account is not proven', () => {
it('should revert', async () => { it('should revert', async () => {})
})
}) })
describe('when the corresponding account is proven', () => { describe('when the corresponding account is proven', () => {
describe('when provided an invalid slot inclusion proof', () => { describe('when provided an invalid slot inclusion proof', () => {
it('should revert', async () => { it('should revert', async () => {})
})
}) })
describe('when provided a valid slot inclusion proof', () => { describe('when provided a valid slot inclusion proof', () => {})
})
}) })
}) })
...@@ -47,63 +36,45 @@ describe('OVM_StateTransitioner', () => { ...@@ -47,63 +36,45 @@ describe('OVM_StateTransitioner', () => {
describe('commitContractState', () => { describe('commitContractState', () => {
describe('when the account was not changed', () => { describe('when the account was not changed', () => {
it('should revert', async () => { it('should revert', async () => {})
})
}) })
describe('when the account was changed', () => { describe('when the account was changed', () => {
describe('when the account has not been committed', () => { describe('when the account has not been committed', () => {
it('should commit the account and update the state', async () => { it('should commit the account and update the state', async () => {})
})
}) })
describe('when the account was already committed', () => { describe('when the account was already committed', () => {
it('should revert', () => { it('should revert', () => {})
})
}) })
}) })
}) })
describe('commitStorageSlot', () => { describe('commitStorageSlot', () => {
describe('when the slot was not changed', () => { describe('when the slot was not changed', () => {
it('should revert', async () => { it('should revert', async () => {})
})
}) })
describe('when the slot was changed', () => { describe('when the slot was changed', () => {
describe('when the slot has not been committed', () => { describe('when the slot has not been committed', () => {
it('should commit the slot and update the state', async () => { it('should commit the slot and update the state', async () => {})
})
}) })
describe('when the slot was already committed', () => { describe('when the slot was already committed', () => {
it('should revert', () => { it('should revert', () => {})
})
}) })
}) })
}) })
describe('completeTransition', () => { describe('completeTransition', () => {
describe('when there are uncommitted accounts', () => { describe('when there are uncommitted accounts', () => {
it('should revert', async () => { it('should revert', async () => {})
})
}) })
describe('when there are uncommitted storage slots', () => { describe('when there are uncommitted storage slots', () => {
it('should revert', async () => { it('should revert', async () => {})
})
}) })
describe('when all state changes are committed', () => { describe('when all state changes are committed', () => {})
})
}) })
}) })
...@@ -2,19 +2,22 @@ ...@@ -2,19 +2,22 @@
import fsExtra from 'fs-extra' import fsExtra from 'fs-extra'
import { internalTask } from '@nomiclabs/buidler/config' import { internalTask } from '@nomiclabs/buidler/config'
import { pluralize } from '@nomiclabs/buidler/internal/util/strings' import { pluralize } from '@nomiclabs/buidler/internal/util/strings'
import { getArtifactFromContractOutput, saveArtifact } from '@nomiclabs/buidler/internal/artifacts' import {
getArtifactFromContractOutput,
saveArtifact,
} from '@nomiclabs/buidler/internal/artifacts'
import { import {
TASK_COMPILE_GET_COMPILER_INPUT, TASK_COMPILE_GET_COMPILER_INPUT,
TASK_BUILD_ARTIFACTS, TASK_BUILD_ARTIFACTS,
TASK_COMPILE_GET_SOURCE_PATHS, TASK_COMPILE_GET_SOURCE_PATHS,
TASK_COMPILE_CHECK_CACHE, TASK_COMPILE_CHECK_CACHE,
TASK_COMPILE_COMPILE TASK_COMPILE_COMPILE,
} from '@nomiclabs/buidler/builtin-tasks/task-names' } from '@nomiclabs/buidler/builtin-tasks/task-names'
internalTask( internalTask(
TASK_COMPILE_GET_COMPILER_INPUT, TASK_COMPILE_GET_COMPILER_INPUT,
async (_, { config, run }, runSuper) => { async (_, { config, run }, runSuper) => {
const input = await runSuper(); const input = await runSuper()
// Insert the "storageLayout" input option. // Insert the "storageLayout" input option.
input.settings.outputSelection['*']['*'].push('storageLayout') input.settings.outputSelection['*']['*'].push('storageLayout')
...@@ -25,51 +28,51 @@ internalTask( ...@@ -25,51 +28,51 @@ internalTask(
internalTask(TASK_BUILD_ARTIFACTS).setAction( internalTask(TASK_BUILD_ARTIFACTS).setAction(
async ({ force }, { config, run }) => { async ({ force }, { config, run }) => {
const sources = await run(TASK_COMPILE_GET_SOURCE_PATHS); const sources = await run(TASK_COMPILE_GET_SOURCE_PATHS)
if (sources.length === 0) { if (sources.length === 0) {
console.log("No Solidity source file available."); console.log('No Solidity source file available.')
return; return
} }
const isCached: boolean = await run(TASK_COMPILE_CHECK_CACHE, { force }); const isCached: boolean = await run(TASK_COMPILE_CHECK_CACHE, { force })
if (isCached) { if (isCached) {
console.log( console.log(
"All contracts have already been compiled, skipping compilation." 'All contracts have already been compiled, skipping compilation.'
); )
return; return
} }
const compilationOutput = await run(TASK_COMPILE_COMPILE); const compilationOutput = await run(TASK_COMPILE_COMPILE)
if (compilationOutput === undefined) { if (compilationOutput === undefined) {
return; return
} }
await fsExtra.ensureDir(config.paths.artifacts); await fsExtra.ensureDir(config.paths.artifacts)
let numberOfContracts = 0; let numberOfContracts = 0
for (const file of Object.values<any>(compilationOutput.contracts)) { for (const file of Object.values<any>(compilationOutput.contracts)) {
for (const [contractName, contractOutput] of Object.entries(file)) { for (const [contractName, contractOutput] of Object.entries(file)) {
const artifact: any = getArtifactFromContractOutput( const artifact: any = getArtifactFromContractOutput(
contractName, contractName,
contractOutput contractOutput
); )
numberOfContracts += 1; numberOfContracts += 1
// Only difference here, set the "storageLayout" field of the artifact. // Only difference here, set the "storageLayout" field of the artifact.
artifact.storageLayout = (contractOutput as any).storageLayout artifact.storageLayout = (contractOutput as any).storageLayout
await saveArtifact(config.paths.artifacts, artifact); await saveArtifact(config.paths.artifacts, artifact)
} }
} }
console.log( console.log(
"Compiled", 'Compiled',
numberOfContracts, numberOfContracts,
pluralize(numberOfContracts, "contract"), pluralize(numberOfContracts, 'contract'),
"successfully" 'successfully'
); )
} }
) )
...@@ -8,24 +8,31 @@ export const encodeRevertData = ( ...@@ -8,24 +8,31 @@ export const encodeRevertData = (
ovmGasRefund: number = 0 ovmGasRefund: number = 0
): string => { ): string => {
const abiEncoded: string = ethers.utils.defaultAbiCoder.encode( const abiEncoded: string = ethers.utils.defaultAbiCoder.encode(
['uint256','uint256','uint256','bytes'], ['uint256', 'uint256', 'uint256', 'bytes'],
[flag, nuisanceGasLeft, ovmGasRefund, data] [flag, nuisanceGasLeft, ovmGasRefund, data]
) )
return abiEncoded return abiEncoded
} }
export const decodeRevertData = (revertData: string): any => {
export const decodeRevertData = (
revertData: string
): any => {
// const length: number = revertData.length/2 - 1 // const length: number = revertData.length/2 - 1
// const reencodedRevertData = '0x' + hexZeroPad('0x' + length.toString(16), 32) + revertData.slice(2) // const reencodedRevertData = '0x' + hexZeroPad('0x' + length.toString(16), 32) + revertData.slice(2)
const decoded = ethers.utils.defaultAbiCoder.decode( const decoded = ethers.utils.defaultAbiCoder.decode(
['uint256','uint256','uint256','bytes'], ['uint256', 'uint256', 'uint256', 'bytes'],
revertData revertData
) )
console.log(`flag is: ${decoded[0].toNumber()}`) console.log(`flag is: ${decoded[0].toNumber()}`)
return '[revertFlag:' + Object.keys(REVERT_FLAGS)[decoded[0]] + ', nuisanceGasLeft:' + decoded[1] + ', ovmGasRefund: ' + decoded[2] + ', data: ' + decoded[3] + ']' return (
'[revertFlag:' +
Object.keys(REVERT_FLAGS)[decoded[0]] +
', nuisanceGasLeft:' +
decoded[1] +
', ovmGasRefund: ' +
decoded[2] +
', data: ' +
decoded[3] +
']'
)
} }
export const REVERT_FLAGS = { export const REVERT_FLAGS = {
...@@ -37,5 +44,5 @@ export const REVERT_FLAGS = { ...@@ -37,5 +44,5 @@ export const REVERT_FLAGS = {
UNSAFE_BYTECODE: 5, UNSAFE_BYTECODE: 5,
CREATE_COLLISION: 6, CREATE_COLLISION: 6,
STATIC_VIOLATION: 7, STATIC_VIOLATION: 7,
CREATE_EXCEPTION: 8 CREATE_EXCEPTION: 8,
} }
...@@ -4,4 +4,4 @@ import { safetyCheckerTests } from './json/safety-checker.test.json' ...@@ -4,4 +4,4 @@ import { safetyCheckerTests } from './json/safety-checker.test.json'
export const RLP_TEST_JSON = rlpTests export const RLP_TEST_JSON = rlpTests
export const CREATE2_TEST_JSON = create2Tests export const CREATE2_TEST_JSON = create2Tests
export const SAFETY_CHECKER_TEST_JSON = safetyCheckerTests export const SAFETY_CHECKER_TEST_JSON = safetyCheckerTests
\ No newline at end of file
...@@ -5,7 +5,7 @@ import { makeAddress } from '../byte-utils' ...@@ -5,7 +5,7 @@ import { makeAddress } from '../byte-utils'
import { OVMAccount } from '../types/ovm-types' import { OVMAccount } from '../types/ovm-types'
export const DUMMY_ACCOUNTS: Array<{ export const DUMMY_ACCOUNTS: Array<{
address: string, address: string
data: OVMAccount data: OVMAccount
}> = [ }> = [
{ {
...@@ -27,5 +27,5 @@ export const DUMMY_ACCOUNTS: Array<{ ...@@ -27,5 +27,5 @@ export const DUMMY_ACCOUNTS: Array<{
codeHash: DUMMY_BYTES32[3], codeHash: DUMMY_BYTES32[3],
ethAddress: NON_ZERO_ADDRESS, ethAddress: NON_ZERO_ADDRESS,
}, },
} },
] ]
...@@ -3,7 +3,7 @@ import { NON_ZERO_ADDRESS } from '../constants' ...@@ -3,7 +3,7 @@ import { NON_ZERO_ADDRESS } from '../constants'
export const DUMMY_CONTEXT = { export const DUMMY_CONTEXT = {
GLOBAL: { GLOBAL: {
ovmCHAINID: 11 ovmCHAINID: 11,
}, },
TRANSACTION: { TRANSACTION: {
ovmORIGIN: NON_ZERO_ADDRESS, ovmORIGIN: NON_ZERO_ADDRESS,
...@@ -15,6 +15,6 @@ export const DUMMY_CONTEXT = { ...@@ -15,6 +15,6 @@ export const DUMMY_CONTEXT = {
MESSAGE: { MESSAGE: {
ovmCALLER: NON_ZERO_ADDRESS, ovmCALLER: NON_ZERO_ADDRESS,
ovmADDRESS: NON_ZERO_ADDRESS, ovmADDRESS: NON_ZERO_ADDRESS,
ovmSTATICCTX: true ovmSTATICCTX: true,
} },
} }
...@@ -24,7 +24,7 @@ export const bindMockWatcherToVM = (): void => { ...@@ -24,7 +24,7 @@ export const bindMockWatcherToVM = (): void => {
// Set up some things we'll need for later. // Set up some things we'll need for later.
let txid: string let txid: string
let messages: Array<{ const messages: Array<{
address: string address: string
sighash: string sighash: string
calldata: string calldata: string
...@@ -34,7 +34,7 @@ export const bindMockWatcherToVM = (): void => { ...@@ -34,7 +34,7 @@ export const bindMockWatcherToVM = (): void => {
// Modify the vm.runTx function to capture an ID for each transaction. // Modify the vm.runTx function to capture an ID for each transaction.
const originalRunTx = vm.runTx.bind(vm) const originalRunTx = vm.runTx.bind(vm)
const modifiedRunTx = async (opts: any): Promise<any> => { function modifiedRunTx(opts: any): Promise<any> {
// Buidler runs transactions multiple times (e.g., for gas estimation). // Buidler runs transactions multiple times (e.g., for gas estimation).
// Here we're computing a unique ID for each transaction (based on sender, // Here we're computing a unique ID for each transaction (based on sender,
// nonce, and transaction data) so that we don't log calls multiple times. // nonce, and transaction data) so that we don't log calls multiple times.
...@@ -54,7 +54,7 @@ export const bindMockWatcherToVM = (): void => { ...@@ -54,7 +54,7 @@ export const bindMockWatcherToVM = (): void => {
// Modify the pre-message handler to capture calldata. // Modify the pre-message handler to capture calldata.
const originalBeforeMessageHandler = vmTracer['_beforeMessageHandler' as any] const originalBeforeMessageHandler = vmTracer['_beforeMessageHandler' as any]
const modifiedBeforeMessageHandler = async (message: any, next: any) => { function modifiedBeforeMessageHandler(message: any, next: any) {
// We only care about capturing if we're sending to one of our mocks. // We only care about capturing if we're sending to one of our mocks.
const address = message.to const address = message.to
? toHexString(message.to).toLowerCase() ? toHexString(message.to).toLowerCase()
...@@ -93,7 +93,7 @@ export const bindMockWatcherToVM = (): void => { ...@@ -93,7 +93,7 @@ export const bindMockWatcherToVM = (): void => {
// Modify the post-message handler to insert the correct return data. // Modify the post-message handler to insert the correct return data.
const originalAfterMessageHandler = vmTracer['_afterMessageHandler' as any] const originalAfterMessageHandler = vmTracer['_afterMessageHandler' as any]
const modifiedAfterMessageHandler = async (result: any, next: any) => { function modifiedAfterMessageHandler(result: any, next: any) {
// We don't need to do anything if we haven't stored any mock messages. // We don't need to do anything if we haven't stored any mock messages.
if (messages.length > 0) { if (messages.length > 0) {
// We need to look at the messages backwards since the first result will // We need to look at the messages backwards since the first result will
...@@ -106,13 +106,11 @@ export const bindMockWatcherToVM = (): void => { ...@@ -106,13 +106,11 @@ export const bindMockWatcherToVM = (): void => {
// Compute our return values. // Compute our return values.
const inputParams = contract.__spec const inputParams = contract.__spec
? contract.__spec.interface.decodeFunctionData( ? contract.__spec.interface.decodeFunctionData(
fn.functionName, fn.functionName,
contract.__spec.interface.getSighash(fn.functionName) + message.calldata.slice(2) contract.__spec.interface.getSighash(fn.functionName) +
) message.calldata.slice(2)
: ethers.utils.defaultAbiCoder.decode( )
fn.inputTypes, : ethers.utils.defaultAbiCoder.decode(fn.inputTypes, message.calldata)
message.calldata
)
const returnValues = Array.isArray(fn.returnValues) const returnValues = Array.isArray(fn.returnValues)
? fn.returnValues ? fn.returnValues
...@@ -120,9 +118,9 @@ export const bindMockWatcherToVM = (): void => { ...@@ -120,9 +118,9 @@ export const bindMockWatcherToVM = (): void => {
const returnBuffer = fromHexString( const returnBuffer = fromHexString(
contract.__spec contract.__spec
? contract.__spec.interface.encodeFunctionResult( ? contract.__spec.interface.encodeFunctionResult(
fn.functionName, fn.functionName,
returnValues returnValues
) )
: ethers.utils.defaultAbiCoder.encode(fn.outputTypes, returnValues) : ethers.utils.defaultAbiCoder.encode(fn.outputTypes, returnValues)
) )
...@@ -175,18 +173,20 @@ export const bindMockContractToVM = ( ...@@ -175,18 +173,20 @@ export const bindMockContractToVM = (
} }
} }
const sighash = mock.interface.getSighash(functionName) const sig = mock.interface.getSighash(functionName)
return calls[sighash] || [] return calls[sig] || []
} }
if (!Array.isArray(spec)) { if (!Array.isArray(spec)) {
;(mock as any).__spec = spec ;(mock as any).__spec = spec
;(mock as any).__sigmap = Object.keys(mock.interface.functions).reduce(
;(mock as any).__sigmap = Object.keys(mock.interface.functions).reduce((sigmap, fn) => { (sigmap, fn) => {
fn = fn.split('(')[0] fn = fn.split('(')[0]
sigmap[spec.interface.getSighash(fn)] = mock.interface.getSighash(fn) sigmap[spec.interface.getSighash(fn)] = mock.interface.getSighash(fn)
return sigmap return sigmap
}, {}) },
{}
)
} }
;(mock as any).getCallCount = (functionName: string): number => { ;(mock as any).getCallCount = (functionName: string): number => {
...@@ -204,11 +204,9 @@ export const bindMockContractToVM = ( ...@@ -204,11 +204,9 @@ export const bindMockContractToVM = (
const iface = mock.__spec ? mock.__spec.interface : mock.interface const iface = mock.__spec ? mock.__spec.interface : mock.interface
const calldata = iface.getSighash(functionName) + calls[callIndex].slice(10) const calldata = iface.getSighash(functionName) + calls[callIndex].slice(10)
return iface return iface.decodeFunctionData(functionName, calldata).map((element) => {
.decodeFunctionData(functionName, calldata) return element
.map((element) => { })
return element
})
} }
;(mock as any).setReturnValues = ( ;(mock as any).setReturnValues = (
functionName: string, functionName: string,
......
...@@ -6,11 +6,7 @@ import { FunctionFragment, ParamType } from 'ethers/lib/utils' ...@@ -6,11 +6,7 @@ import { FunctionFragment, ParamType } from 'ethers/lib/utils'
/* Internal Imports */ /* Internal Imports */
import { MockContract, MockContractFunction } from './mock-contract.types' import { MockContract, MockContractFunction } from './mock-contract.types'
import { bindMockContractToVM, bindMockWatcherToVM } from './mock-binding' import { bindMockContractToVM, bindMockWatcherToVM } from './mock-binding'
import { import { SolidityCompiler, getDefaultCompiler, compile } from '../compilation'
SolidityCompiler,
getDefaultCompiler,
compile,
} from '../compilation'
/** /**
* Generates contract code for a mock contract. * Generates contract code for a mock contract.
...@@ -210,12 +206,12 @@ export const getMockContract = async ( ...@@ -210,12 +206,12 @@ export const getMockContract = async (
originalDefinePropertyFn(object, name, props) originalDefinePropertyFn(object, name, props)
} }
const MockContract = (await MockContractFactory.deploy()) as MockContract const mock = (await MockContractFactory.deploy()) as MockContract
Object.defineProperty = originalDefinePropertyFn Object.defineProperty = originalDefinePropertyFn
bindMockWatcherToVM() bindMockWatcherToVM()
bindMockContractToVM(MockContract, fns, spec) bindMockContractToVM(mock, fns, spec)
return MockContract return mock
} }
...@@ -19,10 +19,7 @@ export const makeProxies = async ( ...@@ -19,10 +19,7 @@ export const makeProxies = async (
Proxy_Manager.address Proxy_Manager.address
) )
await Proxy_Manager.setProxy( await Proxy_Manager.setProxy(name, Proxy_Forwarder.address)
name,
Proxy_Forwarder.address
)
} }
} }
...@@ -32,15 +29,10 @@ export const setProxyTarget = async ( ...@@ -32,15 +29,10 @@ export const setProxyTarget = async (
target: Contract target: Contract
): Promise<void> => { ): Promise<void> => {
await makeProxies(Proxy_Manager, [name]) await makeProxies(Proxy_Manager, [name])
await Proxy_Manager.setTarget( await Proxy_Manager.setTarget(name, target.address)
name,
target.address
)
} }
export const getProxyManager = async (): Promise<Contract> => { export const getProxyManager = async (): Promise<Contract> => {
return (await ethers.getContractFactory( return (await ethers.getContractFactory('Proxy_Manager')).deploy()
'Proxy_Manager'
)).deploy()
} }
import bre, { ethers } from '@nomiclabs/buidler' import bre, { ethers } from '@nomiclabs/buidler'
import { Contract, BigNumber, ContractFactory } from "ethers"; import { Contract, BigNumber, ContractFactory } from 'ethers'
import { keccak256, defaultAbiCoder } from "ethers/lib/utils"; import { keccak256, defaultAbiCoder } from 'ethers/lib/utils'
import { remove0x } from '../byte-utils' import { remove0x } from '../byte-utils'
import { readArtifact } from '@nomiclabs/buidler/internal/artifacts'; import { readArtifact } from '@nomiclabs/buidler/internal/artifacts'
const getFlattenedKeys = ( const getFlattenedKeys = (depth: number, value: any): string[] => {
depth: number,
value: any,
): string[] => {
if (depth === 0) { if (depth === 0) {
return [] return []
} }
let keys = Object.keys(value) let keys = Object.keys(value)
if (depth > 1) { if (depth > 1) {
keys = keys.concat( keys = keys.concat(getFlattenedKeys(depth - 1, Object.values(value)[0]))
getFlattenedKeys(
depth - 1,
Object.values(value)[0]
)
)
} }
return keys return keys
...@@ -38,29 +30,25 @@ const toHexString32 = ( ...@@ -38,29 +30,25 @@ const toHexString32 = (
} }
} }
const getFlattenedValues = ( const getFlattenedValues = (depth: number, value: any): any[] => {
depth: number,
value: any
): any[] => {
if (depth > 0) { if (depth > 0) {
return getFlattenedValues( return getFlattenedValues(depth - 1, Object.values(value)[0])
depth - 1,
Object.values(value)[0]
)
} }
if (typeof value === 'object' && value !== null) { if (typeof value === 'object' && value !== null) {
return Object.keys(value).map((key) => { return Object.keys(value).map((key) => {
return { return {
label: key, label: key,
value: toHexString32(value[key]) value: toHexString32(value[key]),
} }
}) })
} else { } else {
return [{ return [
label: "default", {
value: toHexString32(value) label: 'default',
}] value: toHexString32(value),
},
]
} }
} }
...@@ -68,33 +56,24 @@ const getStorageSlotHash = ( ...@@ -68,33 +56,24 @@ const getStorageSlotHash = (
slot: number, slot: number,
depth: number, depth: number,
value: any value: any
): string =>{ ): string => {
let keys = [] let keys = []
if (typeof value === 'object' && value !== null) { if (typeof value === 'object' && value !== null) {
keys = getFlattenedKeys(depth, value) keys = getFlattenedKeys(depth, value)
} }
if (keys.length === 0) { if (keys.length === 0) {
return defaultAbiCoder.encode( return defaultAbiCoder.encode(['uint256'], [slot])
['uint256'],
[slot]
)
} else { } else {
let slotHash = toHexString32(slot) let slotHash = toHexString32(slot)
for (const key of keys) { for (const key of keys) {
slotHash = keccak256( slotHash = keccak256(toHexString32(key) + remove0x(slotHash))
toHexString32(key) +
remove0x(slotHash)
)
} }
return slotHash return slotHash
} }
} }
const parseInputSlots = ( const parseInputSlots = (layout: any, inputTypeName: string): any[] => {
layout: any,
inputTypeName: string
): any[] => {
const inputType = layout.types[inputTypeName] const inputType = layout.types[inputTypeName]
if (inputType.encoding === 'mapping') { if (inputType.encoding === 'mapping') {
...@@ -104,14 +83,16 @@ const parseInputSlots = ( ...@@ -104,14 +83,16 @@ const parseInputSlots = (
return inputType.members.map((member: any) => { return inputType.members.map((member: any) => {
return { return {
label: member.label, label: member.label,
slot: member.slot slot: member.slot,
} }
}) })
} else { } else {
return [{ return [
label: "default", {
slot: 0 label: 'default',
}] slot: 0,
},
]
} }
} else { } else {
throw new Error('Encoding type not supported.') throw new Error('Encoding type not supported.')
...@@ -122,17 +103,23 @@ export const getModifiableStorageFactory = async ( ...@@ -122,17 +103,23 @@ export const getModifiableStorageFactory = async (
name: string name: string
): Promise<ContractFactory> => { ): Promise<ContractFactory> => {
const contractFactory = await ethers.getContractFactory(name) const contractFactory = await ethers.getContractFactory(name)
const proxyFactory = await ethers.getContractFactory('Helper_ModifiableStorage') const proxyFactory = await ethers.getContractFactory(
'Helper_ModifiableStorage'
)
const originalDeploy = contractFactory.deploy.bind(contractFactory) const originalDeploy = contractFactory.deploy.bind(contractFactory)
contractFactory.deploy = async (...args: any[]): Promise<Contract> => { contractFactory.deploy = async (...args: any[]): Promise<Contract> => {
const originalDefinePropertyFn = Object.defineProperty const originalDefinePropertyFn = Object.defineProperty
Object.defineProperty = (object: any, name: string, props: any): void => { Object.defineProperty = (
object: any,
propName: string,
props: any
): void => {
if (props.writable === false) { if (props.writable === false) {
props.writable = true props.writable = true
} }
originalDefinePropertyFn(object, name, props) originalDefinePropertyFn(object, propName, props)
} }
const contract = await originalDeploy(...args) const contract = await originalDeploy(...args)
...@@ -144,14 +131,16 @@ export const getModifiableStorageFactory = async ( ...@@ -144,14 +131,16 @@ export const getModifiableStorageFactory = async (
;(contract as any).__setContractStorage = async (value: any) => { ;(contract as any).__setContractStorage = async (value: any) => {
await setContractStorage( await setContractStorage(
contract, contract,
(await readArtifact(bre.config.paths.artifacts, name) as any).storageLayout, ((await readArtifact(bre.config.paths.artifacts, name)) as any)
.storageLayout,
value value
) )
} }
;(contract as any).__checkContractStorage = async (value: any) => { ;(contract as any).__checkContractStorage = async (value: any) => {
await checkContractStorage( await checkContractStorage(
contract, contract,
(await readArtifact(bre.config.paths.artifacts, name) as any).storageLayout, ((await readArtifact(bre.config.paths.artifacts, name)) as any)
.storageLayout,
value value
) )
} }
...@@ -171,40 +160,35 @@ export const setContractStorage = async ( ...@@ -171,40 +160,35 @@ export const setContractStorage = async (
storage = storage || {} storage = storage || {}
for (const [key, value] of Object.entries(storage)) { for (const [key, value] of Object.entries(storage)) {
const layoutMap = layout.storage.find((layoutMap: any) => { const layoutMap = layout.storage.find((lmap: any) => {
return layoutMap.label === key return lmap.label === key
}) })
const inputSlots = parseInputSlots(layout, layoutMap.type) const inputSlots = parseInputSlots(layout, layoutMap.type)
const slot = parseInt(layoutMap.slot) const slot = parseInt(layoutMap.slot, 10)
const depth = (layoutMap.type.match(/t_mapping/g) || []).length const depth = (layoutMap.type.match(/t_mapping/g) || []).length
if (typeof value !== 'object') { if (typeof value !== 'object') {
const slotHash = getStorageSlotHash(slot, depth, value) const slotHash = getStorageSlotHash(slot, depth, value)
await contract.__setStorageSlot( await contract.__setStorageSlot(slotHash, toHexString32(value as string))
slotHash,
toHexString32(value as string)
)
} else { } else {
for (const [subKey, subValue] of Object.entries(value)) { for (const [subKey, subValue] of Object.entries(value)) {
const baseSlotHash = getStorageSlotHash(slot, depth, { const baseSlotHash = getStorageSlotHash(slot, depth, {
[subKey]: subValue [subKey]: subValue,
}) })
const slotValues = getFlattenedValues(depth, { const slotValues = getFlattenedValues(depth, {
[subKey]: subValue [subKey]: subValue,
}) })
for (let i = 0; i < slotValues.length; i++) { for (const slotValue of slotValues) {
const slotValue = slotValues[i]
const slotIndex = inputSlots.find((inputSlot) => { const slotIndex = inputSlots.find((inputSlot) => {
return inputSlot.label === slotValue.label return inputSlot.label === slotValue.label
}).slot }).slot
const slotHash = toHexString32(BigNumber.from(baseSlotHash).add(slotIndex)) const slotHash = toHexString32(
BigNumber.from(baseSlotHash).add(slotIndex)
await contract.__setStorageSlot(
slotHash,
slotValue.value
) )
await contract.__setStorageSlot(slotHash, slotValue.value)
} }
} }
} }
...@@ -219,45 +203,48 @@ export const checkContractStorage = async ( ...@@ -219,45 +203,48 @@ export const checkContractStorage = async (
storage = storage || {} storage = storage || {}
for (const [key, value] of Object.entries(storage)) { for (const [key, value] of Object.entries(storage)) {
const layoutMap = layout.storage.find((layoutMap: any) => { const layoutMap = layout.storage.find((lmap: any) => {
return layoutMap.label === key return lmap.label === key
}) })
const inputSlots = parseInputSlots(layout, layoutMap.type) const inputSlots = parseInputSlots(layout, layoutMap.type)
const slot = parseInt(layoutMap.slot) const slot = parseInt(layoutMap.slot, 10)
const depth = (layoutMap.type.match(/t_mapping/g) || []).length const depth = (layoutMap.type.match(/t_mapping/g) || []).length
if (typeof value !== 'object') { if (typeof value !== 'object') {
const slotHash = getStorageSlotHash(slot, depth, value) const slotHash = getStorageSlotHash(slot, depth, value)
const retSlotValue = await contract.__getStorageSlot( const retSlotValue = await contract.__getStorageSlot(slotHash)
slotHash
)
if (retSlotValue !== toHexString32(value as string)) { if (retSlotValue !== toHexString32(value as string)) {
throw new Error(`Resulting state of ${key} (${retSlotValue}) did not match expected state (${toHexString32(value as string)})`) throw new Error(
`Resulting state of ${key} (${retSlotValue}) did not match expected state (${toHexString32(
value as string
)})`
)
} }
} else { } else {
for (const [subKey, subValue] of Object.entries(value)) { for (const [subKey, subValue] of Object.entries(value)) {
const baseSlotHash = getStorageSlotHash(slot, depth, { const baseSlotHash = getStorageSlotHash(slot, depth, {
[subKey]: subValue [subKey]: subValue,
}) })
const slotValues = getFlattenedValues(depth, { const slotValues = getFlattenedValues(depth, {
[subKey]: subValue [subKey]: subValue,
}) })
for (let i = 0; i < slotValues.length; i++) { for (const slotValue of slotValues) {
const slotValue = slotValues[i]
const slotIndex = inputSlots.find((inputSlot) => { const slotIndex = inputSlots.find((inputSlot) => {
return inputSlot.label === slotValue.label return inputSlot.label === slotValue.label
}).slot }).slot
const slotHash = toHexString32(BigNumber.from(baseSlotHash).add(slotIndex)) const slotHash = toHexString32(
BigNumber.from(baseSlotHash).add(slotIndex)
const retSlotValue = await contract.__getStorageSlot(
slotHash
) )
const retSlotValue = await contract.__getStorageSlot(slotHash)
if (retSlotValue !== slotValue.value) { if (retSlotValue !== slotValue.value) {
throw new Error(`Resulting state of ${slotValue.label} (${retSlotValue}) did not match expected state (${slotValue.value}).`) throw new Error(
`Resulting state of ${slotValue.label} (${retSlotValue}) did not match expected state (${slotValue.value}).`
)
} }
} }
} }
......
...@@ -22,11 +22,9 @@ const setPlaceholderStrings = ( ...@@ -22,11 +22,9 @@ const setPlaceholderStrings = (
ovmStateManager: Contract, ovmStateManager: Contract,
ovmSafetyChecker: Contract, ovmSafetyChecker: Contract,
ovmCallHelper: Contract, ovmCallHelper: Contract,
ovmRevertHelper: Contract, ovmRevertHelper: Contract
): any => { ): any => {
const setPlaceholder = ( const setPlaceholder = (kv: string): string => {
kv: string
): string => {
if (kv === '$OVM_EXECUTION_MANAGER') { if (kv === '$OVM_EXECUTION_MANAGER') {
return ovmExecutionManager.address return ovmExecutionManager.address
} else if (kv === '$OVM_STATE_MANAGER') { } else if (kv === '$OVM_STATE_MANAGER') {
...@@ -82,13 +80,13 @@ const setPlaceholderStrings = ( ...@@ -82,13 +80,13 @@ const setPlaceholderStrings = (
return test return test
} }
const fixtureDeployContracts = async (): Promise <{ const fixtureDeployContracts = async (): Promise<{
OVM_SafetyChecker: Contract, OVM_SafetyChecker: Contract
OVM_StateManager: Contract, OVM_StateManager: Contract
OVM_ExecutionManager: Contract, OVM_ExecutionManager: Contract
OVM_CallHelper: Contract, OVM_CallHelper: Contract
OVM_RevertHelper: Contract, OVM_RevertHelper: Contract
OVM_CreateStorer: Contract, OVM_CreateStorer: Contract
OVM_InvalidHelper: Contract OVM_InvalidHelper: Contract
}> => { }> => {
const Factory__OVM_SafetyChecker = await ethers.getContractFactory( const Factory__OVM_SafetyChecker = await ethers.getContractFactory(
...@@ -115,8 +113,12 @@ const fixtureDeployContracts = async (): Promise <{ ...@@ -115,8 +113,12 @@ const fixtureDeployContracts = async (): Promise <{
) )
const OVM_SafetyChecker = await Factory__OVM_SafetyChecker.deploy() const OVM_SafetyChecker = await Factory__OVM_SafetyChecker.deploy()
const OVM_ExecutionManager = await Factory__OVM_ExecutionManager.deploy(OVM_SafetyChecker.address) const OVM_ExecutionManager = await Factory__OVM_ExecutionManager.deploy(
const OVM_StateManager = await Factory__OVM_StateManager.deploy(OVM_ExecutionManager.address) OVM_SafetyChecker.address
)
const OVM_StateManager = await Factory__OVM_StateManager.deploy(
OVM_ExecutionManager.address
)
const OVM_CallHelper = await Factory__Helper_CodeContractForCalls.deploy() const OVM_CallHelper = await Factory__Helper_CodeContractForCalls.deploy()
const OVM_RevertHelper = await Factory__Helper_CodeContractForReverts.deploy() const OVM_RevertHelper = await Factory__Helper_CodeContractForReverts.deploy()
const OVM_CreateStorer = await Factory__Helper_CreateEMResponsesStorer.deploy() const OVM_CreateStorer = await Factory__Helper_CreateEMResponsesStorer.deploy()
...@@ -129,32 +131,28 @@ const fixtureDeployContracts = async (): Promise <{ ...@@ -129,32 +131,28 @@ const fixtureDeployContracts = async (): Promise <{
OVM_CallHelper, OVM_CallHelper,
OVM_RevertHelper, OVM_RevertHelper,
OVM_CreateStorer, OVM_CreateStorer,
OVM_InvalidHelper OVM_InvalidHelper,
} }
} }
export const runExecutionManagerTest = ( export const runExecutionManagerTest = (test: TestDefinition): void => {
test: TestDefinition
): void => {
test.preState = test.preState || {} test.preState = test.preState || {}
test.postState = test.postState || {} test.postState = test.postState || {}
describe(`Standard test: ${test.name}`, () => { describe(`Standard test: ${test.name}`, () => {
test.parameters.map((parameters) => { test.parameters.map((parameters) => {
if (isTestDefinition(parameters)) { if (isTestDefinition(parameters)) {
runExecutionManagerTest( runExecutionManagerTest({
{ ...parameters,
...parameters, preState: {
preState: { ...test.preState,
...test.preState, ...parameters.preState,
...parameters.preState },
}, postState: {
postState: { ...test.postState,
...test.postState, ...parameters.postState,
...parameters.postState },
} })
}
)
} else { } else {
let OVM_SafetyChecker: Contract let OVM_SafetyChecker: Contract
let OVM_StateManager: Contract let OVM_StateManager: Contract
...@@ -196,28 +194,33 @@ export const runExecutionManagerTest = ( ...@@ -196,28 +194,33 @@ export const runExecutionManagerTest = (
}) })
beforeEach(async () => { beforeEach(async () => {
await OVM_ExecutionManager.__setContractStorage(replacedTest.preState.ExecutionManager) await OVM_ExecutionManager.__setContractStorage(
await OVM_StateManager.__setContractStorage(replacedTest.preState.StateManager) replacedTest.preState.ExecutionManager
)
await OVM_StateManager.__setContractStorage(
replacedTest.preState.StateManager
)
}) })
afterEach(async () => { afterEach(async () => {
await OVM_ExecutionManager.__checkContractStorage({ await OVM_ExecutionManager.__checkContractStorage({
...replacedTest.postState.ExecutionManager ...replacedTest.postState.ExecutionManager,
}) })
await OVM_StateManager.__checkContractStorage({ await OVM_StateManager.__checkContractStorage({
...replacedTest.postState.StateManager ...replacedTest.postState.StateManager,
}) })
}) })
parameters.steps.map((step, idx) => { parameters.steps.map((step, idx) => {
const scopedFunction = (!!test.focus) ? it.only : it const scopedFunction = !!test.focus ? it.only : it
scopedFunction(`should run test: ${test.name} ${idx}`, async () => { scopedFunction(`should run test: ${test.name} ${idx}`, async () => {
const testGenerator = getTestGenerator( const testGenerator = getTestGenerator(
replacedParams.steps[idx], replacedParams.steps[idx],
OVM_ExecutionManager, OVM_ExecutionManager,
OVM_CallHelper, OVM_CallHelper,
OVM_CreateStorer, OVM_CreateStorer,
(await ethers.getContractFactory('Helper_CodeContractForCreates')).interface, (await ethers.getContractFactory('Helper_CodeContractForCreates'))
.interface,
OVM_RevertHelper, OVM_RevertHelper,
OVM_InvalidHelper OVM_InvalidHelper
) )
...@@ -225,21 +228,28 @@ export const runExecutionManagerTest = ( ...@@ -225,21 +228,28 @@ export const runExecutionManagerTest = (
const callResult = await OVM_ExecutionManager.provider.call({ const callResult = await OVM_ExecutionManager.provider.call({
to: OVM_ExecutionManager.address, to: OVM_ExecutionManager.address,
data: testGenerator.getCalldata(), data: testGenerator.getCalldata(),
gasLimit: GAS_LIMIT gasLimit: GAS_LIMIT,
}) })
await OVM_ExecutionManager.signer.sendTransaction({ await OVM_ExecutionManager.signer.sendTransaction({
to: OVM_ExecutionManager.address, to: OVM_ExecutionManager.address,
data: testGenerator.getCalldata(), data: testGenerator.getCalldata(),
gasLimit: GAS_LIMIT gasLimit: GAS_LIMIT,
}) })
const interpretation = testGenerator.interpretActualReturnData(callResult, true) const interpretation = testGenerator.interpretActualReturnData(
callResult,
true
)
console.log('interpretation of actual results:\n' + interpretation) // in future we can add conditional here but for now always assume succeed console.log('interpretation of actual results:\n' + interpretation) // in future we can add conditional here but for now always assume succeed
const interpretationOfExpected = testGenerator.interpretActualReturnData(
const interpretationOfExpected = testGenerator.interpretActualReturnData(testGenerator.getReturnData(), true) testGenerator.getReturnData(),
console.log('interpretation of expected: \n' + interpretationOfExpected) true
)
console.log(
'interpretation of expected: \n' + interpretationOfExpected
)
expect(callResult).to.equal(testGenerator.getReturnData()) //, 'got bad response, looks like it did:\n' + testGenerator.interpretActualReturnData(callResult)) expect(callResult).to.equal(testGenerator.getReturnData()) //, 'got bad response, looks like it did:\n' + testGenerator.interpretActualReturnData(callResult))
}) })
......
...@@ -5,7 +5,12 @@ export type SolidityFunctionParameter = string | number | BigNumber ...@@ -5,7 +5,12 @@ export type SolidityFunctionParameter = string | number | BigNumber
export interface TestStep { export interface TestStep {
functionName: string functionName: string
functionParams: Array<SolidityFunctionParameter | SolidityFunctionParameter[] | TestStep[] | boolean> functionParams: Array<
| SolidityFunctionParameter
| SolidityFunctionParameter[]
| TestStep[]
| boolean
>
expectedReturnStatus: boolean expectedReturnStatus: boolean
expectedReturnValues: any[] expectedReturnValues: any[]
} }
...@@ -18,14 +23,14 @@ export interface TestDefinition { ...@@ -18,14 +23,14 @@ export interface TestDefinition {
name: string name: string
focus?: boolean focus?: boolean
preState?: { preState?: {
ExecutionManager?: any, ExecutionManager?: any
StateManager?: any StateManager?: any
}, }
parameters: Array<TestParameters | TestDefinition>, parameters: Array<TestParameters | TestDefinition>
postState?: { postState?: {
ExecutionManager?: any, ExecutionManager?: any
StateManager?: any StateManager?: any
}, }
} }
export const isTestDefinition = ( export const isTestDefinition = (
......
{ {
"compilerOptions": { "compilerOptions": {
"module": "commonjs",
"target": "es2017",
"declaration": true,
"noImplicitAny": false,
"removeComments": true,
"noLib": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"sourceMap": true,
"outDir": "./build", "outDir": "./build",
"baseUrl": "./", "baseUrl": "./",
"resolveJsonModule": true, "resolveJsonModule": true,
"esModuleInterop": true "esModuleInterop": true,
"lib": [
"es7"
],
"typeRoots": [
"node_modules/@types"
]
}, },
"include": ["*.ts", "**/*.ts", "artifacts/*.json"], "include": ["*.ts", "**/*.ts", "artifacts/*.json"],
"exclude": ["./build", "node_modules"], "exclude": ["./build", "node_modules"],
......
{
"extends": [
"tslint:latest",
"tslint-config-prettier",
"tslint-plugin-prettier"
],
"rulesDirectory": [
"tslint-no-focused-test"
],
"rules": {
"ban-types": false,
"comment-format": false,
"interface-name": false,
"max-classes-per-file": false,
"member-ordering": false,
"no-bitwise": false,
"no-empty-interface": false,
"no-implicit-dependencies": [true, "dev"],
"no-string-literal": false,
"no-submodule-imports": false,
"no-unused-expression": false,
"object-literal-sort-keys": false,
"ordered-imports": false,
"prettier": [true, "prettier-config.json"],
"semicolon": false,
"variable-name": false,
"no-focused-test": true,
"no-console": false,
"array-type": false,
"class-name": false
},
"linterOptions": {
"exclude": [
"**/node_modules/**/*"
]
}
}
This diff is collapsed.
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