Commit 5c62840b authored by mergify[bot]'s avatar mergify[bot] Committed by GitHub

Merge branch 'develop' into jg/tx_lifecycle_mgmt

parents 18524dbd 2fc8ed42
...@@ -330,7 +330,8 @@ jobs: ...@@ -330,7 +330,8 @@ jobs:
patterns: contracts-bedrock,hardhat-deploy-config patterns: contracts-bedrock,hardhat-deploy-config
- run: - run:
name: lint name: lint
command: yarn lint:check command: |
yarn lint:check || echo "export LINT_STATUS=1" >> "$BASH_ENV"
working_directory: packages/contracts-bedrock working_directory: packages/contracts-bedrock
- run: - run:
name: slither name: slither
...@@ -342,18 +343,44 @@ jobs: ...@@ -342,18 +343,44 @@ jobs:
name: gas snapshot name: gas snapshot
command: | command: |
forge --version forge --version
yarn gas-snapshot --check yarn gas-snapshot --check || echo "export GAS_SNAPSHOT_STATUS=1" >> "$BASH_ENV"
environment: environment:
FOUNDRY_PROFILE: ci FOUNDRY_PROFILE: ci
working_directory: packages/contracts-bedrock working_directory: packages/contracts-bedrock
- run: - run:
name: storage snapshot name: storage snapshot
command: yarn storage-snapshot && git diff --exit-code .storage-layout command: |
yarn storage-snapshot
git diff --exit-code .storage-layout || echo "export STORAGE_SNAPSHOT_STATUS=1" >> "$BASH_ENV"
working_directory: packages/contracts-bedrock working_directory: packages/contracts-bedrock
- run: - run:
name: invariant docs name: invariant docs
command: yarn autogen:invariant-docs && git diff --exit-code ./invariant-docs/*.md command: |
yarn autogen:invariant-docs
git diff --exit-code ./invariant-docs/*.md || echo "export INVARIANT_DOCS_STATUS=1" >> "$BASH_ENV"
working_directory: packages/contracts-bedrock working_directory: packages/contracts-bedrock
- run:
name: check statuses
command: |
if [[ "$LINT_STATUS" -ne 0 ]]; then
FAILED=1
echo "Linting failed, see job output for details."
fi
if [[ "$GAS_SNAPSHOT_STATUS" -ne 0 ]]; then
FAILED=1
echo "Gas snapshot failed, see job output for details."
fi
if [[ "$STORAGE_SNAPSHOT_STATUS" -ne 0 ]]; then
echo "Storage snapshot failed, see job output for details."
FAILED=1
fi
if [[ "$INVARIANT_DOCS_STATUS" -ne 0 ]]; then
echo "Invariant docs failed, see job output for details."
FAILED=1
fi
if [[ "$FAILED" -ne 0 ]]; then
exit 1
fi
contracts-bedrock-validate-spaces: contracts-bedrock-validate-spaces:
docker: docker:
......
...@@ -61,7 +61,7 @@ def main(): ...@@ -61,7 +61,7 @@ def main():
addresses = read_json(addresses_json_path) addresses = read_json(addresses_json_path)
else: else:
log.info('Deploying contracts.') log.info('Deploying contracts.')
run_command(['yarn', 'hardhat', '--network', 'devnetL1', 'deploy'], env={ run_command(['yarn', 'hardhat', '--network', 'devnetL1', 'deploy', '--tags', 'l1'], env={
'CHAIN_ID': '900', 'CHAIN_ID': '900',
'L1_RPC': 'http://localhost:8545', 'L1_RPC': 'http://localhost:8545',
'PRIVATE_KEY_DEPLOYER': 'ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80' 'PRIVATE_KEY_DEPLOYER': 'ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'
......
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -13,7 +13,7 @@ const WETH9StorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"con ...@@ -13,7 +13,7 @@ const WETH9StorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"con
var WETH9StorageLayout = new(solc.StorageLayout) var WETH9StorageLayout = new(solc.StorageLayout)
var WETH9DeployedBin = "0x6080604052600436106100bc5760003560e01c8063313ce56711610074578063a9059cbb1161004e578063a9059cbb146102cb578063d0e30db0146100bc578063dd62ed3e14610311576100bc565b8063313ce5671461024b57806370a082311461027657806395d89b41146102b6576100bc565b806318160ddd116100a557806318160ddd146101aa57806323b872dd146101d15780632e1a7d4d14610221576100bc565b806306fdde03146100c6578063095ea7b314610150575b6100c4610359565b005b3480156100d257600080fd5b506100db6103a8565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101155781810151838201526020016100fd565b50505050905090810190601f1680156101425780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015c57600080fd5b506101966004803603604081101561017357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610454565b604080519115158252519081900360200190f35b3480156101b657600080fd5b506101bf6104c7565b60408051918252519081900360200190f35b3480156101dd57600080fd5b50610196600480360360608110156101f457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013590911690604001356104cb565b34801561022d57600080fd5b506100c46004803603602081101561024457600080fd5b503561066b565b34801561025757600080fd5b50610260610700565b6040805160ff9092168252519081900360200190f35b34801561028257600080fd5b506101bf6004803603602081101561029957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610709565b3480156102c257600080fd5b506100db61071b565b3480156102d757600080fd5b50610196600480360360408110156102ee57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610793565b34801561031d57600080fd5b506101bf6004803603604081101561033457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160200135166107a7565b33600081815260036020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b6000805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b820191906000526020600020905b81548152906001019060200180831161042f57829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b4790565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120548211156104fd57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610573575073ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156105ed5773ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020548211156105b557600080fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020805483900390555b73ffffffffffffffffffffffffffffffffffffffff808516600081815260036020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b3360009081526003602052604090205481111561068757600080fd5b33600081815260036020526040808220805485900390555183156108fc0291849190818181858888f193505050501580156106c6573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60025460ff1681565b60036020526000908152604090205481565b60018054604080516020600284861615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b60006107a03384846104cb565b9392505050565b60046020908152600092835260408084209091529082529020548156fea265627a7a72315820fd69d075d01838a66174ca9cefc98bf8f255e049a94475b253ffc70bf383f90564736f6c63430005110032" var WETH9DeployedBin = "0x6080604052600436106100bc5760003560e01c8063313ce56711610074578063a9059cbb1161004e578063a9059cbb146102cb578063d0e30db0146100bc578063dd62ed3e14610311576100bc565b8063313ce5671461024b57806370a082311461027657806395d89b41146102b6576100bc565b806318160ddd116100a557806318160ddd146101aa57806323b872dd146101d15780632e1a7d4d14610221576100bc565b806306fdde03146100c6578063095ea7b314610150575b6100c4610359565b005b3480156100d257600080fd5b506100db6103a8565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101155781810151838201526020016100fd565b50505050905090810190601f1680156101425780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015c57600080fd5b506101966004803603604081101561017357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610454565b604080519115158252519081900360200190f35b3480156101b657600080fd5b506101bf6104c7565b60408051918252519081900360200190f35b3480156101dd57600080fd5b50610196600480360360608110156101f457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013590911690604001356104cb565b34801561022d57600080fd5b506100c46004803603602081101561024457600080fd5b503561066b565b34801561025757600080fd5b50610260610700565b6040805160ff9092168252519081900360200190f35b34801561028257600080fd5b506101bf6004803603602081101561029957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610709565b3480156102c257600080fd5b506100db61071b565b3480156102d757600080fd5b50610196600480360360408110156102ee57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610793565b34801561031d57600080fd5b506101bf6004803603604081101561033457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160200135166107a7565b33600081815260036020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b6000805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b820191906000526020600020905b81548152906001019060200180831161042f57829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b4790565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120548211156104fd57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610573575073ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156105ed5773ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020548211156105b557600080fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020805483900390555b73ffffffffffffffffffffffffffffffffffffffff808516600081815260036020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b3360009081526003602052604090205481111561068757600080fd5b33600081815260036020526040808220805485900390555183156108fc0291849190818181858888f193505050501580156106c6573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60025460ff1681565b60036020526000908152604090205481565b60018054604080516020600284861615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b60006107a03384846104cb565b9392505050565b60046020908152600092835260408084209091529082529020548156fea265627a7a7231582097535febf1aaaa55cc90c4da08f528faef2bfe1cff05b0d29e635ce42047349664736f6c63430005110032"
func init() { func init() {
if err := json.Unmarshal([]byte(WETH9StorageLayoutJSON), WETH9StorageLayout); err != nil { if err := json.Unmarshal([]byte(WETH9StorageLayoutJSON), WETH9StorageLayout); err != nil {
......
...@@ -36,7 +36,7 @@ func NewDataSourceFactory(log log.Logger, cfg *rollup.Config, fetcher L1Transact ...@@ -36,7 +36,7 @@ func NewDataSourceFactory(log log.Logger, cfg *rollup.Config, fetcher L1Transact
return &DataSourceFactory{log: log, cfg: cfg, fetcher: fetcher} return &DataSourceFactory{log: log, cfg: cfg, fetcher: fetcher}
} }
// OpenData returns a CalldataSourceImpl. This struct implements the `Next` function. // OpenData returns a DataIter. This struct implements the `Next` function.
func (ds *DataSourceFactory) OpenData(ctx context.Context, id eth.BlockID, batcherAddr common.Address) DataIter { func (ds *DataSourceFactory) OpenData(ctx context.Context, id eth.BlockID, batcherAddr common.Address) DataIter {
return NewDataSource(ctx, ds.log, ds.cfg, ds.fetcher, id, batcherAddr) return NewDataSource(ctx, ds.log, ds.cfg, ds.fetcher, id, batcherAddr)
} }
......
...@@ -70,13 +70,13 @@ func ProcessSystemConfigUpdateLogEvent(destSysCfg *eth.SystemConfig, ev *types.L ...@@ -70,13 +70,13 @@ func ProcessSystemConfigUpdateLogEvent(destSysCfg *eth.SystemConfig, ev *types.L
return fmt.Errorf("expected 3 event topics (event identity, indexed version, indexed updateType), got %d", len(ev.Topics)) return fmt.Errorf("expected 3 event topics (event identity, indexed version, indexed updateType), got %d", len(ev.Topics))
} }
if ev.Topics[0] != ConfigUpdateEventABIHash { if ev.Topics[0] != ConfigUpdateEventABIHash {
return fmt.Errorf("invalid deposit event selector: %s, expected %s", ev.Topics[0], DepositEventABIHash) return fmt.Errorf("invalid SystemConfig update event: %s, expected %s", ev.Topics[0], ConfigUpdateEventABIHash)
} }
// indexed 0 // indexed 0
version := ev.Topics[1] version := ev.Topics[1]
if version != ConfigUpdateEventVersion0 { if version != ConfigUpdateEventVersion0 {
return fmt.Errorf("unrecognized L1 sysCfg update event version: %s", version) return fmt.Errorf("unrecognized SystemConfig update event version: %s", version)
} }
// indexed 1 // indexed 1
updateType := ev.Topics[2] updateType := ev.Topics[2]
......
...@@ -30,7 +30,9 @@ ...@@ -30,7 +30,9 @@
"@eth-optimism/contracts-periphery/ds-test", "@eth-optimism/contracts-periphery/ds-test",
"@eth-optimism/contracts-periphery/forge-std", "@eth-optimism/contracts-periphery/forge-std",
"@eth-optimism/contracts-periphery/@rari-capital/solmate", "@eth-optimism/contracts-periphery/@rari-capital/solmate",
"forta-agent" "forta-agent",
"@eth-optimism/contracts-bedrock/@safe-global/safe-contracts",
"@eth-optimism/contracts-bedrock/solady"
] ]
}, },
"private": true, "private": true,
......
...@@ -12,9 +12,9 @@ import { FeeVault } from "../universal/FeeVault.sol"; ...@@ -12,9 +12,9 @@ import { FeeVault } from "../universal/FeeVault.sol";
*/ */
contract BaseFeeVault is FeeVault, Semver { contract BaseFeeVault is FeeVault, Semver {
/** /**
* @custom:semver 1.0.0 * @custom:semver 1.1.0
* *
* @param _recipient Address that will receive the accumulated fees. * @param _recipient Address that will receive the accumulated fees.
*/ */
constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 0, 0) {} constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 1, 0) {}
} }
...@@ -16,5 +16,5 @@ contract L1FeeVault is FeeVault, Semver { ...@@ -16,5 +16,5 @@ contract L1FeeVault is FeeVault, Semver {
* *
* @param _recipient Address that will receive the accumulated fees. * @param _recipient Address that will receive the accumulated fees.
*/ */
constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 0, 0) {} constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 1, 0) {}
} }
...@@ -20,7 +20,7 @@ import { Semver } from "../universal/Semver.sol"; ...@@ -20,7 +20,7 @@ import { Semver } from "../universal/Semver.sol";
*/ */
contract L2ERC721Bridge is ERC721Bridge, Semver { contract L2ERC721Bridge is ERC721Bridge, Semver {
/** /**
* @custom:semver 1.0.0 * @custom:semver 1.1.0
* *
* @param _messenger Address of the CrossDomainMessenger on this network. * @param _messenger Address of the CrossDomainMessenger on this network.
* @param _otherBridge Address of the ERC721 bridge on the other network. * @param _otherBridge Address of the ERC721 bridge on the other network.
......
...@@ -13,11 +13,11 @@ import { FeeVault } from "../universal/FeeVault.sol"; ...@@ -13,11 +13,11 @@ import { FeeVault } from "../universal/FeeVault.sol";
*/ */
contract SequencerFeeVault is FeeVault, Semver { contract SequencerFeeVault is FeeVault, Semver {
/** /**
* @custom:semver 1.0.0 * @custom:semver 1.1.0
* *
* @param _recipient Address that will receive the accumulated fees. * @param _recipient Address that will receive the accumulated fees.
*/ */
constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 0, 0) {} constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 1, 0) {}
/** /**
* @custom:legacy * @custom:legacy
......
...@@ -17,6 +17,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -17,6 +17,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['ProxyAdmin', 'setup'] deployFn.tags = ['ProxyAdmin', 'setup', 'l1']
export default deployFn export default deployFn
...@@ -17,6 +17,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -17,6 +17,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['AddressManager', 'setup'] deployFn.tags = ['AddressManager', 'setup', 'l1']
export default deployFn export default deployFn
...@@ -16,6 +16,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -16,6 +16,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['L1StandardBridgeProxy', 'setup'] deployFn.tags = ['L1StandardBridgeProxy', 'setup', 'l1']
export default deployFn export default deployFn
...@@ -20,6 +20,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -20,6 +20,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['L2OutputOracleProxy', 'setup'] deployFn.tags = ['L2OutputOracleProxy', 'setup', 'l1']
export default deployFn export default deployFn
...@@ -13,6 +13,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -13,6 +13,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['L1CrossDomainMessengerProxy', 'setup'] deployFn.tags = ['L1CrossDomainMessengerProxy', 'setup', 'l1']
export default deployFn export default deployFn
...@@ -20,6 +20,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -20,6 +20,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['OptimismPortalProxy', 'setup'] deployFn.tags = ['OptimismPortalProxy', 'setup', 'l1']
export default deployFn export default deployFn
...@@ -20,6 +20,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -20,6 +20,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['OptimismMintableERC20FactoryProxy', 'setup'] deployFn.tags = ['OptimismMintableERC20FactoryProxy', 'setup', 'l1']
export default deployFn export default deployFn
...@@ -16,6 +16,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -16,6 +16,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['L1ERC721BridgeProxy', 'setup'] deployFn.tags = ['L1ERC721BridgeProxy', 'setup', 'l1']
export default deployFn export default deployFn
...@@ -20,6 +20,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -20,6 +20,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['SystemConfigProxy', 'setup'] deployFn.tags = ['SystemConfigProxy', 'setup', 'l1']
export default deployFn export default deployFn
...@@ -16,6 +16,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -16,6 +16,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['SystemDictatorProxy', 'setup'] deployFn.tags = ['SystemDictatorProxy', 'setup', 'l1']
export default deployFn export default deployFn
...@@ -26,6 +26,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -26,6 +26,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['L1CrossDomainMessengerImpl', 'setup'] deployFn.tags = ['L1CrossDomainMessengerImpl', 'setup', 'l1']
export default deployFn export default deployFn
...@@ -32,6 +32,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -32,6 +32,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['L1StandardBridgeImpl', 'setup'] deployFn.tags = ['L1StandardBridgeImpl', 'setup', 'l1']
export default deployFn export default deployFn
...@@ -60,6 +60,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -60,6 +60,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['L2OutputOracleImpl', 'setup'] deployFn.tags = ['L2OutputOracleImpl', 'setup', 'l1']
export default deployFn export default deployFn
...@@ -67,6 +67,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -67,6 +67,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['OptimismPortalImpl', 'setup'] deployFn.tags = ['OptimismPortalImpl', 'setup', 'l1']
export default deployFn export default deployFn
...@@ -26,6 +26,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -26,6 +26,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['OptimismMintableERC20FactoryImpl', 'setup'] deployFn.tags = ['OptimismMintableERC20FactoryImpl', 'setup', 'l1']
export default deployFn export default deployFn
...@@ -27,6 +27,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -27,6 +27,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['L1ERC721BridgeImpl', 'setup'] deployFn.tags = ['L1ERC721BridgeImpl', 'setup', 'l1']
export default deployFn export default deployFn
...@@ -26,6 +26,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -26,6 +26,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['PortalSenderImpl', 'setup'] deployFn.tags = ['PortalSenderImpl', 'setup', 'l1']
export default deployFn export default deployFn
...@@ -66,6 +66,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -66,6 +66,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['SystemConfigImpl', 'setup'] deployFn.tags = ['SystemConfigImpl', 'setup', 'l1']
export default deployFn export default deployFn
...@@ -12,6 +12,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -12,6 +12,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['SystemDictatorImpl', 'setup'] deployFn.tags = ['SystemDictatorImpl', 'setup', 'l1']
export default deployFn export default deployFn
...@@ -200,6 +200,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -200,6 +200,6 @@ const deployFn: DeployFunction = async (hre) => {
} }
} }
deployFn.tags = ['SystemDictatorImpl', 'setup'] deployFn.tags = ['SystemDictatorImpl', 'setup', 'l1']
export default deployFn export default deployFn
...@@ -279,14 +279,14 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -279,14 +279,14 @@ const deployFn: DeployFunction = async (hre) => {
need to restart the system, run exit1() followed by finalize(). need to restart the system, run exit1() followed by finalize().
`, `,
checks: async () => { checks: async () => {
assert( const messenger = await AddressManager.getAddress(
(await AddressManager.getAddress('OVM_L1CrossDomainMessenger')) === 'OVM_L1CrossDomainMessenger'
ethers.constants.AddressZero
) )
assert(messenger === ethers.constants.AddressZero)
}, },
}) })
} }
deployFn.tags = ['SystemDictatorSteps', 'phase1'] deployFn.tags = ['SystemDictatorSteps', 'phase1', 'l1']
export default deployFn export default deployFn
...@@ -116,10 +116,8 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -116,10 +116,8 @@ const deployFn: DeployFunction = async (hre) => {
'BondManager', 'BondManager',
] ]
for (const dead of deads) { for (const dead of deads) {
assert( const addr = await AddressManager.getAddress(dead)
(await AddressManager.getAddress(dead)) === assert(addr === ethers.constants.AddressZero)
ethers.constants.AddressZero
)
} }
}, },
}) })
...@@ -372,6 +370,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -372,6 +370,6 @@ const deployFn: DeployFunction = async (hre) => {
} }
} }
deployFn.tags = ['SystemDictatorSteps', 'phase2'] deployFn.tags = ['SystemDictatorSteps', 'phase2', 'l1']
export default deployFn export default deployFn
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -9,7 +9,9 @@ remappings = [ ...@@ -9,7 +9,9 @@ remappings = [
'@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/', '@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/',
'@rari-capital/solmate/=node_modules/@rari-capital/solmate', '@rari-capital/solmate/=node_modules/@rari-capital/solmate',
'forge-std/=node_modules/forge-std/src', 'forge-std/=node_modules/forge-std/src',
'ds-test/=node_modules/ds-test/src' 'ds-test/=node_modules/ds-test/src',
'@safe-global/safe-contracts=node_modules/@safe-global/safe-contracts/',
'solady/=node_modules/solady/src'
] ]
extra_output = ['devdoc', 'userdoc', 'metadata', 'storageLayout'] extra_output = ['devdoc', 'userdoc', 'metadata', 'storageLayout']
bytecode_hash = 'none' bytecode_hash = 'none'
......
...@@ -80,6 +80,8 @@ ...@@ -80,6 +80,8 @@
"forge-std": "https://github.com/foundry-rs/forge-std.git#46264e9788017fc74f9f58b7efa0bc6e1df6d410", "forge-std": "https://github.com/foundry-rs/forge-std.git#46264e9788017fc74f9f58b7efa0bc6e1df6d410",
"glob": "^7.1.6", "glob": "^7.1.6",
"hardhat-deploy": "^0.11.4", "hardhat-deploy": "^0.11.4",
"@safe-global/safe-contracts": "https://github.com/safe-global/safe-contracts.git#v1.3.0-libs.0",
"solady": "https://github.com/Vectorized/solady.git#v0.0.85",
"solhint": "^3.3.7", "solhint": "^3.3.7",
"solhint-plugin-prettier": "^0.0.5", "solhint-plugin-prettier": "^0.0.5",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
......
This diff is collapsed.
...@@ -351,7 +351,7 @@ const check = { ...@@ -351,7 +351,7 @@ const check = {
signer signer
) )
await assertSemver(SequencerFeeVault, 'SequencerFeeVault') await assertSemver(SequencerFeeVault, 'SequencerFeeVault', '1.1.0')
const RECIPIENT = await SequencerFeeVault.RECIPIENT() const RECIPIENT = await SequencerFeeVault.RECIPIENT()
assert(RECIPIENT !== hre.ethers.constants.AddressZero) assert(RECIPIENT !== hre.ethers.constants.AddressZero)
...@@ -594,7 +594,7 @@ const check = { ...@@ -594,7 +594,7 @@ const check = {
signer signer
) )
await assertSemver(BaseFeeVault, 'BaseFeeVault') await assertSemver(BaseFeeVault, 'BaseFeeVault', '1.1.0')
const MIN_WITHDRAWAL_AMOUNT = await BaseFeeVault.MIN_WITHDRAWAL_AMOUNT() const MIN_WITHDRAWAL_AMOUNT = await BaseFeeVault.MIN_WITHDRAWAL_AMOUNT()
console.log(` - MIN_WITHDRAWAL_AMOUNT: ${MIN_WITHDRAWAL_AMOUNT}`) console.log(` - MIN_WITHDRAWAL_AMOUNT: ${MIN_WITHDRAWAL_AMOUNT}`)
...@@ -617,7 +617,7 @@ const check = { ...@@ -617,7 +617,7 @@ const check = {
signer signer
) )
await assertSemver(L1FeeVault, 'L1FeeVault') await assertSemver(L1FeeVault, 'L1FeeVault', '1.1.0')
const MIN_WITHDRAWAL_AMOUNT = await L1FeeVault.MIN_WITHDRAWAL_AMOUNT() const MIN_WITHDRAWAL_AMOUNT = await L1FeeVault.MIN_WITHDRAWAL_AMOUNT()
console.log(` - MIN_WITHDRAWAL_AMOUNT: ${MIN_WITHDRAWAL_AMOUNT}`) console.log(` - MIN_WITHDRAWAL_AMOUNT: ${MIN_WITHDRAWAL_AMOUNT}`)
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
**Table of Contents** **Table of Contents**
- [Proposing L2 Output Commitments](#proposing-l2-output-commitments) - [Proposing L2 Output Commitments](#proposing-l2-output-commitments)
- [L2OutputOracle v1.0.0](#l2outputoracle-v100)
- [L2OutputOracle v2.0.0](#l2outputoracle-v200)
- [L2 Output Commitment Construction](#l2-output-commitment-construction) - [L2 Output Commitment Construction](#l2-output-commitment-construction)
- [L2 Output Oracle Smart Contract](#l2-output-oracle-smart-contract) - [L2 Output Oracle Smart Contract](#l2-output-oracle-smart-contract)
- [Configuration](#configuration) - [Configuration](#configuration)
...@@ -20,11 +22,11 @@ ...@@ -20,11 +22,11 @@
<!-- END doctoc generated TOC please keep comment here to allow auto update --> <!-- END doctoc generated TOC please keep comment here to allow auto update -->
After processing one or more blocks the outputs will need to be synchronized with L1 for trustless execution of After processing one or more blocks the outputs will need to be synchronized with the settlement layer (L1)
L2-to-L1 messaging, such as withdrawals. Outputs are hashed in a tree-structured form which minimizes the cost of for trustless execution of L2-to-L1 messaging, such as withdrawals.
proving any piece of data captured by the outputs. These output proposals act as the bridge's view into the L2 state.
Proposers submit the output roots to L1 and can be contested with a fault proof, Actors called "Proposers" submit the output roots to the settlement layer (L1) and can be contested with a fault proof,
with a bond at stake if the proof is wrong. with a bond at stake if the proof is wrong. The [op-proposer](../op-proposer/) in one such implementation of a proposer.
_Note_: Fault proofs on Optimism are not fully specified at this time. Although fault proof _Note_: Fault proofs on Optimism are not fully specified at this time. Although fault proof
construction and verification [is implemented in Cannon][cannon], construction and verification [is implemented in Cannon][cannon],
...@@ -35,24 +37,89 @@ are part of later specification milestones. ...@@ -35,24 +37,89 @@ are part of later specification milestones.
## Proposing L2 Output Commitments ## Proposing L2 Output Commitments
The proposer's role is to construct and submit output roots, which are commitments made on a configurable interval, The proposer's role is to construct and submit output roots, which are commitments to the L2's state,
to the `L2OutputOracle` contract running on L1. It does this by running the [L2 output proposer](../op-proposer/), to the `L2OutputOracle` contract on L1 (the settlement layer). To do this, the proposer periodically
a service which periodically queries the rollup node's queries the [rollup node](./rollup-node.md) for the latest output root derived from the latest
[`optimism_outputAtBlock` rpc method](./rollup-node.md#l2-output-rpc-method) for the latest output root derived [finalized](rollup-node.md#finalization-guarantees) L1 block. It then takes the output root and
from the latest [finalized](rollup-node.md#finalization-guarantees) L1 block. The construction of this output root is submits it to the `L2OutputOracle` contract on the settlement layer (L1).
described [below](#l2-output-commitment-construction).
### L2OutputOracle v1.0.0
The submission of output proposals is permissioned to a single account. It is expected that this
account continues to submit output proposals over time to ensure that user withdrawals do not halt.
The [L2 output proposer](../op-proposer) is expected to submit output roots on a deterministic
interval based on the configured `SUBMISSION_INTERVAL` in the `L2OutputOracle`. The larger
the `SUBMISSION_INTERVAL`, the less often L1 transactions need to be sent to the `L2OutputOracle`
contract, but L2 users will need to wait a bit longer for an output root to be included in L1 (the settlement layer)
that includes their intention to withdrawal from the system.
The honest `op-proposer` algorithm assumes a connection to the `L2OutputOracle` contract to know
the L2 block number that corresponds to the next output proposal that must be submitted. It also
assumes a connection to an `op-node` to be able to query the `optimism_syncStatus` RPC endpoint.
```python
import time
while True:
next_checkpoint_block = L2OutputOracle.nextBlockNumber()
rollup_status = op_node_client.sync_status()
if rollup_status.finalized_l2.number >= next_checkpoint_block:
output = op_node_client.output_at_block(next_checkpoint_block)
tx = send_transaction(output)
time.sleep(poll_interval)
```
A `CHALLENGER` account can delete multiple output roots by calling the `deleteL2Outputs()` function
and specifying the index of the first output to delete, this will also delete all subsequent outputs.
### L2OutputOracle v2.0.0
The submission of output proposals is permissionless and there is no interval at which output
proposals must be submitted at. It is expected that users will "just in time" propose an output
proposal to facilitate their own withdrawal. A bond must be placed with an output proposal to
disincentivize the proposal of malicious outputs. If it can be proven that the output is malicious,
either via fault proof or by an attestation proof, then the bond can be slashed and used as a
payment to the users who paid for gas to remove the malicious output.
The `op-proposer` can still be used to submit output proposals. A naive implementation of the
`op-proposer` will submit output proposals on an interval. However, this is not required, and other
proposer implementations may submit valid outputs at any time. A more ideal implementation
will use heuristics such as time of last submission or number of pending withdrawals that have
yet to be included in an output proposal.
A single iteration of this proposer (posting one output root to L1) is depicted below:
```mermaid
sequenceDiagram
participant L1
participant Rollup Node
participant Proposer
L1->>L1: L1 block finalized
L1->>Rollup Node: L1 block finalized
Proposer->>Rollup Node: optimism_syncStatus
Rollup Node->>Proposer: sync status { finalized L1 block num }
Proposer->>Rollup Node: optimism_outputAtBlock
Rollup Node->>Proposer: output root
Proposer->>L1: Query L2OutputOracle for this output root
L1->>Proposer: output root or nil
Proposer->>Proposer: stop if the current output is already proposed
Proposer->>L1: L2OutputOracle.proposeOutputRoot
```
If there is no newly finalized output, the service continues querying until it receives one. It then submits this Since there may be multiple proposers running simultaneously when permissionless output proposals are enabled,
output, and the appropriate timestamp, to the [L2 Output Root](#l2-output-root-smart-contract) contract's the [op-proposer](../op-proposer/) will check that it's output root has not been posted for the given L2 block
`proposeL2Output()` function. The timestamp block number must correspond to the `startingBlockNumber` plus the next number before sending the proposal transaction. This is shown in the sequence diagram above when the `Proposer`
multiple of the `SUBMISSION_INTERVAL` value. queries the `L2OutputOracle` for the output root. If it receives an output root that is equal to the one it
received from the rollup node, it will **not** send this output root in a transaction to the `L2OutputOracle`.
The proposer may also delete multiple output roots by calling the `deleteL2Outputs()` function and specifying the Also note, while the [op-proposer](../op-proposer/) implementation submits outputs _only_ based on finalized
index of the first output to delete, this will also delete all subsequent outputs. or safe L2 blocks, other proposer implementations may submit outputs corresponding to unsafe (non-finalized)
L2 blocks. This comes with risk as it will be possible for [batchers](./batcher.md) to submit L2 blocks that
do not correspond to the output that have already been made available (implying those outputs are now _invalid_).
> **Note regarding future work:** In the initial version of the system, the proposer will be the same entity as the Version `v2.0.0` includes breaking changes to the `L2OutputOracle` ABI.
> sequencer, which is a trusted role. In the future proposers may need to submit a bond in order to post L2 output
> roots, and some or all of this bond may be taken in the event of a faulty proposal.
## L2 Output Commitment Construction ## L2 Output Commitment Construction
...@@ -163,7 +230,7 @@ will not match that of the block with that number and the call will revert. ...@@ -163,7 +230,7 @@ will not match that of the block with that number and the call will revert.
### Constants ### Constants
| Name | Value | Unit | | Name | Value | Unit |
| --------------------- | ----- | ------- | | --------------------- | ------- | ------- |
| `SUBMISSION_INTERVAL` | TBD | blocks | | `SUBMISSION_INTERVAL` | `120` | blocks |
| `L2_BLOCK_TIME` | `2` | seconds | | `L2_BLOCK_TIME` | `2` | seconds |
...@@ -3760,6 +3760,10 @@ ...@@ -3760,6 +3760,10 @@
"@safe-global/safe-gateway-typescript-sdk" "^3.5.3" "@safe-global/safe-gateway-typescript-sdk" "^3.5.3"
ethers "^5.7.2" ethers "^5.7.2"
"@safe-global/safe-contracts@https://github.com/safe-global/safe-contracts.git#v1.3.0-libs.0":
version "1.3.0"
resolved "https://github.com/safe-global/safe-contracts.git#767ef36bba88bdbc0c9fe3708a4290cabef4c376"
"@safe-global/safe-gateway-typescript-sdk@^3.5.3": "@safe-global/safe-gateway-typescript-sdk@^3.5.3":
version "3.7.0" version "3.7.0"
resolved "https://registry.yarnpkg.com/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.7.0.tgz#2af52f1bc73759b1b6a549fed598781c8c5fce72" resolved "https://registry.yarnpkg.com/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.7.0.tgz#2af52f1bc73759b1b6a549fed598781c8c5fce72"
...@@ -19354,6 +19358,10 @@ socks@^2.3.3, socks@^2.6.1: ...@@ -19354,6 +19358,10 @@ socks@^2.3.3, socks@^2.6.1:
ip "^1.1.5" ip "^1.1.5"
smart-buffer "^4.1.0" smart-buffer "^4.1.0"
"solady@https://github.com/Vectorized/solady.git#v0.0.85":
version "0.0.85"
resolved "https://github.com/Vectorized/solady.git#507e0d84872f435d497e6d2ce10e7f484392db4f"
solc@0.7.3: solc@0.7.3:
version "0.7.3" version "0.7.3"
resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a"
......
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