Commit 142448c5 authored by OptimismBot's avatar OptimismBot Committed by GitHub

Merge pull request #5956 from ethereum-optimism/clabby/ct/remove-contracts

chore(packages): Remove legacy `contracts`
parents ea288d1f 4042543d
......@@ -84,7 +84,6 @@ jobs:
- "packages/balance-monitor/node_modules"
- "packages/chain-mon/node_modules"
- "packages/common-ts/node_modules"
- "packages/contracts/node_modules"
- "packages/contracts-bedrock/node_modules"
- "packages/contracts-governance/node_modules"
- "packages/contracts-periphery/node_modules"
......@@ -108,13 +107,6 @@ jobs:
paths:
- "packages/*/dist"
- "packages/*/artifacts"
- "packages/contracts/src/contract-artifacts.ts"
- "packages/contracts/src/contract-deployed-artifacts.ts"
- "packages/contracts/chugsplash"
- "packages/contracts/L1"
- "packages/contracts/L2"
- "packages/contracts/libraries"
- "packages/contracts/standards"
docker-build:
environment:
......@@ -672,10 +664,6 @@ jobs:
name: Check common-ts
command: npx depcheck
working_directory: packages/common-ts
- run:
name: Check contracts
command: npx depcheck
working_directory: packages/contracts
- run:
name: Check contracts-periphery
command: npx depcheck
......
---
C-Protocol-Critical:
- 'packages/data-transport-layer/**/*.ts'
- 'packages/contracts/**/*.sol'
- 'packages/contracts-bedrock/**/*.sol'
- 'l2geth/**/*.go'
......@@ -18,11 +18,6 @@ artifacts
cache
l2geth/build/bin
packages/contracts/deployments/custom
packages/contracts/coverage*
packages/contracts/@ens*
packages/contracts/@openzeppelin*
packages/contracts/hardhat*
packages/contracts-periphery/coverage*
packages/contracts-periphery/@openzeppelin*
packages/contracts-periphery/hardhat*
......
......@@ -81,7 +81,6 @@ Refer to the Directory Structure section below to understand which packages are
~~ Pre-BEDROCK ~~
├── <a href="./packages">packages</a>
│ ├── <a href="./packages/common-ts">common-ts</a>: Common tools for building apps in TypeScript
│ ├── <a href="./packages/contracts">contracts</a>: L1 and L2 smart contracts for Optimism
│ ├── <a href="./packages/contracts-periphery">contracts-periphery</a>: Peripheral contracts for Optimism
│ ├── <a href="./packages/core-utils">core-utils</a>: Low-level utilities that make building Optimism easier
│ ├── <a href="./packages/data-transport-layer">data-transport-layer</a>: Service for indexing Optimism-related L1 data
......
ignores: [
"@codechecks/client",
"@ethersproject/bytes",
"@openzeppelin/contracts",
"@openzeppelin/contracts-upgradeable",
"@typechain/ethers-v5",
"prettier-plugin-solidity",
"solhint-plugin-prettier",
"ts-generator",
"@babel/eslint-parser",
"@typescript-eslint/parser",
"eslint-plugin-import",
"eslint-plugin-unicorn",
"eslint-plugin-jsdoc",
"eslint-plugin-prefer-arrow",
"eslint-plugin-react",
"@typescript-eslint/eslint-plugin",
"eslint-config-prettier",
"eslint-plugin-prettier"
]
# Name for the network to deploy to ("mainnet", "kovan", etc.)
CONTRACTS_TARGET_NETWORK=
# Private key that will send deployment transactions
CONTRACTS_DEPLOYER_KEY=
# RPC URL connected to the L1 chain we're deploying to
CONTRACTS_RPC_URL=
# Your Etherscan API key for the L1 network
ETHERSCAN_API_KEY=
module.exports = {
extends: '../../.eslintrc.js',
ignorePatterns: [
'src/contract-artifacts.ts',
'src/contract-deployed-artifacts.ts',
],
}
*.sol linguist-language=Solidity
src/contract-artifacts.ts
src/contract-deployed-artifacts.ts
/chugsplash
/L1
/L2
/libraries
/standards
"*.{ts,js}":
- eslint
"*.sol":
- yarn solhint -f table
# WETH9 is a standard we should not modify it.
contracts/L2/predeploys/WETH9.sol
contracts/L2/predeploys/IWETH9.sol
coverage
module.exports = {
...require('../../.prettierrc.js'),
}
module.exports = {
skipFiles: [
'./test-helpers',
'./test-libraries',
'./L2/predeploys/OVM_DeployerWhitelist.sol'
],
mocha: {
grep: "@skip-on-coverage",
invert: true
}
};
{
"extends": "solhint:recommended",
"plugins": ["prettier"],
"rules": {
"prettier/prettier": "error",
"compiler-version": "off",
"code-complexity": ["warn", 5],
"max-line-length": ["error", 100],
"func-param-name-mixedcase": "error",
"modifier-name-mixedcase": "error",
"ordering": "warn",
"not-rely-on-time": "off",
"no-complex-fallback": "off",
"not-rely-on-block-hash": "off",
"reentrancy": "off",
"contract-name-camelcase": "off"
}
}
node_modules
# WETH9 is a standard we should not modify it.
contracts/L2/predeploys/WETH9.sol
contracts/L2/predeploys/IWETH9.sol
This diff is collapsed.
(The MIT License)
Copyright 2020-2021 Optimism
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# Optimism Smart Contracts
[![codecov](https://codecov.io/gh/ethereum-optimism/optimism/branch/master/graph/badge.svg?token=0VTG7PG7YR&flag=contracts-tests)](https://codecov.io/gh/ethereum-optimism/optimism)
`@eth-optimism/contracts` contains the various Solidity smart contracts used within the Optimism system.
Some of these contracts are [meant to be deployed to Ethereum ("Layer 1")](https://github.com/ethereum-optimism/optimism/tree/develop/packages/contracts/contracts/L1), while others are [meant to be deployed to Optimism ("Layer 2")](https://github.com/ethereum-optimism/optimism/tree/develop/packages/contracts/contracts/L2).
Within each contract file you'll find the network upon which the contract is meant to be deloyed, listed as either `EVM` (for Ethereum) or `OVM` (for Optimism).
If neither `EVM` nor `OVM` are listed, the contract is likely intended to be used on either network.
## Usage (npm)
You can import `@eth-optimism/contracts` to use the Optimism contracts within your own codebase.
Install via `npm` or `yarn`:
```shell
npm install @eth-optimism/contracts
```
Within your contracts:
```solidity
import { SomeContract } from "@eth-optimism/contracts/path/to/SomeContract.sol";
```
Note that the `/path/to/SomeContract.sol` is the path to the target contract within the [contracts folder](https://github.com/ethereum-optimism/optimism/tree/develop/packages/contracts/contracts) inside of this package.
For example, the [L1CrossDomainMessenger](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L1/messaging/L1CrossDomainMessenger.sol) contract is located at `packages/contracts/contracts/L1/messaging/L1CrossDomainMessenger.sol`, relative to this README.
You would therefore import the contract as:
```solidity
import { L1CrossDomainMessenger } from "@eth-optimism/contracts/L1/messaging/L1CrossDomainMessenger.sol";
```
## Guide for Developers
### Setup
Install the following:
- [`Node.js` (14+)](https://nodejs.org/en/)
- [`npm`](https://www.npmjs.com/get-npm)
- [`yarn`](https://classic.yarnpkg.com/en/docs/install/)
Clone the repo:
```shell
git clone https://github.com/ethereum-optimism/contracts.git
cd contracts
```
Install `npm` packages:
```shell
yarn install
```
### Running Tests
Tests are executed via `yarn`:
```shell
yarn test
```
Run specific tests by giving a path to the file you want to run:
```shell
yarn test ./test/path/to/my/test.spec.ts
```
### Measuring test coverage:
```shell
yarn test:coverage
```
The output is most easily viewable by opening the html file in your browser:
```shell
open ./coverage/index.html
```
### Compiling and Building
Compile and build the various required with the `build` command:
```shell
yarn build
```
### Deploying the Contracts
#### Required environment variables
You must set several required environment variables before you can execute a deployment.
Duplicate the file [`.env.example`](./.env.example) and rename your duplicate to `.env`.
Fill out each of the environment variables before continuing.
#### Creating a deployment configuration
Before you can carry out a deployment, you must create a deployment configuration file inside of the [deploy-config](./deploy-config/) folder.
Deployment configuration files are TypeScript files that export an object that conforms to the `DeployConfig` type.
See [mainnet.ts](./deploy-config/mainnet.ts) for an example deployment configuration.
We recommend duplicating an existing deployment config and modifying it to satisfy your requirements.
#### Executing a deployment
Once you've created your deploy config, you can execute a deployment with the following command:
```
npx hardhat deploy --network <my network name>
```
Note that this only applies to fresh deployments.
If you want to upgrade an existing system (instead of deploying a new system from scratch), you must use the following command instead:
```
npx hardhat deploy --network <my network name> --tags upgrade
```
During the deployment process, you will be asked to transfer ownership of several contracts to a special contract address.
You will also be asked to verify various configuration values.
This is a safety mechanism to make sure that actions within an upgrade are performed atomically.
Ownership of these addresses will be automatically returned to the original owner address once the upgrade is complete.
The original owner can always recover ownership from the upgrade contract in an emergency.
Please read these instructions carefully, verify each of the presented configuration values, and carefully confirm that the contract you are giving ownership to has not been compromised (e.g., check the code on Etherscan).
After your deployment is complete, your new contracts will be written to an artifacts directory in `./deployments/<my network name>`.
#### Verifying contract source code
Contracts will be automatically verified via both [Etherscan](https://etherscan.io) and [Sourcify](https://sourcify.dev/) during the deployment process.
If there was an issue with verification during the deployment, you can manually verify your contracts with the command:
```
npx hardhat etherscan-verify --network <my network name>
```
#### Creating a genesis file
Optimism expects that certain contracts (called "predeploys") be deployed to the L2 network at pre-determined addresses.
We guarantee this by creating a genesis file in which certain contracts are already within the L2 state at the genesis block.
To create the genesis file for your network, you must first deploy the L1 contracts using the appropriate commands from above.
Once you've deployed your contracts, run the following command:
```
npx hardhat take-dump --network <my network name>
```
A genesis file will be created for you at `/genesis/<my network name>.json`.
You can then ingest this file via `geth init`.
### Hardhat tasks
#### Whitelisting
Optimism has removed the whitelist from the Optimism mainnet.
However, if you are running your own network and still wish to use the whitelist, you can manage the whitelist with the `whitelist` task.
Run the following to get help text for the `whitelist` command:
```
npx hardhat whitelist --help
```
#### Withdrawing fees
Any wallet can trigger a withdrawal of fees within the `SequencerFeeWallet` contract on L2 back to L1 as long as a threshold balance has been reached.
Fees within the wallet will return to a fixed address on L1.
Run the following to get help text for the `withdraw-fees` command:
```
npx hardhat withdraw-fees --help
```
## Security
Please refer to our [Security Policy](https://github.com/ethereum-optimism/.github/security/policy) for information about how to disclose security issues with this code.
We also maintain a [bug bounty program via Immunefi](https://immunefi.com/bounty/optimism/) with a maximum payout of $2,000,042 for critical bug reports.
checks:
- name: eth-gas-reporter/codechecks
settings:
speculativeBranchSelection: false
branches:
- develop
- master
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import { Lib_AddressManager } from "../../libraries/resolver/Lib_AddressManager.sol";
/**
* @title AddressDictator
* @dev The AddressDictator (glory to Arstotzka) is a contract that allows us to safely manipulate
* many different addresses in the AddressManager without transferring ownership of the
* AddressManager to a hot wallet or hardware wallet.
*/
contract AddressDictator {
/*********
* Types *
*********/
struct NamedAddress {
string name;
address addr;
}
/*************
* Variables *
*************/
Lib_AddressManager public manager;
address public finalOwner;
NamedAddress[] namedAddresses;
/***************
* Constructor *
***************/
/**
* @param _manager Address of the AddressManager contract.
* @param _finalOwner Address to transfer AddressManager ownership to afterwards.
* @param _names Array of names to associate an address with.
* @param _addresses Array of addresses to associate with the name.
*/
constructor(
Lib_AddressManager _manager,
address _finalOwner,
string[] memory _names,
address[] memory _addresses
) {
manager = _manager;
finalOwner = _finalOwner;
require(
_names.length == _addresses.length,
"AddressDictator: Must provide an equal number of names and addresses."
);
for (uint256 i = 0; i < _names.length; i++) {
namedAddresses.push(NamedAddress({ name: _names[i], addr: _addresses[i] }));
}
}
/********************
* Public Functions *
********************/
/**
* Called to finalize the transfer, this function is callable by anyone, but will only result in
* an upgrade if this contract is the owner Address Manager.
*/
// slither-disable-next-line calls-loop
function setAddresses() external {
for (uint256 i = 0; i < namedAddresses.length; i++) {
manager.setAddress(namedAddresses[i].name, namedAddresses[i].addr);
}
// note that this will revert if _finalOwner == currentOwner
manager.transferOwnership(finalOwner);
}
/**
* Transfers ownership of this contract to the finalOwner.
* Only callable by the Final Owner, which is intended to be our multisig.
* This function shouldn't be necessary, but it gives a sense of reassurance that we can recover
* if something really surprising goes wrong.
*/
function returnOwnership() external {
require(msg.sender == finalOwner, "AddressDictator: only callable by finalOwner");
manager.transferOwnership(finalOwner);
}
/******************
* View Functions *
******************/
/**
* Returns the full namedAddresses array.
*/
function getNamedAddresses() external view returns (NamedAddress[] memory) {
return namedAddresses;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import { L1ChugSplashProxy } from "../../chugsplash/L1ChugSplashProxy.sol";
import { iL1ChugSplashDeployer } from "../../chugsplash/interfaces/iL1ChugSplashDeployer.sol";
/**
* @title ChugSplashDictator
* @dev Like the AddressDictator, but specifically for the Proxy__OVM_L1StandardBridge. We're
* working on a generalized version of this but this is good enough for the moment.
*/
contract ChugSplashDictator is iL1ChugSplashDeployer {
/*************
* Variables *
*************/
// slither-disable-next-line constable-states
bool public isUpgrading = true;
L1ChugSplashProxy public target;
address public finalOwner;
bytes32 public codeHash;
bytes32 public messengerSlotKey;
bytes32 public messengerSlotVal;
bytes32 public bridgeSlotKey;
bytes32 public bridgeSlotVal;
/***************
* Constructor *
***************/
constructor(
L1ChugSplashProxy _target,
address _finalOwner,
bytes32 _codeHash,
bytes32 _messengerSlotKey,
bytes32 _messengerSlotVal,
bytes32 _bridgeSlotKey,
bytes32 _bridgeSlotVal
) {
target = _target;
finalOwner = _finalOwner;
codeHash = _codeHash;
messengerSlotKey = _messengerSlotKey;
messengerSlotVal = _messengerSlotVal;
bridgeSlotKey = _bridgeSlotKey;
bridgeSlotVal = _bridgeSlotVal;
}
/********************
* Public Functions *
********************/
function doActions(bytes memory _code) external {
require(keccak256(_code) == codeHash, "ChugSplashDictator: Incorrect code hash.");
target.setCode(_code);
target.setStorage(messengerSlotKey, messengerSlotVal);
target.setStorage(bridgeSlotKey, bridgeSlotVal);
target.setOwner(finalOwner);
}
/**
* Transfers ownership of this contract to the finalOwner.
* Only callable by the finalOwner, which is intended to be our multisig.
* This function shouldn't be necessary, but it gives a sense of reassurance that we can
* recover if something really surprising goes wrong.
*/
function returnOwnership() external {
require(msg.sender == finalOwner, "ChugSplashDictator: only callable by finalOwner");
target.setOwner(finalOwner);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
/* Interface Imports */
import { ICrossDomainMessenger } from "../../libraries/bridge/ICrossDomainMessenger.sol";
/**
* @title IL1CrossDomainMessenger
*/
interface IL1CrossDomainMessenger is ICrossDomainMessenger {
/*******************
* Data Structures *
*******************/
struct L2MessageInclusionProof {
bytes32 stateRoot;
Lib_OVMCodec.ChainBatchHeader stateRootBatchHeader;
Lib_OVMCodec.ChainInclusionProof stateRootProof;
bytes stateTrieWitness;
bytes storageTrieWitness;
}
/********************
* Public Functions *
********************/
/**
* Relays a cross domain message to a contract.
* @param _target Target contract address.
* @param _sender Message sender address.
* @param _message Message to send to the target.
* @param _messageNonce Nonce for the provided message.
* @param _proof Inclusion proof for the given message.
*/
function relayMessage(
address _target,
address _sender,
bytes memory _message,
uint256 _messageNonce,
L2MessageInclusionProof memory _proof
) external;
/**
* Replays a cross domain message to the target messenger.
* @param _target Target contract address.
* @param _sender Original sender address.
* @param _message Message to send to the target.
* @param _queueIndex CTC Queue index for the message to replay.
* @param _oldGasLimit Original gas limit used to send the message.
* @param _newGasLimit New gas limit to be used for this message.
*/
function replayMessage(
address _target,
address _sender,
bytes memory _message,
uint256 _queueIndex,
uint32 _oldGasLimit,
uint32 _newGasLimit
) external;
}
// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.9.0;
/**
* @title IL1ERC20Bridge
*/
interface IL1ERC20Bridge {
/**********
* Events *
**********/
event ERC20DepositInitiated(
address indexed _l1Token,
address indexed _l2Token,
address indexed _from,
address _to,
uint256 _amount,
bytes _data
);
event ERC20WithdrawalFinalized(
address indexed _l1Token,
address indexed _l2Token,
address indexed _from,
address _to,
uint256 _amount,
bytes _data
);
/********************
* Public Functions *
********************/
/**
* @dev get the address of the corresponding L2 bridge contract.
* @return Address of the corresponding L2 bridge contract.
*/
function l2TokenBridge() external returns (address);
/**
* @dev deposit an amount of the ERC20 to the caller's balance on L2.
* @param _l1Token Address of the L1 ERC20 we are depositing
* @param _l2Token Address of the L1 respective L2 ERC20
* @param _amount Amount of the ERC20 to deposit
* @param _l2Gas Gas limit required to complete the deposit on L2.
* @param _data Optional data to forward to L2. This data is provided
* solely as a convenience for external contracts. Aside from enforcing a maximum
* length, these contracts provide no guarantees about its content.
*/
function depositERC20(
address _l1Token,
address _l2Token,
uint256 _amount,
uint32 _l2Gas,
bytes calldata _data
) external;
/**
* @dev deposit an amount of ERC20 to a recipient's balance on L2.
* @param _l1Token Address of the L1 ERC20 we are depositing
* @param _l2Token Address of the L1 respective L2 ERC20
* @param _to L2 address to credit the withdrawal to.
* @param _amount Amount of the ERC20 to deposit.
* @param _l2Gas Gas limit required to complete the deposit on L2.
* @param _data Optional data to forward to L2. This data is provided
* solely as a convenience for external contracts. Aside from enforcing a maximum
* length, these contracts provide no guarantees about its content.
*/
function depositERC20To(
address _l1Token,
address _l2Token,
address _to,
uint256 _amount,
uint32 _l2Gas,
bytes calldata _data
) external;
/*************************
* Cross-chain Functions *
*************************/
/**
* @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the
* L1 ERC20 token.
* This call will fail if the initialized withdrawal from L2 has not been finalized.
*
* @param _l1Token Address of L1 token to finalizeWithdrawal for.
* @param _l2Token Address of L2 token where withdrawal was initiated.
* @param _from L2 address initiating the transfer.
* @param _to L1 address to credit the withdrawal to.
* @param _amount Amount of the ERC20 to deposit.
* @param _data Data provided by the sender on L2. This data is provided
* solely as a convenience for external contracts. Aside from enforcing a maximum
* length, these contracts provide no guarantees about its content.
*/
function finalizeERC20Withdrawal(
address _l1Token,
address _l2Token,
address _from,
address _to,
uint256 _amount,
bytes calldata _data
) external;
}
// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.9.0;
import "./IL1ERC20Bridge.sol";
/**
* @title IL1StandardBridge
*/
interface IL1StandardBridge is IL1ERC20Bridge {
/**********
* Events *
**********/
event ETHDepositInitiated(
address indexed _from,
address indexed _to,
uint256 _amount,
bytes _data
);
event ETHWithdrawalFinalized(
address indexed _from,
address indexed _to,
uint256 _amount,
bytes _data
);
/********************
* Public Functions *
********************/
/**
* @dev Deposit an amount of the ETH to the caller's balance on L2.
* @param _l2Gas Gas limit required to complete the deposit on L2.
* @param _data Optional data to forward to L2. This data is provided
* solely as a convenience for external contracts. Aside from enforcing a maximum
* length, these contracts provide no guarantees about its content.
*/
function depositETH(uint32 _l2Gas, bytes calldata _data) external payable;
/**
* @dev Deposit an amount of ETH to a recipient's balance on L2.
* @param _to L2 address to credit the withdrawal to.
* @param _l2Gas Gas limit required to complete the deposit on L2.
* @param _data Optional data to forward to L2. This data is provided
* solely as a convenience for external contracts. Aside from enforcing a maximum
* length, these contracts provide no guarantees about its content.
*/
function depositETHTo(
address _to,
uint32 _l2Gas,
bytes calldata _data
) external payable;
/*************************
* Cross-chain Functions *
*************************/
/**
* @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the
* L1 ETH token. Since only the xDomainMessenger can call this function, it will never be called
* before the withdrawal is finalized.
* @param _from L2 address initiating the transfer.
* @param _to L1 address to credit the withdrawal to.
* @param _amount Amount of the ERC20 to deposit.
* @param _data Optional data to forward to L2. This data is provided
* solely as a convenience for external contracts. Aside from enforcing a maximum
* length, these contracts provide no guarantees about its content.
*/
function finalizeETHWithdrawal(
address _from,
address _to,
uint256 _amount,
bytes calldata _data
) external;
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/* Interface Imports */
import { IL1StandardBridge } from "./IL1StandardBridge.sol";
import { IL1ERC20Bridge } from "./IL1ERC20Bridge.sol";
import { IL2ERC20Bridge } from "../../L2/messaging/IL2ERC20Bridge.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
/* Library Imports */
import { CrossDomainEnabled } from "../../libraries/bridge/CrossDomainEnabled.sol";
import { Lib_PredeployAddresses } from "../../libraries/constants/Lib_PredeployAddresses.sol";
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
/**
* @title L1StandardBridge
* @dev The L1 ETH and ERC20 Bridge is a contract which stores deposited L1 funds and standard
* tokens that are in use on L2. It synchronizes a corresponding L2 Bridge, informing it of deposits
* and listening to it for newly finalized withdrawals.
*
*/
contract L1StandardBridge is IL1StandardBridge, CrossDomainEnabled {
using SafeERC20 for IERC20;
/********************************
* External Contract References *
********************************/
address public l2TokenBridge;
// Maps L1 token to L2 token to balance of the L1 token deposited
mapping(address => mapping(address => uint256)) public deposits;
/***************
* Constructor *
***************/
// This contract lives behind a proxy, so the constructor parameters will go unused.
constructor() CrossDomainEnabled(address(0)) {}
/******************
* Initialization *
******************/
/**
* @param _l1messenger L1 Messenger address being used for cross-chain communications.
* @param _l2TokenBridge L2 standard bridge address.
*/
// slither-disable-next-line external-function
function initialize(address _l1messenger, address _l2TokenBridge) public {
require(messenger == address(0), "Contract has already been initialized.");
messenger = _l1messenger;
l2TokenBridge = _l2TokenBridge;
}
/**************
* Depositing *
**************/
/** @dev Modifier requiring sender to be EOA. This check could be bypassed by a malicious
* contract via initcode, but it takes care of the user error we want to avoid.
*/
modifier onlyEOA() {
// Used to stop deposits from contracts (avoid accidentally lost tokens)
require(!Address.isContract(msg.sender), "Account not EOA");
_;
}
/**
* @dev This function can be called with no data
* to deposit an amount of ETH to the caller's balance on L2.
* Since the receive function doesn't take data, a conservative
* default amount is forwarded to L2.
*/
receive() external payable onlyEOA {
_initiateETHDeposit(msg.sender, msg.sender, 200_000, bytes(""));
}
/**
* @inheritdoc IL1StandardBridge
*/
function depositETH(uint32 _l2Gas, bytes calldata _data) external payable onlyEOA {
_initiateETHDeposit(msg.sender, msg.sender, _l2Gas, _data);
}
/**
* @inheritdoc IL1StandardBridge
*/
function depositETHTo(
address _to,
uint32 _l2Gas,
bytes calldata _data
) external payable {
_initiateETHDeposit(msg.sender, _to, _l2Gas, _data);
}
/**
* @dev Performs the logic for deposits by storing the ETH and informing the L2 ETH Gateway of
* the deposit.
* @param _from Account to pull the deposit from on L1.
* @param _to Account to give the deposit to on L2.
* @param _l2Gas Gas limit required to complete the deposit on L2.
* @param _data Optional data to forward to L2. This data is provided
* solely as a convenience for external contracts. Aside from enforcing a maximum
* length, these contracts provide no guarantees about its content.
*/
function _initiateETHDeposit(
address _from,
address _to,
uint32 _l2Gas,
bytes memory _data
) internal {
// Construct calldata for finalizeDeposit call
bytes memory message = abi.encodeWithSelector(
IL2ERC20Bridge.finalizeDeposit.selector,
address(0),
Lib_PredeployAddresses.OVM_ETH,
_from,
_to,
msg.value,
_data
);
// Send calldata into L2
// slither-disable-next-line reentrancy-events
sendCrossDomainMessage(l2TokenBridge, _l2Gas, message);
// slither-disable-next-line reentrancy-events
emit ETHDepositInitiated(_from, _to, msg.value, _data);
}
/**
* @inheritdoc IL1ERC20Bridge
*/
function depositERC20(
address _l1Token,
address _l2Token,
uint256 _amount,
uint32 _l2Gas,
bytes calldata _data
) external virtual onlyEOA {
_initiateERC20Deposit(_l1Token, _l2Token, msg.sender, msg.sender, _amount, _l2Gas, _data);
}
/**
* @inheritdoc IL1ERC20Bridge
*/
function depositERC20To(
address _l1Token,
address _l2Token,
address _to,
uint256 _amount,
uint32 _l2Gas,
bytes calldata _data
) external virtual {
_initiateERC20Deposit(_l1Token, _l2Token, msg.sender, _to, _amount, _l2Gas, _data);
}
/**
* @dev Performs the logic for deposits by informing the L2 Deposited Token
* contract of the deposit and calling a handler to lock the L1 funds. (e.g. transferFrom)
*
* @param _l1Token Address of the L1 ERC20 we are depositing
* @param _l2Token Address of the L1 respective L2 ERC20
* @param _from Account to pull the deposit from on L1
* @param _to Account to give the deposit to on L2
* @param _amount Amount of the ERC20 to deposit.
* @param _l2Gas Gas limit required to complete the deposit on L2.
* @param _data Optional data to forward to L2. This data is provided
* solely as a convenience for external contracts. Aside from enforcing a maximum
* length, these contracts provide no guarantees about its content.
*/
function _initiateERC20Deposit(
address _l1Token,
address _l2Token,
address _from,
address _to,
uint256 _amount,
uint32 _l2Gas,
bytes calldata _data
) internal {
// When a deposit is initiated on L1, the L1 Bridge transfers the funds to itself for future
// withdrawals. The use of safeTransferFrom enables support of "broken tokens" which do not
// return a boolean value.
// slither-disable-next-line reentrancy-events, reentrancy-benign
IERC20(_l1Token).safeTransferFrom(_from, address(this), _amount);
// Construct calldata for _l2Token.finalizeDeposit(_to, _amount)
bytes memory message = abi.encodeWithSelector(
IL2ERC20Bridge.finalizeDeposit.selector,
_l1Token,
_l2Token,
_from,
_to,
_amount,
_data
);
// Send calldata into L2
// slither-disable-next-line reentrancy-events, reentrancy-benign
sendCrossDomainMessage(l2TokenBridge, _l2Gas, message);
// slither-disable-next-line reentrancy-benign
deposits[_l1Token][_l2Token] = deposits[_l1Token][_l2Token] + _amount;
// slither-disable-next-line reentrancy-events
emit ERC20DepositInitiated(_l1Token, _l2Token, _from, _to, _amount, _data);
}
/*************************
* Cross-chain Functions *
*************************/
/**
* @inheritdoc IL1StandardBridge
*/
function finalizeETHWithdrawal(
address _from,
address _to,
uint256 _amount,
bytes calldata _data
) external onlyFromCrossDomainAccount(l2TokenBridge) {
// slither-disable-next-line reentrancy-events
(bool success, ) = _to.call{ value: _amount }(new bytes(0));
require(success, "TransferHelper::safeTransferETH: ETH transfer failed");
// slither-disable-next-line reentrancy-events
emit ETHWithdrawalFinalized(_from, _to, _amount, _data);
}
/**
* @inheritdoc IL1ERC20Bridge
*/
function finalizeERC20Withdrawal(
address _l1Token,
address _l2Token,
address _from,
address _to,
uint256 _amount,
bytes calldata _data
) external onlyFromCrossDomainAccount(l2TokenBridge) {
deposits[_l1Token][_l2Token] = deposits[_l1Token][_l2Token] - _amount;
// When a withdrawal is finalized on L1, the L1 Bridge transfers the funds to the withdrawer
// slither-disable-next-line reentrancy-events
IERC20(_l1Token).safeTransfer(_to, _amount);
// slither-disable-next-line reentrancy-events
emit ERC20WithdrawalFinalized(_l1Token, _l2Token, _from, _to, _amount, _data);
}
/*****************************
* Temporary - Migrating ETH *
*****************************/
/**
* @dev Adds ETH balance to the account. This is meant to allow for ETH
* to be migrated from an old gateway to a new gateway.
* NOTE: This is left for one upgrade only so we are able to receive the migrated ETH from the
* old contract
*/
function donateETH() external payable {}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/* Library Imports */
import { Lib_Buffer } from "../../libraries/utils/Lib_Buffer.sol";
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
/* Interface Imports */
import { IChainStorageContainer } from "./IChainStorageContainer.sol";
/**
* @title ChainStorageContainer
* @dev The Chain Storage Container provides its owner contract with read, write and delete
* functionality. This provides gas efficiency gains by enabling it to overwrite storage slots which
* can no longer be used in a fraud proof due to the fraud window having passed, and the associated
* chain state or transactions being finalized.
* Three distinct Chain Storage Containers will be deployed on Layer 1:
* 1. Stores transaction batches for the Canonical Transaction Chain
* 2. Stores queued transactions for the Canonical Transaction Chain
* 3. Stores chain state batches for the State Commitment Chain
*
*/
contract ChainStorageContainer is IChainStorageContainer, Lib_AddressResolver {
/*************
* Libraries *
*************/
using Lib_Buffer for Lib_Buffer.Buffer;
/*************
* Variables *
*************/
string public owner;
Lib_Buffer.Buffer internal buffer;
/***************
* Constructor *
***************/
/**
* @param _libAddressManager Address of the Address Manager.
* @param _owner Name of the contract that owns this container (will be resolved later).
*/
constructor(address _libAddressManager, string memory _owner)
Lib_AddressResolver(_libAddressManager)
{
owner = _owner;
}
/**********************
* Function Modifiers *
**********************/
modifier onlyOwner() {
require(
msg.sender == resolve(owner),
"ChainStorageContainer: Function can only be called by the owner."
);
_;
}
/********************
* Public Functions *
********************/
/**
* @inheritdoc IChainStorageContainer
*/
// slither-disable-next-line external-function
function setGlobalMetadata(bytes27 _globalMetadata) public onlyOwner {
return buffer.setExtraData(_globalMetadata);
}
/**
* @inheritdoc IChainStorageContainer
*/
// slither-disable-next-line external-function
function getGlobalMetadata() public view returns (bytes27) {
return buffer.getExtraData();
}
/**
* @inheritdoc IChainStorageContainer
*/
// slither-disable-next-line external-function
function length() public view returns (uint256) {
return uint256(buffer.getLength());
}
/**
* @inheritdoc IChainStorageContainer
*/
// slither-disable-next-line external-function
function push(bytes32 _object) public onlyOwner {
buffer.push(_object);
}
/**
* @inheritdoc IChainStorageContainer
*/
// slither-disable-next-line external-function
function push(bytes32 _object, bytes27 _globalMetadata) public onlyOwner {
buffer.push(_object, _globalMetadata);
}
/**
* @inheritdoc IChainStorageContainer
*/
// slither-disable-next-line external-function
function get(uint256 _index) public view returns (bytes32) {
return buffer.get(uint40(_index));
}
/**
* @inheritdoc IChainStorageContainer
*/
// slither-disable-next-line external-function
function deleteElementsAfterInclusive(uint256 _index) public onlyOwner {
buffer.deleteElementsAfterInclusive(uint40(_index));
}
/**
* @inheritdoc IChainStorageContainer
*/
// slither-disable-next-line external-function
function deleteElementsAfterInclusive(uint256 _index, bytes27 _globalMetadata)
public
onlyOwner
{
buffer.deleteElementsAfterInclusive(uint40(_index), _globalMetadata);
}
}
// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.9.0;
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
/* Interface Imports */
import { IChainStorageContainer } from "./IChainStorageContainer.sol";
/**
* @title ICanonicalTransactionChain
*/
interface ICanonicalTransactionChain {
/**********
* Events *
**********/
event L2GasParamsUpdated(
uint256 l2GasDiscountDivisor,
uint256 enqueueGasCost,
uint256 enqueueL2GasPrepaid
);
event TransactionEnqueued(
address indexed _l1TxOrigin,
address indexed _target,
uint256 _gasLimit,
bytes _data,
uint256 indexed _queueIndex,
uint256 _timestamp
);
event QueueBatchAppended(
uint256 _startingQueueIndex,
uint256 _numQueueElements,
uint256 _totalElements
);
event SequencerBatchAppended(
uint256 _startingQueueIndex,
uint256 _numQueueElements,
uint256 _totalElements
);
event TransactionBatchAppended(
uint256 indexed _batchIndex,
bytes32 _batchRoot,
uint256 _batchSize,
uint256 _prevTotalElements,
bytes _extraData
);
/***********
* Structs *
***********/
struct BatchContext {
uint256 numSequencedTransactions;
uint256 numSubsequentQueueTransactions;
uint256 timestamp;
uint256 blockNumber;
}
/*******************************
* Authorized Setter Functions *
*******************************/
/**
* Allows the Burn Admin to update the parameters which determine the amount of gas to burn.
* The value of enqueueL2GasPrepaid is immediately updated as well.
*/
function setGasParams(uint256 _l2GasDiscountDivisor, uint256 _enqueueGasCost) external;
/********************
* Public Functions *
********************/
/**
* Accesses the batch storage container.
* @return Reference to the batch storage container.
*/
function batches() external view returns (IChainStorageContainer);
/**
* Retrieves the total number of elements submitted.
* @return _totalElements Total submitted elements.
*/
function getTotalElements() external view returns (uint256 _totalElements);
/**
* Retrieves the total number of batches submitted.
* @return _totalBatches Total submitted batches.
*/
function getTotalBatches() external view returns (uint256 _totalBatches);
/**
* Returns the index of the next element to be enqueued.
* @return Index for the next queue element.
*/
function getNextQueueIndex() external view returns (uint40);
/**
* Gets the queue element at a particular index.
* @param _index Index of the queue element to access.
* @return _element Queue element at the given index.
*/
function getQueueElement(uint256 _index)
external
view
returns (Lib_OVMCodec.QueueElement memory _element);
/**
* Returns the timestamp of the last transaction.
* @return Timestamp for the last transaction.
*/
function getLastTimestamp() external view returns (uint40);
/**
* Returns the blocknumber of the last transaction.
* @return Blocknumber for the last transaction.
*/
function getLastBlockNumber() external view returns (uint40);
/**
* Get the number of queue elements which have not yet been included.
* @return Number of pending queue elements.
*/
function getNumPendingQueueElements() external view returns (uint40);
/**
* Retrieves the length of the queue, including
* both pending and canonical transactions.
* @return Length of the queue.
*/
function getQueueLength() external view returns (uint40);
/**
* Adds a transaction to the queue.
* @param _target Target contract to send the transaction to.
* @param _gasLimit Gas limit for the given transaction.
* @param _data Transaction data.
*/
function enqueue(
address _target,
uint256 _gasLimit,
bytes memory _data
) external;
/**
* Allows the sequencer to append a batch of transactions.
* @dev This function uses a custom encoding scheme for efficiency reasons.
* .param _shouldStartAtElement Specific batch we expect to start appending to.
* .param _totalElementsToAppend Total number of batch elements we expect to append.
* .param _contexts Array of batch contexts.
* .param _transactionDataFields Array of raw transaction data.
*/
function appendSequencerBatch(
// uint40 _shouldStartAtElement,
// uint24 _totalElementsToAppend,
// BatchContext[] _contexts,
// bytes[] _transactionDataFields
) external;
}
// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.9.0;
/**
* @title IChainStorageContainer
*/
interface IChainStorageContainer {
/********************
* Public Functions *
********************/
/**
* Sets the container's global metadata field. We're using `bytes27` here because we use five
* bytes to maintain the length of the underlying data structure, meaning we have an extra
* 27 bytes to store arbitrary data.
* @param _globalMetadata New global metadata to set.
*/
function setGlobalMetadata(bytes27 _globalMetadata) external;
/**
* Retrieves the container's global metadata field.
* @return Container global metadata field.
*/
function getGlobalMetadata() external view returns (bytes27);
/**
* Retrieves the number of objects stored in the container.
* @return Number of objects in the container.
*/
function length() external view returns (uint256);
/**
* Pushes an object into the container.
* @param _object A 32 byte value to insert into the container.
*/
function push(bytes32 _object) external;
/**
* Pushes an object into the container. Function allows setting the global metadata since
* we'll need to touch the "length" storage slot anyway, which also contains the global
* metadata (it's an optimization).
* @param _object A 32 byte value to insert into the container.
* @param _globalMetadata New global metadata for the container.
*/
function push(bytes32 _object, bytes27 _globalMetadata) external;
/**
* Retrieves an object from the container.
* @param _index Index of the particular object to access.
* @return 32 byte object value.
*/
function get(uint256 _index) external view returns (bytes32);
/**
* Removes all objects after and including a given index.
* @param _index Object index to delete from.
*/
function deleteElementsAfterInclusive(uint256 _index) external;
/**
* Removes all objects after and including a given index. Also allows setting the global
* metadata field.
* @param _index Object index to delete from.
* @param _globalMetadata New global metadata for the container.
*/
function deleteElementsAfterInclusive(uint256 _index, bytes27 _globalMetadata) external;
}
// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.9.0;
/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
/**
* @title IStateCommitmentChain
*/
interface IStateCommitmentChain {
/**********
* Events *
**********/
event StateBatchAppended(
uint256 indexed _batchIndex,
bytes32 _batchRoot,
uint256 _batchSize,
uint256 _prevTotalElements,
bytes _extraData
);
event StateBatchDeleted(uint256 indexed _batchIndex, bytes32 _batchRoot);
/********************
* Public Functions *
********************/
/**
* Retrieves the total number of elements submitted.
* @return _totalElements Total submitted elements.
*/
function getTotalElements() external view returns (uint256 _totalElements);
/**
* Retrieves the total number of batches submitted.
* @return _totalBatches Total submitted batches.
*/
function getTotalBatches() external view returns (uint256 _totalBatches);
/**
* Retrieves the timestamp of the last batch submitted by the sequencer.
* @return _lastSequencerTimestamp Last sequencer batch timestamp.
*/
function getLastSequencerTimestamp() external view returns (uint256 _lastSequencerTimestamp);
/**
* Appends a batch of state roots to the chain.
* @param _batch Batch of state roots.
* @param _shouldStartAtElement Index of the element at which this batch should start.
*/
function appendStateBatch(bytes32[] calldata _batch, uint256 _shouldStartAtElement) external;
/**
* Deletes all state roots after (and including) a given batch.
* @param _batchHeader Header of the batch to start deleting from.
*/
function deleteStateBatch(Lib_OVMCodec.ChainBatchHeader memory _batchHeader) external;
/**
* Verifies a batch inclusion proof.
* @param _element Hash of the element to verify a proof for.
* @param _batchHeader Header of the batch in which the element was included.
* @param _proof Merkle inclusion proof for the element.
* @return _verified Whether or not the batch inclusion proof is verified.
*/
function verifyStateCommitment(
bytes32 _element,
Lib_OVMCodec.ChainBatchHeader memory _batchHeader,
Lib_OVMCodec.ChainInclusionProof memory _proof
) external view returns (bool _verified);
/**
* Checks whether a given batch is still inside its fraud proof window.
* @param _batchHeader Header of the batch to check.
* @return _inside Whether or not the batch is inside the fraud proof window.
*/
function insideFraudProofWindow(Lib_OVMCodec.ChainBatchHeader memory _batchHeader)
external
view
returns (bool _inside);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/* Interface Imports */
import { IBondManager } from "./IBondManager.sol";
/* Contract Imports */
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
/**
* @title BondManager
* @dev This contract is, for now, a stub of the "real" BondManager that does nothing but
* allow the "OVM_Proposer" to submit state root batches.
*
*/
contract BondManager is IBondManager, Lib_AddressResolver {
/**
* @param _libAddressManager Address of the Address Manager.
*/
constructor(address _libAddressManager) Lib_AddressResolver(_libAddressManager) {}
/**
* @inheritdoc IBondManager
*/
// slither-disable-next-line external-function
function isCollateralized(address _who) public view returns (bool) {
// Only authenticate sequencer to submit state root batches.
return _who == resolve("OVM_Proposer");
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/**
* @title IBondManager
*/
interface IBondManager {
/********************
* Public Functions *
********************/
/**
* Checks whether a given address is properly collateralized and can perform actions within
* the system.
* @param _who Address to check.
* @return true if the address is properly collateralized, false otherwise.
*/
function isCollateralized(address _who) external view returns (bool);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/* Interface Imports */
import { ICrossDomainMessenger } from "../../libraries/bridge/ICrossDomainMessenger.sol";
/**
* @title IL2CrossDomainMessenger
*/
interface IL2CrossDomainMessenger is ICrossDomainMessenger {
/********************
* Public Functions *
********************/
/**
* Relays a cross domain message to a contract.
* @param _target Target contract address.
* @param _sender Message sender address.
* @param _message Message to send to the target.
* @param _messageNonce Nonce for the provided message.
*/
function relayMessage(
address _target,
address _sender,
bytes memory _message,
uint256 _messageNonce
) external;
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/**
* @title IL2ERC20Bridge
*/
interface IL2ERC20Bridge {
/**********
* Events *
**********/
event WithdrawalInitiated(
address indexed _l1Token,
address indexed _l2Token,
address indexed _from,
address _to,
uint256 _amount,
bytes _data
);
event DepositFinalized(
address indexed _l1Token,
address indexed _l2Token,
address indexed _from,
address _to,
uint256 _amount,
bytes _data
);
event DepositFailed(
address indexed _l1Token,
address indexed _l2Token,
address indexed _from,
address _to,
uint256 _amount,
bytes _data
);
/********************
* Public Functions *
********************/
/**
* @dev get the address of the corresponding L1 bridge contract.
* @return Address of the corresponding L1 bridge contract.
*/
function l1TokenBridge() external returns (address);
/**
* @dev initiate a withdraw of some tokens to the caller's account on L1
* @param _l2Token Address of L2 token where withdrawal was initiated.
* @param _amount Amount of the token to withdraw.
* @param _l1Gas Unused, but included for potential forward compatibility considerations.
* @param _data Optional data to forward to L1. This data is provided
* solely as a convenience for external contracts. Aside from enforcing a maximum
* length, these contracts provide no guarantees about its content.
*/
function withdraw(
address _l2Token,
uint256 _amount,
uint32 _l1Gas,
bytes calldata _data
) external;
/**
* @dev initiate a withdraw of some token to a recipient's account on L1.
* @param _l2Token Address of L2 token where withdrawal is initiated.
* @param _to L1 adress to credit the withdrawal to.
* @param _amount Amount of the token to withdraw.
* @param _l1Gas Unused, but included for potential forward compatibility considerations.
* @param _data Optional data to forward to L1. This data is provided
* solely as a convenience for external contracts. Aside from enforcing a maximum
* length, these contracts provide no guarantees about its content.
*/
function withdrawTo(
address _l2Token,
address _to,
uint256 _amount,
uint32 _l1Gas,
bytes calldata _data
) external;
/*************************
* Cross-chain Functions *
*************************/
/**
* @dev Complete a deposit from L1 to L2, and credits funds to the recipient's balance of this
* L2 token. This call will fail if it did not originate from a corresponding deposit in
* L1StandardTokenBridge.
* @param _l1Token Address for the l1 token this is called with
* @param _l2Token Address for the l2 token this is called with
* @param _from Account to pull the deposit from on L2.
* @param _to Address to receive the withdrawal at
* @param _amount Amount of the token to withdraw
* @param _data Data provider by the sender on L1. This data is provided
* solely as a convenience for external contracts. Aside from enforcing a maximum
* length, these contracts provide no guarantees about its content.
*/
function finalizeDeposit(
address _l1Token,
address _l2Token,
address _from,
address _to,
uint256 _amount,
bytes calldata _data
) external;
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/* Library Imports */
import { AddressAliasHelper } from "../../standards/AddressAliasHelper.sol";
import { Lib_CrossDomainUtils } from "../../libraries/bridge/Lib_CrossDomainUtils.sol";
import { Lib_DefaultValues } from "../../libraries/constants/Lib_DefaultValues.sol";
import { Lib_PredeployAddresses } from "../../libraries/constants/Lib_PredeployAddresses.sol";
/* Interface Imports */
import { IL2CrossDomainMessenger } from "./IL2CrossDomainMessenger.sol";
import { iOVM_L2ToL1MessagePasser } from "../predeploys/iOVM_L2ToL1MessagePasser.sol";
/**
* @title L2CrossDomainMessenger
* @dev The L2 Cross Domain Messenger contract sends messages from L2 to L1, and is the entry point
* for L2 messages sent via the L1 Cross Domain Messenger.
*
*/
contract L2CrossDomainMessenger is IL2CrossDomainMessenger {
/*************
* Variables *
*************/
mapping(bytes32 => bool) public relayedMessages;
mapping(bytes32 => bool) public successfulMessages;
mapping(bytes32 => bool) public sentMessages;
uint256 public messageNonce;
address internal xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER;
address public l1CrossDomainMessenger;
/***************
* Constructor *
***************/
/**
* @param _l1CrossDomainMessenger Address of the L1 CrossDomainMessenger
*/
constructor(address _l1CrossDomainMessenger) {
l1CrossDomainMessenger = _l1CrossDomainMessenger;
}
/********************
* Public Functions *
********************/
// slither-disable-next-line external-function
function xDomainMessageSender() public view returns (address) {
require(
xDomainMsgSender != Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER,
"xDomainMessageSender is not set"
);
return xDomainMsgSender;
}
/**
* Sends a cross domain message to the target messenger.
* @param _target Target contract address.
* @param _message Message to send to the target.
* @param _gasLimit Gas limit for the provided message.
*/
// slither-disable-next-line external-function
function sendMessage(
address _target,
bytes memory _message,
uint32 _gasLimit
) public {
bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata(
_target,
msg.sender,
_message,
messageNonce
);
sentMessages[keccak256(xDomainCalldata)] = true;
// Actually send the message.
// slither-disable-next-line reentrancy-no-eth, reentrancy-events
iOVM_L2ToL1MessagePasser(Lib_PredeployAddresses.L2_TO_L1_MESSAGE_PASSER).passMessageToL1(
xDomainCalldata
);
// Emit an event before we bump the nonce or the nonce will be off by one.
// slither-disable-next-line reentrancy-events
emit SentMessage(_target, msg.sender, _message, messageNonce, _gasLimit);
// slither-disable-next-line reentrancy-no-eth
messageNonce += 1;
}
/**
* Relays a cross domain message to a contract.
* @inheritdoc IL2CrossDomainMessenger
*/
// slither-disable-next-line external-function
function relayMessage(
address _target,
address _sender,
bytes memory _message,
uint256 _messageNonce
) public {
// Since it is impossible to deploy a contract to an address on L2 which matches
// the alias of the L1CrossDomainMessenger, this check can only pass when it is called in
// the first call from of a deposit transaction. Thus reentrancy is prevented here.
require(
AddressAliasHelper.undoL1ToL2Alias(msg.sender) == l1CrossDomainMessenger,
"Provided message could not be verified."
);
bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata(
_target,
_sender,
_message,
_messageNonce
);
bytes32 xDomainCalldataHash = keccak256(xDomainCalldata);
require(
successfulMessages[xDomainCalldataHash] == false,
"Provided message has already been received."
);
// Prevent calls to OVM_L2ToL1MessagePasser, which would enable
// an attacker to maliciously craft the _message to spoof
// a call from any L2 account.
if (_target == Lib_PredeployAddresses.L2_TO_L1_MESSAGE_PASSER) {
// Write to the successfulMessages mapping and return immediately.
successfulMessages[xDomainCalldataHash] = true;
return;
}
xDomainMsgSender = _sender;
// slither-disable-next-line reentrancy-no-eth, reentrancy-events, reentrancy-benign
(bool success, ) = _target.call(_message);
// slither-disable-next-line reentrancy-benign
xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER;
// Mark the message as received if the call was successful. Ensures that a message can be
// relayed multiple times in the case that the call reverted.
if (success == true) {
// slither-disable-next-line reentrancy-no-eth
successfulMessages[xDomainCalldataHash] = true;
// slither-disable-next-line reentrancy-events
emit RelayedMessage(xDomainCalldataHash);
} else {
// slither-disable-next-line reentrancy-events
emit FailedRelayedMessage(xDomainCalldataHash);
}
// Store an identifier that can be used to prove that the given message was relayed by some
// user. Gives us an easy way to pay relayers for their work.
bytes32 relayId = keccak256(abi.encodePacked(xDomainCalldata, msg.sender, block.number));
// slither-disable-next-line reentrancy-benign
relayedMessages[relayId] = true;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/* Interface Imports */
import { IL1StandardBridge } from "../../L1/messaging/IL1StandardBridge.sol";
import { IL1ERC20Bridge } from "../../L1/messaging/IL1ERC20Bridge.sol";
import { IL2ERC20Bridge } from "./IL2ERC20Bridge.sol";
/* Library Imports */
import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
import { CrossDomainEnabled } from "../../libraries/bridge/CrossDomainEnabled.sol";
import { Lib_PredeployAddresses } from "../../libraries/constants/Lib_PredeployAddresses.sol";
/* Contract Imports */
import { IL2StandardERC20 } from "../../standards/IL2StandardERC20.sol";
/**
* @title L2StandardBridge
* @dev The L2 Standard bridge is a contract which works together with the L1 Standard bridge to
* enable ETH and ERC20 transitions between L1 and L2.
* This contract acts as a minter for new tokens when it hears about deposits into the L1 Standard
* bridge.
* This contract also acts as a burner of the tokens intended for withdrawal, informing the L1
* bridge to release L1 funds.
*/
contract L2StandardBridge is IL2ERC20Bridge, CrossDomainEnabled {
/********************************
* External Contract References *
********************************/
address public l1TokenBridge;
/***************
* Constructor *
***************/
/**
* @param _l2CrossDomainMessenger Cross-domain messenger used by this contract.
* @param _l1TokenBridge Address of the L1 bridge deployed to the main chain.
*/
constructor(address _l2CrossDomainMessenger, address _l1TokenBridge)
CrossDomainEnabled(_l2CrossDomainMessenger)
{
l1TokenBridge = _l1TokenBridge;
}
/***************
* Withdrawing *
***************/
/**
* @inheritdoc IL2ERC20Bridge
*/
function withdraw(
address _l2Token,
uint256 _amount,
uint32 _l1Gas,
bytes calldata _data
) external virtual {
_initiateWithdrawal(_l2Token, msg.sender, msg.sender, _amount, _l1Gas, _data);
}
/**
* @inheritdoc IL2ERC20Bridge
*/
function withdrawTo(
address _l2Token,
address _to,
uint256 _amount,
uint32 _l1Gas,
bytes calldata _data
) external virtual {
_initiateWithdrawal(_l2Token, msg.sender, _to, _amount, _l1Gas, _data);
}
/**
* @dev Performs the logic for withdrawals by burning the token and informing
* the L1 token Gateway of the withdrawal.
* @param _l2Token Address of L2 token where withdrawal is initiated.
* @param _from Account to pull the withdrawal from on L2.
* @param _to Account to give the withdrawal to on L1.
* @param _amount Amount of the token to withdraw.
* @param _l1Gas Unused, but included for potential forward compatibility considerations.
* @param _data Optional data to forward to L1. This data is provided
* solely as a convenience for external contracts. Aside from enforcing a maximum
* length, these contracts provide no guarantees about its content.
*/
function _initiateWithdrawal(
address _l2Token,
address _from,
address _to,
uint256 _amount,
uint32 _l1Gas,
bytes calldata _data
) internal {
// When a withdrawal is initiated, we burn the withdrawer's funds to prevent subsequent L2
// usage
// slither-disable-next-line reentrancy-events
IL2StandardERC20(_l2Token).burn(msg.sender, _amount);
// Construct calldata for l1TokenBridge.finalizeERC20Withdrawal(_to, _amount)
// slither-disable-next-line reentrancy-events
address l1Token = IL2StandardERC20(_l2Token).l1Token();
bytes memory message;
if (_l2Token == Lib_PredeployAddresses.OVM_ETH) {
message = abi.encodeWithSelector(
IL1StandardBridge.finalizeETHWithdrawal.selector,
_from,
_to,
_amount,
_data
);
} else {
message = abi.encodeWithSelector(
IL1ERC20Bridge.finalizeERC20Withdrawal.selector,
l1Token,
_l2Token,
_from,
_to,
_amount,
_data
);
}
// Send message up to L1 bridge
// slither-disable-next-line reentrancy-events
sendCrossDomainMessage(l1TokenBridge, _l1Gas, message);
// slither-disable-next-line reentrancy-events
emit WithdrawalInitiated(l1Token, _l2Token, msg.sender, _to, _amount, _data);
}
/************************************
* Cross-chain Function: Depositing *
************************************/
/**
* @inheritdoc IL2ERC20Bridge
*/
function finalizeDeposit(
address _l1Token,
address _l2Token,
address _from,
address _to,
uint256 _amount,
bytes calldata _data
) external virtual onlyFromCrossDomainAccount(l1TokenBridge) {
// Check the target token is compliant and
// verify the deposited token on L1 matches the L2 deposited token representation here
if (
// slither-disable-next-line reentrancy-events
ERC165Checker.supportsInterface(_l2Token, 0x1d1d8b63) &&
_l1Token == IL2StandardERC20(_l2Token).l1Token()
) {
// When a deposit is finalized, we credit the account on L2 with the same amount of
// tokens.
// slither-disable-next-line reentrancy-events
IL2StandardERC20(_l2Token).mint(_to, _amount);
// slither-disable-next-line reentrancy-events
emit DepositFinalized(_l1Token, _l2Token, _from, _to, _amount, _data);
} else {
// Either the L2 token which is being deposited-into disagrees about the correct address
// of its L1 token, or does not support the correct interface.
// This should only happen if there is a malicious L2 token, or if a user somehow
// specified the wrong L2 token address to deposit into.
// In either case, we stop the process here and construct a withdrawal
// message so that users can get their funds out in some cases.
// There is no way to prevent malicious token contracts altogether, but this does limit
// user error and mitigate some forms of malicious contract behavior.
bytes memory message = abi.encodeWithSelector(
IL1ERC20Bridge.finalizeERC20Withdrawal.selector,
_l1Token,
_l2Token,
_to, // switched the _to and _from here to bounce back the deposit to the sender
_from,
_amount,
_data
);
// Send message up to L1 bridge
// slither-disable-next-line reentrancy-events
sendCrossDomainMessage(l1TokenBridge, 0, message);
// slither-disable-next-line reentrancy-events
emit DepositFailed(_l1Token, _l2Token, _from, _to, _amount, _data);
}
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/* Contract Imports */
import { L2StandardERC20 } from "../../standards/L2StandardERC20.sol";
import { Lib_PredeployAddresses } from "../../libraries/constants/Lib_PredeployAddresses.sol";
/**
* @title L2StandardTokenFactory
* @dev Factory contract for creating standard L2 token representations of L1 ERC20s
* compatible with and working on the standard bridge.
*/
contract L2StandardTokenFactory {
event StandardL2TokenCreated(address indexed _l1Token, address indexed _l2Token);
/**
* @dev Creates an instance of the standard ERC20 token on L2.
* @param _l1Token Address of the corresponding L1 token.
* @param _name ERC20 name.
* @param _symbol ERC20 symbol.
*/
function createStandardL2Token(
address _l1Token,
string memory _name,
string memory _symbol
) external {
require(_l1Token != address(0), "Must provide L1 token address");
L2StandardERC20 l2Token = new L2StandardERC20(
Lib_PredeployAddresses.L2_STANDARD_BRIDGE,
_l1Token,
_name,
_symbol
);
emit StandardL2TokenCreated(_l1Token, address(l2Token));
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/**
* @title OVM_DeployerWhitelist
* @dev The Deployer Whitelist is a temporary predeploy used to provide additional safety during the
* initial phases of our mainnet roll out. It is owned by the Optimism team, and defines accounts
* which are allowed to deploy contracts on Layer2. The Execution Manager will only allow an
* ovmCREATE or ovmCREATE2 operation to proceed if the deployer's address whitelisted.
*/
contract OVM_DeployerWhitelist {
/**********
* Events *
**********/
event OwnerChanged(address oldOwner, address newOwner);
event WhitelistStatusChanged(address deployer, bool whitelisted);
event WhitelistDisabled(address oldOwner);
/**********************
* Contract Constants *
**********************/
// WARNING: When owner is set to address(0), the whitelist is disabled.
address public owner;
mapping(address => bool) public whitelist;
/**********************
* Function Modifiers *
**********************/
/**
* Blocks functions to anyone except the contract owner.
*/
modifier onlyOwner() {
require(msg.sender == owner, "Function can only be called by the owner of this contract.");
_;
}
/********************
* Public Functions *
********************/
/**
* Adds or removes an address from the deployment whitelist.
* @param _deployer Address to update permissions for.
* @param _isWhitelisted Whether or not the address is whitelisted.
*/
function setWhitelistedDeployer(address _deployer, bool _isWhitelisted) external onlyOwner {
whitelist[_deployer] = _isWhitelisted;
emit WhitelistStatusChanged(_deployer, _isWhitelisted);
}
/**
* Updates the owner of this contract.
* @param _owner Address of the new owner.
*/
// slither-disable-next-line external-function
function setOwner(address _owner) public onlyOwner {
// Prevent users from setting the whitelist owner to address(0) except via
// enableArbitraryContractDeployment. If you want to burn the whitelist owner, send it to
// any other address that doesn't have a corresponding knowable private key.
require(
_owner != address(0),
"OVM_DeployerWhitelist: can only be disabled via enableArbitraryContractDeployment"
);
emit OwnerChanged(owner, _owner);
owner = _owner;
}
/**
* Permanently enables arbitrary contract deployment and deletes the owner.
*/
function enableArbitraryContractDeployment() external onlyOwner {
emit WhitelistDisabled(owner);
owner = address(0);
}
/**
* Checks whether an address is allowed to deploy contracts.
* @param _deployer Address to check.
* @return _allowed Whether or not the address can deploy contracts.
*/
function isDeployerAllowed(address _deployer) external view returns (bool) {
return (owner == address(0) || whitelist[_deployer]);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/* Library Imports */
import { Lib_PredeployAddresses } from "../../libraries/constants/Lib_PredeployAddresses.sol";
/* Contract Imports */
import { L2StandardERC20 } from "../../standards/L2StandardERC20.sol";
/**
* @title OVM_ETH
* @dev The ETH predeploy provides an ERC20 interface for ETH deposited to Layer 2. Note that
* unlike on Layer 1, Layer 2 accounts do not have a balance field.
*/
contract OVM_ETH is L2StandardERC20 {
/***************
* Constructor *
***************/
constructor()
L2StandardERC20(Lib_PredeployAddresses.L2_STANDARD_BRIDGE, address(0), "Ether", "ETH")
{}
// ETH ERC20 features are disabled until further notice.
// Discussion here: https://github.com/ethereum-optimism/optimism/discussions/1444
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
revert("OVM_ETH: transfer is disabled pending further community discussion.");
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
revert("OVM_ETH: approve is disabled pending further community discussion.");
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public virtual override returns (bool) {
revert("OVM_ETH: transferFrom is disabled pending further community discussion.");
}
function increaseAllowance(address spender, uint256 addedValue)
public
virtual
override
returns (bool)
{
revert("OVM_ETH: increaseAllowance is disabled pending further community discussion.");
}
function decreaseAllowance(address spender, uint256 subtractedValue)
public
virtual
override
returns (bool)
{
revert("OVM_ETH: decreaseAllowance is disabled pending further community discussion.");
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/* External Imports */
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
/**
* @title OVM_GasPriceOracle
* @dev This contract exposes the current l2 gas price, a measure of how congested the network
* currently is. This measure is used by the Sequencer to determine what fee to charge for
* transactions. When the system is more congested, the l2 gas price will increase and fees
* will also increase as a result.
*
* All public variables are set while generating the initial L2 state. The
* constructor doesn't run in practice as the L2 state generation script uses
* the deployed bytecode instead of running the initcode.
*/
contract OVM_GasPriceOracle is Ownable {
/*************
* Variables *
*************/
// Current L2 gas price
uint256 public gasPrice;
// Current L1 base fee
uint256 public l1BaseFee;
// Amortized cost of batch submission per transaction
uint256 public overhead;
// Value to scale the fee up by
uint256 public scalar;
// Number of decimals of the scalar
uint256 public decimals;
/***************
* Constructor *
***************/
/**
* @param _owner Address that will initially own this contract.
*/
constructor(address _owner) Ownable() {
transferOwnership(_owner);
}
/**********
* Events *
**********/
event GasPriceUpdated(uint256);
event L1BaseFeeUpdated(uint256);
event OverheadUpdated(uint256);
event ScalarUpdated(uint256);
event DecimalsUpdated(uint256);
/********************
* Public Functions *
********************/
/**
* Allows the owner to modify the l2 gas price.
* @param _gasPrice New l2 gas price.
*/
// slither-disable-next-line external-function
function setGasPrice(uint256 _gasPrice) public onlyOwner {
gasPrice = _gasPrice;
emit GasPriceUpdated(_gasPrice);
}
/**
* Allows the owner to modify the l1 base fee.
* @param _baseFee New l1 base fee
*/
// slither-disable-next-line external-function
function setL1BaseFee(uint256 _baseFee) public onlyOwner {
l1BaseFee = _baseFee;
emit L1BaseFeeUpdated(_baseFee);
}
/**
* Allows the owner to modify the overhead.
* @param _overhead New overhead
*/
// slither-disable-next-line external-function
function setOverhead(uint256 _overhead) public onlyOwner {
overhead = _overhead;
emit OverheadUpdated(_overhead);
}
/**
* Allows the owner to modify the scalar.
* @param _scalar New scalar
*/
// slither-disable-next-line external-function
function setScalar(uint256 _scalar) public onlyOwner {
scalar = _scalar;
emit ScalarUpdated(_scalar);
}
/**
* Allows the owner to modify the decimals.
* @param _decimals New decimals
*/
// slither-disable-next-line external-function
function setDecimals(uint256 _decimals) public onlyOwner {
decimals = _decimals;
emit DecimalsUpdated(_decimals);
}
/**
* Computes the L1 portion of the fee
* based on the size of the RLP encoded tx
* and the current l1BaseFee
* @param _data Unsigned RLP encoded tx, 6 elements
* @return L1 fee that should be paid for the tx
*/
// slither-disable-next-line external-function
function getL1Fee(bytes memory _data) public view returns (uint256) {
uint256 l1GasUsed = getL1GasUsed(_data);
uint256 l1Fee = l1GasUsed * l1BaseFee;
uint256 divisor = 10**decimals;
uint256 unscaled = l1Fee * scalar;
uint256 scaled = unscaled / divisor;
return scaled;
}
// solhint-disable max-line-length
/**
* Computes the amount of L1 gas used for a transaction
* The overhead represents the per batch gas overhead of
* posting both transaction and state roots to L1 given larger
* batch sizes.
* 4 gas for 0 byte
* https://github.com/ethereum/go-ethereum/blob/9ada4a2e2c415e6b0b51c50e901336872e028872/params/protocol_params.go#L33
* 16 gas for non zero byte
* https://github.com/ethereum/go-ethereum/blob/9ada4a2e2c415e6b0b51c50e901336872e028872/params/protocol_params.go#L87
* This will need to be updated if calldata gas prices change
* Account for the transaction being unsigned
* Padding is added to account for lack of signature on transaction
* 1 byte for RLP V prefix
* 1 byte for V
* 1 byte for RLP R prefix
* 32 bytes for R
* 1 byte for RLP S prefix
* 32 bytes for S
* Total: 68 bytes of padding
* @param _data Unsigned RLP encoded tx, 6 elements
* @return Amount of L1 gas used for a transaction
*/
// solhint-enable max-line-length
function getL1GasUsed(bytes memory _data) public view returns (uint256) {
uint256 total = 0;
for (uint256 i = 0; i < _data.length; i++) {
if (_data[i] == 0) {
total += 4;
} else {
total += 16;
}
}
uint256 unsigned = total + overhead;
return unsigned + (68 * 16);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/* Interface Imports */
import { iOVM_L2ToL1MessagePasser } from "./iOVM_L2ToL1MessagePasser.sol";
/**
* @title OVM_L2ToL1MessagePasser
* @dev The L2 to L1 Message Passer is a utility contract which facilitate an L1 proof of the
* of a message on L2. The L1 Cross Domain Messenger performs this proof in its
* _verifyStorageProof function, which verifies the existence of the transaction hash in this
* contract's `sentMessages` mapping.
*/
contract OVM_L2ToL1MessagePasser is iOVM_L2ToL1MessagePasser {
/**********************
* Contract Variables *
**********************/
mapping(bytes32 => bool) public sentMessages;
/********************
* Public Functions *
********************/
/**
* @inheritdoc iOVM_L2ToL1MessagePasser
*/
// slither-disable-next-line external-function
function passMessageToL1(bytes memory _message) public {
// Note: although this function is public, only messages sent from the
// L2CrossDomainMessenger will be relayed by the L1CrossDomainMessenger.
// This is enforced by a check in L1CrossDomainMessenger._verifyStorageProof().
sentMessages[keccak256(abi.encodePacked(_message, msg.sender))] = true;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/* Library Imports */
import { Lib_PredeployAddresses } from "../../libraries/constants/Lib_PredeployAddresses.sol";
/* Contract Imports */
import { L2StandardBridge } from "../messaging/L2StandardBridge.sol";
/**
* @title OVM_SequencerFeeVault
* @dev Simple holding contract for fees paid to the Sequencer. Likely to be replaced in the future
* but "good enough for now".
*/
contract OVM_SequencerFeeVault {
/*************
* Constants *
*************/
// Minimum ETH balance that can be withdrawn in a single withdrawal.
uint256 public constant MIN_WITHDRAWAL_AMOUNT = 15 ether;
/*************
* Variables *
*************/
// Address on L1 that will hold the fees once withdrawn. Dynamically initialized within l2geth.
address public l1FeeWallet;
/***************
* Constructor *
***************/
/**
* @param _l1FeeWallet Initial address for the L1 wallet that will hold fees once withdrawn.
* Currently HAS NO EFFECT in production because l2geth will mutate this storage slot during
* the genesis block. This is ONLY for testing purposes.
*/
constructor(address _l1FeeWallet) {
l1FeeWallet = _l1FeeWallet;
}
/************
* Fallback *
************/
// slither-disable-next-line locked-ether
receive() external payable {}
/********************
* Public Functions *
********************/
// slither-disable-next-line external-function
function withdraw() public {
require(
address(this).balance >= MIN_WITHDRAWAL_AMOUNT,
// solhint-disable-next-line max-line-length
"OVM_SequencerFeeVault: withdrawal amount must be greater than minimum withdrawal amount"
);
L2StandardBridge(Lib_PredeployAddresses.L2_STANDARD_BRIDGE).withdrawTo(
Lib_PredeployAddresses.OVM_ETH,
l1FeeWallet,
address(this).balance,
0,
bytes("")
);
}
}
This diff is collapsed.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/**
* @title iOVM_L1BlockNumber
*/
interface iOVM_L1BlockNumber {
/********************
* Public Functions *
********************/
/**
* @return Block number of L1
*/
function getL1BlockNumber() external view returns (uint256);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/**
* @title iOVM_L2ToL1MessagePasser
*/
interface iOVM_L2ToL1MessagePasser {
/**********
* Events *
**********/
event L2ToL1Message(uint256 _nonce, address _sender, bytes _data);
/********************
* Public Functions *
********************/
/**
* Passes a message to L1.
* @param _message Message to pass to L1.
*/
function passMessageToL1(bytes calldata _message) external;
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/**
* @title iL1ChugSplashDeployer
*/
interface iL1ChugSplashDeployer {
function isUpgrading() external view returns (bool);
}
// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.9.0;
/* Interface Imports */
import { ICrossDomainMessenger } from "./ICrossDomainMessenger.sol";
/**
* @title CrossDomainEnabled
* @dev Helper contract for contracts performing cross-domain communications
*
* Compiler used: defined by inheriting contract
*/
contract CrossDomainEnabled {
/*************
* Variables *
*************/
// Messenger contract used to send and recieve messages from the other domain.
address public messenger;
/***************
* Constructor *
***************/
/**
* @param _messenger Address of the CrossDomainMessenger on the current layer.
*/
constructor(address _messenger) {
messenger = _messenger;
}
/**********************
* Function Modifiers *
**********************/
/**
* Enforces that the modified function is only callable by a specific cross-domain account.
* @param _sourceDomainAccount The only account on the originating domain which is
* authenticated to call this function.
*/
modifier onlyFromCrossDomainAccount(address _sourceDomainAccount) {
require(
msg.sender == address(getCrossDomainMessenger()),
"OVM_XCHAIN: messenger contract unauthenticated"
);
require(
getCrossDomainMessenger().xDomainMessageSender() == _sourceDomainAccount,
"OVM_XCHAIN: wrong sender of cross-domain message"
);
_;
}
/**********************
* Internal Functions *
**********************/
/**
* Gets the messenger, usually from storage. This function is exposed in case a child contract
* needs to override.
* @return The address of the cross-domain messenger contract which should be used.
*/
function getCrossDomainMessenger() internal virtual returns (ICrossDomainMessenger) {
return ICrossDomainMessenger(messenger);
}
/**q
* Sends a message to an account on another domain
* @param _crossDomainTarget The intended recipient on the destination domain
* @param _message The data to send to the target (usually calldata to a function with
* `onlyFromCrossDomainAccount()`)
* @param _gasLimit The gasLimit for the receipt of the message on the target domain.
*/
function sendCrossDomainMessage(
address _crossDomainTarget,
uint32 _gasLimit,
bytes memory _message
) internal {
// slither-disable-next-line reentrancy-events, reentrancy-benign
getCrossDomainMessenger().sendMessage(_crossDomainTarget, _message, _gasLimit);
}
}
// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.9.0;
/**
* @title ICrossDomainMessenger
*/
interface ICrossDomainMessenger {
/**********
* Events *
**********/
event SentMessage(
address indexed target,
address sender,
bytes message,
uint256 messageNonce,
uint256 gasLimit
);
event RelayedMessage(bytes32 indexed msgHash);
event FailedRelayedMessage(bytes32 indexed msgHash);
/*************
* Variables *
*************/
function xDomainMessageSender() external view returns (address);
/********************
* Public Functions *
********************/
/**
* Sends a cross domain message to the target messenger.
* @param _target Target contract address.
* @param _message Message to send to the target.
* @param _gasLimit Gas limit for the provided message.
*/
function sendMessage(
address _target,
bytes calldata _message,
uint32 _gasLimit
) external;
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/**
* @title Lib_CrossDomainUtils
*/
library Lib_CrossDomainUtils {
/**
* Generates the correct cross domain calldata for a message.
* @param _target Target contract address.
* @param _sender Message sender address.
* @param _message Message to send to the target.
* @param _messageNonce Nonce for the provided message.
* @return ABI encoded cross domain calldata.
*/
function encodeXDomainCalldata(
address _target,
address _sender,
bytes memory _message,
uint256 _messageNonce
) internal pure returns (bytes memory) {
return
abi.encodeWithSignature(
"relayMessage(address,address,bytes,uint256)",
_target,
_sender,
_message,
_messageNonce
);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/**
* @title Lib_DefaultValues
*/
library Lib_DefaultValues {
// The default x-domain message sender being set to a non-zero value makes
// deployment a bit more expensive, but in exchange the refund on every call to
// `relayMessage` by the L1 and L2 messengers will be higher.
address internal constant DEFAULT_XDOMAIN_SENDER = 0x000000000000000000000000000000000000dEaD;
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/**
* @title Lib_PredeployAddresses
*/
library Lib_PredeployAddresses {
address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000000;
address internal constant L1_MESSAGE_SENDER = 0x4200000000000000000000000000000000000001;
address internal constant DEPLOYER_WHITELIST = 0x4200000000000000000000000000000000000002;
address payable internal constant OVM_ETH = payable(0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000);
address internal constant L2_CROSS_DOMAIN_MESSENGER =
0x4200000000000000000000000000000000000007;
address internal constant LIB_ADDRESS_MANAGER = 0x4200000000000000000000000000000000000008;
address internal constant PROXY_EOA = 0x4200000000000000000000000000000000000009;
address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000010;
address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011;
address internal constant L2_STANDARD_TOKEN_FACTORY =
0x4200000000000000000000000000000000000012;
address internal constant L1_BLOCK_NUMBER = 0x4200000000000000000000000000000000000013;
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/* Library Imports */
import { Lib_AddressManager } from "./Lib_AddressManager.sol";
/**
* @title Lib_AddressResolver
*/
abstract contract Lib_AddressResolver {
/*************
* Variables *
*************/
Lib_AddressManager public libAddressManager;
/***************
* Constructor *
***************/
/**
* @param _libAddressManager Address of the Lib_AddressManager.
*/
constructor(address _libAddressManager) {
libAddressManager = Lib_AddressManager(_libAddressManager);
}
/********************
* Public Functions *
********************/
/**
* Resolves the address associated with a given name.
* @param _name Name to resolve an address for.
* @return Address associated with the given name.
*/
function resolve(string memory _name) public view returns (address) {
return libAddressManager.getAddress(_name);
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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