Commit 3ad9f739 authored by Matthew Slipper's avatar Matthew Slipper Committed by GitHub

Merge pull request #2282 from ethereum-optimism/develop

develop => master
parents a3a5b11d dfd5ac6e
---
'@eth-optimism/sdk': patch
---
Fix typo in constructor docstring
---
'@eth-optimism/sdk': major
---
Update README and bump SDK to 1.0.0
......@@ -27,6 +27,7 @@ module.exports = {
parserOptions: {
project: 'tsconfig.json',
sourceType: 'module',
allowAutomaticSingleRunInference: true,
},
rules: {
'@typescript-eslint/adjacent-overload-signatures': 'error',
......@@ -102,13 +103,9 @@ module.exports = {
'import/no-extraneous-dependencies': ['error'],
'import/no-internal-modules': 'off',
'import/order': [
"error",
'error',
{
groups: [
'builtin',
'external',
'internal',
],
groups: ['builtin', 'external', 'internal'],
'newlines-between': 'always',
},
],
......
......@@ -43,8 +43,8 @@ func NewMetrics(monitoredTokens map[string]string) *Metrics {
return &Metrics{
SyncHeight: promauto.NewGaugeVec(prometheus.GaugeOpts{
Name: "l1_sync_height",
Help: "The max height of the indexer's last batch of L1 blocks.",
Name: "sync_height",
Help: "The max height of the indexer's last batch of L1/L1 blocks.",
Namespace: metricsNamespace,
}, []string{
"chain",
......@@ -66,7 +66,7 @@ func NewMetrics(monitoredTokens map[string]string) *Metrics {
"symbol",
}),
StateBatchesCount: prometheus.NewCounter(prometheus.CounterOpts{
StateBatchesCount: promauto.NewCounter(prometheus.CounterOpts{
Name: "state_batches_count",
Help: "The number of state batches indexed.",
Namespace: metricsNamespace,
......@@ -101,7 +101,7 @@ func NewMetrics(monitoredTokens map[string]string) *Metrics {
"chain",
}),
CachedTokensCount: prometheus.NewCounterVec(prometheus.CounterOpts{
CachedTokensCount: promauto.NewCounterVec(prometheus.CounterOpts{
Name: "cached_tokens_count",
Help: "How many tokens are in the cache",
Namespace: metricsNamespace,
......@@ -118,7 +118,7 @@ func (m *Metrics) SetL1SyncHeight(height uint64) {
}
func (m *Metrics) SetL2SyncHeight(height uint64) {
m.SyncHeight.WithLabelValues("l1").Set(float64(height))
m.SyncHeight.WithLabelValues("l2").Set(float64(height))
}
func (m *Metrics) RecordDeposit(addr common.Address) {
......
{
"name": "indexer",
"name": "@eth-optimism/indexer",
"version": "0.0.1",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"private": true,
"license": "MIT"
}
......@@ -94,9 +94,9 @@ type Service struct {
latestHeader uint64
headerSelector *ConfirmedHeaderSelector
metrics *metrics.Metrics
metrics *metrics.Metrics
tokenCache map[common.Address]*db.Token
wg sync.WaitGroup
wg sync.WaitGroup
}
type IndexerStatus struct {
......@@ -289,10 +289,15 @@ func (s *Service) Update(newHeader *types.Header) error {
logger.Error("Error querying state batches", "err", err)
}
for _, header := range headers {
for i, header := range headers {
blockHash := header.Hash
number := header.Number.Uint64()
deposits := depositsByBlockHash[blockHash]
batches := stateBatches[blockHash]
if len(deposits) == 0 && len(batches) == 0 && i != len(headers)-1 {
continue
}
block := &db.IndexedL1Block{
Hash: blockHash,
......@@ -313,7 +318,6 @@ func (s *Service) Update(newHeader *types.Header) error {
return err
}
batches := stateBatches[blockHash]
err = s.cfg.DB.AddStateBatch(batches)
if err != nil {
logger.Error(
......
......@@ -69,15 +69,15 @@ func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) {
}
type ServiceConfig struct {
Context context.Context
Metrics *metrics.Metrics
L2Client *l2ethclient.Client
ChainID *big.Int
ConfDepth uint64
MaxHeaderBatchSize uint64
StartBlockNumber uint64
StartBlockHash string
DB *db.Database
Context context.Context
Metrics *metrics.Metrics
L2Client *l2ethclient.Client
ChainID *big.Int
ConfDepth uint64
MaxHeaderBatchSize uint64
StartBlockNumber uint64
StartBlockHash string
DB *db.Database
}
type Service struct {
......@@ -89,9 +89,9 @@ type Service struct {
latestHeader uint64
headerSelector *ConfirmedHeaderSelector
metrics *metrics.Metrics
metrics *metrics.Metrics
tokenCache map[common.Address]*db.Token
wg sync.WaitGroup
wg sync.WaitGroup
}
type IndexerStatus struct {
......@@ -267,11 +267,15 @@ func (s *Service) Update(newHeader *types.Header) error {
}
}
for _, header := range headers {
for i, header := range headers {
blockHash := header.Hash()
number := header.Number.Uint64()
withdrawals := withdrawalsByBlockHash[blockHash]
if len(withdrawals) == 0 && i != len(headers)-1 {
continue
}
block := &db.IndexedL2Block{
Hash: blockHash,
ParentHash: header.ParentHash,
......
......@@ -8,12 +8,7 @@
"packages/*",
"l2geth",
"integration-tests",
"specs",
"go/gas-oracle",
"go/batch-submitter",
"go/l2geth-exporter",
"go/proxyd",
"go/op-exporter",
"go/*",
"ops/docker/rpc-proxy",
"ops/docker/hardhat"
],
......
......@@ -66,7 +66,6 @@
"devDependencies": {
"@codechecks/client": "^0.1.11",
"@defi-wonderland/smock": "^2.0.2",
"@eth-optimism/smock": "1.1.10",
"@nomiclabs/ethereumjs-vm": "^4.2.2",
"@nomiclabs/hardhat-ethers": "^2.0.2",
"@nomiclabs/hardhat-etherscan": "^2.1.6",
......
/* External Imports */
import { ethers } from 'hardhat'
import { Signer, ContractFactory, Contract, BigNumber } from 'ethers'
import { smockit, MockContract } from '@eth-optimism/smock'
import { smock, MockContractFactory } from '@defi-wonderland/smock'
import {
smock,
MockContractFactory,
FakeContract,
} from '@defi-wonderland/smock'
import {
remove0x,
toHexString,
......@@ -56,9 +59,9 @@ describe('L1CrossDomainMessenger', () => {
AddressManager = await makeAddressManager()
})
let Mock__TargetContract: MockContract
let Mock__L2CrossDomainMessenger: MockContract
let Mock__StateCommitmentChain: MockContract
let Fake__TargetContract: FakeContract
let Fake__L2CrossDomainMessenger: FakeContract
let Fake__StateCommitmentChain: FakeContract
let Factory__CanonicalTransactionChain: ContractFactory
let Factory__ChainStorageContainer: ContractFactory
......@@ -66,28 +69,28 @@ describe('L1CrossDomainMessenger', () => {
let CanonicalTransactionChain: Contract
before(async () => {
Mock__TargetContract = await smockit(
Fake__TargetContract = await smock.fake<Contract>(
await ethers.getContractFactory('Helper_SimpleProxy')
)
Mock__L2CrossDomainMessenger = await smockit(
Fake__L2CrossDomainMessenger = await smock.fake<Contract>(
await ethers.getContractFactory('L2CrossDomainMessenger'),
{
address: predeploys.L2CrossDomainMessenger,
}
)
Mock__StateCommitmentChain = await smockit(
Fake__StateCommitmentChain = await smock.fake<Contract>(
await ethers.getContractFactory('StateCommitmentChain')
)
await AddressManager.setAddress(
'L2CrossDomainMessenger',
Mock__L2CrossDomainMessenger.address
Fake__L2CrossDomainMessenger.address
)
await setProxyTarget(
AddressManager,
'StateCommitmentChain',
Mock__StateCommitmentChain
Fake__StateCommitmentChain
)
Factory__CanonicalTransactionChain = await ethers.getContractFactory(
......@@ -178,7 +181,7 @@ describe('L1CrossDomainMessenger', () => {
['address', 'address', 'uint256', 'bytes'],
[
applyL1ToL2Alias(L1CrossDomainMessenger.address),
Mock__L2CrossDomainMessenger.address,
Fake__L2CrossDomainMessenger.address,
gasLimit,
calldata,
]
......@@ -322,7 +325,7 @@ describe('L1CrossDomainMessenger', () => {
.to.emit(CanonicalTransactionChain, 'TransactionEnqueued')
.withArgs(
applyL1ToL2Alias(L1CrossDomainMessenger.address),
Mock__L2CrossDomainMessenger.address,
Fake__L2CrossDomainMessenger.address,
newGasLimit,
encodeXDomainCalldata(target, sender, message, queueIndex),
newQueueIndex,
......@@ -388,7 +391,7 @@ describe('L1CrossDomainMessenger', () => {
const storageKey = ethers.utils.keccak256(
ethers.utils.keccak256(
calldata + remove0x(Mock__L2CrossDomainMessenger.address)
calldata + remove0x(Fake__L2CrossDomainMessenger.address)
) + '00'.repeat(32)
)
const storageGenerator = await TrieTestGenerator.fromNodes({
......@@ -439,8 +442,8 @@ describe('L1CrossDomainMessenger', () => {
let proof: any
let calldata: string
before(async () => {
target = Mock__TargetContract.address
message = Mock__TargetContract.interface.encodeFunctionData('setTarget', [
target = Fake__TargetContract.address
message = Fake__TargetContract.interface.encodeFunctionData('setTarget', [
NON_ZERO_ADDRESS,
])
sender = await signer.getAddress()
......@@ -455,18 +458,12 @@ describe('L1CrossDomainMessenger', () => {
})
beforeEach(async () => {
Mock__StateCommitmentChain.smocked.verifyStateCommitment.will.return.with(
true
)
Mock__StateCommitmentChain.smocked.insideFraudProofWindow.will.return.with(
false
)
Fake__StateCommitmentChain.verifyStateCommitment.returns(true)
Fake__StateCommitmentChain.insideFraudProofWindow.returns(false)
})
it('should revert if still inside the fraud proof window', async () => {
Mock__StateCommitmentChain.smocked.insideFraudProofWindow.will.return.with(
true
)
Fake__StateCommitmentChain.insideFraudProofWindow.returns(true)
const proof1 = {
stateRoot: ethers.constants.HashZero,
......@@ -502,9 +499,7 @@ describe('L1CrossDomainMessenger', () => {
})
it('should revert if provided an invalid state root proof', async () => {
Mock__StateCommitmentChain.smocked.verifyStateCommitment.will.return.with(
false
)
Fake__StateCommitmentChain.verifyStateCommitment.returns(false)
const proof1 = {
stateRoot: ethers.constants.HashZero,
......
/* External Imports */
import { ethers } from 'hardhat'
import { Signer, ContractFactory, Contract } from 'ethers'
import { smoddit } from '@eth-optimism/smock'
import { MockContract, smock } from '@defi-wonderland/smock'
import { expectApprox } from '@eth-optimism/core-utils'
/* Internal Imports */
......@@ -92,7 +92,7 @@ describe('[GAS BENCHMARK] Depositing via the standard bridge [ @skip-on-coverage
})
// 4 Bridge
let L1ERC20: Contract
let L1ERC20: MockContract<Contract>
let L1StandardBridge: Contract
before('Deploy the bridge and setup the token', async () => {
// Deploy the Bridge
......@@ -105,14 +105,12 @@ describe('[GAS BENCHMARK] Depositing via the standard bridge [ @skip-on-coverage
)
L1ERC20 = await (
await smoddit('@openzeppelin/contracts/token/ERC20/ERC20.sol:ERC20')
await smock.mock('@openzeppelin/contracts/token/ERC20/ERC20.sol:ERC20')
).deploy('L1ERC20', 'ERC')
const aliceAddress = await alice.getAddress()
await L1ERC20.smodify.put({
_totalSupply: INITIAL_TOTAL_L1_SUPPLY,
_balances: {
[aliceAddress]: INITIAL_TOTAL_L1_SUPPLY,
},
await L1ERC20.setVariable('_totalSupply', INITIAL_TOTAL_L1_SUPPLY)
await L1ERC20.setVariable('_balances', {
[aliceAddress]: INITIAL_TOTAL_L1_SUPPLY,
})
})
......
/* External Imports */
import { ethers } from 'hardhat'
import { Signer, ContractFactory, Contract } from 'ethers'
import { smockit, MockContract } from '@eth-optimism/smock'
import { smock, FakeContract } from '@defi-wonderland/smock'
import {
AppendSequencerBatchParams,
BatchContext,
......@@ -46,7 +46,7 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain [ @skip-on-coverage ]', () =
})
let AddressManager: Contract
let Mock__StateCommitmentChain: MockContract
let Fake__StateCommitmentChain: FakeContract
before(async () => {
AddressManager = await makeAddressManager()
await AddressManager.setAddress(
......@@ -54,14 +54,14 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain [ @skip-on-coverage ]', () =
await sequencer.getAddress()
)
Mock__StateCommitmentChain = await smockit(
Fake__StateCommitmentChain = await smock.fake<Contract>(
await ethers.getContractFactory('StateCommitmentChain')
)
await setProxyTarget(
AddressManager,
'StateCommitmentChain',
Mock__StateCommitmentChain
Fake__StateCommitmentChain
)
})
......
/* External Imports */
import { ethers } from 'hardhat'
import { Signer, ContractFactory, Contract } from 'ethers'
import { smockit, MockContract } from '@eth-optimism/smock'
import { smock, FakeContract } from '@defi-wonderland/smock'
import {
AppendSequencerBatchParams,
encodeAppendSequencerBatch,
......@@ -69,7 +69,7 @@ describe('CanonicalTransactionChain', () => {
})
let AddressManager: Contract
let Mock__StateCommitmentChain: MockContract
let Fake__StateCommitmentChain: FakeContract
before(async () => {
AddressManager = await makeAddressManager()
await AddressManager.setAddress(
......@@ -77,14 +77,14 @@ describe('CanonicalTransactionChain', () => {
await sequencer.getAddress()
)
Mock__StateCommitmentChain = await smockit(
Fake__StateCommitmentChain = await smock.fake<Contract>(
await ethers.getContractFactory('StateCommitmentChain')
)
await setProxyTarget(
AddressManager,
'StateCommitmentChain',
Mock__StateCommitmentChain
Fake__StateCommitmentChain
)
})
......
/* External Imports */
import { ethers } from 'hardhat'
import { Signer, ContractFactory, Contract, constants } from 'ethers'
import { smockit, MockContract } from '@eth-optimism/smock'
import { smock, FakeContract } from '@defi-wonderland/smock'
/* Internal Imports */
import { expect } from '../../../setup'
......@@ -25,26 +25,26 @@ describe('StateCommitmentChain', () => {
AddressManager = await makeAddressManager()
})
let Mock__CanonicalTransactionChain: MockContract
let Mock__BondManager: MockContract
let Fake__CanonicalTransactionChain: FakeContract
let Fake__BondManager: FakeContract
before(async () => {
Mock__CanonicalTransactionChain = await smockit(
Fake__CanonicalTransactionChain = await smock.fake<Contract>(
await ethers.getContractFactory('CanonicalTransactionChain')
)
await setProxyTarget(
AddressManager,
'CanonicalTransactionChain',
Mock__CanonicalTransactionChain
Fake__CanonicalTransactionChain
)
Mock__BondManager = await smockit(
Fake__BondManager = await smock.fake<Contract>(
await ethers.getContractFactory('BondManager')
)
await setProxyTarget(AddressManager, 'BondManager', Mock__BondManager)
await setProxyTarget(AddressManager, 'BondManager', Fake__BondManager)
Mock__BondManager.smocked.isCollateralized.will.return.with(true)
Fake__BondManager.isCollateralized.returns(true)
await AddressManager.setAddress(
'OVM_Proposer',
......@@ -114,7 +114,7 @@ describe('StateCommitmentChain', () => {
describe('when submitting more elements than present in the CanonicalTransactionChain', () => {
before(() => {
Mock__CanonicalTransactionChain.smocked.getTotalElements.will.return.with(
Fake__CanonicalTransactionChain.getTotalElements.returns(
batch.length - 1
)
})
......@@ -130,9 +130,7 @@ describe('StateCommitmentChain', () => {
describe('when not submitting more elements than present in the CanonicalTransactionChain', () => {
before(() => {
Mock__CanonicalTransactionChain.smocked.getTotalElements.will.return.with(
batch.length
)
Fake__CanonicalTransactionChain.getTotalElements.returns(batch.length)
})
it('should append the state batch', async () => {
......@@ -143,7 +141,7 @@ describe('StateCommitmentChain', () => {
describe('when a sequencer submits ', () => {
beforeEach(async () => {
Mock__CanonicalTransactionChain.smocked.getTotalElements.will.return.with(
Fake__CanonicalTransactionChain.getTotalElements.returns(
batch.length * 2
)
......@@ -182,7 +180,7 @@ describe('StateCommitmentChain', () => {
})
describe('when the proposer has not previously staked at the BondManager', () => {
before(() => {
Mock__BondManager.smocked.isCollateralized.will.return.with(false)
Fake__BondManager.isCollateralized.returns(false)
})
it('should revert', async () => {
......@@ -207,13 +205,11 @@ describe('StateCommitmentChain', () => {
}
before(() => {
Mock__BondManager.smocked.isCollateralized.will.return.with(true)
Fake__BondManager.isCollateralized.returns(true)
})
beforeEach(async () => {
Mock__CanonicalTransactionChain.smocked.getTotalElements.will.return.with(
batch.length
)
Fake__CanonicalTransactionChain.getTotalElements.returns(batch.length)
await StateCommitmentChain.appendStateBatch(batch, 0)
batchHeader.extraData = ethers.utils.defaultAbiCoder.encode(
['uint256', 'address'],
......@@ -329,9 +325,7 @@ describe('StateCommitmentChain', () => {
describe('when one batch element has been inserted', () => {
beforeEach(async () => {
const batch = [NON_NULL_BYTES32]
Mock__CanonicalTransactionChain.smocked.getTotalElements.will.return.with(
batch.length
)
Fake__CanonicalTransactionChain.getTotalElements.returns(batch.length)
await StateCommitmentChain.appendStateBatch(batch, 0)
})
......@@ -343,9 +337,7 @@ describe('StateCommitmentChain', () => {
describe('when 64 batch elements have been inserted in one batch', () => {
beforeEach(async () => {
const batch = Array(64).fill(NON_NULL_BYTES32)
Mock__CanonicalTransactionChain.smocked.getTotalElements.will.return.with(
batch.length
)
Fake__CanonicalTransactionChain.getTotalElements.returns(batch.length)
await StateCommitmentChain.appendStateBatch(batch, 0)
})
......@@ -357,7 +349,7 @@ describe('StateCommitmentChain', () => {
describe('when 32 batch elements have been inserted in each of two batches', () => {
beforeEach(async () => {
const batch = Array(32).fill(NON_NULL_BYTES32)
Mock__CanonicalTransactionChain.smocked.getTotalElements.will.return.with(
Fake__CanonicalTransactionChain.getTotalElements.returns(
batch.length * 2
)
await StateCommitmentChain.appendStateBatch(batch, 0)
......@@ -380,9 +372,7 @@ describe('StateCommitmentChain', () => {
describe('when one batch has been inserted', () => {
beforeEach(async () => {
const batch = [NON_NULL_BYTES32]
Mock__CanonicalTransactionChain.smocked.getTotalElements.will.return.with(
batch.length
)
Fake__CanonicalTransactionChain.getTotalElements.returns(batch.length)
await StateCommitmentChain.appendStateBatch(batch, 0)
})
......@@ -394,7 +384,7 @@ describe('StateCommitmentChain', () => {
describe('when 8 batches have been inserted', () => {
beforeEach(async () => {
const batch = [NON_NULL_BYTES32]
Mock__CanonicalTransactionChain.smocked.getTotalElements.will.return.with(
Fake__CanonicalTransactionChain.getTotalElements.returns(
batch.length * 8
)
......@@ -422,9 +412,7 @@ describe('StateCommitmentChain', () => {
let timestamp
beforeEach(async () => {
const batch = [NON_NULL_BYTES32]
Mock__CanonicalTransactionChain.smocked.getTotalElements.will.return.with(
batch.length
)
Fake__CanonicalTransactionChain.getTotalElements.returns(batch.length)
await StateCommitmentChain.appendStateBatch(batch, 0)
timestamp = await getEthTime(ethers.provider)
})
......@@ -455,13 +443,11 @@ describe('StateCommitmentChain', () => {
const element = NON_NULL_BYTES32
before(async () => {
Mock__BondManager.smocked.isCollateralized.will.return.with(true)
Fake__BondManager.isCollateralized.returns(true)
})
beforeEach(async () => {
Mock__CanonicalTransactionChain.smocked.getTotalElements.will.return.with(
batch.length
)
Fake__CanonicalTransactionChain.getTotalElements.returns(batch.length)
await StateCommitmentChain.appendStateBatch(batch, 0)
batchHeader.extraData = ethers.utils.defaultAbiCoder.encode(
['uint256', 'address'],
......
/* External Imports */
import hre, { ethers } from 'hardhat'
import { Signer, ContractFactory, Contract } from 'ethers'
import { smockit, MockContract } from '@eth-optimism/smock'
import { applyL1ToL2Alias } from '@eth-optimism/core-utils'
import { smock, MockContractFactory } from '@defi-wonderland/smock'
import {
smock,
MockContractFactory,
FakeContract,
} from '@defi-wonderland/smock'
/* Internal Imports */
import { expect } from '../../../setup'
......@@ -20,17 +23,17 @@ describe('L2CrossDomainMessenger', () => {
;[signer] = await ethers.getSigners()
})
let Mock__TargetContract: MockContract
let Mock__L1CrossDomainMessenger: MockContract
let Mock__OVM_L2ToL1MessagePasser: MockContract
let Fake__TargetContract: FakeContract
let Fake__L1CrossDomainMessenger: FakeContract
let Fake__OVM_L2ToL1MessagePasser: FakeContract
before(async () => {
Mock__TargetContract = await smockit(
Fake__TargetContract = await smock.fake<Contract>(
await ethers.getContractFactory('Helper_SimpleProxy')
)
Mock__L1CrossDomainMessenger = await smockit(
Fake__L1CrossDomainMessenger = await smock.fake<Contract>(
await ethers.getContractFactory('L1CrossDomainMessenger')
)
Mock__OVM_L2ToL1MessagePasser = await smockit(
Fake__OVM_L2ToL1MessagePasser = await smock.fake<Contract>(
await ethers.getContractFactory('OVM_L2ToL1MessagePasser'),
{ address: predeploys.OVM_L2ToL1MessagePasser }
)
......@@ -39,7 +42,7 @@ describe('L2CrossDomainMessenger', () => {
let impersonatedL1CrossDomainMessengerSender: Signer
before(async () => {
const impersonatedAddress = applyL1ToL2Alias(
Mock__L1CrossDomainMessenger.address
Fake__L1CrossDomainMessenger.address
)
await hre.network.provider.request({
method: 'hardhat_impersonateAccount',
......@@ -64,7 +67,7 @@ describe('L2CrossDomainMessenger', () => {
let L2CrossDomainMessenger: Contract
beforeEach(async () => {
L2CrossDomainMessenger = await Factory__L2CrossDomainMessenger.deploy(
Mock__L1CrossDomainMessenger.address
Fake__L1CrossDomainMessenger.address
)
})
......@@ -77,7 +80,7 @@ describe('L2CrossDomainMessenger', () => {
)
Mock__L2CrossDomainMessenger =
await Mock__Factory__L2CrossDomainMessenger.deploy(
Mock__L1CrossDomainMessenger.address
Fake__L1CrossDomainMessenger.address
)
})
......@@ -103,10 +106,10 @@ describe('L2CrossDomainMessenger', () => {
).to.not.be.reverted
expect(
Mock__OVM_L2ToL1MessagePasser.smocked.passMessageToL1.calls[0]
).to.deep.equal([
encodeXDomainCalldata(target, await signer.getAddress(), message, 0),
])
Fake__OVM_L2ToL1MessagePasser.passMessageToL1.getCall(0).args[0]
).to.deep.equal(
encodeXDomainCalldata(target, await signer.getAddress(), message, 0)
)
})
it('should be able to send the same message twice', async () => {
......@@ -123,8 +126,8 @@ describe('L2CrossDomainMessenger', () => {
let message: string
let sender: string
before(async () => {
target = Mock__TargetContract.address
message = Mock__TargetContract.interface.encodeFunctionData('setTarget', [
target = Fake__TargetContract.address
message = Fake__TargetContract.interface.encodeFunctionData('setTarget', [
NON_ZERO_ADDRESS,
])
sender = await signer.getAddress()
......@@ -146,9 +149,9 @@ describe('L2CrossDomainMessenger', () => {
impersonatedL1CrossDomainMessengerSender
).relayMessage(target, sender, message, 0)
expect(Mock__TargetContract.smocked.setTarget.calls[0]).to.deep.equal([
NON_ZERO_ADDRESS,
])
expect(Fake__TargetContract.setTarget.getCall(0).args[0]).to.deep.equal(
NON_ZERO_ADDRESS
)
})
it('the xDomainMessageSender is reset to the original value', async () => {
......@@ -179,7 +182,7 @@ describe('L2CrossDomainMessenger', () => {
it('should not make a call if the target is the L2 MessagePasser', async () => {
target = predeploys.OVM_L2ToL1MessagePasser
message = Mock__OVM_L2ToL1MessagePasser.interface.encodeFunctionData(
message = Fake__OVM_L2ToL1MessagePasser.interface.encodeFunctionData(
'passMessageToL1(bytes)',
[NON_NULL_BYTES32]
)
......@@ -193,7 +196,7 @@ describe('L2CrossDomainMessenger', () => {
// There should be no 'relayedMessage' event logged in the receipt.
const logs = (
await Mock__OVM_L2ToL1MessagePasser.provider.getTransactionReceipt(
await Fake__OVM_L2ToL1MessagePasser.provider.getTransactionReceipt(
(
await resProm
).hash
......
/* External Imports */
import { ethers } from 'hardhat'
import { Signer, ContractFactory, Contract } from 'ethers'
import { smoddit } from '@eth-optimism/smock'
import {
smock,
MockContractFactory,
MockContract,
} from '@defi-wonderland/smock'
/* Internal Imports */
import { expect } from '../../../setup'
......@@ -9,13 +13,13 @@ import { predeploys, getContractInterface } from '../../../../src'
describe('L2StandardTokenFactory', () => {
let signer: Signer
let Factory__L1ERC20: ContractFactory
let L1ERC20: Contract
let Factory__L1ERC20: MockContractFactory<ContractFactory>
let L1ERC20: MockContract<Contract>
let L2StandardTokenFactory: Contract
before(async () => {
;[signer] = await ethers.getSigners()
// deploy an ERC20 contract on L1
Factory__L1ERC20 = await smoddit(
Factory__L1ERC20 = await smock.mock(
'@openzeppelin/contracts/token/ERC20/ERC20.sol:ERC20'
)
L1ERC20 = await Factory__L1ERC20.deploy('L1ERC20', 'ERC')
......
/* External Imports */
import { ethers } from 'hardhat'
import { ContractFactory, Contract } from 'ethers'
import { MockContract, smockit } from '@eth-optimism/smock'
import { smock, FakeContract } from '@defi-wonderland/smock'
import { remove0x } from '@eth-optimism/core-utils'
import { keccak256 } from 'ethers/lib/utils'
......@@ -25,9 +25,9 @@ const callPredeploy = async (
// TODO: rewrite this test to bypass the execution manager
describe.skip('OVM_L2ToL1MessagePasser', () => {
let Mock__OVM_ExecutionManager: MockContract
let Fake__OVM_ExecutionManager: FakeContract
before(async () => {
Mock__OVM_ExecutionManager = await smockit(
Fake__OVM_ExecutionManager = await smock.fake<Contract>(
await ethers.getContractFactory('OVM_ExecutionManager')
)
})
......@@ -38,7 +38,7 @@ describe.skip('OVM_L2ToL1MessagePasser', () => {
await ethers.getContractFactory('Helper_PredeployCaller')
).deploy()
Helper_PredeployCaller.setTarget(Mock__OVM_ExecutionManager.address)
Helper_PredeployCaller.setTarget(Fake__OVM_ExecutionManager.address)
})
let Factory__OVM_L2ToL1MessagePasser: ContractFactory
......@@ -55,9 +55,7 @@ describe.skip('OVM_L2ToL1MessagePasser', () => {
describe('passMessageToL1', () => {
before(async () => {
Mock__OVM_ExecutionManager.smocked.ovmCALLER.will.return.with(
NON_ZERO_ADDRESS
)
Fake__OVM_ExecutionManager.ovmCALLER.returns(NON_ZERO_ADDRESS)
})
for (const size of ELEMENT_TEST_SIZES) {
......
/* Imports: External */
import hre from 'hardhat'
import { MockContract, smockit } from '@eth-optimism/smock'
import { smock, FakeContract } from '@defi-wonderland/smock'
import { Contract, Signer } from 'ethers'
/* Imports: Internal */
......@@ -13,9 +13,9 @@ describe('OVM_SequencerFeeVault', () => {
;[signer1] = await hre.ethers.getSigners()
})
let Mock__L2StandardBridge: MockContract
let Fake__L2StandardBridge: FakeContract
before(async () => {
Mock__L2StandardBridge = await smockit('L2StandardBridge', {
Fake__L2StandardBridge = await smock.fake<Contract>('L2StandardBridge', {
address: predeploys.L2StandardBridge,
})
})
......@@ -42,13 +42,21 @@ describe('OVM_SequencerFeeVault', () => {
await expect(OVM_SequencerFeeVault.withdraw()).to.not.be.reverted
expect(Mock__L2StandardBridge.smocked.withdrawTo.calls[0]).to.deep.equal([
predeploys.OVM_ETH,
await signer1.getAddress(),
amount,
0,
'0x',
])
expect(
Fake__L2StandardBridge.withdrawTo.getCall(0).args[0]
).to.deep.equal(predeploys.OVM_ETH)
expect(
Fake__L2StandardBridge.withdrawTo.getCall(0).args[1]
).to.deep.equal(await signer1.getAddress())
expect(
Fake__L2StandardBridge.withdrawTo.getCall(0).args[2]
).to.deep.equal(amount)
expect(
Fake__L2StandardBridge.withdrawTo.getCall(0).args[3]
).to.deep.equal(0)
expect(
Fake__L2StandardBridge.withdrawTo.getCall(0).args[4]
).to.deep.equal('0x')
})
it('should succeed when the contract has more than sufficient balance', async () => {
......@@ -62,14 +70,21 @@ describe('OVM_SequencerFeeVault', () => {
})
await expect(OVM_SequencerFeeVault.withdraw()).to.not.be.reverted
expect(Mock__L2StandardBridge.smocked.withdrawTo.calls[0]).to.deep.equal([
predeploys.OVM_ETH,
await signer1.getAddress(),
amount,
0,
'0x',
])
expect(
Fake__L2StandardBridge.withdrawTo.getCall(1).args[0]
).to.deep.equal(predeploys.OVM_ETH)
expect(
Fake__L2StandardBridge.withdrawTo.getCall(1).args[1]
).to.deep.equal(await signer1.getAddress())
expect(
Fake__L2StandardBridge.withdrawTo.getCall(1).args[2]
).to.deep.equal(amount)
expect(
Fake__L2StandardBridge.withdrawTo.getCall(1).args[3]
).to.deep.equal(0)
expect(
Fake__L2StandardBridge.withdrawTo.getCall(1).args[4]
).to.deep.equal('0x')
})
it('should have an owner in storage slot 0x00...00', async () => {
......
/* Imports: External */
import hre from 'hardhat'
import { Contract, Signer } from 'ethers'
import { smockit } from '@eth-optimism/smock'
import { smock } from '@defi-wonderland/smock'
/* Imports: Internal */
import { expect } from '../../setup'
......@@ -170,11 +170,13 @@ describe('L1ChugSplashProxy', () => {
})
it('should throw an error if the owner has signalled an upgrade', async () => {
const owner = await smockit(getContractInterface('iL1ChugSplashDeployer'))
const owner = await smock.fake<Contract>(
getContractInterface('iL1ChugSplashDeployer')
)
const factory = await hre.ethers.getContractFactory('L1ChugSplashProxy')
const proxy = await factory.deploy(owner.address)
owner.smocked.isUpgrading.will.return.with(true)
owner.isUpgrading.returns(true)
await expect(
owner.wallet.sendTransaction({
......
/* External Imports */
import { ethers } from 'hardhat'
import { Contract } from 'ethers'
import { FakeContract } from '@defi-wonderland/smock'
export const setProxyTarget = async (
AddressManager: Contract,
name: string,
target: Contract
target: FakeContract
): Promise<void> => {
const SimpleProxy: Contract = await (
await ethers.getContractFactory('Helper_SimpleProxy')
......
ignores: [
"@eth-optimism/core-utils",
"ts-mocha",
]
\ No newline at end of file
"typedoc",
]
......@@ -4,19 +4,33 @@
The `@eth-optimism/sdk` package provides a set of tools for interacting with Optimism.
## NOTICE
WARNING: This package is currently under construction.
You can definitely try to use it, but you probably won't have a good time.
Lots of pieces are missing.
We will announce the 1.0.0 release on Discord and on Twitter once it's ready, keep an eye out!
## Installation
```
npm install @eth-optimism/sdk
```
## API
## Docs
You can find auto-generated API documentation over at [sdk.optimism.io](https://sdk.optimism.io).
## Using the SDK
### CrossChainMessenger
The [`CrossChainMessenger`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/sdk/src/cross-chain-messenger.ts) class simplifies the process of moving assets and data between Ethereum and Optimism.
You can use this class to, for example, initiate a withdrawal of ERC20 tokens from Optimism back to Ethereum, accurately track when the withdrawal is ready to be finalized on Ethereum, and execute the finalization transaction after the challenge period has elapsed.
The `CrossChainMessenger` can handle deposits and withdrawals of ETH and any ERC20-compatible token.
Detailed API descriptions can be found at [sdk.optimism.io](https://sdk.optimism.io/classes/crosschainmessenger).
The `CrossChainMessenger` automatically connects to all relevant contracts so complex configuration is not necessary.
### L2Provider and related utilities
The Optimism SDK includes [various utilities](https://github.com/ethereum-optimism/optimism/blob/develop/packages/sdk/src/l2-provider.ts) for handling Optimism's [transaction fee model](https://community.optimism.io/docs/developers/build/transaction-fees/).
For instance, [`estimateTotalGasCost`](https://sdk.optimism.io/modules.html#estimateTotalGasCost) will estimate the total cost (in wei) to send at transaction on Optimism including both the L2 execution cost and the L1 data cost.
You can also use the [`asL2Provider`](https://sdk.optimism.io/modules.html#asL2Provider) function to wrap an ethers Provider object into an `L2Provider` which will have all of these helper functions attached.
### Other utilities
TODO: Fill this in once the initial package version is finished.
The SDK contains other useful helper functions and constants.
For a complete list, refer to the auto-generated [SDK documentation](https://sdk.optimism.io/)
......@@ -16,7 +16,8 @@
"lint:fix": "yarn lint:check --fix",
"pre-commit": "lint-staged",
"test": "hardhat test",
"test:coverage": "nyc hardhat test && nyc merge .nyc_output coverage.json"
"test:coverage": "nyc hardhat test && nyc merge .nyc_output coverage.json",
"autogen:docs": "typedoc --out docs src/index.ts"
},
"keywords": [
"optimism",
......@@ -60,6 +61,7 @@
"nyc": "^15.1.0",
"prettier": "^2.3.1",
"ts-mocha": "^8.0.0",
"typedoc": "^0.22.13",
"typescript": "^4.3.5"
},
"dependencies": {
......
......@@ -64,7 +64,7 @@ export class CrossChainMessenger implements ICrossChainMessenger {
*
* @param opts Options for the provider.
* @param opts.l1SignerOrProvider Signer or Provider for the L1 chain, or a JSON-RPC url.
* @param opts.l1SignerOrProvider Signer or Provider for the L2 chain, or a JSON-RPC url.
* @param opts.l2SignerOrProvider Signer or Provider for the L2 chain, or a JSON-RPC url.
* @param opts.l1ChainId Chain ID for the L1 chain.
* @param opts.depositConfirmationBlocks Optional number of blocks before a deposit is confirmed.
* @param opts.l1BlockTimeSeconds Optional estimated block time in seconds for the L1 chain.
......
......@@ -497,23 +497,6 @@
minimatch "^3.0.4"
strip-json-comments "^3.1.1"
"@eth-optimism/core-utils@^0.5.1":
version "0.5.5"
resolved "https://registry.yarnpkg.com/@eth-optimism/core-utils/-/core-utils-0.5.5.tgz#0e2bb95b23965fb51adfb8ba6841c3afd26a6411"
integrity sha512-N/uyZjHltnvnQyBOE498EGlqeYvWRUQTW6BpXhexKljEXZpnria4J4MFO9s1lJOpogLXTaS+lhM1Ic8zUNj8Pg==
dependencies:
"@ethersproject/abstract-provider" "^5.4.1"
ethers "^5.4.5"
lodash "^4.17.21"
"@eth-optimism/smock@1.1.10":
version "1.1.10"
resolved "https://registry.yarnpkg.com/@eth-optimism/smock/-/smock-1.1.10.tgz#98a6eefc994ccf707f52ab06849468f3cc57bdb7"
integrity sha512-XPx1x9odF/noTBHzIhRgL9ihhr769WgUhf9dOm6X7bjSWRAVsII3IqbdB4ssPycaoSuNSmv8HG1xTLgfgcyOYw==
dependencies:
"@eth-optimism/core-utils" "^0.5.1"
bn.js "^5.2.0"
"@ethereum-waffle/chai@^3.4.0":
version "3.4.0"
resolved "https://registry.yarnpkg.com/@ethereum-waffle/chai/-/chai-3.4.0.tgz#2477877410a96bf370edd64df905b04fb9aba9d5"
......@@ -712,7 +695,7 @@
"@ethersproject/properties" "^5.4.0"
"@ethersproject/strings" "^5.4.0"
"@ethersproject/abstract-provider@5.4.1", "@ethersproject/abstract-provider@^5.4.0", "@ethersproject/abstract-provider@^5.4.1":
"@ethersproject/abstract-provider@5.4.1", "@ethersproject/abstract-provider@^5.4.0":
version "5.4.1"
resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.4.1.tgz#e404309a29f771bd4d28dbafadcaa184668c2a6e"
integrity sha512-3EedfKI3LVpjSKgAxoUaI+gB27frKsxzm+r21w9G60Ugk+3wVLQwhi1LsEJAKNV7WoZc8CIpNrATlL1QFABjtQ==
......@@ -4574,6 +4557,13 @@ brace-expansion@^1.1.7:
balanced-match "^1.0.0"
concat-map "0.0.1"
brace-expansion@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
dependencies:
balanced-match "^1.0.0"
braces@^2.3.1:
version "2.3.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729"
......@@ -7176,7 +7166,7 @@ ethers@^4.0.32, ethers@^4.0.40:
uuid "2.0.1"
xmlhttprequest "1.8.0"
ethers@^5.0.0, ethers@^5.0.1, ethers@^5.0.2, ethers@^5.4.5:
ethers@^5.0.0, ethers@^5.0.1, ethers@^5.0.2:
version "5.4.5"
resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.4.5.tgz#cec133b9f5b514dc55e2561ee7aa7218c33affd7"
integrity sha512-PPZ6flOAj230sXEWf/r/It6ZZ5c7EOVWx+PU87Glkbg79OtT7pLE1WgL4MRdwx6iF7HzSOvUUI+8cAmcdzo12w==
......@@ -8219,6 +8209,18 @@ glob@^7.0.0, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, gl
once "^1.3.0"
path-is-absolute "^1.0.0"
glob@^7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^3.0.4"
once "^1.3.0"
path-is-absolute "^1.0.0"
global-modules@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780"
......@@ -9697,6 +9699,11 @@ json5@^2.1.0, json5@^2.1.2, json5@^2.2.0:
dependencies:
minimist "^1.2.5"
jsonc-parser@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.0.0.tgz#abdd785701c7e7eaca8a9ec8cf070ca51a745a22"
integrity sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==
jsonfile@^2.1.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8"
......@@ -10418,6 +10425,11 @@ ltgt@~2.1.1:
resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.1.3.tgz#10851a06d9964b971178441c23c9e52698eece34"
integrity sha1-EIUaBtmWS5cReEQcI8nlJpjuzjQ=
lunr@^2.3.9:
version "2.3.9"
resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1"
integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==
make-dir@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
......@@ -10532,6 +10544,11 @@ marked@^0.7.0:
resolved "https://registry.yarnpkg.com/marked/-/marked-0.7.0.tgz#b64201f051d271b1edc10a04d1ae9b74bb8e5c0e"
integrity sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==
marked@^4.0.12:
version "4.0.12"
resolved "https://registry.yarnpkg.com/marked/-/marked-4.0.12.tgz#2262a4e6fd1afd2f13557726238b69a48b982f7d"
integrity sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==
match-all@^1.2.6:
version "1.2.6"
resolved "https://registry.yarnpkg.com/match-all/-/match-all-1.2.6.tgz#66d276ad6b49655551e63d3a6ee53e8be0566f8d"
......@@ -10847,6 +10864,13 @@ minimalistic-crypto-utils@^1.0.1:
dependencies:
brace-expansion "^1.1.7"
minimatch@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b"
integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==
dependencies:
brace-expansion "^2.0.1"
minimist-options@4.1.0, minimist-options@^4.0.2:
version "4.1.0"
resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619"
......@@ -13700,6 +13724,15 @@ shelljs@^0.8.3:
interpret "^1.0.0"
rechoir "^0.6.2"
shiki@^0.10.1:
version "0.10.1"
resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.10.1.tgz#6f9a16205a823b56c072d0f1a0bcd0f2646bef14"
integrity sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==
dependencies:
jsonc-parser "^3.0.0"
vscode-oniguruma "^1.6.1"
vscode-textmate "5.2.0"
side-channel@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
......@@ -15138,6 +15171,17 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
typedoc@^0.22.13:
version "0.22.13"
resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.22.13.tgz#d061f8f0fb7c9d686e48814f245bddeea4564e66"
integrity sha512-NHNI7Dr6JHa/I3+c62gdRNXBIyX7P33O9TafGLd07ur3MqzcKgwTvpg18EtvCLHJyfeSthAtCLpM7WkStUmDuQ==
dependencies:
glob "^7.2.0"
lunr "^2.3.9"
marked "^4.0.12"
minimatch "^5.0.1"
shiki "^0.10.1"
typescript@^4.3.4, typescript@^4.3.5:
version "4.3.5"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.5.tgz#4d1c37cc16e893973c45a06886b7113234f119f4"
......@@ -15460,6 +15504,16 @@ verror@1.10.0:
core-util-is "1.0.2"
extsprintf "^1.2.0"
vscode-oniguruma@^1.6.1:
version "1.6.2"
resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz#aeb9771a2f1dbfc9083c8a7fdd9cccaa3f386607"
integrity sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==
vscode-textmate@5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.2.0.tgz#01f01760a391e8222fe4f33fbccbd1ad71aed74e"
integrity sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==
wcwidth@^1.0.0, wcwidth@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
......
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