Skip to content
This repository has been archived by the owner on Dec 5, 2021. It is now read-only.

[pull] develop from ethereum-optimism:develop #27

Merged
merged 6 commits into from
Jun 1, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 5 additions & 0 deletions .changeset/cold-cows-cross.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@eth-optimism/integration-tests': patch
---

Reduce test timeout from 100 to 20 seconds
6 changes: 6 additions & 0 deletions .changeset/fuzzy-dogs-share.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@eth-optimism/l2geth': patch
'@eth-optimism/core-utils': patch
---

Implement the next fee spec in both geth and in core-utils
5 changes: 5 additions & 0 deletions .changeset/late-countries-guess.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@eth-optimism/contracts': patch
---

Update contracts README to add deploy instructions.
5 changes: 5 additions & 0 deletions .changeset/thin-waves-bathe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@eth-optimism/contracts': patch
---

Minor change to how deploy.ts is invoked
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.sh text eol=lf
61 changes: 61 additions & 0 deletions .github/workflows/static-analysis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: Static analysis

on:
push:
branches:
- master
- develop
pull_request:
workflow_dispatch:

env:
PYTEST_ADDOPTS: "--color=yes"

jobs:
slither:
name: Slither run
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

- name: Fetch history
run: git fetch

- name: Setup node
uses: actions/setup-node@v1
with:
node-version: '12.x'

- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"

- uses: actions/cache@v2
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-

- name: Install Dependencies
# only install dependencies if there was a change in the deps
# if: steps.yarn-cache.outputs.cache-hit != 'true'
run: yarn install

- name: Build
run: yarn build

- name: Set up Python 3.8
uses: actions/setup-python@v2
with:
python-version: '3.8'

- name: Install Slither
run: pip3 install slither-analyzer

- name: Run analysis
working-directory: ./packages/contracts
shell: bash
run: yarn test:slither
continue-on-error: true
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ cache-ovm
l2geth/build/bin
packages/contracts/deployments/custom
packages/contracts/coverage*
packages/contracts/@ens*
packages/contracts/@openzeppelin*
packages/contracts/hardhat*

packages/data-transport-layer/db

