Skip to content

Commit

Permalink
require timestamp is set on execution (#61)
Browse files Browse the repository at this point in the history
  • Loading branch information
masonforest authored Mar 31, 2020
1 parent 42f92d9 commit ef07f76
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 42 deletions.
9 changes: 9 additions & 0 deletions packages/core-utils/src/app/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,3 +280,12 @@ export const runInDomain = async (
const domainToUse: domain.Domain = !!d ? d : domain.create()
return domainToUse.run(func)
}

/**
* Gets the current number of seconds since the epoch.
*
* @returns The seconds since epoch.
*/
export const getCurrentTime = (): number => {
return Math.round(Date.now() / 1000)
}
25 changes: 25 additions & 0 deletions packages/core-utils/src/app/test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,29 @@ export class TestUtils {
"Function didn't throw as expected or threw the wrong error."
)
}

public static async assertRevertsAsync(
revertMessage: string,
func: () => Promise<any>
): Promise<void> {
let succeeded = true
try {
await func()
succeeded = false
} catch (e) {
if (e instanceof Error) {
assert.equal(
e.message,
`VM Exception while processing transaction: revert ${revertMessage}`
)
} else {
succeeded = false
}
}

assert(
succeeded,
"Function didn't throw as expected or threw the wrong error."
)
}
}
4 changes: 1 addition & 3 deletions packages/ovm/src/contracts/ExecutionManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ contract ExecutionManager is FullStateManager {
address _l1MsgSenderAddress,
bool _allowRevert
) public {
require(_timestamp > 0, "Timestamp must be greater than 0");
uint _nonce = getOvmContractNonce(_fromAddress);
// Initialize our context
initializeContext(_timestamp, _queueOrigin, _fromAddress, _l1MsgSenderAddress);
Expand Down Expand Up @@ -397,9 +398,6 @@ contract ExecutionManager is FullStateManager {
* returndata: uint256 representing the current timestamp.
*/
function ovmTIMESTAMP() public view {
// First make sure the timestamp was set
require(executionContext.timestamp != 0, "Error: attempting to access non-existent timestamp.");

uint t = executionContext.timestamp;

assembly {
Expand Down
30 changes: 18 additions & 12 deletions packages/ovm/test/contracts/execution-manager.call-opcodes.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ import '../setup'

/* External Imports */
import { Address } from '@eth-optimism/rollup-core'
import { getLogger, remove0x, add0x, TestUtils } from '@eth-optimism/core-utils'
import {
getLogger,
remove0x,
add0x,
TestUtils,
getCurrentTime,
} from '@eth-optimism/core-utils'

import { Contract, ContractFactory, ethers } from 'ethers'
import { createMockProvider, deployContract, getWallets } from 'ethereum-waffle'
Expand Down Expand Up @@ -132,7 +138,7 @@ describe('Execution Manager -- Call opcodes', () => {
const data: string =
encodeMethodId('executeCall') +
encodeRawArguments([
0,
getCurrentTime(),
0,
addressToBytes32Address(callContractAddress),
methodIds.makeCall,
Expand Down Expand Up @@ -202,7 +208,7 @@ describe('Execution Manager -- Call opcodes', () => {
const data: string =
methodIds.executeCall +
encodeRawArguments([
0,
getCurrentTime(),
0,
addressToBytes32Address(callContractAddress),
methodIds.makeDelegateCall,
Expand Down Expand Up @@ -253,7 +259,7 @@ describe('Execution Manager -- Call opcodes', () => {
const data: string =
methodIds.executeCall +
encodeRawArguments([
0,
getCurrentTime(),
0,
addressToBytes32Address(callContractAddress),
methodIds.makeDelegateCall,
Expand Down Expand Up @@ -355,7 +361,7 @@ describe('Execution Manager -- Call opcodes', () => {
const data: string =
methodIds.executeCall +
encodeRawArguments([
0,
getCurrentTime(),
0,
addressToBytes32Address(callContractAddress),
methodIds.makeStaticCallThenCall,
Expand All @@ -374,7 +380,7 @@ describe('Execution Manager -- Call opcodes', () => {
const data: string =
methodIds.executeCall +
encodeRawArguments([
0,
getCurrentTime(),
0,
addressToBytes32Address(callContractAddress),
methodIds.makeStaticCall,
Expand All @@ -396,7 +402,7 @@ describe('Execution Manager -- Call opcodes', () => {
const data: string =
methodIds.executeCall +
encodeRawArguments([
0,
getCurrentTime(),
0,
addressToBytes32Address(callContractAddress),
methodIds.makeStaticCall,
Expand All @@ -420,7 +426,7 @@ describe('Execution Manager -- Call opcodes', () => {
const data: string =
methodIds.executeCall +
encodeRawArguments([
0,
getCurrentTime(),
0,
addressToBytes32Address(callContractAddress),
methodIds.makeStaticCall,
Expand All @@ -447,7 +453,7 @@ describe('Execution Manager -- Call opcodes', () => {
const data: string =
methodIds.executeCall +
encodeRawArguments([
0,
getCurrentTime(),
0,
addressToBytes32Address(callContractAddress),
methodIds.makeStaticCall,
Expand All @@ -470,7 +476,7 @@ describe('Execution Manager -- Call opcodes', () => {
const data: string =
methodIds.executeCall +
encodeRawArguments([
0,
getCurrentTime(),
0,
addressToBytes32Address(callContractAddress),
methodIds.makeStaticCall,
Expand Down Expand Up @@ -498,7 +504,7 @@ describe('Execution Manager -- Call opcodes', () => {
const data: string =
methodIds.executeCall +
encodeRawArguments([
0,
getCurrentTime(),
0,
addressToBytes32Address(callContractAddress),
methodIds.makeStaticCall,
Expand All @@ -522,7 +528,7 @@ describe('Execution Manager -- Call opcodes', () => {
const executeCall = (args: any[]): Promise<string> => {
return executeOVMCall(executionManager, 'executeCall', [
encodeRawArguments([
0,
getCurrentTime(),
0,
addressToBytes32Address(callContractAddress),
methodIds.makeCall,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
hexStrToNumber,
remove0x,
TestUtils,
getCurrentTime,
} from '@eth-optimism/core-utils'

import { Contract, ContractFactory, ethers } from 'ethers'
Expand Down Expand Up @@ -152,18 +153,7 @@ describe('Execution Manager -- Context opcodes', () => {
})

describe('ovmTIMESTAMP', async () => {
it('reverts when TIMESTAMP is not set', async () => {
await TestUtils.assertThrowsAsync(async () => {
await executeCall([
contractAddress32,
methodIds.callThroughExecutionManager,
contract2Address32,
methodIds.getTIMESTAMP,
])
})
})

it('properly retrieves TIMESTAMP when timestamp is set', async () => {
it('properly retrieves TIMESTAMP', async () => {
const timestamp: number = 1582890922
const result = await executeOVMCall(executionManager, 'executeCall', [
timestamp,
Expand Down Expand Up @@ -201,7 +191,7 @@ describe('Execution Manager -- Context opcodes', () => {
it('gets Queue Origin when it is 0', async () => {
const queueOrigin: string = '00'.repeat(32)
const result = await executeOVMCall(executionManager, 'executeCall', [
0,
getCurrentTime(),
queueOrigin,
contractAddress32,
methodIds.callThroughExecutionManager,
Expand All @@ -218,7 +208,7 @@ describe('Execution Manager -- Context opcodes', () => {
it('properly retrieves Queue Origin when queue origin is set', async () => {
const queueOrigin: string = '00'.repeat(30) + '1111'
const result = await executeOVMCall(executionManager, 'executeCall', [
0,
getCurrentTime(),
queueOrigin,
contractAddress32,
methodIds.callThroughExecutionManager,
Expand All @@ -235,7 +225,7 @@ describe('Execution Manager -- Context opcodes', () => {

const executeCall = (args: any[]): Promise<string> => {
return executeOVMCall(executionManager, 'executeCall', [
encodeRawArguments([0, 0, ...args]),
encodeRawArguments([getCurrentTime(), 0, ...args]),
])
}
})
58 changes: 53 additions & 5 deletions packages/ovm/test/contracts/execution-manager.executeCall.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ import '../setup'

/* External Imports */
import { Address } from '@eth-optimism/rollup-core'
import { getLogger, padToLength, ZERO_ADDRESS } from '@eth-optimism/core-utils'
import {
getLogger,
padToLength,
ZERO_ADDRESS,
TestUtils,
getCurrentTime,
} from '@eth-optimism/core-utils'

import { Contract, ContractFactory, ethers } from 'ethers'
import { createMockProvider, deployContract, getWallets } from 'ethereum-waffle'
Expand Down Expand Up @@ -75,6 +81,48 @@ describe('Execution Manager -- Call opcodes', () => {
})

describe('executeNonEOACall', async () => {
it('fails if the provided timestamp is 0', async () => {
// Create the variables we will use for setStorage
const intParam = 0
const bytesParam = '0xdeadbeef'
// Generate our tx calldata
const calldata = getUnsignedTransactionCalldata(
dummyContract,
'dummyFunction',
[intParam, bytesParam]
)
const nonce = await executionManager.getOvmContractNonce(wallet.address)
const transaction = {
nonce,
gasLimit: GAS_LIMIT,
gasPrice: 0,
to: dummyContractAddress,
value: 0,
data: calldata,
chainId: CHAIN_ID,
}
const signedMessage = await wallet.sign(transaction)
const [v, r, s] = ethers.utils.RLP.decode(signedMessage).slice(-3)

await TestUtils.assertRevertsAsync(
'Timestamp must be greater than 0',
async () => {
// Call using Ethers
const tx = await executionManager.executeEOACall(
0,
0,
transaction.nonce,
transaction.to,
transaction.data,
padToLength(v, 4),
padToLength(r, 64),
padToLength(s, 64)
)
await provider.waitForTransaction(tx.hash)
}
)
})

it('properly executes a raw call -- 0 param', async () => {
// Create the variables we will use for setStorage
const intParam = 0
Expand All @@ -98,7 +146,7 @@ describe('Execution Manager -- Call opcodes', () => {

// Call using Ethers
const tx = await executionManager.executeUnsignedEOACall(
0,
getCurrentTime(),
0,
transaction.to,
transaction.data,
Expand Down Expand Up @@ -136,7 +184,7 @@ describe('Execution Manager -- Call opcodes', () => {

// Call using Ethers
const tx = await executionManager.executeEOACall(
0,
getCurrentTime(),
0,
transaction.nonce,
transaction.to,
Expand Down Expand Up @@ -173,7 +221,7 @@ describe('Execution Manager -- Call opcodes', () => {

// Call using Ethers
const tx = await executionManager.executeEOACall(
0,
getCurrentTime(),
0,
transaction.nonce,
transaction.to,
Expand Down Expand Up @@ -213,7 +261,7 @@ describe('Execution Manager -- Call opcodes', () => {

// Call using Ethers
const tx = await executionManager.executeEOACall(
0,
getCurrentTime(),
0,
transaction.nonce,
transaction.to,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import '../setup'
import { Address } from '@eth-optimism/rollup-core'
import {
getLogger,
getCurrentTime,
remove0x,
add0x,
TestUtils,
Expand Down Expand Up @@ -163,15 +164,15 @@ describe('Execution Manager -- L1 <-> L2 Opcodes', () => {
ethereumjsAbi.methodID('getL1MessageSender', [])
)

it('should return the l1 message sender provided', async () => {
it.only('should return the l1 message sender provided', async () => {
const l1MessageSenderPrecompileAddr =
'0x4200000000000000000000000000000000000001'
const testL1MsgSenderAddress = '0x' + '01'.repeat(20)

const callResult = await callExecutionManagerExecuteUnsignedEOACall(
executionManager,
[
0,
getCurrentTime(),
0,
l1MessageSenderPrecompileAddr,
getL1MessageSenderMethodId,
Expand Down
13 changes: 11 additions & 2 deletions packages/ovm/test/contracts/simple-storage.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import '../setup'
/* External Imports */
import { Address } from '@eth-optimism/rollup-core'
import { createMockProvider, deployContract, getWallets } from 'ethereum-waffle'
import { getLogger, add0x } from '@eth-optimism/core-utils'
import { getLogger, add0x, getCurrentTime } from '@eth-optimism/core-utils'
import { Contract, ContractFactory, ethers } from 'ethers'
import { TransactionReceipt } from 'ethers/providers'
import * as ethereumjsAbi from 'ethereumjs-abi'
Expand Down Expand Up @@ -118,7 +118,16 @@ describe('SimpleStorage', () => {
const callData = getUnsignedTransactionCalldata(
executionManager,
'executeEOACall',
[0, 0, transaction.nonce, transaction.to, transaction.data, v, r, s]
[
getCurrentTime(),
0,
transaction.nonce,
transaction.to,
transaction.data,
v,
r,
s,
]
)

const result = await executionManager.provider.call({
Expand Down
Loading

0 comments on commit ef07f76

Please sign in to comment.