Skip to content
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ const defaultWhitelist: EVMOpcode[] = [
Opcode.EXP,
Opcode.EXTCODECOPY,
Opcode.EXTCODESIZE,
Opcode.EXTCODEHASH,
Opcode.GAS,
Opcode.GT,
Opcode.INVALID,
Expand All @@ -93,6 +94,7 @@ const defaultWhitelist: EVMOpcode[] = [
Opcode.MULMOD,
Opcode.NOT,
Opcode.OR,
Opcode.ORIGIN,
Opcode.PC,
Opcode.POP,
Opcode.PUSH1,
Expand Down
14 changes: 12 additions & 2 deletions packages/rollup-dev-tools/src/tools/transpiler/transpiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,16 +135,21 @@ export class TranspilerImpl implements Transpiler {
const deployedBytecodeTranspilationResult: TaggedTranspilationResult = this.transpileBytecodePreservingTags(
taggedDeployedEVMBytecode
)
// todo error handle however above

if (!deployedBytecodeTranspilationResult.succeeded) {
errors.push(
...(deployedBytecodeTranspilationResult as ErroredTranspilation).errors
)
return {
succeeded: false,
errors,
}
}
const transpiledDeployedBytecode: EVMBytecode =
deployedBytecodeTranspilationResult.bytecodeWithTags

log.debug(`Fixing constant indices for transpiled deployed bytecode...`)
log.debug(`Fixing the constant indices for transpiled deployed bytecode...`)
log.debug(`errors are: ${JSON.stringify(errors)}`)
// Note that fixTaggedConstantOffsets() scrubs all fixed tags, so we do not re-fix when we use finalTranspiledDeployedBytecode to reconstruct the returned initcode
const finalTranspiledDeployedBytecode: EVMBytecode = this.fixTaggedConstantOffsets(
transpiledDeployedBytecode as EVMBytecode,
Expand Down Expand Up @@ -176,6 +181,10 @@ export class TranspilerImpl implements Transpiler {
...(constructorInitLogicTranspilationResult as ErroredTranspilation)
.errors
)
return {
succeeded: false,
errors,
}
}
const transpiledConstructorInitLogic: EVMBytecode =
constructorInitLogicTranspilationResult.bytecodeWithTags
Expand Down Expand Up @@ -241,6 +250,7 @@ export class TranspilerImpl implements Transpiler {
taggedBytecode: EVMBytecode,
errors
): EVMBytecode {
log.debug(`tagged input: ${formatBytecode(taggedBytecode)}`)
const inputAsBuf: Buffer = bytecodeToBuffer(taggedBytecode)
const bytecodeToReturn: EVMBytecode = []
for (const [index, op] of taggedBytecode.entries()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ describe('Solitity contracts should have constants correctly accessible when usi
const bytesMemoryConstB: Buffer = hexStrToBuf(
'BBBbeedfeedBBBBBBbeedfeedBBBBBBbeedfeedBBBBBBbeedfeedBBBBBBbeedfeedBBBBBBbeedfeedBBBBBBbeedfeedBBB'
)
it('should work for the first bytes memory constant', async () => {
it('should work for the second bytes memory constant', async () => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Asked Ben about this, he said that it was just a type-o where he copied a test but forgot to update the name

const retrievedBytesMemoryBVal: Buffer = await getGetterReturnedVal(
deployedGetterAddress,
'getBytesMemoryConstantB',
Expand Down
11 changes: 7 additions & 4 deletions packages/rollup-full-node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@
],
"scripts": {
"all": "yarn clean && yarn build && yarn test && yarn fix && yarn lint",
"build": "waffle waffle-config.json && tsc -p .",
"clean": "rimraf build/ && rimraf test/contracts/build",
"build": "waffle waffle-config-untranspiled.json && waffle waffle-config-transpiled.json && tsc -p .",
"clean": "rimraf build/ && yarn clean-contracts",
"fix": "prettier --config ../../prettier-config.json --write 'index.ts' '{src,test}/**/*.ts'",
"lint": "tslint --format stylish --project .",
"test": "waffle waffle-config.json && mocha --require source-map-support/register --require ts-node/register 'test/**/*.spec.ts' --timeout 8000 --exit",
"test": "yarn build-contracts && mocha --require source-map-support/register --require ts-node/register 'test/**/*.spec.ts' --timeout 8000 --exit",
"server:aggregator": "env DEBUG=\"info:*,error:*\" node ./build/src/exec/aggregator.js",
"server:fullnode": "env DEBUG=\"info:*,error:*\" node ./build/src/exec/fullnode.js",
"server:fullnode:debug": "env DEBUG=\"info:*,error:*,debug:*\" node ./build/src/exec/fullnode.js"
"server:fullnode:debug": "env DEBUG=\"info:*,error:*,debug:*\" node ./build/src/exec/fullnode.js",
"clean-contracts": "rimraf ./test/contracts/build && mkdir ./test/contracts/build && mkdir ./test/contracts/build/transpiled && mkdir ./test/contracts/build/untranspiled",
"build-contracts": "yarn clean-contracts && waffle waffle-config-untranspiled.json && waffle waffle-config-transpiled.json"
},
"keywords": [
"plasma",
Expand All @@ -36,6 +38,7 @@
"@eth-optimism/core-utils": "0.0.1-alpha.9",
"@eth-optimism/ovm": "0.0.1-alpha.9",
"@eth-optimism/rollup-core": "0.0.1-alpha.9",
"@eth-optimism/solc-transpiler": "^0.0.1-alpha.9",
"async-lock": "^1.2.2",
"axios": "^0.19.0",
"cors": "^2.8.5",
Expand Down
2 changes: 1 addition & 1 deletion packages/rollup-full-node/test/app/handler.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
deployOvmContract,
DefaultWeb3Handler,
} from '../../src/app'
import * as SimpleStorage from '../contracts/build/SimpleStorage.json'
import * as SimpleStorage from '../contracts/build/untranspiled/SimpleStorage.json'
import { ethers, ContractFactory } from 'ethers'
import { FullnodeHandler } from '../../src/types'

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
pragma solidity ^0.5.0;
import "./CallerReturner.sol";

contract CallerGetter {
function getMsgSenderFrom(address _callerReturner) public view returns(address) {
return CallerReturner(_callerReturner).getMsgSender();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pragma solidity ^0.5.0;

contract CallerReturner {
function getMsgSender() public view returns(address) {
return msg.sender;
}
}
19 changes: 19 additions & 0 deletions packages/rollup-full-node/test/contracts/transpiled/ExtCode.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
pragma solidity ^0.5.0;

contract ExtCode {
function getExtCodeSizeOf(address _addr) public returns(uint) {
uint toReturn;
assembly {
toReturn:= extcodesize(_addr)
}
return toReturn;
}

function getExtCodeHashOf(address _addr) public returns(bytes32) {
bytes32 toReturn;
assembly {
toReturn:= extcodehash(_addr)
}
return toReturn;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pragma solidity ^0.5.0;

contract OriginGetter {
function getTxOrigin() public view returns(address) {
return tx.origin;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pragma solidity ^0.5.0;

contract SelfAware {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lulz

function getMyAddress() public view returns(address) {
return address(this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
pragma solidity ^0.5.0;
import "./SimpleStorage.sol";

contract SimpleCaller {
function doGetStorageCall(address _target, bytes32 key) public view returns(bytes32) {
return SimpleStorage(_target).getStorage(key);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
pragma solidity ^0.5.0;

contract SimpleStorage {
mapping(bytes32 => bytes32) public builtInStorage;
function setStorage(bytes32 key, bytes32 value) public {
builtInStorage[key] = value;
}

function getStorage(bytes32 key) public view returns (bytes32) {
return builtInStorage[key];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pragma solidity ^0.5.0;

contract TimeGetter {
function getTimestamp() public view returns(uint256) {
return block.timestamp;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import '../../../rollup-dev-tools/test/setup'
/* External Imports */
import {
getLogger,
remove0x,
bufToHexString,
hexStrToBuf,
} from '@eth-optimism/core-utils'
import {
Address,
formatBytecode,
bufferToBytecode,
} from '@eth-optimism/rollup-core'

/* Internal Imports */

import * as SimpleStorage from '../contracts/build/transpiled/SimpleStorage.json'
import * as SimpleCaller from '../contracts/build/transpiled/SimpleCaller.json'
import * as SelfAware from '../contracts/build/transpiled/SelfAware.json'
import * as CallerGetter from '../contracts/build/transpiled/CallerGetter.json'
import * as OriginGetter from '../contracts/build/transpiled/OriginGetter.json'
import * as CallerReturner from '../contracts/build/transpiled/CallerReturner.json'
import * as TimeGetter from '../contracts/build/transpiled/TimeGetter.json'

@karlfloersch karlfloersch Mar 2, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw one thing I forgot to mention is that technically if we were keeping to convention there'd be a comment for Contract Imports which has all of these as opposed to internal imports, even though of course contract imports are internal. But just a note that's the convention that has organically emerged (I think from Kelvin)


import { createMockProvider, getWallets, deployContract } from '../../'

describe(`Various opcodes should be usable in combination with transpiler and full node`, () => {
let provider
let wallet

beforeEach(async () => {
provider = await createMockProvider()
const wallets = getWallets(provider)
wallet = wallets[0]
})

afterEach(() => {
provider.closeOVM()
})

// TEST BASIC FUNCTIONALITIES

it('should process cross-ovm-contract calls', async () => {
const simpleStorage = await deployContract(wallet, SimpleStorage, [], [])
const simpleCaller = await deployContract(wallet, SimpleCaller, [], [])

const storageKey = '0x' + '01'.repeat(32)
const storageValue = '0x' + '02'.repeat(32)

await simpleStorage.setStorage(storageKey, storageValue)

const res = await simpleCaller.doGetStorageCall(
simpleStorage.address,
storageKey
)
res.should.equal(storageValue)
})
it('should work for address(this)', async () => {
const selfAware = await deployContract(wallet, SelfAware, [], [])
const deployedAddress: Address = selfAware.address
const returnedAddress: Address = await selfAware.getMyAddress()
deployedAddress.should.equal(returnedAddress)
})
it.skip('should work for block.timestamp', async () => {
// todo, once we handle timestamps, unskip this test
const timeGetter = await deployContract(wallet, TimeGetter, [], [])
const time = await timeGetter.getTimestamp()
time._hex.should.equal('???')
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've technically added timestamp in 4bf0c7e so this test could be enabled.

it('should work for msg.sender', async () => {
const callerReturner = await deployContract(wallet, CallerReturner, [], [])
const callerGetter = await deployContract(wallet, CallerGetter, [], [])
const result = await callerGetter.getMsgSenderFrom(callerReturner.address)
result.should.equal(callerGetter.address)
})
it('should work for tx.origin', async () => {
const originGetter = await deployContract(wallet, OriginGetter, [], [])
const result = await originGetter.getTxOrigin()
result.should.equal(wallet.address)
})

// SIMPLE STORAGE TEST
it('should set storage & retrieve the value', async () => {
const simpleStorage = await deployContract(wallet, SimpleStorage, [], [])
// Create some constants we will use for storage
const storageKey = '0x' + '01'.repeat(32)
const storageValue = '0x' + '02'.repeat(32)
// Set storage with our new storage elements
await simpleStorage.setStorage(storageKey, storageValue)
// Get the storage
const res = await simpleStorage.getStorage(storageKey)
// Verify we got the value!
res.should.equal(storageValue)
})
})
14 changes: 14 additions & 0 deletions packages/rollup-full-node/waffle-config-transpiled.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"sourcesPath": "./test/contracts/transpiled",
"targetPath": "./test/contracts/build/transpiled",
"npmPath": "../../node_modules",
"solcVersion": "../../node_modules/@eth-optimism/solc-transpiler",
"compilerOptions": {
"outputSelection": {
"*": {
"*": ["*"]
}
},
"executionManagerAddress": "0xA193E42526F1FEA8C99AF609dcEabf30C1c29fAA"
}
}
12 changes: 12 additions & 0 deletions packages/rollup-full-node/waffle-config-untranspiled.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"sourcesPath": "./test/contracts/untranspiled",
"targetPath": "./test/contracts/build/untranspiled",
"npmPath": "../../node_modules",
"compilerOptions": {
"outputSelection": {
"*": {
"*": ["*"]
}
}
}
}
5 changes: 0 additions & 5 deletions packages/rollup-full-node/waffle-config.json

This file was deleted.

Loading