Expand Down
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
14.17.0
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ Extensive documentation is available [here](http://community.optimism.io/docs/)
* [`message-relayer`](./packages/message-relayer): Service for relaying L2 messages to L1
* [`l2geth`](./l2geth): Fork of [go-ethereum v1.9.10](https://github.com/ethereum/go-ethereum/tree/v1.9.10) implementing the [OVM](https://research.paradigm.xyz/optimism#optimistic-geth).
* [`integration-tests`](./integration-tests): Integration tests between a L1 testnet, `l2geth`,
* [`ops`](./ops): Contains Dockerfiles for containerizing each service involved in the protocol,
* [`ops`](./ops): Contains Dockerfiles for containerizing each service involved in the protocol,
as well as a docker-compose file for bringing up local testnets easily

## Quickstart

### Installation

Dependency management is done using `yarn`.
Dependency management is done using `yarn`.

```bash
git clone [email protected]:ethereum-optimism/optimism.git
Expand Down Expand Up @@ -67,7 +67,7 @@ you can run `yarn lerna run test --parallel --since master`
#### Running the integration tests

The integration tests first require bringing up the Optimism stack. This is done via
a Docker Compose network. For better performance, we also recommend enabling Docker
a Docker Compose network. For better performance, we also recommend enabling Docker
BuildKit

```bash
Expand Down Expand Up @@ -110,3 +110,11 @@ can be hard to filter through. In order to view the logs from a specific service
```
docker-compose logs --follow <service name>
```
### Static analysis

To run `slither` locally in `./packages/contracts` do

```
pip3 install slither-analyzer
yarn test:slither
```
2 changes: 1 addition & 1 deletion integration-tests/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const enableGasReport = !!process.env.ENABLE_GAS_REPORT

const config: HardhatUserConfig = {
mocha: {
timeout: 100000,
timeout: 20000,
},
networks: {
optimism: {
Expand Down
6 changes: 5 additions & 1 deletion integration-tests/test/erc20.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Contract, ContractFactory, Wallet } from 'ethers'
import { ethers } from 'hardhat'
import { TxGasLimit, TxGasPrice } from '@eth-optimism/core-utils'
import chai, { expect } from 'chai'
import { GWEI } from './shared/utils'
import { OptimismEnv } from './shared/env'
Expand Down Expand Up @@ -64,7 +65,10 @@ describe('Basic ERC20 interactions', async () => {
const receipt = await transfer.wait()

// The expected fee paid is the value returned by eth_estimateGas
const expectedFeePaid = await ERC20.estimateGas.transfer(other.address, 100)
const gasLimit = await ERC20.estimateGas.transfer(other.address, 100)
const gasPrice = await wallet.getGasPrice()
expect(gasPrice).to.deep.equal(TxGasPrice)
const expectedFeePaid = gasLimit.mul(gasPrice)

// There are two events from the transfer with the first being
// the ETH fee paid and the second of the value transfered (100)
Expand Down
7 changes: 3 additions & 4 deletions integration-tests/test/fee-payment.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import chaiAsPromised from 'chai-as-promised'
chai.use(chaiAsPromised)
import { BigNumber, utils } from 'ethers'
import { OptimismEnv } from './shared/env'
import { L2GasLimit } from '@eth-optimism/core-utils'
import { TxGasLimit } from '@eth-optimism/core-utils'

describe('Fee Payment Integration Tests', async () => {
let env: OptimismEnv
Expand All @@ -29,7 +29,7 @@ describe('Fee Payment Integration Tests', async () => {
)
const executionGas = await (env.ovmEth
.provider as any).send('eth_estimateExecutionGas', [tx])
const decoded = L2GasLimit.decode(gas)
const decoded = TxGasLimit.decode(gas)
expect(BigNumber.from(executionGas)).deep.eq(decoded)
})

Expand All @@ -38,8 +38,7 @@ describe('Fee Payment Integration Tests', async () => {
const balanceBefore = await env.l2Wallet.getBalance()
expect(balanceBefore.gt(amount))

const gas = await env.ovmEth.estimateGas.transfer(other, amount)
const tx = await env.ovmEth.transfer(other, amount, { gasPrice: 1 })
const tx = await env.ovmEth.transfer(other, amount)
const receipt = await tx.wait()
expect(receipt.status).to.eq(1)

Expand Down
4 changes: 2 additions & 2 deletions integration-tests/test/native-eth.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ describe('Native ETH Integration Tests', async () => {
const amount = utils.parseEther('0.5')
const addr = '0x' + '1234'.repeat(10)
const gas = await env.ovmEth.estimateGas.transfer(addr, amount)
expect(gas).to.be.deep.eq(BigNumber.from(0x23284d28fe6d))
expect(gas).to.be.deep.eq(BigNumber.from(0x0ef897216d))
})

it('Should estimate gas for ETH withdraw', async () => {
const amount = utils.parseEther('0.5')
const gas = await env.ovmEth.estimateGas.withdraw(amount)
expect(gas).to.be.deep.eq(BigNumber.from(0x207ad91a77b4))
expect(gas).to.be.deep.eq(BigNumber.from(61400489396))
})
})

Expand Down
48 changes: 32 additions & 16 deletions integration-tests/test/rpc.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import {
injectL2Context,
L2GasLimit,
roundL1GasPrice,
TxGasLimit,
TxGasPrice,
toRpcHexString,
} from '@eth-optimism/core-utils'
import { Wallet, BigNumber, Contract } from 'ethers'
import { ethers } from 'hardhat'
import chai, { expect } from 'chai'
import { sleep, l2Provider, GWEI } from './shared/utils'
import { sleep, l2Provider, l1Provider } from './shared/utils'
import chaiAsPromised from 'chai-as-promised'
import { OptimismEnv } from './shared/env'
import {
Expand Down Expand Up @@ -130,11 +131,25 @@ describe('Basic RPC tests', () => {
const tx = {
...DEFAULT_TRANSACTION,
gasLimit: 1,
gasPrice: 1,
gasPrice: TxGasPrice,
}
const fee = tx.gasPrice.mul(tx.gasLimit)
const gasLimit = 59300000001

await expect(env.l2Wallet.sendTransaction(tx)).to.be.rejectedWith(
'fee too low: 1, use at least tx.gasLimit = 33600000000001 and tx.gasPrice = 1'
`fee too low: ${fee}, use at least tx.gasLimit = ${gasLimit} and tx.gasPrice = ${TxGasPrice.toString()}`
)
})

it('should reject a transaction with an incorrect gas price', async () => {
const tx = {
...DEFAULT_TRANSACTION,
gasLimit: 1,
gasPrice: TxGasPrice.sub(1),
}

await expect(env.l2Wallet.sendTransaction(tx)).to.be.rejectedWith(
`tx.gasPrice must be ${TxGasPrice.toString()}`
)
})

Expand Down Expand Up @@ -198,7 +213,7 @@ describe('Basic RPC tests', () => {
it('correctly exposes revert data for contract calls', async () => {
const req: TransactionRequest = {
...revertingTx,
gasLimit: 934111908999999, // override gas estimation
gasLimit: 59808999999, // override gas estimation
}

const tx = await wallet.sendTransaction(req)
Expand All @@ -221,7 +236,7 @@ describe('Basic RPC tests', () => {
it('correctly exposes revert data for contract creations', async () => {
const req: TransactionRequest = {
...revertingDeployTx,
gasLimit: 1051391908999999, // override gas estimation
gasLimit: 177008999999, // override gas estimation
}

const tx = await wallet.sendTransaction(req)
Expand Down Expand Up @@ -311,12 +326,14 @@ describe('Basic RPC tests', () => {
})

describe('eth_gasPrice', () => {
it('gas price should be 1 gwei', async () => {
expect(await provider.getGasPrice()).to.be.deep.equal(1)
it('gas price should be the fee scalar', async () => {
expect(await provider.getGasPrice()).to.be.deep.equal(
TxGasPrice.toNumber()
)
})
})

describe('eth_estimateGas (returns the fee)', () => {
describe('eth_estimateGas (returns the scaled fee)', () => {
it('gas estimation is deterministic', async () => {
let lastEstimate: BigNumber
for (let i = 0; i < 10; i++) {
Expand All @@ -338,7 +355,7 @@ describe('Basic RPC tests', () => {
to: DEFAULT_TRANSACTION.to,
value: 0,
})
expect(estimate).to.be.eq(33600000119751)
expect(estimate).to.be.eq(0x0dce9004c7)
})

it('should return a gas estimate that grows with the size of data', async () => {
Expand All @@ -349,7 +366,6 @@ describe('Basic RPC tests', () => {
for (const data of dataLen) {
const tx = {
to: '0x' + '1234'.repeat(10),
gasPrice: '0x1',
value: '0x0',
data: '0x' + '00'.repeat(data),
from: '0x' + '1234'.repeat(10),
Expand All @@ -359,16 +375,16 @@ describe('Basic RPC tests', () => {
tx,
])

const decoded = L2GasLimit.decode(estimate)
const decoded = TxGasLimit.decode(estimate)
expect(decoded).to.deep.eq(BigNumber.from(l2Gaslimit))
expect(estimate.toString().endsWith(l2Gaslimit.toString()))

const l2GasPrice = BigNumber.from(0)
// The L2GasPrice should be fetched from the L2GasPrice oracle contract,
// but it does not yet exist. Use the default value for now
const l2GasPrice = BigNumber.from(1)
const expected = L2GasLimit.encode({
const expected = TxGasLimit.encode({
data: tx.data,
l1GasPrice: roundL1GasPrice(l1GasPrice),
l1GasPrice,
l2GasLimit: BigNumber.from(l2Gaslimit),
l2GasPrice,
})
Expand Down
Loading