Commit 886a1507 authored by Elena Gesheva's avatar Elena Gesheva Committed by GitHub

Merge pull request #1033 from...

Merge pull request #1033 from ethereum-optimism/elena/op-790-add-linting-andor-formatting-to-solidity

Add contracts linting
parents db4611a7 e67551c3
......@@ -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 {
......
......@@ -9,7 +9,8 @@ import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolve
import { Lib_MerkleTree } from "../../libraries/utils/Lib_MerkleTree.sol";
/* Interface Imports */
import { iOVM_CanonicalTransactionChain } from "../../iOVM/chain/iOVM_CanonicalTransactionChain.sol";
import { iOVM_CanonicalTransactionChain } from
"../../iOVM/chain/iOVM_CanonicalTransactionChain.sol";
import { iOVM_ChainStorageContainer } from "../../iOVM/chain/iOVM_ChainStorageContainer.sol";
/* Contract Imports */
......@@ -23,8 +24,8 @@ import { Math } from "@openzeppelin/contracts/math/Math.sol";
* @dev The Canonical Transaction Chain (CTC) contract is an append-only log of transactions
* which must be applied to the rollup state. It defines the ordering of rollup transactions by
* writing them to the 'CTC:batches' instance of the Chain Storage Container.
* The CTC also allows any account to 'enqueue' an L2 transaction, which will require that the Sequencer
* will eventually append it to the rollup state.
* The CTC also allows any account to 'enqueue' an L2 transaction, which will require that the
* Sequencer will eventually append it to the rollup state.
* If the Sequencer does not include an enqueued transaction within the 'force inclusion period',
* then any account may force it to be included by calling appendQueueBatch().
*
......@@ -345,6 +346,7 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
// TEMPORARY: Disable `appendQueueBatch` for minnet
revert("appendQueueBatch is currently disabled.");
// solhint-disable max-line-length
// _numQueuedTransactions = Math.min(_numQueuedTransactions, getNumPendingQueueElements());
// require(
// _numQueuedTransactions > 0,
......@@ -381,6 +383,7 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
// _numQueuedTransactions,
// getTotalElements()
// );
// solhint-enable max-line-length
}
/**
......@@ -424,7 +427,9 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
"Must append at least one element."
);
uint40 nextTransactionPtr = uint40(BATCH_CONTEXT_START_POS + BATCH_CONTEXT_SIZE * numContexts);
uint40 nextTransactionPtr = uint40(
BATCH_CONTEXT_START_POS + BATCH_CONTEXT_SIZE * numContexts
);
require(
msg.data.length >= nextTransactionPtr,
......@@ -533,14 +538,16 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
uint40 blockTimestamp;
uint40 blockNumber;
if (curContext.numSubsequentQueueTransactions == 0) {
// The last element is a sequencer tx, therefore pull timestamp and block number from the last context.
// The last element is a sequencer tx, therefore pull timestamp and block number from
// the last context.
blockTimestamp = uint40(curContext.timestamp);
blockNumber = uint40(curContext.blockNumber);
} else {
// The last element is a queue tx, therefore pull timestamp and block number from the queue element.
// curContext.numSubsequentQueueTransactions > 0 which means that we've processed at least one queue element.
// We increment nextQueueIndex after processing each queue element,
// so the index of the last element we processed is nextQueueIndex - 1.
// The last element is a queue tx, therefore pull timestamp and block number from the
// queue element.
// curContext.numSubsequentQueueTransactions > 0 which means that we've processed at
// least one queue element. We increment nextQueueIndex after processing each queue
// element, so the index of the last element we processed is nextQueueIndex - 1.
Lib_OVMCodec.QueueElement memory lastElement = _getQueueElement(
nextQueueIndex - 1,
queueRef
......@@ -667,6 +674,8 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
uint40 nextQueueIndex;
uint40 lastTimestamp;
uint40 lastBlockNumber;
// solhint-disable max-line-length
assembly {
extraData := shr(40, extraData)
totalElements := and(extraData, 0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF)
......@@ -674,6 +683,7 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
lastTimestamp := shr(80, and(extraData, 0x0000000000000000000000000000000000FFFFFFFFFF00000000000000000000))
lastBlockNumber := shr(120, and(extraData, 0x000000000000000000000000FFFFFFFFFF000000000000000000000000000000))
}
// solhint-enable max-line-length
return (
totalElements,
......@@ -764,10 +774,12 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
uint40 elementTimestamp;
uint40 elementBlockNumber;
// solhint-disable max-line-length
assembly {
elementTimestamp := and(timestampAndBlockNumber, 0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF)
elementBlockNumber := shr(40, and(timestampAndBlockNumber, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000))
}
// solhint-enable max-line-length
return Lib_OVMCodec.QueueElement({
transactionHash: transactionHash,
......@@ -834,7 +846,7 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
mstore(add(chainElementStart, 1), ctxTimestamp)
mstore(add(chainElementStart, 33), ctxBlockNumber)
// solhint-disable-next-line max-line-length
calldatacopy(add(chainElementStart, BYTES_TILL_TX_DATA), add(_nextTransactionPtr, 3), _txDataLength)
leafHash := keccak256(chainElementStart, add(BYTES_TILL_TX_DATA, _txDataLength))
......@@ -876,7 +888,7 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
mstore(add(chainElementStart, 1), ctxTimestamp)
mstore(add(chainElementStart, 33), ctxBlockNumber)
// solhint-disable-next-line max-line-length
pop(staticcall(gas(), 0x04, add(txData, 0x20), txDataLength, add(chainElementStart, BYTES_TILL_TX_DATA), txDataLength))
leafHash := keccak256(chainElementStart, add(BYTES_TILL_TX_DATA, txDataLength))
......@@ -989,9 +1001,11 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
_queueRef
);
// If the force inclusion period has passed for an enqueued transaction, it MUST be the next chain element.
// If the force inclusion period has passed for an enqueued transaction, it MUST be the
// next chain element.
require(
block.timestamp < nextQueueElement.timestamp + forceInclusionPeriodSeconds,
// solhint-disable-next-line max-line-length
"Previously enqueued batches have expired and must be appended before a new sequencer batch."
);
......@@ -1009,10 +1023,12 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
}
/**
* Checks that a given batch context is valid based on its previous context, and the next queue elemtent.
* Checks that a given batch context is valid based on its previous context, and the next queue
* elemtent.
* @param _prevContext The previously validated batch context.
* @param _nextContext The batch context to validate with this call.
* @param _nextQueueIndex Index of the next queue element to process for the _nextContext's subsequentQueueElements.
* @param _nextQueueIndex Index of the next queue element to process for the _nextContext's
* subsequentQueueElements.
* @param _queueRef The storage container for the queue.
*/
function _validateNextBatchContext(
......@@ -1061,17 +1077,22 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
internal
view
{
// If the queue is not now empty, check the mononoticity of whatever the next batch that will come in is.
if (_queueLength - _nextQueueIndex > 0 && _finalContext.numSubsequentQueueTransactions == 0) {
// If the queue is not now empty, check the mononoticity of whatever the next batch that
// will come in is.
if (_queueLength - _nextQueueIndex > 0 && _finalContext.numSubsequentQueueTransactions == 0)
{
_validateContextBeforeEnqueue(
_finalContext,
_nextQueueIndex,
_queueRef
);
}
// Batches cannot be added from the future, or subsequent enqueue() contexts would violate monotonicity.
require(_finalContext.timestamp <= block.timestamp, "Context timestamp is from the future.");
require(_finalContext.blockNumber <= block.number, "Context block number is from the future.");
// Batches cannot be added from the future, or subsequent enqueue() contexts would violate
// monotonicity.
require(_finalContext.timestamp <= block.timestamp,
"Context timestamp is from the future.");
require(_finalContext.blockNumber <= block.number,
"Context block number is from the future.");
}
/**
......@@ -1119,7 +1140,8 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
bool
)
{
OVM_ExecutionManager ovmExecutionManager = OVM_ExecutionManager(resolve("OVM_ExecutionManager"));
OVM_ExecutionManager ovmExecutionManager =
OVM_ExecutionManager(resolve("OVM_ExecutionManager"));
uint256 gasLimit = ovmExecutionManager.getMaxTransactionGasLimit();
bytes32 leafHash = _getSequencerLeafHash(_txChainElement);
......@@ -1151,7 +1173,8 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
* @param _transaction The transaction we are verifying inclusion of.
* @param _queueIndex The queueIndex of the queued transaction.
* @param _batchHeader Header of the batch the transaction was included in.
* @param _inclusionProof An inclusion proof into the CTC at a particular index (should point to queue tx).
* @param _inclusionProof An inclusion proof into the CTC at a particular index (should point to
* queue tx).
* @return True if the transaction was included in the specified location, else false.
*/
function _verifyQueueTransaction(
......@@ -1215,7 +1238,8 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
)
{
require(
Lib_OVMCodec.hashBatchHeader(_batchHeader) == batches().get(uint32(_batchHeader.batchIndex)),
Lib_OVMCodec.hashBatchHeader(_batchHeader) ==
batches().get(uint32(_batchHeader.batchIndex)),
"Invalid batch header."
);
......
......@@ -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,
......
......@@ -83,7 +83,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
* Default Context Values *
**************************/
uint256 constant DEFAULT_UINT256 = 0xdefa017defa017defa017defa017defa017defa017defa017defa017defa017d;
uint256 constant DEFAULT_UINT256 =
0xdefa017defa017defa017defa017defa017defa017defa017defa017defa017d;
address constant DEFAULT_ADDRESS = 0xdEfa017defA017DeFA017DEfa017DeFA017DeFa0;
......@@ -92,7 +93,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
*************************************/
/**
* @dev The Execution Manager and State Manager each have this 30 byte prefix, and are uncallable.
* @dev The Execution Manager and State Manager each have this 30 byte prefix,
* and are uncallable.
*/
address constant CONTAINER_CONTRACT_PREFIX = 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000;
......@@ -205,7 +207,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
// OVM_StateManager (expected to be an OVM_StateTransitioner). We can revert here because
// this would make the `run` itself invalid.
require(
// This method may return false during fraud proofs, but always returns true in L2 nodes' State Manager precompile.
// This method may return false during fraud proofs, but always returns true in
// L2 nodes' State Manager precompile.
ovmStateManager.isAuthenticated(msg.sender),
"Only authenticated addresses in ovmStateManager can call this function"
);
......@@ -677,7 +680,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
bytes memory _returndata
)
{
// STATICCALL updates the CALLER, updates the ADDRESS, and runs in a static, valueless context.
// STATICCALL updates the CALLER, updates the ADDRESS, and runs in a static,
// valueless context.
MessageContext memory nextMessageContext = messageContext;
nextMessageContext.ovmCALLER = nextMessageContext.ovmADDRESS;
nextMessageContext.ovmADDRESS = _address;
......@@ -727,7 +731,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
}
/**
* @notice Legacy ovmCALL function which did not support ETH value; this maintains backwards compatibility.
* @notice Legacy ovmCALL function which did not support ETH value; this maintains backwards
* compatibility.
* @param _gasLimit Amount of gas to be passed into this call.
* @param _address Address of the contract to call.
* @param _calldata Data to send along with the call.
......@@ -953,7 +958,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
********************************************/
/**
* Checks whether the given address is on the whitelist to ovmCREATE/ovmCREATE2, and reverts if not.
* Checks whether the given address is on the whitelist to ovmCREATE/ovmCREATE2,
* and reverts if not.
* @param _deployerAddress Address attempting to deploy a contract.
*/
function _checkDeployerAllowed(
......@@ -1048,17 +1054,21 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
bytes memory _returndata
)
{
// We reserve addresses of the form 0xdeaddeaddead...NNNN for the container contracts in L2 geth.
// So, we block calls to these addresses since they are not safe to run as an OVM contract itself.
// We reserve addresses of the form 0xdeaddeaddead...NNNN for the container contracts in L2
// geth. So, we block calls to these addresses since they are not safe to run as an OVM
// contract itself.
if (
(uint256(_contract) & uint256(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000))
(uint256(_contract) &
uint256(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000))
== uint256(CONTAINER_CONTRACT_PREFIX)
) {
// solhint-disable-next-line max-line-length
// EVM does not return data in the success case, see: https://github.com/ethereum/go-ethereum/blob/aae7660410f0ef90279e14afaaf2f429fdc2a186/core/vm/instructions.go#L600-L604
return (true, hex'');
}
// Both 0x0000... and the EVM precompiles have the same address on L1 and L2 --> no trie lookup needed.
// Both 0x0000... and the EVM precompiles have the same address on L1 and L2 -->
// no trie lookup needed.
address codeContractAddress =
uint(_contract) < 100
? _contract
......@@ -1074,11 +1084,13 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
}
/**
* Handles all interactions which involve the execution manager calling out to untrusted code (both calls and creates).
* Ensures that OVM-related measures are enforced, including L2 gas refunds, nuisance gas, and flagged reversions.
* Handles all interactions which involve the execution manager calling out to untrusted code
* (both calls and creates). Ensures that OVM-related measures are enforced, including L2 gas
* refunds, nuisance gas, and flagged reversions.
*
* @param _nextMessageContext Message context to be used for the external message.
* @param _gasLimit Amount of gas to be passed into this message. NOTE: this argument is overwritten in some cases to avoid stack-too-deep.
* @param _gasLimit Amount of gas to be passed into this message. NOTE: this argument is
* overwritten in some cases to avoid stack-too-deep.
* @param _contract OVM address being called or deployed to
* @param _data Data for the message (either calldata or creation code)
* @param _messageType What type of ovmOPCODE this message corresponds to.
......@@ -1100,23 +1112,28 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
)
{
uint256 messageValue = _nextMessageContext.ovmCALLVALUE;
// If there is value in this message, we need to transfer the ETH over before switching contexts.
// If there is value in this message, we need to transfer the ETH over before switching
// contexts.
if (
messageValue > 0
&& _isValueType(_messageType)
) {
// Handle out-of-intrinsic gas consistent with EVM behavior -- the subcall "appears to revert" if we don't have enough gas to transfer the ETH.
// Handle out-of-intrinsic gas consistent with EVM behavior -- the subcall "appears to
// revert" if we don't have enough gas to transfer the ETH.
// Similar to dynamic gas cost of value exceeding gas here:
// solhint-disable-next-line max-line-length
// https://github.com/ethereum/go-ethereum/blob/c503f98f6d5e80e079c1d8a3601d188af2a899da/core/vm/interpreter.go#L268-L273
if (gasleft() < CALL_WITH_VALUE_INTRINSIC_GAS) {
return (false, hex"");
}
// If there *is* enough gas to transfer ETH, then we need to make sure this amount of gas is reserved (i.e. not
// given to the _contract.call below) to guarantee that _handleExternalMessage can't run out of gas.
// In particular, in the event that the call fails, we will need to transfer the ETH back to the sender.
// Taking the lesser of _gasLimit and gasleft() - CALL_WITH_VALUE_INTRINSIC_GAS guarantees that the second
// _attemptForcedEthTransfer below, if needed, always has enough gas to succeed.
// If there *is* enough gas to transfer ETH, then we need to make sure this amount of
// gas is reserved (i.e. not given to the _contract.call below) to guarantee that
// _handleExternalMessage can't run out of gas. In particular, in the event that
// the call fails, we will need to transfer the ETH back to the sender.
// Taking the lesser of _gasLimit and gasleft() - CALL_WITH_VALUE_INTRINSIC_GAS
// guarantees that the second _attemptForcedEthTransfer below, if needed, always has
// enough gas to succeed.
_gasLimit = Math.min(
_gasLimit,
gasleft() - CALL_WITH_VALUE_INTRINSIC_GAS // Cannot overflow due to the above check.
......@@ -1129,8 +1146,10 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
messageValue
);
// If the ETH transfer fails (should only be possible in the case of insufficient balance), then treat this as a revert.
// This mirrors EVM behavior, see https://github.com/ethereum/go-ethereum/blob/2dee31930c9977af2a9fcb518fb9838aa609a7cf/core/vm/evm.go#L298
// If the ETH transfer fails (should only be possible in the case of insufficient
// balance), then treat this as a revert. This mirrors EVM behavior, see
// solhint-disable-next-line max-line-length
// https://github.com/ethereum/go-ethereum/blob/2dee31930c9977af2a9fcb518fb9838aa609a7cf/core/vm/evm.go#L298
if (!transferredOvmEth) {
return (false, hex"");
}
......@@ -1184,16 +1203,18 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
messageValue
);
// Since we transferred it in above and the call reverted, the transfer back should always pass.
// This code path should NEVER be triggered since we sent `messageValue` worth of OVM_ETH into the target
// and reserved sufficient gas to execute the transfer, but in case there is some edge case which has
// been missed, we revert the entire frame (and its parent) to make sure the ETH gets sent back.
// Since we transferred it in above and the call reverted, the transfer back should
// always pass. This code path should NEVER be triggered since we sent `messageValue`
// worth of OVM_ETH into the target and reserved sufficient gas to execute the transfer,
// but in case there is some edge case which has been missed, we revert the entire frame
// (and its parent) to make sure the ETH gets sent back.
if (!transferredOvmEth) {
_revertWithFlag(RevertFlag.OUT_OF_GAS);
}
}
// Switch back to the original message context now that we're out of the call and all OVM_ETH is in the right place.
// Switch back to the original message context now that we're out of the call and all
// OVM_ETH is in the right place.
_switchMessageContext(_nextMessageContext, prevMessageContext);
// Assuming there were no reverts, the message record should be accurate here. We'll update
......@@ -1218,8 +1239,9 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
}
// INTENTIONAL_REVERT, UNSAFE_BYTECODE, STATIC_VIOLATION, and CREATOR_NOT_ALLOWED aren't
// dependent on the input state, so we can just handle them like standard reverts. Our only change here
// is to record the gas refund reported by the call (enforced by safety checking).
// dependent on the input state, so we can just handle them like standard reverts.
// Our only change here is to record the gas refund reported by the call (enforced by
// safety checking).
if (
flag == RevertFlag.INTENTIONAL_REVERT
|| flag == RevertFlag.UNSAFE_BYTECODE
......@@ -1262,7 +1284,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
/**
* Handles the creation-specific safety measures required for OVM contract deployment.
* This function sanitizes the return types for creation messages to match calls (bool, bytes),
* by being an external function which the EM can call, that mimics the success/fail case of the CREATE.
* by being an external function which the EM can call, that mimics the success/fail case of the
* CREATE.
* This allows for consistent handling of both types of messages in _handleExternalMessage().
* Having this step occur as a separate call frame also allows us to easily revert the
* contract deployment in the event that the code is unsafe.
......@@ -1296,6 +1319,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
// developer experience, we do return the remaining gas.
_revertWithFlag(
RevertFlag.UNSAFE_BYTECODE,
// solhint-disable-next-line max-line-length
Lib_ErrorUtils.encodeRevertString("Contract creation code contains unsafe opcodes. Did you use the right compiler or pass an unsafe constructor argument?")
);
}
......@@ -1304,12 +1328,13 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
_initPendingAccount(_address);
// Actually execute the EVM create message.
// NOTE: The inline assembly below means we can NOT make any evm calls between here and then.
// NOTE: The inline assembly below means we can NOT make any evm calls between here and then
address ethAddress = Lib_EthUtils.createContract(_creationCode);
if (ethAddress == address(0)) {
// If the creation fails, the EVM lets us grab its revert data. This may contain a revert flag
// to be used above in _handleExternalMessage, so we pass the revert data back up unmodified.
// If the creation fails, the EVM lets us grab its revert data. This may contain a
// revert flag to be used above in _handleExternalMessage, so we pass the revert data
// back up unmodified.
assembly {
returndatacopy(0,0,returndatasize())
revert(0, returndatasize())
......@@ -1322,6 +1347,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
if (ovmSafetyChecker.isBytecodeSafe(deployedCode) == false) {
_revertWithFlag(
RevertFlag.UNSAFE_BYTECODE,
// solhint-disable-next-line max-line-length
Lib_ErrorUtils.encodeRevertString("Constructor attempted to deploy unsafe bytecode.")
);
}
......@@ -1340,8 +1366,10 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
******************************************/
/**
* Invokes an ovmCALL to OVM_ETH.transfer on behalf of the current ovmADDRESS, allowing us to force movement of OVM_ETH in correspondence with ETH's native value functionality.
* WARNING: this will send on behalf of whatever the messageContext.ovmADDRESS is in storage at the time of the call.
* Invokes an ovmCALL to OVM_ETH.transfer on behalf of the current ovmADDRESS, allowing us to
* force movement of OVM_ETH in correspondence with ETH's native value functionality.
* WARNING: this will send on behalf of whatever the messageContext.ovmADDRESS is in storage
* at the time of the call.
* NOTE: In the future, this could be optimized to directly invoke EM._setContractStorage(...).
* @param _to Amount of OVM_ETH to be sent.
* @param _value Amount of OVM_ETH to send.
......@@ -1362,8 +1390,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
_value
);
// OVM_ETH inherits from the UniswapV2ERC20 standard. In this implementation, its return type
// is a boolean. However, the implementation always returns true if it does not revert.
// OVM_ETH inherits from the UniswapV2ERC20 standard. In this implementation, its return
// type is a boolean. However, the implementation always returns true if it does not revert
// Thus, success of the call frame is sufficient to infer success of the transfer itself.
(bool success, ) = ovmCALL(
gasleft(),
......@@ -1576,7 +1604,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
// on the size of the contract code.
if (_wasAccountAlreadyLoaded == false) {
_useNuisanceGas(
(Lib_EthUtils.getCodeSize(_getAccountEthAddress(_address)) * NUISANCE_GAS_PER_CONTRACT_BYTE) + MIN_NUISANCE_GAS_PER_CONTRACT
(Lib_EthUtils.getCodeSize(_getAccountEthAddress(_address))
* NUISANCE_GAS_PER_CONTRACT_BYTE) + MIN_NUISANCE_GAS_PER_CONTRACT
);
}
}
......@@ -1606,7 +1635,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
if (_wasAccountAlreadyChanged == false) {
ovmStateManager.incrementTotalUncommittedAccounts();
_useNuisanceGas(
(Lib_EthUtils.getCodeSize(_getAccountEthAddress(_address)) * NUISANCE_GAS_PER_CONTRACT_BYTE) + MIN_NUISANCE_GAS_PER_CONTRACT
(Lib_EthUtils.getCodeSize(_getAccountEthAddress(_address))
* NUISANCE_GAS_PER_CONTRACT_BYTE) + MIN_NUISANCE_GAS_PER_CONTRACT
);
}
}
......@@ -1708,11 +1738,12 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
bytes memory _revertdata
)
{
// Out of gas and create exceptions will fundamentally return no data, so simulating it shouldn't either.
// Out of gas and create exceptions will fundamentally return no data, so simulating it
// shouldn't either.
if (
_flag == RevertFlag.OUT_OF_GAS
) {
return bytes('');
return bytes("");
}
// INVALID_STATE_ACCESS doesn't need to return any data other than the flag.
......@@ -1721,7 +1752,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
_flag,
0,
0,
bytes('')
bytes("")
);
}
......@@ -1760,7 +1791,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
RevertFlag.OUT_OF_GAS,
0,
0,
bytes('')
bytes("")
);
}
......@@ -1799,7 +1830,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
)
internal
{
_revertWithFlag(_flag, bytes(''));
_revertWithFlag(_flag, bytes(""));
}
......@@ -1903,9 +1934,9 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
// This check prevents calling run with the default ovmNumber.
// Combined with the first check in run():
// if (transactionContext.ovmNUMBER != DEFAULT_UINT256) { return; }
// It should be impossible to re-enter since run() returns before any other call frames are created.
// Since this value is already being written to storage, we save much gas compared to
// using the standard nonReentrant pattern.
// It should be impossible to re-enter since run() returns before any other call frames are
// created. Since this value is already being written to storage, we save much gas compared
// to using the standard nonReentrant pattern.
if (_transaction.blockNumber == DEFAULT_UINT256) {
return false;
}
......@@ -2046,8 +2077,9 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
)
internal
{
// These conditionals allow us to avoid unneccessary SSTOREs. However, they do mean that the current storage
// value for the messageContext MUST equal the _prevMessageContext argument, or an SSTORE might be erroneously skipped.
// These conditionals allow us to avoid unneccessary SSTOREs. However, they do mean that
// the current storage value for the messageContext MUST equal the _prevMessageContext
// argument, or an SSTORE might be erroneously skipped.
if (_prevMessageContext.ovmCALLER != _nextMessageContext.ovmCALLER) {
messageContext.ovmCALLER = _nextMessageContext.ovmCALLER;
}
......@@ -2134,7 +2166,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
}
/**
* Returns whether or not the given message type (potentially) requires the transfer of ETH value along with the message.
* Returns whether or not the given message type (potentially) requires the transfer of ETH
* value along with the message.
* @param _messageType the message type in question.
*/
function _isValueType(
......@@ -2161,7 +2194,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
/**
* Unreachable helper function for simulating eth_calls with an OVM message context.
* This function will throw an exception in all cases other than when used as a custom entrypoint in L2 Geth to simulate eth_call.
* This function will throw an exception in all cases other than when used as a custom
* entrypoint in L2 Geth to simulate eth_call.
* @param _transaction the message transaction to simulate.
* @param _from the OVM account the simulated call should be from.
* @param _value the amount of ETH value to send.
......
......@@ -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() {
......
// SPDX-License-Identifier: CC0-1.0
/* ERC1820 Pseudo-introspection Registry Contract
* This standard defines a universal registry smart contract where any address (contract or regular account) can
* register which interface it supports and which smart contract is responsible for its implementation.
* This standard defines a universal registry smart contract where any address (contract or regular
* account) can register which interface it supports and which smart contract is responsible for its
* implementation.
*
* Written in 2019 by Jordi Baylina and Jacques Dafflon
*
* To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to
* this software to the public domain worldwide. This software is distributed without any warranty.
* To the extent possible under law, the author(s) have dedicated all copyright and related and
* neighboring rights to this software to the public domain worldwide. This software is distributed
* without any warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
* You should have received a copy of the CC0 Public Domain Dedication along with this software.
* If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
pragma solidity >0.5.0 <0.8.0;
/// @dev The interface a contract MUST implement if it is the implementer of
/// some (other) interface for any address other than itself.
interface ERC1820ImplementerInterface {
/// @notice Indicates whether the contract implements the interface 'interfaceHash' for the address 'addr' or not.
/// @notice Indicates whether the contract implements the interface 'interfaceHash' for the
/// address 'addr' or not.
/// @param interfaceHash keccak256 hash of the name of the interface
/// @param addr Address for which the contract will implement the interface
/// @return ERC1820_ACCEPT_MAGIC only if the contract implements 'interfaceHash' for the address 'addr'.
function canImplementInterfaceForAddress(bytes32 interfaceHash, address addr) external view returns(bytes32);
/// @return ERC1820_ACCEPT_MAGIC only if the contract implements 'interfaceHash' for the address
/// 'addr'.
function canImplementInterfaceForAddress(bytes32 interfaceHash, address addr) external view
returns(bytes32);
}
/**
......@@ -35,25 +40,31 @@ interface ERC1820ImplementerInterface {
contract ERC1820Registry {
bytes4 constant internal INVALID_ID = 0xffffffff;
bytes4 constant internal ERC165ID = 0x01ffc9a7;
bytes32 constant internal ERC1820_ACCEPT_MAGIC = keccak256(abi.encodePacked("ERC1820_ACCEPT_MAGIC"));
bytes32 constant internal ERC1820_ACCEPT_MAGIC =
keccak256(abi.encodePacked("ERC1820_ACCEPT_MAGIC"));
mapping(address => mapping(bytes32 => address)) internal interfaces;
mapping(address => address) internal managers;
mapping(address => mapping(bytes4 => bool)) internal erc165Cached;
/// @notice Indicates a contract is the 'implementer' of 'interfaceHash' for 'addr'.
event InterfaceImplementerSet(address indexed addr, bytes32 indexed interfaceHash, address indexed implementer);
event InterfaceImplementerSet(
address indexed addr,
bytes32 indexed interfaceHash,
address indexed implementer);
/// @notice Indicates 'newManager' is the address of the new manager for 'addr'.
event ManagerChanged(address indexed addr, address indexed newManager);
/// @notice Query if an address implements an interface and through which contract.
/// @param _addr Address being queried for the implementer of an interface.
/// (If '_addr' is the zero address then 'msg.sender' is assumed.)
// (If '_addr' is the zero address then 'msg.sender' is assumed.)
/// @param _interfaceHash Keccak256 hash of the name of the interface as a string.
/// E.g., 'web3.utils.keccak256("ERC777TokensRecipient")' for the 'ERC777TokensRecipient' interface.
/// @return The address of the contract which implements the interface '_interfaceHash' for '_addr'
/// or '0' if '_addr' did not register an implementer for this interface.
function getInterfaceImplementer(address _addr, bytes32 _interfaceHash) external view returns (address) {
// E.g., 'web3.utils.keccak256("ERC777TokensRecipient")' for the 'ERC777TokensRecipient'
// interface.
/// @return The address of the contract which implements the interface '_interfaceHash' for
// '_addr' or '0' if '_addr' did not register an implementer for this interface.
function getInterfaceImplementer(address _addr, bytes32 _interfaceHash) external view
returns (address) {
address addr = _addr == address(0) ? msg.sender : _addr;
if (isERC165Interface(_interfaceHash)) {
bytes4 erc165InterfaceHash = bytes4(_interfaceHash);
......@@ -63,14 +74,16 @@ contract ERC1820Registry {
}
/// @notice Sets the contract which implements a specific interface for an address.
/// Only the manager defined for that address can set it.
/// (Each address is the manager for itself until it sets a new manager.)
// Only the manager defined for that address can set it.
// (Each address is the manager for itself until it sets a new manager.)
/// @param _addr Address for which to set the interface.
/// (If '_addr' is the zero address then 'msg.sender' is assumed.)
// (If '_addr' is the zero address then 'msg.sender' is assumed.)
/// @param _interfaceHash Keccak256 hash of the name of the interface as a string.
/// E.g., 'web3.utils.keccak256("ERC777TokensRecipient")' for the 'ERC777TokensRecipient' interface.
// e.g. 'web3.utils.keccak256("ERC777TokensRecipient")' for the 'ERC777TokensRecipient'
// interface.
/// @param _implementer Contract address implementing '_interfaceHash' for '_addr'.
function setInterfaceImplementer(address _addr, bytes32 _interfaceHash, address _implementer) external {
function setInterfaceImplementer(address _addr, bytes32 _interfaceHash, address _implementer)
external {
address addr = _addr == address(0) ? msg.sender : _addr;
require(getManager(addr) == msg.sender, "Not the manager");
......@@ -87,9 +100,10 @@ contract ERC1820Registry {
}
/// @notice Sets '_newManager' as manager for '_addr'.
/// The new manager will be able to call 'setInterfaceImplementer' for '_addr'.
// The new manager will be able to call 'setInterfaceImplementer' for '_addr'.
/// @param _addr Address for which to set the new manager.
/// @param _newManager Address of the new manager for 'addr'. (Pass '0x0' to reset the manager to '_addr'.)
/// @param _newManager Address of the new manager for 'addr'.
// (Pass '0x0' to reset the manager to '_addr'.)
function setManager(address _addr, address _newManager) external {
require(getManager(_addr) == msg.sender, "Not the manager");
managers[_addr] = _newManager == _addr ? address(0) : _newManager;
......@@ -129,23 +143,27 @@ contract ERC1820Registry {
/// @notice Checks whether a contract implements an ERC165 interface or not.
// If the result is not cached a direct lookup on the contract address is performed.
// If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling
// If the result is not cached or the cached value is out-of-date, the cache MUST be updated
// manually by calling
// 'updateERC165Cache' with the contract address.
/// @param _contract Address of the contract to check.
/// @param _interfaceId ERC165 interface to check.
/// @return True if '_contract' implements '_interfaceId', false otherwise.
function implementsERC165Interface(address _contract, bytes4 _interfaceId) public view returns (bool) {
function implementsERC165Interface(address _contract, bytes4 _interfaceId) public view
returns (bool) {
if (!erc165Cached[_contract][_interfaceId]) {
return implementsERC165InterfaceNoCache(_contract, _interfaceId);
}
return interfaces[_contract][_interfaceId] == _contract;
}
/// @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache.
/// @notice Checks whether a contract implements an ERC165 interface or not without using nor
// updating the cache.
/// @param _contract Address of the contract to check.
/// @param _interfaceId ERC165 interface to check.
/// @return True if '_contract' implements '_interfaceId', false otherwise.
function implementsERC165InterfaceNoCache(address _contract, bytes4 _interfaceId) public view returns (bool) {
function implementsERC165InterfaceNoCache(address _contract, bytes4 _interfaceId) public view
returns (bool) {
uint256 success;
uint256 result;
......@@ -168,8 +186,10 @@ contract ERC1820Registry {
/// @notice Checks whether the hash is a ERC165 interface (ending with 28 zeroes) or not.
/// @param _interfaceHash The hash to check.
/// @return True if '_interfaceHash' is an ERC165 interface (ending with 28 zeroes), false otherwise.
/// @return True if '_interfaceHash' is an ERC165 interface (ending with 28 zeroes),
// false otherwise.
function isERC165Interface(bytes32 _interfaceHash) internal pure returns (bool) {
// solhint-disable-next-line max-line-length
return _interfaceHash & 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0;
}
......@@ -180,7 +200,7 @@ contract ERC1820Registry {
bytes4 erc165ID = ERC165ID;
assembly {
let x := mload(0x40) // Find empty storage location using "free memory pointer"
let x := mload(0x40) // Find empty storage location using "free memory pointer"
mstore(x, erc165ID) // Place signature at beginning of empty storage
mstore(add(x, 0x04), _interfaceId) // Place first argument directly next to signature
......
......@@ -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;
......
......@@ -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,
}
})
......
......@@ -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 source diff could not be displayed because it is too large. You can view the blob instead.
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