Commit df13211c authored by Liam Horne's avatar Liam Horne Committed by GitHub

Merge pull request #1217 from ethereum-optimism/develop

Merge develop into master
parents 0ad9adbc dfa256d8
---
'@eth-optimism/data-transport-layer': patch
---
Allow the L1 gas price to be fetched from either the sequencer or a L1 provider based on the config `--l1-gas-price-backend` as well as overriding the config by using a query param. Valid values are `l1` or `l2` and it defaults to `l1`
---
'@eth-optimism/core-utils': minor
'@eth-optimism/data-transport-layer': patch
---
removed unused functions from core-utils
......@@ -134,5 +134,9 @@ jobs:
# if: steps.yarn-cache.outputs.cache-hit != 'true'
run: yarn install
- name: Lint
- name: Lint JS and TS
run: yarn lint:check
- name: Lint Solidity
working-directory: ./packages/contracts
run: yarn lint:contracts
......@@ -6,7 +6,7 @@ export const FORCE_INCLUSION_PERIOD_SECONDS = 600
export const DEFAULT_ACCOUNTS = defaultAccounts
export const DEFAULT_ACCOUNTS_HARDHAT = defaultAccounts.map((account) => {
return {
balance: ethers.BigNumber.from(account.balance).toHexString(),
balance: account.balance,
privateKey: account.secretKey,
}
})
......
{
"extends": "solhint:recommended",
"plugins": [],
"rules": {
"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"
}
}
......@@ -11,14 +11,19 @@ import { Lib_PredeployAddresses } from "../../../libraries/constants/Lib_Predepl
import { Lib_CrossDomainUtils } from "../../../libraries/bridge/Lib_CrossDomainUtils.sol";
/* Interface Imports */
import { iOVM_L1CrossDomainMessenger } from "../../../iOVM/bridge/messaging/iOVM_L1CrossDomainMessenger.sol";
import { iOVM_CanonicalTransactionChain } from "../../../iOVM/chain/iOVM_CanonicalTransactionChain.sol";
import { iOVM_L1CrossDomainMessenger } from
"../../../iOVM/bridge/messaging/iOVM_L1CrossDomainMessenger.sol";
import { iOVM_CanonicalTransactionChain } from
"../../../iOVM/chain/iOVM_CanonicalTransactionChain.sol";
import { iOVM_StateCommitmentChain } from "../../../iOVM/chain/iOVM_StateCommitmentChain.sol";
/* External Imports */
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { PausableUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol";
import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
import { OwnableUpgradeable } from
"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { PausableUpgradeable } from
"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol";
import { ReentrancyGuardUpgradeable } from
"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
/**
* @title OVM_L1CrossDomainMessenger
......@@ -194,7 +199,8 @@ contract OVM_L1CrossDomainMessenger is
{
address ovmCanonicalTransactionChain = resolve("OVM_CanonicalTransactionChain");
// Use the CTC queue length as nonce
uint40 nonce = iOVM_CanonicalTransactionChain(ovmCanonicalTransactionChain).getQueueLength();
uint40 nonce =
iOVM_CanonicalTransactionChain(ovmCanonicalTransactionChain).getQueueLength();
bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata(
_target,
......@@ -204,7 +210,12 @@ contract OVM_L1CrossDomainMessenger is
);
address l2CrossDomainMessenger = resolve("OVM_L2CrossDomainMessenger");
_sendXDomainMessage(ovmCanonicalTransactionChain, l2CrossDomainMessenger, xDomainCalldata, _gasLimit);
_sendXDomainMessage(
ovmCanonicalTransactionChain,
l2CrossDomainMessenger,
xDomainCalldata,
_gasLimit
);
emit SentMessage(xDomainCalldata);
}
......@@ -298,7 +309,8 @@ contract OVM_L1CrossDomainMessenger is
{
// Verify that the message is in the queue:
address canonicalTransactionChain = resolve("OVM_CanonicalTransactionChain");
Lib_OVMCodec.QueueElement memory element = iOVM_CanonicalTransactionChain(canonicalTransactionChain).getQueueElement(_queueIndex);
Lib_OVMCodec.QueueElement memory element =
iOVM_CanonicalTransactionChain(canonicalTransactionChain).getQueueElement(_queueIndex);
address l2CrossDomainMessenger = resolve("OVM_L2CrossDomainMessenger");
// Compute the transactionHash
......@@ -323,7 +335,12 @@ contract OVM_L1CrossDomainMessenger is
_queueIndex
);
_sendXDomainMessage(canonicalTransactionChain, l2CrossDomainMessenger, xDomainCalldata, _gasLimit);
_sendXDomainMessage(
canonicalTransactionChain,
l2CrossDomainMessenger,
xDomainCalldata,
_gasLimit
);
}
......
......@@ -4,8 +4,10 @@ pragma solidity >0.5.0 <0.8.0;
pragma experimental ABIEncoderV2;
/* Interface Imports */
import { iOVM_L1CrossDomainMessenger } from "../../../iOVM/bridge/messaging/iOVM_L1CrossDomainMessenger.sol";
import { iOVM_L1MultiMessageRelayer } from "../../../iOVM/bridge/messaging/iOVM_L1MultiMessageRelayer.sol";
import { iOVM_L1CrossDomainMessenger } from
"../../../iOVM/bridge/messaging/iOVM_L1CrossDomainMessenger.sol";
import { iOVM_L1MultiMessageRelayer } from
"../../../iOVM/bridge/messaging/iOVM_L1MultiMessageRelayer.sol";
/* Library Imports */
import { Lib_AddressResolver } from "../../../libraries/resolver/Lib_AddressResolver.sol";
......@@ -42,6 +44,7 @@ contract OVM_L1MultiMessageRelayer is iOVM_L1MultiMessageRelayer, Lib_AddressRes
modifier onlyBatchRelayer() {
require(
msg.sender == resolve("OVM_L2BatchMessageRelayer"),
// solhint-disable-next-line max-line-length
"OVM_L1MultiMessageRelayer: Function can only be called by the OVM_L2BatchMessageRelayer"
);
_;
......@@ -58,7 +61,7 @@ contract OVM_L1MultiMessageRelayer is iOVM_L1MultiMessageRelayer, Lib_AddressRes
*/
function batchRelayMessages(
L2ToL1Message[] calldata _messages
)
)
override
external
onlyBatchRelayer
......
......@@ -7,7 +7,8 @@ import { Lib_AddressResolver } from "../../../libraries/resolver/Lib_AddressReso
import { Lib_CrossDomainUtils } from "../../../libraries/bridge/Lib_CrossDomainUtils.sol";
/* Interface Imports */
import { iOVM_L2CrossDomainMessenger } from "../../../iOVM/bridge/messaging/iOVM_L2CrossDomainMessenger.sol";
import { iOVM_L2CrossDomainMessenger } from
"../../../iOVM/bridge/messaging/iOVM_L2CrossDomainMessenger.sol";
import { iOVM_L1MessageSender } from "../../../iOVM/predeploys/iOVM_L1MessageSender.sol";
import { iOVM_L2ToL1MessagePasser } from "../../../iOVM/predeploys/iOVM_L2ToL1MessagePasser.sol";
......@@ -57,8 +58,10 @@ contract OVM_L2CrossDomainMessenger is
/**
* @param _libAddressManager Address of the Address Manager.
*/
constructor(address _libAddressManager) Lib_AddressResolver(_libAddressManager) ReentrancyGuard() {}
constructor(address _libAddressManager)
Lib_AddressResolver(_libAddressManager)
ReentrancyGuard()
{}
/********************
* Public Functions *
......
......@@ -18,8 +18,9 @@ import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
/**
* @title OVM_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.
* @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.
*
* Compiler used: solc
* Runtime target: EVM
......@@ -69,7 +70,9 @@ contract OVM_L1StandardBridge is iOVM_L1StandardBridge, OVM_CrossDomainEnabled {
* 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.
/** @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");
......@@ -136,7 +139,8 @@ contract OVM_L1StandardBridge is iOVM_L1StandardBridge, OVM_CrossDomainEnabled {
}
/**
* @dev Performs the logic for deposits by storing the ETH and informing the L2 ETH Gateway of the deposit.
* @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.
......@@ -235,8 +239,9 @@ contract OVM_L1StandardBridge is iOVM_L1StandardBridge, OVM_CrossDomainEnabled {
)
internal
{
// When a deposit is initiated on L1, the L1 Bridge transfers the funds to itself for future withdrawals.
// safeTransferFrom also checks if the contract has code, so this will fail if _from is an EOA or address(0).
// When a deposit is initiated on L1, the L1 Bridge transfers the funds to itself for future
// withdrawals. safeTransferFrom also checks if the contract has code, so this will fail if
// _from is an EOA or address(0).
IERC20(_l1Token).safeTransferFrom(
_from,
address(this),
......@@ -284,7 +289,7 @@ contract OVM_L1StandardBridge is iOVM_L1StandardBridge, OVM_CrossDomainEnabled {
onlyFromCrossDomainAccount(l2TokenBridge)
{
(bool success, ) = _to.call{value: _amount}(new bytes(0));
require(success, 'TransferHelper::safeTransferETH: ETH transfer failed');
require(success, "TransferHelper::safeTransferETH: ETH transfer failed");
emit ETHWithdrawalFinalized(_from, _to, _amount, _data);
}
......@@ -306,7 +311,7 @@ contract OVM_L1StandardBridge is iOVM_L1StandardBridge, OVM_CrossDomainEnabled {
{
deposits[_l1Token][_l2Token] = deposits[_l1Token][_l2Token].sub(_amount);
// When a withdrawal is finalized on L1, the L1 Bridge transfers the funds to the withdrawer.
// When a withdrawal is finalized on L1, the L1 Bridge transfers the funds to the withdrawer
IERC20(_l1Token).safeTransfer(_to, _amount);
emit ERC20WithdrawalFinalized(_l1Token, _l2Token, _from, _to, _amount, _data);
......@@ -319,7 +324,8 @@ contract OVM_L1StandardBridge is iOVM_L1StandardBridge, OVM_CrossDomainEnabled {
/**
* @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
* 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 {}
}
......@@ -17,10 +17,12 @@ import { IL2StandardERC20 } from "../../../libraries/standards/IL2StandardERC20.
/**
* @title OVM_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.
* @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.
*
* Compiler used: optimistic-solc
* Runtime target: OVM
......@@ -102,7 +104,8 @@ contract OVM_L2StandardBridge is iOVM_L2ERC20Bridge, OVM_CrossDomainEnabled {
}
/**
* @dev Performs the logic for deposits by storing the token and informing the L2 token Gateway of the deposit.
* @dev Performs the logic for deposits by storing the token and informing the L2 token Gateway
* of the deposit.
* @param _l2Token Address of L2 token where withdrawal was initiated.
* @param _from Account to pull the deposit from on L2.
* @param _to Account to give the withdrawal to on L1.
......@@ -122,7 +125,8 @@ contract OVM_L2StandardBridge is iOVM_L2ERC20Bridge, OVM_CrossDomainEnabled {
)
internal
{
// When a withdrawal is initiated, we burn the withdrawer's funds to prevent subsequent L2 usage
// When a withdrawal is initiated, we burn the withdrawer's funds to prevent subsequent L2
// usage
IL2StandardERC20(_l2Token).burn(msg.sender, _amount);
// Construct calldata for l1TokenBridge.finalizeERC20Withdrawal(_to, _amount)
......@@ -185,7 +189,8 @@ contract OVM_L2StandardBridge is iOVM_L2ERC20Bridge, OVM_CrossDomainEnabled {
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.
// When a deposit is finalized, we credit the account on L2 with the same amount of
// tokens.
IL2StandardERC20(_l2Token).mint(_to, _amount);
emit DepositFinalized(_l1Token, _l2Token, _from, _to, _amount, _data);
} else {
......
......@@ -10,10 +10,10 @@ import { iOVM_ChainStorageContainer } from "../../iOVM/chain/iOVM_ChainStorageCo
/**
* @title OVM_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.
* @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
......
......@@ -10,12 +10,13 @@ import { Lib_MerkleTree } from "../../libraries/utils/Lib_MerkleTree.sol";
/* Interface Imports */
import { iOVM_FraudVerifier } from "../../iOVM/verification/iOVM_FraudVerifier.sol";
import { iOVM_StateCommitmentChain } from "../../iOVM/chain/iOVM_StateCommitmentChain.sol";
import { iOVM_CanonicalTransactionChain } from "../../iOVM/chain/iOVM_CanonicalTransactionChain.sol";
import { iOVM_CanonicalTransactionChain } from
"../../iOVM/chain/iOVM_CanonicalTransactionChain.sol";
import { iOVM_BondManager } from "../../iOVM/verification/iOVM_BondManager.sol";
import { iOVM_ChainStorageContainer } from "../../iOVM/chain/iOVM_ChainStorageContainer.sol";
/* External Imports */
import '@openzeppelin/contracts/math/SafeMath.sol';
import "@openzeppelin/contracts/math/SafeMath.sol";
/**
* @title OVM_StateCommitmentChain
......@@ -149,7 +150,9 @@ contract OVM_StateCommitmentChain is iOVM_StateCommitmentChain, Lib_AddressResol
);
require(
getTotalElements() + _batch.length <= iOVM_CanonicalTransactionChain(resolve("OVM_CanonicalTransactionChain")).getTotalElements(),
getTotalElements() + _batch.length <=
iOVM_CanonicalTransactionChain(resolve("OVM_CanonicalTransactionChain"))
.getTotalElements(),
"Number of state roots cannot exceed the number of canonical transactions."
);
......@@ -267,6 +270,7 @@ contract OVM_StateCommitmentChain is iOVM_StateCommitmentChain, Lib_AddressResol
{
bytes27 extraData = batches().getGlobalMetadata();
// solhint-disable max-line-length
uint40 totalElements;
uint40 lastSequencerTimestamp;
assembly {
......@@ -274,6 +278,7 @@ contract OVM_StateCommitmentChain is iOVM_StateCommitmentChain, Lib_AddressResol
totalElements := and(extraData, 0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF)
lastSequencerTimestamp := shr(40, and(extraData, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000))
}
// solhint-enable max-line-length
return (
totalElements,
......
......@@ -51,8 +51,10 @@ contract OVM_SafetyChecker is iOVM_SafetyChecker {
uint256(0x0000000000000000000000000000000000000000000000000000000000000000)
];
// Mask to gate opcode specific cases
// solhint-disable-next-line max-line-length
uint256 opcodeGateMask = ~uint256(0xffffffffffffffffffffffe000000000fffffffff070ffff9c0ffffec000f001);
// Halting opcodes
// solhint-disable-next-line max-line-length
uint256 opcodeHaltingMask = ~uint256(0x4008000000000000000000000000000000000000004000000000000000000001);
// PUSH opcodes
uint256 opcodePushMask = ~uint256(0xffffffff000000000000000000000000);
......@@ -67,6 +69,7 @@ contract OVM_SafetyChecker is iOVM_SafetyChecker {
// current opcode: 0x00...0xff
uint256 opNum;
/* solhint-disable max-line-length */
// inline assembly removes the extra add + bounds check
assembly {
let word := mload(_pc) //load the next 32 bytes at pc into word
......@@ -86,6 +89,7 @@ contract OVM_SafetyChecker is iOVM_SafetyChecker {
opNum := byte(indexInWord, word)
}
/* solhint-enable max-line-length */
// + push opcodes
// + stop opcodes [STOP(0x00),JUMP(0x56),RETURN(0xf3),INVALID(0xfe)]
......@@ -96,11 +100,12 @@ contract OVM_SafetyChecker is iOVM_SafetyChecker {
if (opBit & opcodePushMask == 0) {
// all pushes are valid opcodes
// subsequent bytes are not opcodes. Skip them.
_pc += (opNum - 0x5e); // PUSH1 is 0x60, so opNum-0x5f = PUSHed bytes and we +1 to
// skip the _pc++; line below in order to save gas ((-0x5f + 1) = -0x5e)
_pc += (opNum - 0x5e); // PUSH1 is 0x60, so opNum-0x5f = PUSHed bytes and we
// +1 to skip the _pc++; line below in order to save gas ((-0x5f + 1) = -0x5e)
continue;
} else if (opBit & opcodeHaltingMask == 0) {
// STOP or JUMP or RETURN or INVALID (Note: REVERT is blacklisted, so not included here)
// STOP or JUMP or RETURN or INVALID (Note: REVERT is blacklisted, so not
// included here)
// We are now inside unreachable code until we hit a JUMPDEST!
do {
_pc++;
......@@ -110,7 +115,8 @@ contract OVM_SafetyChecker is iOVM_SafetyChecker {
// encountered a JUMPDEST
if (opNum == 0x5b) break;
// skip PUSHed bytes
if ((1 << opNum) & opcodePushMask == 0) _pc += (opNum - 0x5f); // opNum-0x5f = PUSHed bytes (PUSH1 is 0x60)
// opNum-0x5f = PUSHed bytes (PUSH1 is 0x60)
if ((1 << opNum) & opcodePushMask == 0) _pc += (opNum - 0x5f);
} while (_pc < codeLength);
// opNum is 0x5b, so we don't continue here since the pc++ is fine
} else if (opNum == 0x33) { // Caller opcode
......@@ -129,7 +135,11 @@ contract OVM_SafetyChecker is iOVM_SafetyChecker {
if ((firstOps >> 192) == 0x3350600060045af1) {
_pc += 8;
// Call EM and abort execution if instructed
// CALLER PUSH1 0x00 SWAP1 GAS CALL PC PUSH1 0x0E ADD JUMPI RETURNDATASIZE PUSH1 0x00 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x00 REVERT JUMPDEST RETURNDATASIZE PUSH1 0x01 EQ ISZERO PC PUSH1 0x0a ADD JUMPI PUSH1 0x01 PUSH1 0x00 RETURN JUMPDEST
// CALLER PUSH1 0x00 SWAP1 GAS CALL PC PUSH1 0x0E ADD JUMPI RETURNDATASIZE
// PUSH1 0x00 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x00 REVERT JUMPDEST
// RETURNDATASIZE PUSH1 0x01 EQ ISZERO PC PUSH1 0x0a ADD JUMPI PUSH1 0x01 PUSH1
// 0x00 RETURN JUMPDEST
// solhint-disable-next-line max-line-length
} else if (firstOps == 0x336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760 && secondOps == 0x016000f35b) {
_pc += 37;
} else {
......
......@@ -10,8 +10,9 @@ import { iOVM_StateManager } from "../../iOVM/execution/iOVM_StateManager.sol";
/**
* @title OVM_StateManager
* @dev The State Manager contract holds all storage values for contracts in the OVM. It can only be written to by the
* the Execution Manager and State Transitioner. It runs on L1 during the setup and execution of a fraud proof.
* @dev The State Manager contract holds all storage values for contracts in the OVM. It can only be
* written to by the Execution Manager and State Transitioner. It runs on L1 during the setup and
* execution of a fraud proof.
* The same logic runs on L2, but has been implemented as a precompile in the L2 go-ethereum client
* (see https://github.com/ethereum-optimism/go-ethereum/blob/master/core/vm/ovm_state_manager.go).
*
......@@ -24,10 +25,12 @@ contract OVM_StateManager is iOVM_StateManager {
* Constants *
*************/
bytes32 constant internal EMPTY_ACCOUNT_STORAGE_ROOT = 0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421;
bytes32 constant internal EMPTY_ACCOUNT_CODE_HASH = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
bytes32 constant internal STORAGE_XOR_VALUE = 0xFEEDFACECAFEBEEFFEEDFACECAFEBEEFFEEDFACECAFEBEEFFEEDFACECAFEBEEF;
bytes32 constant internal EMPTY_ACCOUNT_STORAGE_ROOT =
0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421;
bytes32 constant internal EMPTY_ACCOUNT_CODE_HASH =
0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
bytes32 constant internal STORAGE_XOR_VALUE =
0xFEEDFACECAFEBEEFFEEDFACECAFEBEEFFEEDFACECAFEBEEFFEEDFACECAFEBEEF;
/*************
* Variables *
......@@ -42,7 +45,6 @@ contract OVM_StateManager is iOVM_StateManager {
uint256 internal totalUncommittedAccounts;
uint256 internal totalUncommittedContractStorage;
/***************
* Constructor *
***************/
......@@ -57,13 +59,13 @@ contract OVM_StateManager is iOVM_StateManager {
owner = _owner;
}
/**********************
* Function Modifiers *
**********************/
/**
* Simple authentication, this contract should only be accessible to the owner (which is expected to be the State Transitioner during `PRE_EXECUTION`
* Simple authentication, this contract should only be accessible to the owner
* (which is expected to be the State Transitioner during `PRE_EXECUTION`
* or the OVM_ExecutionManager during transaction execution.
*/
modifier authenticated() {
......
......@@ -7,7 +7,8 @@ import { iOVM_ECDSAContractAccount } from "../../iOVM/predeploys/iOVM_ECDSAContr
/* Library Imports */
import { Lib_EIP155Tx } from "../../libraries/codec/Lib_EIP155Tx.sol";
import { Lib_ExecutionManagerWrapper } from "../../libraries/wrappers/Lib_ExecutionManagerWrapper.sol";
import { Lib_ExecutionManagerWrapper } from
"../../libraries/wrappers/Lib_ExecutionManagerWrapper.sol";
import { Lib_PredeployAddresses } from "../../libraries/constants/Lib_PredeployAddresses.sol";
/* Contract Imports */
......@@ -152,9 +153,9 @@ contract OVM_ECDSAContractAccount is iOVM_ECDSAContractAccount {
// cases, but since this is a contract we'd end up bumping the nonce twice.
Lib_ExecutionManagerWrapper.ovmINCREMENTNONCE();
// NOTE: Upgrades are temporarily disabled because users can, in theory, modify their EOA
// so that they don't have to pay any fees to the sequencer. Function will remain disabled
// until a robust solution is in place.
// NOTE: Upgrades are temporarily disabled because users can, in theory, modify their
// EOA so that they don't have to pay any fees to the sequencer. Function will remain
// disabled until a robust solution is in place.
require(
_transaction.to != Lib_ExecutionManagerWrapper.ovmADDRESS(),
"Calls to self are disabled until upgradability is re-enabled."
......
......@@ -41,17 +41,18 @@ contract OVM_ETH is L2StandardERC20, IWETH9 {
/**
* Implements the WETH9 deposit() function as a no-op.
* WARNING: this function does NOT have to do with cross-chain asset bridging. The
* relevant deposit and withdraw functions for that use case can be found at L2StandardBridge.sol.
* This function allows developers to treat OVM_ETH as WETH without any modifications to their code.
* WARNING: this function does NOT have to do with cross-chain asset bridging. The relevant
* deposit and withdraw functions for that use case can be found at L2StandardBridge.sol.
* This function allows developers to treat OVM_ETH as WETH without any modifications to their
* code.
*/
function deposit()
public
payable
override
{
// Calling deposit() with nonzero value will send the ETH to this contract address. Once recieved here,
// We transfer it back by sending to the msg.sender.
// Calling deposit() with nonzero value will send the ETH to this contract address.
// Once received here, we transfer it back by sending to the msg.sender.
_transfer(address(this), msg.sender, msg.value);
emit Deposit(msg.sender, msg.value);
......@@ -59,9 +60,10 @@ contract OVM_ETH is L2StandardERC20, IWETH9 {
/**
* Implements the WETH9 withdraw() function as a no-op.
* WARNING: this function does NOT have to do with cross-chain asset bridging. The
* relevant deposit and withdraw functions for that use case can be found at L2StandardBridge.sol.
* This function allows developers to treat OVM_ETH as WETH without any modifications to their code.
* WARNING: this function does NOT have to do with cross-chain asset bridging. The relevant
* deposit and withdraw functions for that use case can be found at L2StandardBridge.sol.
* This function allows developers to treat OVM_ETH as WETH without any modifications to their
* code.
* @param _wad Amount being withdrawn
*/
function withdraw(
......@@ -70,10 +72,12 @@ contract OVM_ETH is L2StandardERC20, IWETH9 {
external
override
{
// Calling withdraw() with value exceeding the withdrawer's ovmBALANCE should revert, as in WETH9.
// Calling withdraw() with value exceeding the withdrawer's ovmBALANCE should revert,
// as in WETH9.
require(balanceOf(msg.sender) >= _wad);
// Other than emitting an event, OVM_ETH already is native ETH, so we don't need to do anything else.
// Other than emitting an event, OVM_ETH already is native ETH, so we don't need to do
// anything else.
emit Withdrawal(msg.sender, _wad);
}
}
......@@ -36,9 +36,9 @@ contract OVM_L2ToL1MessagePasser is iOVM_L2ToL1MessagePasser {
override
public
{
// Note: although this function is public, only messages sent from the OVM_L2CrossDomainMessenger
// will be relayed by the OVM_L1CrossDomainMessenger. This is enforced by a check in
// OVM_L1CrossDomainMessenger._verifyStorageProof().
// Note: although this function is public, only messages sent from the
// OVM_L2CrossDomainMessenger will be relayed by the OVM_L1CrossDomainMessenger.
// This is enforced by a check in OVM_L1CrossDomainMessenger._verifyStorageProof().
sentMessages[keccak256(
abi.encodePacked(
_message,
......
......@@ -4,13 +4,14 @@ pragma solidity >0.5.0 <0.8.0;
/* Library Imports */
import { Lib_Bytes32Utils } from "../../libraries/utils/Lib_Bytes32Utils.sol";
import { Lib_PredeployAddresses } from "../../libraries/constants/Lib_PredeployAddresses.sol";
import { Lib_ExecutionManagerWrapper } from "../../libraries/wrappers/Lib_ExecutionManagerWrapper.sol";
import { Lib_ExecutionManagerWrapper } from
"../../libraries/wrappers/Lib_ExecutionManagerWrapper.sol";
/**
* @title OVM_ProxyEOA
* @dev The Proxy EOA contract uses a delegate call to execute the logic in an implementation contract.
* In combination with the logic implemented in the ECDSA Contract Account, this enables a form of upgradable
* 'account abstraction' on layer 2.
* @dev The Proxy EOA contract uses a delegate call to execute the logic in an implementation
* contract. In combination with the logic implemented in the ECDSA Contract Account, this enables
* a form of upgradable 'account abstraction' on layer 2.
*
* Compiler used: optimistic-solc
* Runtime target: OVM
......@@ -29,10 +30,9 @@ contract OVM_ProxyEOA {
/*************
* Constants *
*************/
// solhint-disable-next-line max-line-length
bytes32 constant IMPLEMENTATION_KEY = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; //bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1);
/*********************
* Fallback Function *
*********************/
......
......@@ -4,7 +4,8 @@ pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_EIP155Tx } from "../../libraries/codec/Lib_EIP155Tx.sol";
import { Lib_ExecutionManagerWrapper } from "../../libraries/wrappers/Lib_ExecutionManagerWrapper.sol";
import { Lib_ExecutionManagerWrapper } from
"../../libraries/wrappers/Lib_ExecutionManagerWrapper.sol";
import { iOVM_ECDSAContractAccount } from "../../iOVM/predeploys/iOVM_ECDSAContractAccount.sol";
/**
......
......@@ -61,6 +61,7 @@ contract OVM_SequencerFeeVault {
require(
balance >= MIN_WITHDRAWAL_AMOUNT,
// solhint-disable-next-line max-line-length
"OVM_SequencerFeeVault: withdrawal amount must be greater than minimum withdrawal amount"
);
......
......@@ -13,6 +13,7 @@ abstract contract Abs_FraudContributor is Lib_AddressResolver {
uint256 startGas = gasleft();
_;
uint256 gasSpent = startGas - gasleft();
iOVM_BondManager(resolve('OVM_BondManager')).recordGasSpent(preStateRoot, txHash, msg.sender, gasSpent);
iOVM_BondManager(resolve("OVM_BondManager"))
.recordGasSpent(preStateRoot, txHash, msg.sender, gasSpent);
}
}
......@@ -75,9 +75,12 @@ contract OVM_BondManager is iOVM_BondManager, Lib_AddressResolver {
********************/
/// Adds `who` to the list of witnessProviders for the provided `preStateRoot`.
function recordGasSpent(bytes32 _preStateRoot, bytes32 _txHash, address who, uint256 gasSpent) override public {
function recordGasSpent(bytes32 _preStateRoot, bytes32 _txHash, address who, uint256 gasSpent)
override public {
// The sender must be the transitioner that corresponds to the claimed pre-state root
address transitioner = address(iOVM_FraudVerifier(resolve("OVM_FraudVerifier")).getStateTransitioner(_preStateRoot, _txHash));
address transitioner =
address(iOVM_FraudVerifier(resolve("OVM_FraudVerifier"))
.getStateTransitioner(_preStateRoot, _txHash));
require(transitioner == msg.sender, Errors.ONLY_TRANSITIONER);
witnessProviders[_preStateRoot].total += gasSpent;
......
......@@ -9,10 +9,12 @@ import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolve
/* Interface Imports */
import { iOVM_FraudVerifier } from "../../iOVM/verification/iOVM_FraudVerifier.sol";
import { iOVM_StateTransitioner } from "../../iOVM/verification/iOVM_StateTransitioner.sol";
import { iOVM_StateTransitionerFactory } from "../../iOVM/verification/iOVM_StateTransitionerFactory.sol";
import { iOVM_StateTransitionerFactory } from
"../../iOVM/verification/iOVM_StateTransitionerFactory.sol";
import { iOVM_BondManager } from "../../iOVM/verification/iOVM_BondManager.sol";
import { iOVM_StateCommitmentChain } from "../../iOVM/chain/iOVM_StateCommitmentChain.sol";
import { iOVM_CanonicalTransactionChain } from "../../iOVM/chain/iOVM_CanonicalTransactionChain.sol";
import { iOVM_CanonicalTransactionChain } from
"../../iOVM/chain/iOVM_CanonicalTransactionChain.sol";
/* Contract Imports */
import { Abs_FraudContributor } from "./Abs_FraudContributor.sol";
......@@ -108,8 +110,10 @@ contract OVM_FraudVerifier is Lib_AddressResolver, Abs_FraudContributor, iOVM_Fr
return;
}
iOVM_StateCommitmentChain ovmStateCommitmentChain = iOVM_StateCommitmentChain(resolve("OVM_StateCommitmentChain"));
iOVM_CanonicalTransactionChain ovmCanonicalTransactionChain = iOVM_CanonicalTransactionChain(resolve("OVM_CanonicalTransactionChain"));
iOVM_StateCommitmentChain ovmStateCommitmentChain =
iOVM_StateCommitmentChain(resolve("OVM_StateCommitmentChain"));
iOVM_CanonicalTransactionChain ovmCanonicalTransactionChain =
iOVM_CanonicalTransactionChain(resolve("OVM_CanonicalTransactionChain"));
require(
ovmStateCommitmentChain.verifyStateCommitment(
......@@ -131,6 +135,7 @@ contract OVM_FraudVerifier is Lib_AddressResolver, Abs_FraudContributor, iOVM_Fr
);
require (
// solhint-disable-next-line max-line-length
_preStateRootBatchHeader.prevTotalElements + _preStateRootProof.index + 1 == _transactionBatchHeader.prevTotalElements + _transactionProof.index,
"Pre-state root global index must equal to the transaction root global index."
);
......@@ -169,7 +174,8 @@ contract OVM_FraudVerifier is Lib_AddressResolver, Abs_FraudContributor, iOVM_Fr
contributesToFraudProof(_preStateRoot, _txHash)
{
iOVM_StateTransitioner transitioner = getStateTransitioner(_preStateRoot, _txHash);
iOVM_StateCommitmentChain ovmStateCommitmentChain = iOVM_StateCommitmentChain(resolve("OVM_StateCommitmentChain"));
iOVM_StateCommitmentChain ovmStateCommitmentChain =
iOVM_StateCommitmentChain(resolve("OVM_StateCommitmentChain"));
require(
transitioner.isComplete() == true,
......@@ -177,6 +183,7 @@ contract OVM_FraudVerifier is Lib_AddressResolver, Abs_FraudContributor, iOVM_Fr
);
require (
// solhint-disable-next-line max-line-length
_postStateRootBatchHeader.prevTotalElements + _postStateRootProof.index == _preStateRootBatchHeader.prevTotalElements + _preStateRootProof.index + 1,
"Post-state root global index must equal to the pre state root global index plus one."
);
......@@ -208,7 +215,8 @@ contract OVM_FraudVerifier is Lib_AddressResolver, Abs_FraudContributor, iOVM_Fr
_cancelStateTransition(_postStateRootBatchHeader, _preStateRoot);
// TEMPORARY: Remove the transitioner; for minnet.
transitioners[keccak256(abi.encodePacked(_preStateRoot, _txHash))] = iOVM_StateTransitioner(0x0000000000000000000000000000000000000000);
transitioners[keccak256(abi.encodePacked(_preStateRoot, _txHash))] =
iOVM_StateTransitioner(0x0000000000000000000000000000000000000000);
emit FraudProofFinalized(
_preStateRoot,
......@@ -254,14 +262,15 @@ contract OVM_FraudVerifier is Lib_AddressResolver, Abs_FraudContributor, iOVM_Fr
)
internal
{
transitioners[keccak256(abi.encodePacked(_preStateRoot, _txHash))] = iOVM_StateTransitionerFactory(
resolve("OVM_StateTransitionerFactory")
).create(
address(libAddressManager),
_stateTransitionIndex,
_preStateRoot,
_txHash
);
transitioners[keccak256(abi.encodePacked(_preStateRoot, _txHash))] =
iOVM_StateTransitionerFactory(
resolve("OVM_StateTransitionerFactory")
).create(
address(libAddressManager),
_stateTransitionIndex,
_preStateRoot,
_txHash
);
}
/**
......@@ -275,7 +284,8 @@ contract OVM_FraudVerifier is Lib_AddressResolver, Abs_FraudContributor, iOVM_Fr
)
internal
{
iOVM_StateCommitmentChain ovmStateCommitmentChain = iOVM_StateCommitmentChain(resolve("OVM_StateCommitmentChain"));
iOVM_StateCommitmentChain ovmStateCommitmentChain =
iOVM_StateCommitmentChain(resolve("OVM_StateCommitmentChain"));
iOVM_BondManager ovmBondManager = iOVM_BondManager(resolve("OVM_BondManager"));
// Delete the state batch.
......@@ -284,7 +294,8 @@ contract OVM_FraudVerifier is Lib_AddressResolver, Abs_FraudContributor, iOVM_Fr
);
// Get the timestamp and publisher for that block.
(uint256 timestamp, address publisher) = abi.decode(_postStateRootBatchHeader.extraData, (uint256, address));
(uint256 timestamp, address publisher) =
abi.decode(_postStateRootBatchHeader.extraData, (uint256, address));
// Slash the bonds at the bond manager.
ovmBondManager.finalize(
......
......@@ -25,19 +25,20 @@ import { Abs_FraudContributor } from "./Abs_FraudContributor.sol";
/**
* @title OVM_StateTransitioner
* @dev The State Transitioner coordinates the execution of a state transition during the evaluation of a
* fraud proof. It feeds verified input to the Execution Manager's run(), and controls a State Manager (which is
* uniquely created for each fraud proof).
* Once a fraud proof has been initialized, this contract is provided with the pre-state root and verifies
* that the OVM storage slots committed to the State Mangager are contained in that state
* @dev The State Transitioner coordinates the execution of a state transition during the evaluation
* of a fraud proof. It feeds verified input to the Execution Manager's run(), and controls a
* State Manager (which is uniquely created for each fraud proof).
* Once a fraud proof has been initialized, this contract is provided with the pre-state root and
* verifies that the OVM storage slots committed to the State Mangager are contained in that state
* This contract controls the State Manager and Execution Manager, and uses them to calculate the
* post-state root by applying the transaction. The Fraud Verifier can then check for fraud by comparing
* the calculated post-state root with the proposed post-state root.
* post-state root by applying the transaction. The Fraud Verifier can then check for fraud by
* comparing the calculated post-state root with the proposed post-state root.
*
* Compiler used: solc
* Runtime target: EVM
*/
contract OVM_StateTransitioner is Lib_AddressResolver, Abs_FraudContributor, iOVM_StateTransitioner {
contract OVM_StateTransitioner is Lib_AddressResolver, Abs_FraudContributor, iOVM_StateTransitioner
{
/*******************
* Data Structures *
......@@ -72,7 +73,9 @@ contract OVM_StateTransitioner is Lib_AddressResolver, Abs_FraudContributor, iOV
* Constants *
*************/
// solhint-disable-next-line max-line-length
bytes32 internal constant EMPTY_ACCOUNT_CODE_HASH = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
// solhint-disable-next-line max-line-length
bytes32 internal constant EMPTY_ACCOUNT_STORAGE_ROOT = 0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421;
......@@ -99,7 +102,8 @@ contract OVM_StateTransitioner is Lib_AddressResolver, Abs_FraudContributor, iOV
postStateRoot = _preStateRoot;
transactionHash = _transactionHash;
ovmStateManager = iOVM_StateManagerFactory(resolve("OVM_StateManagerFactory")).create(address(this));
ovmStateManager = iOVM_StateManagerFactory(resolve("OVM_StateManagerFactory"))
.create(address(this));
}
......@@ -227,6 +231,7 @@ contract OVM_StateTransitioner is Lib_AddressResolver, Abs_FraudContributor, iOV
// of the code stored on L2.
require(
Lib_EthUtils.getCodeHash(ethContractAddress) == account.codeHash,
// solhint-disable-next-line max-line-length
"OVM_StateTransitioner: Provided L1 contract code hash does not match L2 contract code hash."
);
}
......@@ -338,11 +343,13 @@ contract OVM_StateTransitioner is Lib_AddressResolver, Abs_FraudContributor, iOV
// This includes 1/64 of the gas getting lost because of EIP-150 (lost twice--first
// going into EM, then going into the code contract).
require(
gasleft() >= 100000 + _transaction.gasLimit * 1032 / 1000, // 1032/1000 = 1.032 = (64/63)^2 rounded up
// 1032/1000 = 1.032 = (64/63)^2 rounded up
gasleft() >= 100000 + _transaction.gasLimit * 1032 / 1000,
"Not enough gas to execute transaction deterministically."
);
iOVM_ExecutionManager ovmExecutionManager = iOVM_ExecutionManager(resolve("OVM_ExecutionManager"));
iOVM_ExecutionManager ovmExecutionManager =
iOVM_ExecutionManager(resolve("OVM_ExecutionManager"));
// We call `setExecutionManager` right before `run` (and not earlier) just in case the
// OVM_ExecutionManager address was updated between the time when this contract was created
......
......@@ -7,7 +7,8 @@ import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolve
/* Interface Imports */
import { iOVM_StateTransitioner } from "../../iOVM/verification/iOVM_StateTransitioner.sol";
import { iOVM_StateTransitionerFactory } from "../../iOVM/verification/iOVM_StateTransitionerFactory.sol";
import { iOVM_StateTransitionerFactory } from
"../../iOVM/verification/iOVM_StateTransitionerFactory.sol";
import { iOVM_FraudVerifier } from "../../iOVM/verification/iOVM_FraudVerifier.sol";
/* Contract Imports */
......
......@@ -3,7 +3,9 @@ pragma solidity >0.5.0 <0.8.0;
pragma experimental ABIEncoderV2;
/* Interface Imports */
import { iOVM_L1CrossDomainMessenger } from "../../../iOVM/bridge/messaging/iOVM_L1CrossDomainMessenger.sol";
import { iOVM_L1CrossDomainMessenger } from
"../../../iOVM/bridge/messaging/iOVM_L1CrossDomainMessenger.sol";
interface iOVM_L1MultiMessageRelayer {
struct L2ToL1Message {
......
......@@ -2,7 +2,7 @@
pragma solidity >0.5.0;
pragma experimental ABIEncoderV2;
import './iOVM_L1ERC20Bridge.sol';
import "./iOVM_L1ERC20Bridge.sol";
/**
* @title iOVM_L1StandardBridge
......@@ -29,7 +29,7 @@ interface iOVM_L1StandardBridge is iOVM_L1ERC20Bridge {
/********************
* 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.
......@@ -66,8 +66,8 @@ interface iOVM_L1StandardBridge is iOVM_L1ERC20Bridge {
/**
* @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.
* 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.
......
......@@ -85,8 +85,8 @@ interface iOVM_L2ERC20Bridge {
/**
* @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 OVM_l1TokenGateway.
* L2 token. This call will fail if it did not originate from a corresponding deposit in
* OVM_l1TokenGateway.
* @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.
......
......@@ -119,8 +119,10 @@ interface iOVM_ExecutionManager {
* Contract Creation Opcodes *
*****************************/
function ovmCREATE(bytes memory _bytecode) external returns (address _contract, bytes memory _revertdata);
function ovmCREATE2(bytes memory _bytecode, bytes32 _salt) external returns (address _contract, bytes memory _revertdata);
function ovmCREATE(bytes memory _bytecode) external
returns (address _contract, bytes memory _revertdata);
function ovmCREATE2(bytes memory _bytecode, bytes32 _salt) external
returns (address _contract, bytes memory _revertdata);
/*******************************
......@@ -137,10 +139,14 @@ interface iOVM_ExecutionManager {
****************************/
// Valueless ovmCALL for maintaining backwards compatibility with legacy OVM bytecode.
function ovmCALL(uint256 _gasLimit, address _address, bytes memory _calldata) external returns (bool _success, bytes memory _returndata);
function ovmCALL(uint256 _gasLimit, address _address, uint256 _value, bytes memory _calldata) external returns (bool _success, bytes memory _returndata);
function ovmSTATICCALL(uint256 _gasLimit, address _address, bytes memory _calldata) external returns (bool _success, bytes memory _returndata);
function ovmDELEGATECALL(uint256 _gasLimit, address _address, bytes memory _calldata) external returns (bool _success, bytes memory _returndata);
function ovmCALL(uint256 _gasLimit, address _address, bytes memory _calldata) external
returns (bool _success, bytes memory _returndata);
function ovmCALL(uint256 _gasLimit, address _address, uint256 _value, bytes memory _calldata)
external returns (bool _success, bytes memory _returndata);
function ovmSTATICCALL(uint256 _gasLimit, address _address, bytes memory _calldata) external
returns (bool _success, bytes memory _returndata);
function ovmDELEGATECALL(uint256 _gasLimit, address _address, bytes memory _calldata) external
returns (bool _success, bytes memory _returndata);
/****************************
......@@ -155,7 +161,8 @@ interface iOVM_ExecutionManager {
* Contract Code Opcodes *
*************************/
function ovmEXTCODECOPY(address _contract, uint256 _offset, uint256 _length) external returns (bytes memory _code);
function ovmEXTCODECOPY(address _contract, uint256 _offset, uint256 _length) external
returns (bytes memory _code);
function ovmEXTCODESIZE(address _contract) external returns (uint256 _size);
function ovmEXTCODEHASH(address _contract) external returns (bytes32 _hash);
......
......@@ -42,7 +42,8 @@ interface iOVM_StateManager {
function putAccount(address _address, Lib_OVMCodec.Account memory _account) external;
function putEmptyAccount(address _address) external;
function getAccount(address _address) external view returns (Lib_OVMCodec.Account memory _account);
function getAccount(address _address) external view
returns (Lib_OVMCodec.Account memory _account);
function hasAccount(address _address) external view returns (bool _exists);
function hasEmptyAccount(address _address) external view returns (bool _exists);
function setAccountNonce(address _address, uint256 _nonce) external;
......@@ -50,9 +51,12 @@ interface iOVM_StateManager {
function getAccountEthAddress(address _address) external view returns (address _ethAddress);
function getAccountStorageRoot(address _address) external view returns (bytes32 _storageRoot);
function initPendingAccount(address _address) external;
function commitPendingAccount(address _address, address _ethAddress, bytes32 _codeHash) external;
function testAndSetAccountLoaded(address _address) external returns (bool _wasAccountAlreadyLoaded);
function testAndSetAccountChanged(address _address) external returns (bool _wasAccountAlreadyChanged);
function commitPendingAccount(address _address, address _ethAddress, bytes32 _codeHash)
external;
function testAndSetAccountLoaded(address _address) external
returns (bool _wasAccountAlreadyLoaded);
function testAndSetAccountChanged(address _address) external
returns (bool _wasAccountAlreadyChanged);
function commitAccount(address _address) external returns (bool _wasAccountCommitted);
function incrementTotalUncommittedAccounts() external;
function getTotalUncommittedAccounts() external view returns (uint256 _total);
......@@ -65,13 +69,20 @@ interface iOVM_StateManager {
************************************/
function putContractStorage(address _contract, bytes32 _key, bytes32 _value) external;
function getContractStorage(address _contract, bytes32 _key) external view returns (bytes32 _value);
function hasContractStorage(address _contract, bytes32 _key) external view returns (bool _exists);
function testAndSetContractStorageLoaded(address _contract, bytes32 _key) external returns (bool _wasContractStorageAlreadyLoaded);
function testAndSetContractStorageChanged(address _contract, bytes32 _key) external returns (bool _wasContractStorageAlreadyChanged);
function commitContractStorage(address _contract, bytes32 _key) external returns (bool _wasContractStorageCommitted);
function getContractStorage(address _contract, bytes32 _key) external view
returns (bytes32 _value);
function hasContractStorage(address _contract, bytes32 _key) external view
returns (bool _exists);
function testAndSetContractStorageLoaded(address _contract, bytes32 _key) external
returns (bool _wasContractStorageAlreadyLoaded);
function testAndSetContractStorageChanged(address _contract, bytes32 _key) external
returns (bool _wasContractStorageAlreadyChanged);
function commitContractStorage(address _contract, bytes32 _key) external
returns (bool _wasContractStorageCommitted);
function incrementTotalUncommittedContractStorage() external;
function getTotalUncommittedContractStorage() external view returns (uint256 _total);
function wasContractStorageChanged(address _contract, bytes32 _key) external view returns (bool);
function wasContractStorageCommitted(address _contract, bytes32 _key) external view returns (bool);
function wasContractStorageChanged(address _contract, bytes32 _key) external view
returns (bool);
function wasContractStorageCommitted(address _contract, bytes32 _key) external view
returns (bool);
}
......@@ -9,6 +9,7 @@ interface ERC20 {
/// All the errors which may be encountered on the bond manager
library Errors {
string constant ERC20_ERR = "BondManager: Could not post bond";
// solhint-disable-next-line max-line-length
string constant ALREADY_FINALIZED = "BondManager: Fraud proof for this pre-state root has already been finalized";
string constant SLASHED = "BondManager: Cannot finalize withdrawal, you probably got slashed";
string constant WRONG_STATE = "BondManager: Wrong bond state for proposer";
......@@ -16,9 +17,11 @@ library Errors {
string constant WITHDRAWAL_PENDING = "BondManager: Withdrawal already pending";
string constant TOO_EARLY = "BondManager: Too early to finalize your withdrawal";
// solhint-disable-next-line max-line-length
string constant ONLY_TRANSITIONER = "BondManager: Only the transitioner for this pre-state root may call this function";
// solhint-disable-next-line max-line-length
string constant ONLY_FRAUD_VERIFIER = "BondManager: Only the fraud verifier may call this function";
// solhint-disable-next-line max-line-length
string constant ONLY_STATE_COMMITMENT_CHAIN = "BondManager: Only the state commitment chain may call this function";
string constant WAIT_FOR_DISPUTES = "BondManager: Wait for other potential disputes";
}
......
......@@ -36,7 +36,8 @@ interface iOVM_FraudVerifier {
* Public Functions: Transition Status *
***************************************/
function getStateTransitioner(bytes32 _preStateRoot, bytes32 _txHash) external view returns (iOVM_StateTransitioner _transitioner);
function getStateTransitioner(bytes32 _preStateRoot, bytes32 _txHash) external view
returns (iOVM_StateTransitioner _transitioner);
/****************************************
......
......@@ -2,7 +2,8 @@
pragma solidity >0.5.0 <0.8.0;
/* Interface Imports */
import { iOVM_CrossDomainMessenger } from "../../iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol";
import { iOVM_CrossDomainMessenger } from
"../../iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol";
/**
* @title OVM_CrossDomainEnabled
......
......@@ -138,7 +138,7 @@ library Lib_EIP155Tx {
// We write the encoding of empty bytes when the transaction is a creation, *not* the zero
// address as one might assume.
if (_transaction.isCreate) {
raw[3] = Lib_RLPWriter.writeBytes('');
raw[3] = Lib_RLPWriter.writeBytes("");
} else {
raw[3] = Lib_RLPWriter.writeAddress(_transaction.to);
}
......@@ -153,8 +153,8 @@ library Lib_EIP155Tx {
} else {
// Chain ID *is* included in the unsigned transaction.
raw[6] = Lib_RLPWriter.writeUint(_transaction.chainId);
raw[7] = Lib_RLPWriter.writeBytes('');
raw[8] = Lib_RLPWriter.writeBytes('');
raw[7] = Lib_RLPWriter.writeBytes("");
raw[8] = Lib_RLPWriter.writeBytes("");
}
return Lib_RLPWriter.writeList(raw);
......
......@@ -11,9 +11,11 @@ library Lib_PredeployAddresses {
address internal constant ECDSA_CONTRACT_ACCOUNT = 0x4200000000000000000000000000000000000003;
address internal constant SEQUENCER_ENTRYPOINT = 0x4200000000000000000000000000000000000005;
address payable internal constant OVM_ETH = 0x4200000000000000000000000000000000000006;
// solhint-disable-next-line max-line-length
address internal constant L2_CROSS_DOMAIN_MESSENGER = 0x4200000000000000000000000000000000000007;
address internal constant LIB_ADDRESS_MANAGER = 0x4200000000000000000000000000000000000008;
address internal constant PROXY_EOA = 0x4200000000000000000000000000000000000009;
// solhint-disable-next-line max-line-length
address internal constant EXECUTION_MANAGER_WRAPPER = 0x420000000000000000000000000000000000000B;
address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011;
address internal constant ERC1820_REGISTRY = 0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24;
......
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity =0.7.6;
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
/// @title Interface for WETH9. Also contains the non-ERC20 events normally present in the WETH9 implementation.
/// @title Interface for WETH9. Also contains the non-ERC20 events
/// normally present in the WETH9 implementation.
interface IWETH9 is IERC20 {
event Deposit(address indexed dst, uint256 wad);
event Withdrawal(address indexed src, uint256 wad);
......
......@@ -3,7 +3,7 @@ pragma solidity >=0.5.16 <0.8.0;
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import './IL2StandardERC20.sol';
import "./IL2StandardERC20.sol";
contract L2StandardERC20 is IL2StandardERC20, ERC20 {
address public override l1Token;
......
......@@ -148,7 +148,8 @@ library Lib_MerkleTrie {
)
{
TrieNode[] memory proof = _parseProof(_proof);
(uint256 pathLength, bytes memory keyRemainder, bool isFinalNode) = _walkNodePath(proof, _key, _root);
(uint256 pathLength, bytes memory keyRemainder, bool isFinalNode) =
_walkNodePath(proof, _key, _root);
bool exists = keyRemainder.length == 0;
......@@ -157,7 +158,7 @@ library Lib_MerkleTrie {
"Provided proof is invalid."
);
bytes memory value = exists ? _getNodeValue(proof[pathLength - 1]) : bytes('');
bytes memory value = exists ? _getNodeValue(proof[pathLength - 1]) : bytes("");
return (
exists,
......@@ -253,7 +254,8 @@ library Lib_MerkleTrie {
if (currentNode.decoded.length == BRANCH_NODE_LENGTH) {
if (currentKeyIndex == key.length) {
// We've hit the end of the key, meaning the value should be within this branch node.
// We've hit the end of the key
// meaning the value should be within this branch node.
break;
} else {
// We're not at the end of the key yet.
......@@ -288,7 +290,8 @@ library Lib_MerkleTrie {
} else if (prefix == PREFIX_EXTENSION_EVEN || prefix == PREFIX_EXTENSION_ODD) {
if (sharedNibbleLength != pathRemainder.length) {
// Our extension node is not identical to the remainder.
// We've hit the end of this path, updates will need to modify this extension.
// We've hit the end of this path
// updates will need to modify this extension.
currentNodeID = bytes32(RLP_NULL);
break;
} else {
......@@ -348,6 +351,7 @@ library Lib_MerkleTrie {
TrieNode[] memory newNodes = new TrieNode[](3);
uint256 totalNewNodes = 0;
// solhint-disable-next-line max-line-length
// Reference: https://github.com/ethereumjs/merkle-patricia-tree/blob/c0a10395aab37d42c175a47114ebfcbd7efcf059/src/baseTrie.ts#L294-L313
bool matchLeaf = false;
if (lastNodeType == NodeType.LeafNode) {
......@@ -391,7 +395,8 @@ library Lib_MerkleTrie {
totalNewNodes += 1;
// Create a new leaf node, slicing our remainder since the first byte points
// to our branch node.
newNodes[totalNewNodes] = _makeLeafNode(Lib_BytesUtils.slice(keyRemainder, 1), _value);
newNodes[totalNewNodes] =
_makeLeafNode(Lib_BytesUtils.slice(keyRemainder, 1), _value);
totalNewNodes += 1;
}
} else {
......@@ -429,13 +434,23 @@ library Lib_MerkleTrie {
if (lastNodeType == NodeType.LeafNode) {
// We're dealing with a leaf node.
// We'll modify the key and insert the old leaf node into the branch index.
TrieNode memory modifiedLastNode = _makeLeafNode(lastNodeKey, _getNodeValue(lastNode));
newBranch = _editBranchIndex(newBranch, branchKey, _getNodeHash(modifiedLastNode.encoded));
TrieNode memory modifiedLastNode =
_makeLeafNode(lastNodeKey, _getNodeValue(lastNode));
newBranch =
_editBranchIndex(
newBranch,
branchKey,
_getNodeHash(modifiedLastNode.encoded));
} else if (lastNodeKey.length != 0) {
// We're dealing with a shrinking extension node.
// We need to modify the node to decrease the size of the key.
TrieNode memory modifiedLastNode = _makeExtensionNode(lastNodeKey, _getNodeValue(lastNode));
newBranch = _editBranchIndex(newBranch, branchKey, _getNodeHash(modifiedLastNode.encoded));
TrieNode memory modifiedLastNode =
_makeExtensionNode(lastNodeKey, _getNodeValue(lastNode));
newBranch =
_editBranchIndex(
newBranch,
branchKey,
_getNodeHash(modifiedLastNode.encoded));
} else {
// We're dealing with an unnecessary extension node.
// We're going to delete the node entirely.
......
......@@ -246,7 +246,9 @@ library Lib_Buffer {
uint40 length;
bytes27 extraData;
assembly {
// solhint-disable-next-line max-line-length
length := and(context, 0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF)
// solhint-disable-next-line max-line-length
extraData := and(context, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000)
}
......
......@@ -94,7 +94,7 @@ library Lib_BytesUtils {
)
{
if (_start >= _bytes.length) {
return bytes('');
return bytes("");
}
return slice(_bytes, _start, _bytes.length - _start);
......
......@@ -14,7 +14,8 @@ library Lib_ErrorUtils {
/**
* Encodes an error string into raw solidity-style revert data.
* (i.e. ascii bytes, prefixed with bytes4(keccak("Error(string))"))
* Ref: https://docs.soliditylang.org/en/v0.8.2/control-structures.html?highlight=Error(string)#panic-via-assert-and-error-via-require
* Ref: https://docs.soliditylang.org/en/v0.8.2/control-structures.html?highlight=Error(string)
* #panic-via-assert-and-error-via-require
* @param _reason Reason for the reversion.
* @return Standard solidity revert data for the given reason.
*/
......
......@@ -14,8 +14,8 @@ library Lib_MerkleTree {
/**
* Calculates a merkle root for a list of 32-byte leaf hashes. WARNING: If the number
* of leaves passed in is not a power of two, it pads out the tree with zero hashes.
* If you do not know the original length of elements for the tree you are verifying,
* then this may allow empty leaves past _elements.length to pass a verification check down the line.
* If you do not know the original length of elements for the tree you are verifying, then
* this may allow empty leaves past _elements.length to pass a verification check down the line.
* Note that the _elements argument is modified, therefore it must not be used again afterwards
* @param _elements Array of hashes from which to generate a merkle root.
* @return Merkle root of the leaves, with zero hashes for non-powers-of-two (see above).
......@@ -114,7 +114,8 @@ library Lib_MerkleTree {
* @param _root The Merkle root to verify against.
* @param _leaf The leaf hash to verify inclusion of.
* @param _index The index in the tree of this leaf.
* @param _siblings Array of sibline nodes in the inclusion proof, starting from depth 0 (bottom of the tree).
* @param _siblings Array of sibline nodes in the inclusion proof, starting from depth 0
* (bottom of the tree).
* @param _totalLeaves The total number of leaves originally passed into.
* @return Whether or not the merkle branch and leaf passes verification.
*/
......
......@@ -253,7 +253,8 @@ library Lib_ExecutionManagerWrapper {
bytes memory
)
{
(bool success, bytes memory returndata) = Lib_PredeployAddresses.EXECUTION_MANAGER_WRAPPER.delegatecall(_calldata);
(bool success, bytes memory returndata) =
Lib_PredeployAddresses.EXECUTION_MANAGER_WRAPPER.delegatecall(_calldata);
if (success == true) {
return returndata;
......
......@@ -9,14 +9,17 @@ const deployFn: DeployFunction = async (hre: any) => {
const { deploy } = deployments
const { deployer } = await getNamedAccounts()
const l2TokenFactory = getContractDefinition('OVM_L2StandardTokenFactory', true)
const l2TokenFactory = getContractDefinition(
'OVM_L2StandardTokenFactory',
true
)
await deploy('OVM_L2StandardTokenFactory', {
contract: l2TokenFactory,
args: [],
from: deployer,
log: true,
});
})
}
deployFn.tags = ['OVM_L2StandardTokenFactory']
......
......@@ -45,6 +45,9 @@ const config: HardhatUserConfig = {
version: '0.7.6',
settings: {
optimizer: { enabled: true, runs: 200 },
metadata: {
bytecodeHash: 'none',
},
outputSelection: {
'*': {
'*': ['storageLayout'],
......
......@@ -37,6 +37,7 @@
"posttest:slither": "rm -f @openzeppelin && rm -f @ens && rm -f hardhat",
"lint:check": "eslint .",
"lint:fix": "yarn lint:check --fix",
"lint:contracts": "yarn solhint -f table contracts/optimistic-ethereum/**/*.sol",
"clean": "rm -rf ./dist ./artifacts ./artifacts-ovm ./cache ./cache-ovm ./tsconfig.build.tsbuildinfo",
"deploy": "ts-node \"./bin/deploy.ts\" && yarn generate-markdown",
"serve": "./bin/serve_dump.sh",
......@@ -105,6 +106,7 @@
"lint-staged": "11.0.0",
"random-bytes-seed": "^1.0.3",
"rlp": "^2.2.6",
"solhint": "^3.3.6",
"solidity-coverage": "^0.7.16",
"ts-generator": "0.0.8",
"ts-node": "^9.1.1",
......
......@@ -10,7 +10,7 @@ import { getContractDefinition } from '../../src/contract-defs'
export const DEFAULT_ACCOUNTS = defaultAccounts
export const DEFAULT_ACCOUNTS_HARDHAT = defaultAccounts.map((account) => {
return {
balance: ethers.BigNumber.from(account.balance).toHexString(),
balance: account.balance,
privateKey: account.secretKey,
}
})
......
......@@ -15,10 +15,6 @@ export interface AppendSequencerBatchParams {
transactions: string[] // total_size_bytes[],total_size_bytes[]
}
/**********************
* Internal Functions *
*********************/
const APPEND_SEQUENCER_BATCH_METHOD_ID = 'appendSequencerBatch()'
export const encodeAppendSequencerBatch = (
......
/* Imports: External */
import { ethers } from 'ethers'
/* Imports: Internal */
import { getRandomHexString } from './hex-strings'
/* @returns a random Ethereum address as a string of 40 hex characters, normalized as a checksum address. */
export const getRandomAddress = (): string => {
return ethers.utils.getAddress(getRandomHexString(20))
}
export const assert = (condition: () => boolean, reason?: string) => {
try {
if (condition() === false) {
throw new Error(`Assertion failed: ${reason}`)
}
} catch (err) {
throw new Error(`Assertion failed: ${reason}\n${err}`)
}
}
......@@ -27,16 +27,6 @@ export const add0x = (str: string): string => {
return str.startsWith('0x') ? str : '0x' + str
}
/**
* Returns whether or not the provided string is a hex string.
*
* @param str The string to test.
* @returns True if the provided string is a hex string, false otherwise.
*/
export const isHexString = (inp: any): boolean => {
return typeof inp === 'string' && inp.startsWith('0x')
}
/**
* Casts a hex string to a buffer.
*
......@@ -88,30 +78,5 @@ export const padHexString = (str: string, length: number): string => {
}
}
export const getLen = (pos: { start; end }) => (pos.end - pos.start) * 2
export const encodeHex = (val: any, len: number) =>
remove0x(BigNumber.from(val).toHexString()).padStart(len, '0')
export const toVerifiedBytes = (val: string, len: number) => {
val = remove0x(val)
if (val.length !== len) {
throw new Error('Invalid length!')
}
return val
}
/**
* @param byteLength The length of the hex string in bytes
* @returns a random hex string of the specified byteLength (string length will be byteLength*2)
*/
export const getRandomHexString = (byteLength: number): string => {
return (
'0x' +
[...Array(byteLength * 2)]
.map(() => {
return Math.floor(Math.random() * 16).toString(16)
})
.join('')
)
}
export * from './addresses'
export * from './hex-strings'
export * from './misc'
export * from './common'
......@@ -5,14 +5,12 @@
import { BigNumber } from 'ethers'
import { remove0x } from './common'
const hundredMillion = BigNumber.from(100_000_000)
const feeScalar = 10_000_000
export const TxGasPrice = BigNumber.from(feeScalar + feeScalar / 2)
const txDataZeroGas = 4
const txDataNonZeroGasEIP2028 = 16
const overhead = 4200 + 200 * txDataNonZeroGasEIP2028
const tenThousand = BigNumber.from(10_000)
export const TxGasPrice = BigNumber.from(feeScalar + feeScalar / 2)
export interface EncodableL2GasLimit {
data: Buffer | string
l1GasPrice: BigNumber | number
......
import { expect } from '../setup'
/* Imports: Internal */
import { getRandomAddress } from '../../src'
describe('getRandomAddress', () => {
const random = global.Math.random
before(async () => {
global.Math.random = () => 0.5
})
after(async () => {
global.Math.random = random
})
it('returns a random address string', () => {
expect(getRandomAddress()).to.equal('0x' + '88'.repeat(20))
})
})
......@@ -2,23 +2,7 @@ import { expect } from '../setup'
import { BigNumber } from 'ethers'
/* Imports: Internal */
import { getRandomHexString, toRpcHexString } from '../../src'
describe('getRandomHexString', () => {
const random = global.Math.random
before(async () => {
global.Math.random = () => 0.5
})
after(async () => {
global.Math.random = random
})
it('returns a random address string of the specified length', () => {
expect(getRandomHexString(8)).to.equal('0x' + '88'.repeat(8))
})
})
import { toRpcHexString } from '../../src'
describe('toRpcHexString', () => {
it('should parse 0', () => {
......
import { expect } from '../setup'
import * as fees from '../../src/fees'
import { BigNumber, utils } from 'ethers'
import { utils } from 'ethers'
const hundredBillion = 10 ** 11
const million = 10 ** 6
describe('Fees', () => {
it('should count zeros and ones', () => {
......
......@@ -62,6 +62,8 @@ Here's the list of environment variables you can change:
| DATA_TRANSPORT_LAYER__LEGACY_SEQUENCER_COMPATIBILITY | false | Whether or not to enable "legacy" sequencer sync (without the custom `eth_getBlockRange` endpoint) |
| DATA_TRANSPORT_LAYER__NODE_ENV | development | Environment the service is running in: production, development, or test. |
| DATA_TRANSPORT_LAYER__ETH_NETWORK_NAME | - | L1 Ethereum network the service is deployed to: mainnet, kovan, goerli. |
| DATA_TRANSPORT_LAYER__L1_GAS_PRICE_BACKEND | l1 | Where to pull the l1 gas price from (l1 or l2) |
| DATA_TRANSPORT_LAYER__DEFAULT_BACKEND | l1 | Where to sync transactions from (l1 or l2) |
To enable proper error tracking via Sentry on deployed instances, make sure `NODE_ENV` and `ETH_NETWORK_NAME` are set in addition to [`SENTRY_DSN`](https://docs.sentry.io/platforms/node/).
......@@ -86,6 +88,24 @@ GET /eth/context/latest
}
```
### Latest Ethereum L1 Gas Price
#### Request
```
GET /eth/gasprice
```
Defaults to pulling L1 gas price from config option `DATA_TRANSPORT_LAYER__L1_GAS_PRICE_BACKEND`. Can be overridden with query parameter `backend` (`/eth/gasprice?backend=l1`).
#### Response
```ts
{
"gasPrice": string
}
```
### Enqueue by Index
#### Request
......@@ -145,7 +165,7 @@ GET /transaction/index/{index: number}
} | null,
"queueIndex": number | null,
},
"batch": {
"index": number,
"blockNumber": number,
......@@ -181,7 +201,7 @@ GET /batch/transaction/index/{index: number}
"prevTotalElements": number,
"extraData": string
},
"transactions": [
{
"index": number,
......@@ -266,7 +286,7 @@ GET /batch/stateroot/index/{index: number}
"prevTotalElements": number,
"extraData": string
},
"stateRoots": [
{
"index": number,
......
/* Imports: External */
import { fromHexString, EventArgsAddressSet } from '@eth-optimism/core-utils'
import { fromHexString } from '@eth-optimism/core-utils'
import { BaseService, Metrics } from '@eth-optimism/common-ts'
import { JsonRpcProvider } from '@ethersproject/providers'
import { LevelUp } from 'levelup'
......
......@@ -34,6 +34,7 @@ export interface L1DataTransportServiceOptions {
sentryDsn?: string
sentryTraceRate?: number
defaultBackend: string
l1GasPriceBackend: string
}
const optionSettings = {
......
......@@ -46,6 +46,7 @@ type ethNetwork = 'mainnet' | 'kovan' | 'goerli'
false
),
defaultBackend: config.str('default-backend', 'l1'),
l1GasPriceBackend: config.str('l1-gas-price-backend', 'l1'),
useSentry: config.bool('use-sentry', false),
sentryDsn: config.str('sentry-dsn'),
sentryTraceRate: config.ufloat('sentry-trace-rate', 0.05),
......
......@@ -51,12 +51,23 @@ const optionSettings = {
return validators.isUrl(val) || validators.isJsonRpcProvider(val)
},
},
l2RpcProvider: {
validate: (val: unknown) => {
return validators.isUrl(val) || validators.isJsonRpcProvider(val)
},
},
defaultBackend: {
default: 'l1',
validate: (val: string) => {
return val === 'l1' || val === 'l2'
},
},
l1GasPriceBackend: {
default: 'l1',
validate: (val: string) => {
return val === 'l1' || val === 'l2'
},
},
}
export class L1TransportServer extends BaseService<L1TransportServerOptions> {
......@@ -69,6 +80,7 @@ export class L1TransportServer extends BaseService<L1TransportServerOptions> {
server: any
db: TransportDB
l1RpcProvider: JsonRpcProvider
l2RpcProvider: JsonRpcProvider
} = {} as any
protected async _init(): Promise<void> {
......@@ -82,6 +94,11 @@ export class L1TransportServer extends BaseService<L1TransportServerOptions> {
? new JsonRpcProvider(this.options.l1RpcProvider)
: this.options.l1RpcProvider
this.state.l2RpcProvider =
typeof this.options.l2RpcProvider === 'string'
? new JsonRpcProvider(this.options.l2RpcProvider)
: this.options.l2RpcProvider
this._initializeApp()
}
......@@ -133,6 +150,26 @@ export class L1TransportServer extends BaseService<L1TransportServerOptions> {
if (this.options.useSentry) {
this.state.app.use(Sentry.Handlers.errorHandler())
}
this.logger.info('HTTP Server Options', {
defaultBackend: this.options.defaultBackend,
l1GasPriceBackend: this.options.l1GasPriceBackend,
})
if (this.state.l1RpcProvider) {
this.logger.info('HTTP Server L1 RPC Provider initialized', {
url: this.state.l1RpcProvider.connection.url,
})
} else {
this.logger.warn('HTTP Server L1 RPC Provider not initialized')
}
if (this.state.l2RpcProvider) {
this.logger.info('HTTP Server L2 RPC Provider initialized', {
url: this.state.l2RpcProvider.connection.url,
})
} else {
this.logger.warn('HTTP Server L2 RPC Provider not initialized')
}
}
/**
......@@ -271,8 +308,21 @@ export class L1TransportServer extends BaseService<L1TransportServerOptions> {
this._registerRoute(
'get',
'/eth/gasprice',
async (): Promise<GasPriceResponse> => {
const gasPrice = await this.state.l1RpcProvider.getGasPrice()
async (req): Promise<GasPriceResponse> => {
const backend = req.query.backend || this.options.l1GasPriceBackend
let gasPrice: BigNumber
if (backend === 'l1') {
gasPrice = await this.state.l1RpcProvider.getGasPrice()
} else if (backend === 'l2') {
const response = await this.state.l2RpcProvider.send(
'rollup_gasPrices',
[]
)
gasPrice = BigNumber.from(response.l1GasPrice)
} else {
throw new Error(`Unknown L1 gas price backend: ${backend}`)
}
return {
gasPrice: gasPrice.toString(),
......
......@@ -14,7 +14,12 @@ try {
ReturnData,
} = require('hardhat/internal/hardhat-network/provider/return-data')
decodeRevertReason = (value: Buffer) => {
return new ReturnData(value).decodeError()
const returnData = new ReturnData(value)
if (returnData.isErrorReturnData()) {
return returnData.decodeError()
} else {
return ''
}
}
}
// Handle hardhat ^2.2.0
......
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