Commit 4c1d0c27 authored by mergify[bot]'s avatar mergify[bot] Committed by GitHub

Merge branch 'develop' into jm/sbn-specs

parents 69396038 5d0a3af6
---
'@eth-optimism/contracts-bedrock': patch
---
Make lint check and fix scripts match
......@@ -548,7 +548,6 @@ jobs:
devnet:
machine:
image: ubuntu-2204:2022.10.2
docker_layer_caching: true
parameters:
deploy:
description: Deploy contracts
......@@ -595,16 +594,41 @@ jobs:
working_directory: packages/contracts-bedrock
- run:
name: Deposit ERC20 through the bridge
command: timeout 5m npx hardhat deposit-erc20 --network devnetL1 --l1-contracts-json-path ../../.devnet/sdk-addresses.json
command: timeout 8m npx hardhat deposit-erc20 --network devnetL1 --l1-contracts-json-path ../../.devnet/sdk-addresses.json
working_directory: packages/sdk
- run:
name: Deposit ETH through the bridge
command: timeout 5m npx hardhat deposit-eth --network devnetL1 --l1-contracts-json-path ../../.devnet/sdk-addresses.json
command: timeout 8m npx hardhat deposit-eth --network devnetL1 --l1-contracts-json-path ../../.devnet/sdk-addresses.json
working_directory: packages/sdk
- run:
name: Check the status
command: npx hardhat check-op-node
working_directory: packages/contracts-bedrock
- run:
name: Dump op-node logs
command: |
docker logs ops-bedrock-op-node-1 || echo "No logs."
when: on_fail
- run:
name: Dump op-geth logs
command: |
docker logs ops-bedrock-l2-1 || echo "No logs."
when: on_fail
- run:
name: Dump l1 logs
command: |
docker logs ops-bedrock-l1-1 || echo "No logs."
when: on_fail
- run:
name: Dump op-batcher logs
command: |
docker logs ops-bedrock-op-batcher-1 || echo "No logs."
when: on_fail
- run:
name: Dump op-proposer logs
command: |
docker logs ops-bedrock-op-proposer-1 || echo "No logs."
when: on_fail
- when:
condition:
and:
......
......@@ -84,7 +84,7 @@ func NewBatchSubmitter(cfg Config, l log.Logger) (*BatchSubmitter, error) {
signer := func(chainID *big.Int) SignerFn {
s := types.LatestSignerForChainID(chainID)
return func(rawTx types.TxData) (*types.Transaction, error) {
return func(_ context.Context, rawTx types.TxData) (*types.Transaction, error) {
return types.SignNewTx(sequencerPrivKey, s, rawTx)
}
}
......
......@@ -16,7 +16,7 @@ import (
const networkTimeout = 2 * time.Second // How long a single network request can take. TODO: put in a config somewhere
type SignerFn func(rawTx types.TxData) (*types.Transaction, error)
type SignerFn func(ctx context.Context, rawTx types.TxData) (*types.Transaction, error)
// TransactionManager wraps the simple txmgr package to make it easy to send & wait for transactions
type TransactionManager struct {
......@@ -121,7 +121,7 @@ func (t *TransactionManager) CraftTx(ctx context.Context, data []byte) (*types.T
}
rawTx.Gas = gas
return t.signerFn(rawTx)
return t.signerFn(ctx, rawTx)
}
// UpdateGasPrice signs an otherwise identical txn to the one provided but with
......@@ -146,5 +146,5 @@ func (t *TransactionManager) UpdateGasPrice(ctx context.Context, tx *types.Trans
// Only log the new tip/fee cap because the updateGasPrice closure reuses the same initial transaction
t.log.Trace("updating gas price", "tip_cap", gasTipCap, "fee_cap", gasFeeCap)
return t.signerFn(rawTx)
return t.signerFn(ctx, rawTx)
}
package actions
import (
"math/big"
"testing"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"
)
// TestLargeL1Gaps tests the case that there is a gap between two L1 blocks which
// is larger than the sequencer drift.
// This test has the following parameters:
// L1 Block time: 4s. L2 Block time: 2s. Sequencer Drift: 32s
//
// It generates 8 L1 blocks & 16 L2 blocks.
// Then generates an L1 block that has a time delta of 48s.
// It then generates the 24 L2 blocks.
// Then it generates 3 more L1 blocks.
// At this point it can verify that the batches where properly generated.
// Note: It batches submits when possible.
func TestLargeL1Gaps(gt *testing.T) {
t := NewDefaultTesting(gt)
dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams)
dp.DeployConfig.L1BlockTime = 4
dp.DeployConfig.L2BlockTime = 2
dp.DeployConfig.SequencerWindowSize = 4
dp.DeployConfig.MaxSequencerDrift = 32
sd := e2eutils.Setup(t, dp, defaultAlloc)
log := testlog.Logger(t, log.LvlDebug)
sd, miner, sequencer, sequencerEngine, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log)
signer := types.LatestSigner(sd.L2Cfg.Config)
cl := sequencerEngine.EthClient()
aliceTx := func() {
n, err := cl.PendingNonceAt(t.Ctx(), dp.Addresses.Alice)
require.NoError(t, err)
tx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{
ChainID: sd.L2Cfg.Config.ChainID,
Nonce: n,
GasTipCap: big.NewInt(2 * params.GWei),
GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee(), big.NewInt(2*params.GWei)),
Gas: params.TxGas,
To: &dp.Addresses.Bob,
Value: e2eutils.Ether(2),
})
require.NoError(gt, cl.SendTransaction(t.Ctx(), tx))
}
makeL2BlockWithAliceTx := func() {
aliceTx()
sequencer.ActL2StartBlock(t)
sequencerEngine.ActL2IncludeTx(dp.Addresses.Alice)(t) // include a test tx from alice
sequencer.ActL2EndBlock(t)
}
verifyChainStateOnSequencer := func(l1Number, unsafeHead, unsafeHeadOrigin, safeHead, safeHeadOrigin uint64) {
require.Equal(t, l1Number, miner.l1Chain.CurrentHeader().Number.Uint64())
require.Equal(t, unsafeHead, sequencer.L2Unsafe().Number)
require.Equal(t, unsafeHeadOrigin, sequencer.L2Unsafe().L1Origin.Number)
require.Equal(t, safeHead, sequencer.L2Safe().Number)
require.Equal(t, safeHeadOrigin, sequencer.L2Safe().L1Origin.Number)
}
verifyChainStateOnVerifier := func(l1Number, unsafeHead, unsafeHeadOrigin, safeHead, safeHeadOrigin uint64) {
require.Equal(t, l1Number, miner.l1Chain.CurrentHeader().Number.Uint64())
require.Equal(t, unsafeHead, verifier.L2Unsafe().Number)
require.Equal(t, unsafeHeadOrigin, verifier.L2Unsafe().L1Origin.Number)
require.Equal(t, safeHead, verifier.L2Safe().Number)
require.Equal(t, safeHeadOrigin, verifier.L2Safe().L1Origin.Number)
}
// Make 8 L1 blocks & 16 L2 blocks.
miner.ActL1StartBlock(4)(t)
miner.ActL1EndBlock(t)
sequencer.ActL1HeadSignal(t)
sequencer.ActL2PipelineFull(t)
makeL2BlockWithAliceTx()
makeL2BlockWithAliceTx()
for i := 0; i < 7; i++ {
batcher.ActSubmitAll(t)
miner.ActL1StartBlock(4)(t)
miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t)
miner.ActL1EndBlock(t)
sequencer.ActL1HeadSignal(t)
sequencer.ActL2PipelineFull(t)
makeL2BlockWithAliceTx()
makeL2BlockWithAliceTx()
}
verifyChainStateOnSequencer(8, 16, 8, 14, 7)
// Make the really long L1 block. Do include previous batches
batcher.ActSubmitAll(t)
miner.ActL1StartBlock(48)(t)
miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t)
miner.ActL1EndBlock(t)
sequencer.ActL1HeadSignal(t)
sequencer.ActL2PipelineFull(t)
verifyChainStateOnSequencer(9, 16, 8, 16, 8)
// Make the L2 blocks corresponding to the long L1 block
for i := 0; i < 24; i++ {
makeL2BlockWithAliceTx()
}
verifyChainStateOnSequencer(9, 40, 9, 16, 8)
// Check how many transactions from alice got included on L2
// We created one transaction for every L2 block. So we should have created 40 transactions.
// The first 16 L2 block where included without issue.
// Then over the long block, 32s seq drift / 2s block time => 16 blocks with transactions
// That leaves 8 blocks without transactions. So we should have 16+16 = 32 transactions on chain.
n, err := cl.PendingNonceAt(t.Ctx(), dp.Addresses.Alice)
require.NoError(t, err)
require.Equal(t, uint64(40), n)
n, err = cl.NonceAt(t.Ctx(), dp.Addresses.Alice, nil)
require.NoError(t, err)
require.Equal(t, uint64(32), n)
// Make more L1 blocks to get past the sequence window for the large range.
// Do batch submit the previous L2 blocks.
batcher.ActSubmitAll(t)
miner.ActL1StartBlock(4)(t)
miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t)
miner.ActL1EndBlock(t)
// We are not able to do eager batch derivation for these L2 blocks because
// we reject batches with a greater timestamp than the drift.
verifyChainStateOnSequencer(10, 40, 9, 16, 8)
for i := 0; i < 2; i++ {
miner.ActL1StartBlock(4)(t)
miner.ActL1EndBlock(t)
}
// Run the pipeline against the batches + to be auto-generated batches.
sequencer.ActL1HeadSignal(t)
sequencer.ActL2PipelineFull(t)
verifyChainStateOnSequencer(12, 40, 9, 40, 9)
// Recheck nonce. Will fail if no batches where submitted
n, err = cl.NonceAt(t.Ctx(), dp.Addresses.Alice, nil)
require.NoError(t, err)
require.Equal(t, uint64(32), n) // 16 valid blocks with txns. Get seq drift non-empty (32/2 => 16) & 8 forced empty
// Check that the verifier got the same result
verifier.ActL1HeadSignal(t)
verifier.ActL2PipelineFull(t)
verifyChainStateOnVerifier(12, 40, 9, 40, 9)
require.Equal(t, verifier.L2Safe(), sequencer.L2Safe())
}
......@@ -163,7 +163,8 @@ func (e *L2Engine) ActL2IncludeTx(from common.Address) Action {
return
}
if e.l2ForceEmpty {
t.InvalidAction("cannot include any sequencer txs")
e.log.Info("Skipping including a transaction because e.L2ForceEmpty is true")
// t.InvalidAction("cannot include any sequencer txs")
return
}
......
package actions
import (
"context"
"crypto/ecdsa"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
......@@ -32,6 +34,7 @@ type L2Proposer struct {
func NewL2Proposer(t Testing, log log.Logger, cfg *ProposerCfg, l1 *ethclient.Client, rollupCl *sources.RollupClient) *L2Proposer {
chainID, err := l1.ChainID(t.Ctx())
require.NoError(t, err)
signer := opcrypto.PrivateKeySignerFn(cfg.ProposerKey, chainID)
dr, err := proposer.NewDriver(proposer.DriverConfig{
Log: log,
Name: "proposer",
......@@ -40,7 +43,9 @@ func NewL2Proposer(t Testing, log log.Logger, cfg *ProposerCfg, l1 *ethclient.Cl
AllowNonFinalized: cfg.AllowNonFinalized,
L2OOAddr: cfg.OutputOracleAddr,
From: crypto.PubkeyToAddress(cfg.ProposerKey.PublicKey),
SignerFn: opcrypto.PrivateKeySignerFn(cfg.ProposerKey, chainID),
SignerFn: func(_ context.Context, addr common.Address, tx *types.Transaction) (*types.Transaction, error) {
return signer(addr, tx)
},
})
require.NoError(t, err)
return &L2Proposer{
......
......@@ -22,6 +22,8 @@ import (
var bigOne = big.NewInt(1)
var supportedL2OutputVersion = eth.Bytes32{}
type SignerFn func(context.Context, common.Address, *types.Transaction) (*types.Transaction, error)
type DriverConfig struct {
Log log.Logger
Name string
......@@ -44,7 +46,7 @@ type DriverConfig struct {
From common.Address
// SignerFn is the function used to sign transactions
SignerFn bind.SignerFn
SignerFn SignerFn
}
type Driver struct {
......@@ -182,8 +184,10 @@ func (d *Driver) CraftTx(ctx context.Context, start, end, nonce *big.Int) (*type
}
opts := &bind.TransactOpts{
From: d.cfg.From,
Signer: d.cfg.SignerFn,
From: d.cfg.From,
Signer: func(addr common.Address, tx *types.Transaction) (*types.Transaction, error) {
return d.cfg.SignerFn(ctx, addr, tx)
},
Context: ctx,
Nonce: nonce,
NoSend: true,
......@@ -225,8 +229,10 @@ func (d *Driver) CraftTx(ctx context.Context, start, end, nonce *big.Int) (*type
// NOTE: This method SHOULD NOT publish the resulting transaction.
func (d *Driver) UpdateGasPrice(ctx context.Context, tx *types.Transaction) (*types.Transaction, error) {
opts := &bind.TransactOpts{
From: d.cfg.From,
Signer: d.cfg.SignerFn,
From: d.cfg.From,
Signer: func(addr common.Address, tx *types.Transaction) (*types.Transaction, error) {
return d.cfg.SignerFn(ctx, addr, tx)
},
Context: ctx,
Nonce: new(big.Int).SetUint64(tx.Nonce()),
NoSend: true,
......
......@@ -15,8 +15,8 @@ import (
hdwallet "github.com/ethereum-optimism/go-ethereum-hdwallet"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
......@@ -161,13 +161,16 @@ func NewL2OutputSubmitter(
}
}
signer := func(chainID *big.Int) bind.SignerFn {
return opcrypto.PrivateKeySignerFn(l2OutputPrivKey, chainID)
signer := func(chainID *big.Int) SignerFn {
s := opcrypto.PrivateKeySignerFn(l2OutputPrivKey, chainID)
return func(_ context.Context, addr common.Address, tx *types.Transaction) (*types.Transaction, error) {
return s(addr, tx)
}
}
return NewL2OutputSubmitterWithSigner(cfg, crypto.PubkeyToAddress(l2OutputPrivKey.PublicKey), signer, gitVersion, l)
}
type SignerFactory func(chainID *big.Int) bind.SignerFn
type SignerFactory func(chainID *big.Int) SignerFn
func NewL2OutputSubmitterWithSigner(
cfg Config,
......
......@@ -58,8 +58,8 @@ def main():
pr_urls = os.getenv('CIRCLE_PULL_REQUESTS', None)
pr_urls = pr_urls.split(',') if pr_urls else []
if len(pr_urls) == 0:
log.info('Not a PR build, skipping build')
exit_nobuild()
log.info('Not a PR build, triggering build')
exit_build()
if len(pr_urls) > 1:
log.warning('Multiple PR URLs found, choosing the first one. PRs found:')
for url in pr_urls:
......
......@@ -230,11 +230,11 @@ OptimismMintableERC721_Test:test_constructor_succeeds() (gas: 24162)
OptimismMintableERC721_Test:test_safeMint_notBridge_reverts() (gas: 11142)
OptimismMintableERC721_Test:test_safeMint_succeeds() (gas: 140502)
OptimismMintableERC721_Test:test_tokenURI_succeeds() (gas: 163420)
OptimismMintableERC721Factory_Test:test_constructor_succeeds() (gas: 9983)
OptimismMintableERC721Factory_Test:test_constructor_succeeds() (gas: 10005)
OptimismMintableERC721Factory_Test:test_constructor_zeroBridge_reverts() (gas: 39114)
OptimismMintableERC721Factory_Test:test_constructor_zeroRemoteChainId_reverts() (gas: 41265)
OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_succeeds() (gas: 2276418)
OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_zeroRemoteToken_reverst() (gas: 9395)
OptimismMintableERC721Factory_Test:test_constructor_zeroRemoteChainId_reverts() (gas: 41287)
OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_succeeds() (gas: 2276374)
OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_zeroRemoteToken_reverts() (gas: 9373)
OptimismPortalUpgradeable_Test:test_initialize_cannotInitImpl_reverts() (gas: 10791)
OptimismPortalUpgradeable_Test:test_initialize_cannotInitProxy_reverts() (gas: 15833)
OptimismPortalUpgradeable_Test:test_params_initValuesOnProxy_succeeds() (gas: 16011)
......
......@@ -428,10 +428,11 @@ contract ERC721Bridge_Initializer is Messenger_Initializer {
L1Bridge = new L1ERC721Bridge(address(L1Messenger), Predeploys.L2_ERC721_BRIDGE);
// Deploy the implementation for the L2ERC721Bridge and etch it into the predeploy address.
vm.etch(Predeploys.L2_ERC721_BRIDGE, address(new L2ERC721Bridge(
Predeploys.L2_CROSS_DOMAIN_MESSENGER,
address(L1Bridge)
)).code);
vm.etch(
Predeploys.L2_ERC721_BRIDGE,
address(new L2ERC721Bridge(Predeploys.L2_CROSS_DOMAIN_MESSENGER, address(L1Bridge)))
.code
);
// Set up a reference to the L2ERC721Bridge.
L2Bridge = L2ERC721Bridge(Predeploys.L2_ERC721_BRIDGE);
......
......@@ -49,20 +49,12 @@ contract OptimismMintableERC721Factory_Test is ERC721Bridge_Initializer {
// Expect a token creation event.
vm.expectEmit(true, true, true, true);
emit OptimismMintableERC721Created(
predicted,
address(1234),
alice
);
emit OptimismMintableERC721Created(predicted, address(1234), alice);
// Create the token.
vm.prank(alice);
OptimismMintableERC721 created = OptimismMintableERC721(
factory.createOptimismMintableERC721(
address(1234),
"L2Token",
"L2T"
)
factory.createOptimismMintableERC721(address(1234), "L2Token", "L2T")
);
// Token address should be correct.
......@@ -79,13 +71,9 @@ contract OptimismMintableERC721Factory_Test is ERC721Bridge_Initializer {
assertEq(created.REMOTE_CHAIN_ID(), 1);
}
function test_createOptimismMintableERC721_zeroRemoteToken_reverst() external {
function test_createOptimismMintableERC721_zeroRemoteToken_reverts() external {
// Try to create a token with a zero remote token address.
vm.expectRevert("OptimismMintableERC721Factory: L1 token address cannot be address(0)");
factory.createOptimismMintableERC721(
address(0),
"L2Token",
"L2T"
);
factory.createOptimismMintableERC721(address(0), "L2Token", "L2T");
}
}
......@@ -17,6 +17,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['ProxyAdmin']
deployFn.tags = ['ProxyAdmin', 'setup']
export default deployFn
......@@ -17,6 +17,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['AddressManager']
deployFn.tags = ['AddressManager', 'setup']
export default deployFn
......@@ -16,6 +16,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['L1StandardBridgeProxy']
deployFn.tags = ['L1StandardBridgeProxy', 'setup']
export default deployFn
......@@ -20,6 +20,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['L2OutputOracleProxy']
deployFn.tags = ['L2OutputOracleProxy', 'setup']
export default deployFn
......@@ -13,6 +13,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['L1CrossDomainMessengerProxy']
deployFn.tags = ['L1CrossDomainMessengerProxy', 'setup']
export default deployFn
......@@ -20,6 +20,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['OptimismPortalProxy']
deployFn.tags = ['OptimismPortalProxy', 'setup']
export default deployFn
......@@ -20,6 +20,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['OptimismMintableERC20FactoryProxy']
deployFn.tags = ['OptimismMintableERC20FactoryProxy', 'setup']
export default deployFn
......@@ -16,6 +16,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['L1ERC721BridgeProxy']
deployFn.tags = ['L1ERC721BridgeProxy', 'setup']
export default deployFn
......@@ -20,6 +20,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['SystemConfigProxy']
deployFn.tags = ['SystemConfigProxy', 'setup']
export default deployFn
......@@ -16,6 +16,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['SystemDictatorProxy']
deployFn.tags = ['SystemDictatorProxy', 'setup']
export default deployFn
......@@ -32,6 +32,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['L1CrossDomainMessengerImpl']
deployFn.tags = ['L1CrossDomainMessengerImpl', 'setup']
export default deployFn
......@@ -32,6 +32,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['L1StandardBridgeImpl']
deployFn.tags = ['L1StandardBridgeImpl', 'setup']
export default deployFn
......@@ -41,6 +41,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['L2OutputOracleImpl']
deployFn.tags = ['L2OutputOracleImpl', 'setup']
export default deployFn
......@@ -35,6 +35,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['OptimismPortalImpl']
deployFn.tags = ['OptimismPortalImpl', 'setup']
export default deployFn
......@@ -26,6 +26,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['OptimismMintableERC20FactoryImpl']
deployFn.tags = ['OptimismMintableERC20FactoryImpl', 'setup']
export default deployFn
......@@ -27,6 +27,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['L1ERC721BridgeImpl']
deployFn.tags = ['L1ERC721BridgeImpl', 'setup']
export default deployFn
......@@ -26,6 +26,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['PortalSenderImpl']
deployFn.tags = ['PortalSenderImpl', 'setup']
export default deployFn
......@@ -45,6 +45,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['SystemConfigImpl']
deployFn.tags = ['SystemConfigImpl', 'setup']
export default deployFn
......@@ -12,6 +12,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['SystemDictatorImpl']
deployFn.tags = ['SystemDictatorImpl', 'setup']
export default deployFn
......@@ -188,6 +188,6 @@ const deployFn: DeployFunction = async (hre) => {
}
}
deployFn.tags = ['SystemDictatorImpl']
deployFn.tags = ['SystemDictatorImpl', 'setup']
export default deployFn
......@@ -11,6 +11,7 @@ import {
assertContractVariable,
getContractsFromArtifacts,
getDeploymentAddress,
jsonifyTransaction,
} from '../src/deploy-utils'
const deployFn: DeployFunction = async (hre) => {
......@@ -123,8 +124,14 @@ const deployFn: DeployFunction = async (hre) => {
console.log(`Setting AddressManager owner to MSD`)
await AddressManager.transferOwnership(SystemDictator.address)
} else {
const tx = await AddressManager.populateTransaction.transferOwnership(
SystemDictator.address
)
console.log(`Please transfer AddressManager owner to MSD`)
console.log(`AddressManager address: ${AddressManager.address}`)
console.log(`MSD address: ${SystemDictator.address}`)
console.log(`JSON:`)
console.log(jsonifyTransaction(tx))
}
// Wait for the ownership transfer to complete.
......@@ -151,8 +158,15 @@ const deployFn: DeployFunction = async (hre) => {
console.log(`Setting L1CrossDomainMessenger owner to MSD`)
await L1CrossDomainMessenger.transferOwnership(SystemDictator.address)
} else {
const tx =
await L1CrossDomainMessenger.populateTransaction.transferOwnership(
SystemDictator.address
)
console.log(`Please transfer L1CrossDomainMessenger owner to MSD`)
console.log(`L1XDM address: ${L1CrossDomainMessenger.address}`)
console.log(`MSD address: ${SystemDictator.address}`)
console.log(`JSON:`)
console.log(jsonifyTransaction(tx))
}
// Wait for the ownership transfer to complete.
......@@ -179,8 +193,16 @@ const deployFn: DeployFunction = async (hre) => {
console.log(`Setting L1StandardBridge owner to MSD`)
await L1StandardBridgeProxyWithSigner.setOwner(SystemDictator.address)
} else {
const tx = await L1StandardBridgeProxy.populateTransaction.setOwner(
SystemDictator.address
)
console.log(`Please transfer L1StandardBridge (proxy) owner to MSD`)
console.log(
`L1StandardBridgeProxy address: ${L1StandardBridgeProxy.address}`
)
console.log(`MSD address: ${SystemDictator.address}`)
console.log(`JSON:`)
console.log(jsonifyTransaction(tx))
}
// Wait for the ownership transfer to complete.
......@@ -209,8 +231,14 @@ const deployFn: DeployFunction = async (hre) => {
console.log(`Setting L1ERC721Bridge owner to MSD`)
await L1ERC721BridgeProxyWithSigner.changeAdmin(SystemDictator.address)
} else {
const tx = await L1ERC721BridgeProxy.populateTransaction.changeAdmin(
SystemDictator.address
)
console.log(`Please transfer L1ERC721Bridge (proxy) owner to MSD`)
console.log(`L1ERC721BridgeProxy address: ${L1ERC721BridgeProxy.address}`)
console.log(`MSD address: ${SystemDictator.address}`)
console.log(`JSON:`)
console.log(jsonifyTransaction(tx))
}
// Wait for the ownership transfer to complete.
......@@ -264,7 +292,11 @@ const deployFn: DeployFunction = async (hre) => {
console.log(`Executing step ${opts.step}...`)
await SystemDictator[`step${opts.step}`]()
} else {
const tx = await SystemDictator.populateTransaction[`step${opts.step}`]()
console.log(`Please execute step ${opts.step}...`)
console.log(`MSD address: ${SystemDictator.address}`)
console.log(`JSON:`)
console.log(jsonifyTransaction(tx))
}
// Wait for the step to complete.
......@@ -566,7 +598,11 @@ const deployFn: DeployFunction = async (hre) => {
console.log(`Finalizing deployment...`)
await SystemDictator.finalize()
} else {
const tx = await SystemDictator.populateTransaction.finalize()
console.log(`Please finalize deployment...`)
console.log(`MSD address: ${SystemDictator.address}`)
console.log(`JSON:`)
console.log(jsonifyTransaction(tx))
}
await awaitCondition(
......
......@@ -33,10 +33,10 @@
"clean": "rm -rf ./dist ./artifacts ./forge-artifacts ./cache ./tsconfig.tsbuildinfo ./tsconfig.build.tsbuildinfo ./src/contract-artifacts.ts ./test-case-generator/fuzz",
"lint:ts:check": "eslint . --max-warnings=0",
"lint:forge-tests:check": "ts-node scripts/forge-test-names.ts",
"lint:contracts:check": "yarn solhint -f table 'contracts/**/*.sol' && yarn lint:forge-tests:check",
"lint:contracts:check": "yarn solhint -f table 'contracts/**/*.sol' && yarn prettier --check 'contracts/**/*.sol' && yarn lint:forge-tests:check",
"lint:check": "yarn lint:contracts:check && yarn lint:ts:check",
"lint:ts:fix": "eslint --fix .",
"lint:contracts:fix": "yarn prettier --write 'contracts/**/*.sol'",
"lint:contracts:fix": "yarn solhint --fix 'contracts/**/*.sol' && yarn prettier --write 'contracts/**/*.sol'",
"lint:fix": "yarn lint:contracts:fix && yarn lint:ts:fix",
"lint": "yarn lint:fix && yarn lint:check",
"typechain": "typechain --target ethers-v5 --out-dir dist/types --glob 'artifacts/!(build-info)/**/+([a-zA-Z0-9_]).json'",
......
......@@ -276,3 +276,16 @@ export const getDeploymentAddress = async (
const deployment = await hre.deployments.get(name)
return deployment.address
}
export const jsonifyTransaction = (tx: ethers.PopulatedTransaction): string => {
return JSON.stringify(
{
to: tx.to,
data: tx.data,
value: tx.value,
chainId: tx.chainId,
},
null,
2
)
}
......@@ -7,3 +7,4 @@ import './validate-spacers'
import './solidity'
import './accounts'
import './check-l2'
import './update-dynamic-oracle-config'
import readline from 'readline'
import { task, types } from 'hardhat/config'
import { ethers, Wallet } from 'ethers'
import { getContractsFromArtifacts } from '../src/deploy-utils'
task('update-dynamic-oracle-config', 'Updates the dynamic oracle config.')
.addParam(
'l2OutputOracleStartingTimestamp',
'Starting timestamp for the L2 output oracle.',
null,
types.int
)
.addParam('noSend', 'Do not send the transaction.', true, types.boolean)
.addOptionalParam(
'privateKey',
'Private key to send transaction',
process.env.PRIVATE_KEY,
types.string
)
.setAction(async (args, hre) => {
const { l2OutputOracleStartingTimestamp, noSend, privateKey } = args
const wallet = new Wallet(privateKey, hre.ethers.provider)
const [SystemDictator] = await getContractsFromArtifacts(hre, [
{
name: 'SystemDictatorProxy',
iface: 'SystemDictator',
signerOrProvider: wallet,
},
])
const currStep = await SystemDictator.currentStep()
if (currStep !== 5) {
throw new Error(`Current step is ${currStep}, expected 5`)
}
if (await SystemDictator.dynamicConfigSet()) {
throw new Error('Dynamic config already set')
}
const l2OutputOracleStartingBlockNumber =
hre.deployConfig.l2OutputOracleStartingBlockNumber
console.log(
`This task will set the L2 output oracle's starting timestamp and block number.`
)
console.log(
`It can only be run once. Please carefully check the values below:`
)
console.log(
`L2OO starting block number: ${l2OutputOracleStartingBlockNumber}`
)
console.log(
`L2OO starting block timestamp: ${l2OutputOracleStartingTimestamp}`
)
await prompt('Press enter to continue...')
if (noSend) {
const tx =
await SystemDictator.populateTransaction.updateL2OutputOracleDynamicConfig(
{
l2OutputOracleStartingBlockNumber,
l2OutputOracleStartingTimestamp,
}
)
console.log(`Sending is disabled. Transaction data:`)
// Need to delete tx.from for Ethers to properly serialize the tx
delete tx.from
console.log(ethers.utils.serializeTransaction(tx))
console.log(`Calldata (for multisigs):`)
console.log(tx.data)
} else {
console.log(`Sending transaction...`)
const tx = await SystemDictator.updateL2OutputOracleDynamicConfig({
l2OutputOracleStartingBlockNumber,
l2OutputOracleStartingTimestamp,
})
console.log(
`Transaction sent with hash ${tx.hash}. Waiting for receipt...`
)
const receipt = await tx.wait(1)
console.log(`Transaction included in block ${receipt.blockNumber}`)
}
})
const prompt = async (question: string) => {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
})
return new Promise<void>((resolve) => {
rl.question(question, () => {
rl.close()
resolve()
})
})
}
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