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: ...@@ -134,5 +134,9 @@ jobs:
# if: steps.yarn-cache.outputs.cache-hit != 'true' # if: steps.yarn-cache.outputs.cache-hit != 'true'
run: yarn install run: yarn install
- name: Lint - name: Lint JS and TS
run: yarn lint:check 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 ...@@ -6,7 +6,7 @@ export const FORCE_INCLUSION_PERIOD_SECONDS = 600
export const DEFAULT_ACCOUNTS = defaultAccounts export const DEFAULT_ACCOUNTS = defaultAccounts
export const DEFAULT_ACCOUNTS_HARDHAT = defaultAccounts.map((account) => { export const DEFAULT_ACCOUNTS_HARDHAT = defaultAccounts.map((account) => {
return { return {
balance: ethers.BigNumber.from(account.balance).toHexString(), balance: account.balance,
privateKey: account.secretKey, 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 ...@@ -11,14 +11,19 @@ import { Lib_PredeployAddresses } from "../../../libraries/constants/Lib_Predepl
import { Lib_CrossDomainUtils } from "../../../libraries/bridge/Lib_CrossDomainUtils.sol"; import { Lib_CrossDomainUtils } from "../../../libraries/bridge/Lib_CrossDomainUtils.sol";
/* Interface Imports */ /* Interface Imports */
import { iOVM_L1CrossDomainMessenger } from "../../../iOVM/bridge/messaging/iOVM_L1CrossDomainMessenger.sol"; import { iOVM_L1CrossDomainMessenger } from
import { iOVM_CanonicalTransactionChain } from "../../../iOVM/chain/iOVM_CanonicalTransactionChain.sol"; "../../../iOVM/bridge/messaging/iOVM_L1CrossDomainMessenger.sol";
import { iOVM_CanonicalTransactionChain } from
"../../../iOVM/chain/iOVM_CanonicalTransactionChain.sol";
import { iOVM_StateCommitmentChain } from "../../../iOVM/chain/iOVM_StateCommitmentChain.sol"; import { iOVM_StateCommitmentChain } from "../../../iOVM/chain/iOVM_StateCommitmentChain.sol";
/* External Imports */ /* External Imports */
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import { OwnableUpgradeable } from
import { PausableUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol"; "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; import { PausableUpgradeable } from
"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol";
import { ReentrancyGuardUpgradeable } from
"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
/** /**
* @title OVM_L1CrossDomainMessenger * @title OVM_L1CrossDomainMessenger
...@@ -194,7 +199,8 @@ contract OVM_L1CrossDomainMessenger is ...@@ -194,7 +199,8 @@ contract OVM_L1CrossDomainMessenger is
{ {
address ovmCanonicalTransactionChain = resolve("OVM_CanonicalTransactionChain"); address ovmCanonicalTransactionChain = resolve("OVM_CanonicalTransactionChain");
// Use the CTC queue length as nonce // 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( bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata(
_target, _target,
...@@ -204,7 +210,12 @@ contract OVM_L1CrossDomainMessenger is ...@@ -204,7 +210,12 @@ contract OVM_L1CrossDomainMessenger is
); );
address l2CrossDomainMessenger = resolve("OVM_L2CrossDomainMessenger"); address l2CrossDomainMessenger = resolve("OVM_L2CrossDomainMessenger");
_sendXDomainMessage(ovmCanonicalTransactionChain, l2CrossDomainMessenger, xDomainCalldata, _gasLimit); _sendXDomainMessage(
ovmCanonicalTransactionChain,
l2CrossDomainMessenger,
xDomainCalldata,
_gasLimit
);
emit SentMessage(xDomainCalldata); emit SentMessage(xDomainCalldata);
} }
...@@ -298,7 +309,8 @@ contract OVM_L1CrossDomainMessenger is ...@@ -298,7 +309,8 @@ contract OVM_L1CrossDomainMessenger is
{ {
// Verify that the message is in the queue: // Verify that the message is in the queue:
address canonicalTransactionChain = resolve("OVM_CanonicalTransactionChain"); 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"); address l2CrossDomainMessenger = resolve("OVM_L2CrossDomainMessenger");
// Compute the transactionHash // Compute the transactionHash
...@@ -323,7 +335,12 @@ contract OVM_L1CrossDomainMessenger is ...@@ -323,7 +335,12 @@ contract OVM_L1CrossDomainMessenger is
_queueIndex _queueIndex
); );
_sendXDomainMessage(canonicalTransactionChain, l2CrossDomainMessenger, xDomainCalldata, _gasLimit); _sendXDomainMessage(
canonicalTransactionChain,
l2CrossDomainMessenger,
xDomainCalldata,
_gasLimit
);
} }
......
...@@ -4,8 +4,10 @@ pragma solidity >0.5.0 <0.8.0; ...@@ -4,8 +4,10 @@ pragma solidity >0.5.0 <0.8.0;
pragma experimental ABIEncoderV2; pragma experimental ABIEncoderV2;
/* Interface Imports */ /* Interface Imports */
import { iOVM_L1CrossDomainMessenger } from "../../../iOVM/bridge/messaging/iOVM_L1CrossDomainMessenger.sol"; import { iOVM_L1CrossDomainMessenger } from
import { iOVM_L1MultiMessageRelayer } from "../../../iOVM/bridge/messaging/iOVM_L1MultiMessageRelayer.sol"; "../../../iOVM/bridge/messaging/iOVM_L1CrossDomainMessenger.sol";
import { iOVM_L1MultiMessageRelayer } from
"../../../iOVM/bridge/messaging/iOVM_L1MultiMessageRelayer.sol";
/* Library Imports */ /* Library Imports */
import { Lib_AddressResolver } from "../../../libraries/resolver/Lib_AddressResolver.sol"; import { Lib_AddressResolver } from "../../../libraries/resolver/Lib_AddressResolver.sol";
...@@ -42,6 +44,7 @@ contract OVM_L1MultiMessageRelayer is iOVM_L1MultiMessageRelayer, Lib_AddressRes ...@@ -42,6 +44,7 @@ contract OVM_L1MultiMessageRelayer is iOVM_L1MultiMessageRelayer, Lib_AddressRes
modifier onlyBatchRelayer() { modifier onlyBatchRelayer() {
require( require(
msg.sender == resolve("OVM_L2BatchMessageRelayer"), msg.sender == resolve("OVM_L2BatchMessageRelayer"),
// solhint-disable-next-line max-line-length
"OVM_L1MultiMessageRelayer: Function can only be called by the OVM_L2BatchMessageRelayer" "OVM_L1MultiMessageRelayer: Function can only be called by the OVM_L2BatchMessageRelayer"
); );
_; _;
...@@ -58,7 +61,7 @@ contract OVM_L1MultiMessageRelayer is iOVM_L1MultiMessageRelayer, Lib_AddressRes ...@@ -58,7 +61,7 @@ contract OVM_L1MultiMessageRelayer is iOVM_L1MultiMessageRelayer, Lib_AddressRes
*/ */
function batchRelayMessages( function batchRelayMessages(
L2ToL1Message[] calldata _messages L2ToL1Message[] calldata _messages
) )
override override
external external
onlyBatchRelayer onlyBatchRelayer
......
...@@ -7,7 +7,8 @@ import { Lib_AddressResolver } from "../../../libraries/resolver/Lib_AddressReso ...@@ -7,7 +7,8 @@ import { Lib_AddressResolver } from "../../../libraries/resolver/Lib_AddressReso
import { Lib_CrossDomainUtils } from "../../../libraries/bridge/Lib_CrossDomainUtils.sol"; import { Lib_CrossDomainUtils } from "../../../libraries/bridge/Lib_CrossDomainUtils.sol";
/* Interface Imports */ /* 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_L1MessageSender } from "../../../iOVM/predeploys/iOVM_L1MessageSender.sol";
import { iOVM_L2ToL1MessagePasser } from "../../../iOVM/predeploys/iOVM_L2ToL1MessagePasser.sol"; import { iOVM_L2ToL1MessagePasser } from "../../../iOVM/predeploys/iOVM_L2ToL1MessagePasser.sol";
...@@ -57,8 +58,10 @@ contract OVM_L2CrossDomainMessenger is ...@@ -57,8 +58,10 @@ contract OVM_L2CrossDomainMessenger is
/** /**
* @param _libAddressManager Address of the Address Manager. * @param _libAddressManager Address of the Address Manager.
*/ */
constructor(address _libAddressManager) Lib_AddressResolver(_libAddressManager) ReentrancyGuard() {} constructor(address _libAddressManager)
Lib_AddressResolver(_libAddressManager)
ReentrancyGuard()
{}
/******************** /********************
* Public Functions * * Public Functions *
......
...@@ -18,8 +18,9 @@ import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; ...@@ -18,8 +18,9 @@ import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
/** /**
* @title OVM_L1StandardBridge * @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. * @dev The L1 ETH and ERC20 Bridge is a contract which stores deposited L1 funds and standard
* It synchronizes a corresponding L2 Bridge, informing it of deposits, and listening to it for newly finalized withdrawals. * 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 * Compiler used: solc
* Runtime target: EVM * Runtime target: EVM
...@@ -69,7 +70,9 @@ contract OVM_L1StandardBridge is iOVM_L1StandardBridge, OVM_CrossDomainEnabled { ...@@ -69,7 +70,9 @@ contract OVM_L1StandardBridge is iOVM_L1StandardBridge, OVM_CrossDomainEnabled {
* Depositing * * 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() { modifier onlyEOA() {
// Used to stop deposits from contracts (avoid accidentally lost tokens) // Used to stop deposits from contracts (avoid accidentally lost tokens)
require(!Address.isContract(msg.sender), "Account not EOA"); require(!Address.isContract(msg.sender), "Account not EOA");
...@@ -136,7 +139,8 @@ contract OVM_L1StandardBridge is iOVM_L1StandardBridge, OVM_CrossDomainEnabled { ...@@ -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 _from Account to pull the deposit from on L1.
* @param _to Account to give the deposit to on L2. * @param _to Account to give the deposit to on L2.
* @param _l2Gas Gas limit required to complete the deposit 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 { ...@@ -235,8 +239,9 @@ contract OVM_L1StandardBridge is iOVM_L1StandardBridge, OVM_CrossDomainEnabled {
) )
internal internal
{ {
// When a deposit is initiated on L1, the L1 Bridge transfers the funds to itself for future withdrawals. // When a deposit is initiated on L1, the L1 Bridge transfers the funds to itself for future
// safeTransferFrom also checks if the contract has code, so this will fail if _from is an EOA or address(0). // withdrawals. safeTransferFrom also checks if the contract has code, so this will fail if
// _from is an EOA or address(0).
IERC20(_l1Token).safeTransferFrom( IERC20(_l1Token).safeTransferFrom(
_from, _from,
address(this), address(this),
...@@ -284,7 +289,7 @@ contract OVM_L1StandardBridge is iOVM_L1StandardBridge, OVM_CrossDomainEnabled { ...@@ -284,7 +289,7 @@ contract OVM_L1StandardBridge is iOVM_L1StandardBridge, OVM_CrossDomainEnabled {
onlyFromCrossDomainAccount(l2TokenBridge) onlyFromCrossDomainAccount(l2TokenBridge)
{ {
(bool success, ) = _to.call{value: _amount}(new bytes(0)); (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); emit ETHWithdrawalFinalized(_from, _to, _amount, _data);
} }
...@@ -306,7 +311,7 @@ contract OVM_L1StandardBridge is iOVM_L1StandardBridge, OVM_CrossDomainEnabled { ...@@ -306,7 +311,7 @@ contract OVM_L1StandardBridge is iOVM_L1StandardBridge, OVM_CrossDomainEnabled {
{ {
deposits[_l1Token][_l2Token] = deposits[_l1Token][_l2Token].sub(_amount); 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); IERC20(_l1Token).safeTransfer(_to, _amount);
emit ERC20WithdrawalFinalized(_l1Token, _l2Token, _from, _to, _amount, _data); emit ERC20WithdrawalFinalized(_l1Token, _l2Token, _from, _to, _amount, _data);
...@@ -319,7 +324,8 @@ contract OVM_L1StandardBridge is iOVM_L1StandardBridge, OVM_CrossDomainEnabled { ...@@ -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 * @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. * 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 {} function donateETH() external payable {}
} }
...@@ -17,10 +17,12 @@ import { IL2StandardERC20 } from "../../../libraries/standards/IL2StandardERC20. ...@@ -17,10 +17,12 @@ import { IL2StandardERC20 } from "../../../libraries/standards/IL2StandardERC20.
/** /**
* @title OVM_L2StandardBridge * @title OVM_L2StandardBridge
* @dev The L2 Standard bridge is a contract which works together with the L1 Standard bridge to enable * @dev The L2 Standard bridge is a contract which works together with the L1 Standard bridge to
* ETH and ERC20 transitions between L1 and L2. * 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 acts as a minter for new tokens when it hears about deposits into the L1 Standard
* This contract also acts as a burner of the tokens intended for withdrawal, informing the L1 bridge to release L1 funds. * 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 * Compiler used: optimistic-solc
* Runtime target: OVM * Runtime target: OVM
...@@ -102,7 +104,8 @@ contract OVM_L2StandardBridge is iOVM_L2ERC20Bridge, OVM_CrossDomainEnabled { ...@@ -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 _l2Token Address of L2 token where withdrawal was initiated.
* @param _from Account to pull the deposit from on L2. * @param _from Account to pull the deposit from on L2.
* @param _to Account to give the withdrawal to on L1. * @param _to Account to give the withdrawal to on L1.
...@@ -122,7 +125,8 @@ contract OVM_L2StandardBridge is iOVM_L2ERC20Bridge, OVM_CrossDomainEnabled { ...@@ -122,7 +125,8 @@ contract OVM_L2StandardBridge is iOVM_L2ERC20Bridge, OVM_CrossDomainEnabled {
) )
internal 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); IL2StandardERC20(_l2Token).burn(msg.sender, _amount);
// Construct calldata for l1TokenBridge.finalizeERC20Withdrawal(_to, _amount) // Construct calldata for l1TokenBridge.finalizeERC20Withdrawal(_to, _amount)
...@@ -185,7 +189,8 @@ contract OVM_L2StandardBridge is iOVM_L2ERC20Bridge, OVM_CrossDomainEnabled { ...@@ -185,7 +189,8 @@ contract OVM_L2StandardBridge is iOVM_L2ERC20Bridge, OVM_CrossDomainEnabled {
ERC165Checker.supportsInterface(_l2Token, 0x1d1d8b63) && ERC165Checker.supportsInterface(_l2Token, 0x1d1d8b63) &&
_l1Token == IL2StandardERC20(_l2Token).l1Token() _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); IL2StandardERC20(_l2Token).mint(_to, _amount);
emit DepositFinalized(_l1Token, _l2Token, _from, _to, _amount, _data); emit DepositFinalized(_l1Token, _l2Token, _from, _to, _amount, _data);
} else { } else {
......
...@@ -9,7 +9,8 @@ import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolve ...@@ -9,7 +9,8 @@ import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolve
import { Lib_MerkleTree } from "../../libraries/utils/Lib_MerkleTree.sol"; import { Lib_MerkleTree } from "../../libraries/utils/Lib_MerkleTree.sol";
/* Interface Imports */ /* 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"; import { iOVM_ChainStorageContainer } from "../../iOVM/chain/iOVM_ChainStorageContainer.sol";
/* Contract Imports */ /* Contract Imports */
...@@ -23,8 +24,8 @@ import { Math } from "@openzeppelin/contracts/math/Math.sol"; ...@@ -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 * @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 * 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. * 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 * The CTC also allows any account to 'enqueue' an L2 transaction, which will require that the
* will eventually append it to the rollup state. * Sequencer will eventually append it to the rollup state.
* If the Sequencer does not include an enqueued transaction within the 'force inclusion period', * 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(). * then any account may force it to be included by calling appendQueueBatch().
* *
...@@ -345,6 +346,7 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad ...@@ -345,6 +346,7 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
// TEMPORARY: Disable `appendQueueBatch` for minnet // TEMPORARY: Disable `appendQueueBatch` for minnet
revert("appendQueueBatch is currently disabled."); revert("appendQueueBatch is currently disabled.");
// solhint-disable max-line-length
// _numQueuedTransactions = Math.min(_numQueuedTransactions, getNumPendingQueueElements()); // _numQueuedTransactions = Math.min(_numQueuedTransactions, getNumPendingQueueElements());
// require( // require(
// _numQueuedTransactions > 0, // _numQueuedTransactions > 0,
...@@ -381,6 +383,7 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad ...@@ -381,6 +383,7 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
// _numQueuedTransactions, // _numQueuedTransactions,
// getTotalElements() // getTotalElements()
// ); // );
// solhint-enable max-line-length
} }
/** /**
...@@ -424,7 +427,9 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad ...@@ -424,7 +427,9 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
"Must append at least one element." "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( require(
msg.data.length >= nextTransactionPtr, msg.data.length >= nextTransactionPtr,
...@@ -533,14 +538,16 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad ...@@ -533,14 +538,16 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
uint40 blockTimestamp; uint40 blockTimestamp;
uint40 blockNumber; uint40 blockNumber;
if (curContext.numSubsequentQueueTransactions == 0) { 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); blockTimestamp = uint40(curContext.timestamp);
blockNumber = uint40(curContext.blockNumber); blockNumber = uint40(curContext.blockNumber);
} else { } else {
// The last element is a queue tx, therefore pull timestamp and block number from the queue element. // The last element is a queue tx, therefore pull timestamp and block number from the
// curContext.numSubsequentQueueTransactions > 0 which means that we've processed at least one queue element. // queue element.
// We increment nextQueueIndex after processing each queue element, // curContext.numSubsequentQueueTransactions > 0 which means that we've processed at
// so the index of the last element we processed is nextQueueIndex - 1. // 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( Lib_OVMCodec.QueueElement memory lastElement = _getQueueElement(
nextQueueIndex - 1, nextQueueIndex - 1,
queueRef queueRef
...@@ -667,6 +674,8 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad ...@@ -667,6 +674,8 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
uint40 nextQueueIndex; uint40 nextQueueIndex;
uint40 lastTimestamp; uint40 lastTimestamp;
uint40 lastBlockNumber; uint40 lastBlockNumber;
// solhint-disable max-line-length
assembly { assembly {
extraData := shr(40, extraData) extraData := shr(40, extraData)
totalElements := and(extraData, 0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF) totalElements := and(extraData, 0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF)
...@@ -674,6 +683,7 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad ...@@ -674,6 +683,7 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
lastTimestamp := shr(80, and(extraData, 0x0000000000000000000000000000000000FFFFFFFFFF00000000000000000000)) lastTimestamp := shr(80, and(extraData, 0x0000000000000000000000000000000000FFFFFFFFFF00000000000000000000))
lastBlockNumber := shr(120, and(extraData, 0x000000000000000000000000FFFFFFFFFF000000000000000000000000000000)) lastBlockNumber := shr(120, and(extraData, 0x000000000000000000000000FFFFFFFFFF000000000000000000000000000000))
} }
// solhint-enable max-line-length
return ( return (
totalElements, totalElements,
...@@ -764,10 +774,12 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad ...@@ -764,10 +774,12 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
uint40 elementTimestamp; uint40 elementTimestamp;
uint40 elementBlockNumber; uint40 elementBlockNumber;
// solhint-disable max-line-length
assembly { assembly {
elementTimestamp := and(timestampAndBlockNumber, 0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF) elementTimestamp := and(timestampAndBlockNumber, 0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF)
elementBlockNumber := shr(40, and(timestampAndBlockNumber, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000)) elementBlockNumber := shr(40, and(timestampAndBlockNumber, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000))
} }
// solhint-enable max-line-length
return Lib_OVMCodec.QueueElement({ return Lib_OVMCodec.QueueElement({
transactionHash: transactionHash, transactionHash: transactionHash,
...@@ -834,7 +846,7 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad ...@@ -834,7 +846,7 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
mstore(add(chainElementStart, 1), ctxTimestamp) mstore(add(chainElementStart, 1), ctxTimestamp)
mstore(add(chainElementStart, 33), ctxBlockNumber) mstore(add(chainElementStart, 33), ctxBlockNumber)
// solhint-disable-next-line max-line-length
calldatacopy(add(chainElementStart, BYTES_TILL_TX_DATA), add(_nextTransactionPtr, 3), _txDataLength) calldatacopy(add(chainElementStart, BYTES_TILL_TX_DATA), add(_nextTransactionPtr, 3), _txDataLength)
leafHash := keccak256(chainElementStart, add(BYTES_TILL_TX_DATA, _txDataLength)) leafHash := keccak256(chainElementStart, add(BYTES_TILL_TX_DATA, _txDataLength))
...@@ -876,7 +888,7 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad ...@@ -876,7 +888,7 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
mstore(add(chainElementStart, 1), ctxTimestamp) mstore(add(chainElementStart, 1), ctxTimestamp)
mstore(add(chainElementStart, 33), ctxBlockNumber) 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)) pop(staticcall(gas(), 0x04, add(txData, 0x20), txDataLength, add(chainElementStart, BYTES_TILL_TX_DATA), txDataLength))
leafHash := keccak256(chainElementStart, add(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 ...@@ -989,9 +1001,11 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
_queueRef _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( require(
block.timestamp < nextQueueElement.timestamp + forceInclusionPeriodSeconds, 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." "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 ...@@ -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 _prevContext The previously validated batch context.
* @param _nextContext The batch context to validate with this call. * @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. * @param _queueRef The storage container for the queue.
*/ */
function _validateNextBatchContext( function _validateNextBatchContext(
...@@ -1061,17 +1077,22 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad ...@@ -1061,17 +1077,22 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
internal internal
view view
{ {
// If the queue is not now empty, check the mononoticity of whatever the next batch that will come in is. // If the queue is not now empty, check the mononoticity of whatever the next batch that
if (_queueLength - _nextQueueIndex > 0 && _finalContext.numSubsequentQueueTransactions == 0) { // will come in is.
if (_queueLength - _nextQueueIndex > 0 && _finalContext.numSubsequentQueueTransactions == 0)
{
_validateContextBeforeEnqueue( _validateContextBeforeEnqueue(
_finalContext, _finalContext,
_nextQueueIndex, _nextQueueIndex,
_queueRef _queueRef
); );
} }
// Batches cannot be added from the future, or subsequent enqueue() contexts would violate monotonicity. // Batches cannot be added from the future, or subsequent enqueue() contexts would violate
require(_finalContext.timestamp <= block.timestamp, "Context timestamp is from the future."); // monotonicity.
require(_finalContext.blockNumber <= block.number, "Context block number is from the future."); 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 ...@@ -1119,7 +1140,8 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
bool bool
) )
{ {
OVM_ExecutionManager ovmExecutionManager = OVM_ExecutionManager(resolve("OVM_ExecutionManager")); OVM_ExecutionManager ovmExecutionManager =
OVM_ExecutionManager(resolve("OVM_ExecutionManager"));
uint256 gasLimit = ovmExecutionManager.getMaxTransactionGasLimit(); uint256 gasLimit = ovmExecutionManager.getMaxTransactionGasLimit();
bytes32 leafHash = _getSequencerLeafHash(_txChainElement); bytes32 leafHash = _getSequencerLeafHash(_txChainElement);
...@@ -1151,7 +1173,8 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad ...@@ -1151,7 +1173,8 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
* @param _transaction The transaction we are verifying inclusion of. * @param _transaction The transaction we are verifying inclusion of.
* @param _queueIndex The queueIndex of the queued transaction. * @param _queueIndex The queueIndex of the queued transaction.
* @param _batchHeader Header of the batch the transaction was included in. * @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. * @return True if the transaction was included in the specified location, else false.
*/ */
function _verifyQueueTransaction( function _verifyQueueTransaction(
...@@ -1215,7 +1238,8 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad ...@@ -1215,7 +1238,8 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
) )
{ {
require( require(
Lib_OVMCodec.hashBatchHeader(_batchHeader) == batches().get(uint32(_batchHeader.batchIndex)), Lib_OVMCodec.hashBatchHeader(_batchHeader) ==
batches().get(uint32(_batchHeader.batchIndex)),
"Invalid batch header." "Invalid batch header."
); );
......
...@@ -10,10 +10,10 @@ import { iOVM_ChainStorageContainer } from "../../iOVM/chain/iOVM_ChainStorageCo ...@@ -10,10 +10,10 @@ import { iOVM_ChainStorageContainer } from "../../iOVM/chain/iOVM_ChainStorageCo
/** /**
* @title OVM_ChainStorageContainer * @title OVM_ChainStorageContainer
* @dev The Chain Storage Container provides its owner contract with read, write and delete functionality. * @dev The Chain Storage Container provides its owner contract with read, write and delete
* This provides gas efficiency gains by enabling it to overwrite storage slots which can no longer be used * functionality. This provides gas efficiency gains by enabling it to overwrite storage slots which
* in a fraud proof due to the fraud window having passed, and the associated chain state or * can no longer be used in a fraud proof due to the fraud window having passed, and the associated
* transactions being finalized. * chain state or transactions being finalized.
* Three distinct Chain Storage Containers will be deployed on Layer 1: * Three distinct Chain Storage Containers will be deployed on Layer 1:
* 1. Stores transaction batches for the Canonical Transaction Chain * 1. Stores transaction batches for the Canonical Transaction Chain
* 2. Stores queued transactions 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"; ...@@ -10,12 +10,13 @@ import { Lib_MerkleTree } from "../../libraries/utils/Lib_MerkleTree.sol";
/* Interface Imports */ /* Interface Imports */
import { iOVM_FraudVerifier } from "../../iOVM/verification/iOVM_FraudVerifier.sol"; import { iOVM_FraudVerifier } from "../../iOVM/verification/iOVM_FraudVerifier.sol";
import { iOVM_StateCommitmentChain } from "../../iOVM/chain/iOVM_StateCommitmentChain.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_BondManager } from "../../iOVM/verification/iOVM_BondManager.sol";
import { iOVM_ChainStorageContainer } from "../../iOVM/chain/iOVM_ChainStorageContainer.sol"; import { iOVM_ChainStorageContainer } from "../../iOVM/chain/iOVM_ChainStorageContainer.sol";
/* External Imports */ /* External Imports */
import '@openzeppelin/contracts/math/SafeMath.sol'; import "@openzeppelin/contracts/math/SafeMath.sol";
/** /**
* @title OVM_StateCommitmentChain * @title OVM_StateCommitmentChain
...@@ -149,7 +150,9 @@ contract OVM_StateCommitmentChain is iOVM_StateCommitmentChain, Lib_AddressResol ...@@ -149,7 +150,9 @@ contract OVM_StateCommitmentChain is iOVM_StateCommitmentChain, Lib_AddressResol
); );
require( 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." "Number of state roots cannot exceed the number of canonical transactions."
); );
...@@ -267,6 +270,7 @@ contract OVM_StateCommitmentChain is iOVM_StateCommitmentChain, Lib_AddressResol ...@@ -267,6 +270,7 @@ contract OVM_StateCommitmentChain is iOVM_StateCommitmentChain, Lib_AddressResol
{ {
bytes27 extraData = batches().getGlobalMetadata(); bytes27 extraData = batches().getGlobalMetadata();
// solhint-disable max-line-length
uint40 totalElements; uint40 totalElements;
uint40 lastSequencerTimestamp; uint40 lastSequencerTimestamp;
assembly { assembly {
...@@ -274,6 +278,7 @@ contract OVM_StateCommitmentChain is iOVM_StateCommitmentChain, Lib_AddressResol ...@@ -274,6 +278,7 @@ contract OVM_StateCommitmentChain is iOVM_StateCommitmentChain, Lib_AddressResol
totalElements := and(extraData, 0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF) totalElements := and(extraData, 0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF)
lastSequencerTimestamp := shr(40, and(extraData, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000)) lastSequencerTimestamp := shr(40, and(extraData, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000))
} }
// solhint-enable max-line-length
return ( return (
totalElements, totalElements,
......
...@@ -83,7 +83,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ...@@ -83,7 +83,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
* Default Context Values * * Default Context Values *
**************************/ **************************/
uint256 constant DEFAULT_UINT256 = 0xdefa017defa017defa017defa017defa017defa017defa017defa017defa017d; uint256 constant DEFAULT_UINT256 =
0xdefa017defa017defa017defa017defa017defa017defa017defa017defa017d;
address constant DEFAULT_ADDRESS = 0xdEfa017defA017DeFA017DEfa017DeFA017DeFa0; address constant DEFAULT_ADDRESS = 0xdEfa017defA017DeFA017DEfa017DeFA017DeFa0;
...@@ -92,7 +93,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ...@@ -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; address constant CONTAINER_CONTRACT_PREFIX = 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000;
...@@ -205,7 +207,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ...@@ -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 // OVM_StateManager (expected to be an OVM_StateTransitioner). We can revert here because
// this would make the `run` itself invalid. // this would make the `run` itself invalid.
require( 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), ovmStateManager.isAuthenticated(msg.sender),
"Only authenticated addresses in ovmStateManager can call this function" "Only authenticated addresses in ovmStateManager can call this function"
); );
...@@ -677,7 +680,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ...@@ -677,7 +680,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
bytes memory _returndata 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; MessageContext memory nextMessageContext = messageContext;
nextMessageContext.ovmCALLER = nextMessageContext.ovmADDRESS; nextMessageContext.ovmCALLER = nextMessageContext.ovmADDRESS;
nextMessageContext.ovmADDRESS = _address; nextMessageContext.ovmADDRESS = _address;
...@@ -727,7 +731,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ...@@ -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 _gasLimit Amount of gas to be passed into this call.
* @param _address Address of the contract to call. * @param _address Address of the contract to call.
* @param _calldata Data to send along with the call. * @param _calldata Data to send along with the call.
...@@ -953,7 +958,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ...@@ -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. * @param _deployerAddress Address attempting to deploy a contract.
*/ */
function _checkDeployerAllowed( function _checkDeployerAllowed(
...@@ -1048,17 +1054,21 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ...@@ -1048,17 +1054,21 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
bytes memory _returndata bytes memory _returndata
) )
{ {
// We reserve addresses of the form 0xdeaddeaddead...NNNN for the container contracts in L2 geth. // We reserve addresses of the form 0xdeaddeaddead...NNNN for the container contracts in L2
// So, we block calls to these addresses since they are not safe to run as an OVM contract itself. // geth. So, we block calls to these addresses since they are not safe to run as an OVM
// contract itself.
if ( if (
(uint256(_contract) & uint256(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000)) (uint256(_contract) &
uint256(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000))
== uint256(CONTAINER_CONTRACT_PREFIX) == 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 // 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''); 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 = address codeContractAddress =
uint(_contract) < 100 uint(_contract) < 100
? _contract ? _contract
...@@ -1074,11 +1084,13 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ...@@ -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). * Handles all interactions which involve the execution manager calling out to untrusted code
* Ensures that OVM-related measures are enforced, including L2 gas refunds, nuisance gas, and flagged reversions. * (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 _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 _contract OVM address being called or deployed to
* @param _data Data for the message (either calldata or creation code) * @param _data Data for the message (either calldata or creation code)
* @param _messageType What type of ovmOPCODE this message corresponds to. * @param _messageType What type of ovmOPCODE this message corresponds to.
...@@ -1100,23 +1112,28 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ...@@ -1100,23 +1112,28 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
) )
{ {
uint256 messageValue = _nextMessageContext.ovmCALLVALUE; 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 ( if (
messageValue > 0 messageValue > 0
&& _isValueType(_messageType) && _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: // 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 // https://github.com/ethereum/go-ethereum/blob/c503f98f6d5e80e079c1d8a3601d188af2a899da/core/vm/interpreter.go#L268-L273
if (gasleft() < CALL_WITH_VALUE_INTRINSIC_GAS) { if (gasleft() < CALL_WITH_VALUE_INTRINSIC_GAS) {
return (false, hex""); 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 // If there *is* enough gas to transfer ETH, then we need to make sure this amount of
// given to the _contract.call below) to guarantee that _handleExternalMessage can't run out of gas. // gas is reserved (i.e. not given to the _contract.call below) to guarantee that
// In particular, in the event that the call fails, we will need to transfer the ETH back to the sender. // _handleExternalMessage can't run out of gas. In particular, in the event that
// Taking the lesser of _gasLimit and gasleft() - CALL_WITH_VALUE_INTRINSIC_GAS guarantees that the second // the call fails, we will need to transfer the ETH back to the sender.
// _attemptForcedEthTransfer below, if needed, always has enough gas to succeed. // 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 = Math.min(
_gasLimit, _gasLimit,
gasleft() - CALL_WITH_VALUE_INTRINSIC_GAS // Cannot overflow due to the above check. 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 { ...@@ -1129,8 +1146,10 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
messageValue messageValue
); );
// If the ETH transfer fails (should only be possible in the case of insufficient balance), then treat this as a revert. // If the ETH transfer fails (should only be possible in the case of insufficient
// This mirrors EVM behavior, see https://github.com/ethereum/go-ethereum/blob/2dee31930c9977af2a9fcb518fb9838aa609a7cf/core/vm/evm.go#L298 // 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) { if (!transferredOvmEth) {
return (false, hex""); return (false, hex"");
} }
...@@ -1184,16 +1203,18 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ...@@ -1184,16 +1203,18 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
messageValue messageValue
); );
// Since we transferred it in above and the call reverted, the transfer back should always pass. // Since we transferred it in above and the call reverted, the transfer back should
// This code path should NEVER be triggered since we sent `messageValue` worth of OVM_ETH into the target // always pass. This code path should NEVER be triggered since we sent `messageValue`
// and reserved sufficient gas to execute the transfer, but in case there is some edge case which has // worth of OVM_ETH into the target and reserved sufficient gas to execute the transfer,
// been missed, we revert the entire frame (and its parent) to make sure the ETH gets sent back. // 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) { if (!transferredOvmEth) {
_revertWithFlag(RevertFlag.OUT_OF_GAS); _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); _switchMessageContext(_nextMessageContext, prevMessageContext);
// Assuming there were no reverts, the message record should be accurate here. We'll update // 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 { ...@@ -1218,8 +1239,9 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
} }
// INTENTIONAL_REVERT, UNSAFE_BYTECODE, STATIC_VIOLATION, and CREATOR_NOT_ALLOWED aren't // 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 // dependent on the input state, so we can just handle them like standard reverts.
// is to record the gas refund reported by the call (enforced by safety checking). // Our only change here is to record the gas refund reported by the call (enforced by
// safety checking).
if ( if (
flag == RevertFlag.INTENTIONAL_REVERT flag == RevertFlag.INTENTIONAL_REVERT
|| flag == RevertFlag.UNSAFE_BYTECODE || flag == RevertFlag.UNSAFE_BYTECODE
...@@ -1262,7 +1284,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ...@@ -1262,7 +1284,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
/** /**
* Handles the creation-specific safety measures required for OVM contract deployment. * 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), * 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(). * 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 * 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. * contract deployment in the event that the code is unsafe.
...@@ -1296,6 +1319,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ...@@ -1296,6 +1319,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
// developer experience, we do return the remaining gas. // developer experience, we do return the remaining gas.
_revertWithFlag( _revertWithFlag(
RevertFlag.UNSAFE_BYTECODE, 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?") 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 { ...@@ -1304,12 +1328,13 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
_initPendingAccount(_address); _initPendingAccount(_address);
// Actually execute the EVM create message. // 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); address ethAddress = Lib_EthUtils.createContract(_creationCode);
if (ethAddress == address(0)) { if (ethAddress == address(0)) {
// If the creation fails, the EVM lets us grab its revert data. This may contain a revert flag // If the creation fails, the EVM lets us grab its revert data. This may contain a
// to be used above in _handleExternalMessage, so we pass the revert data back up unmodified. // revert flag to be used above in _handleExternalMessage, so we pass the revert data
// back up unmodified.
assembly { assembly {
returndatacopy(0,0,returndatasize()) returndatacopy(0,0,returndatasize())
revert(0, returndatasize()) revert(0, returndatasize())
...@@ -1322,6 +1347,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ...@@ -1322,6 +1347,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
if (ovmSafetyChecker.isBytecodeSafe(deployedCode) == false) { if (ovmSafetyChecker.isBytecodeSafe(deployedCode) == false) {
_revertWithFlag( _revertWithFlag(
RevertFlag.UNSAFE_BYTECODE, RevertFlag.UNSAFE_BYTECODE,
// solhint-disable-next-line max-line-length
Lib_ErrorUtils.encodeRevertString("Constructor attempted to deploy unsafe bytecode.") Lib_ErrorUtils.encodeRevertString("Constructor attempted to deploy unsafe bytecode.")
); );
} }
...@@ -1340,8 +1366,10 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ...@@ -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. * Invokes an ovmCALL to OVM_ETH.transfer on behalf of the current ovmADDRESS, allowing us to
* WARNING: this will send on behalf of whatever the messageContext.ovmADDRESS is in storage at the time of the call. * 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(...). * NOTE: In the future, this could be optimized to directly invoke EM._setContractStorage(...).
* @param _to Amount of OVM_ETH to be sent. * @param _to Amount of OVM_ETH to be sent.
* @param _value Amount of OVM_ETH to send. * @param _value Amount of OVM_ETH to send.
...@@ -1362,8 +1390,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ...@@ -1362,8 +1390,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
_value _value
); );
// OVM_ETH inherits from the UniswapV2ERC20 standard. In this implementation, its return type // OVM_ETH inherits from the UniswapV2ERC20 standard. In this implementation, its return
// is a boolean. However, the implementation always returns true if it does not revert. // 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. // Thus, success of the call frame is sufficient to infer success of the transfer itself.
(bool success, ) = ovmCALL( (bool success, ) = ovmCALL(
gasleft(), gasleft(),
...@@ -1576,7 +1604,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ...@@ -1576,7 +1604,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
// on the size of the contract code. // on the size of the contract code.
if (_wasAccountAlreadyLoaded == false) { if (_wasAccountAlreadyLoaded == false) {
_useNuisanceGas( _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 { ...@@ -1606,7 +1635,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
if (_wasAccountAlreadyChanged == false) { if (_wasAccountAlreadyChanged == false) {
ovmStateManager.incrementTotalUncommittedAccounts(); ovmStateManager.incrementTotalUncommittedAccounts();
_useNuisanceGas( _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 { ...@@ -1708,11 +1738,12 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
bytes memory _revertdata 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 ( if (
_flag == RevertFlag.OUT_OF_GAS _flag == RevertFlag.OUT_OF_GAS
) { ) {
return bytes(''); return bytes("");
} }
// INVALID_STATE_ACCESS doesn't need to return any data other than the flag. // 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 { ...@@ -1721,7 +1752,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
_flag, _flag,
0, 0,
0, 0,
bytes('') bytes("")
); );
} }
...@@ -1760,7 +1791,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ...@@ -1760,7 +1791,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
RevertFlag.OUT_OF_GAS, RevertFlag.OUT_OF_GAS,
0, 0,
0, 0,
bytes('') bytes("")
); );
} }
...@@ -1799,7 +1830,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ...@@ -1799,7 +1830,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
) )
internal internal
{ {
_revertWithFlag(_flag, bytes('')); _revertWithFlag(_flag, bytes(""));
} }
...@@ -1903,9 +1934,9 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ...@@ -1903,9 +1934,9 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
// This check prevents calling run with the default ovmNumber. // This check prevents calling run with the default ovmNumber.
// Combined with the first check in run(): // Combined with the first check in run():
// if (transactionContext.ovmNUMBER != DEFAULT_UINT256) { return; } // if (transactionContext.ovmNUMBER != DEFAULT_UINT256) { return; }
// It should be impossible to re-enter since run() returns before any other call frames are created. // It should be impossible to re-enter since run() returns before any other call frames are
// Since this value is already being written to storage, we save much gas compared to // created. Since this value is already being written to storage, we save much gas compared
// using the standard nonReentrant pattern. // to using the standard nonReentrant pattern.
if (_transaction.blockNumber == DEFAULT_UINT256) { if (_transaction.blockNumber == DEFAULT_UINT256) {
return false; return false;
} }
...@@ -2046,8 +2077,9 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ...@@ -2046,8 +2077,9 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
) )
internal internal
{ {
// These conditionals allow us to avoid unneccessary SSTOREs. However, they do mean that the current storage // These conditionals allow us to avoid unneccessary SSTOREs. However, they do mean that
// value for the messageContext MUST equal the _prevMessageContext argument, or an SSTORE might be erroneously skipped. // the current storage value for the messageContext MUST equal the _prevMessageContext
// argument, or an SSTORE might be erroneously skipped.
if (_prevMessageContext.ovmCALLER != _nextMessageContext.ovmCALLER) { if (_prevMessageContext.ovmCALLER != _nextMessageContext.ovmCALLER) {
messageContext.ovmCALLER = _nextMessageContext.ovmCALLER; messageContext.ovmCALLER = _nextMessageContext.ovmCALLER;
} }
...@@ -2134,7 +2166,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ...@@ -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. * @param _messageType the message type in question.
*/ */
function _isValueType( function _isValueType(
...@@ -2161,7 +2194,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ...@@ -2161,7 +2194,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
/** /**
* Unreachable helper function for simulating eth_calls with an OVM message context. * 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 _transaction the message transaction to simulate.
* @param _from the OVM account the simulated call should be from. * @param _from the OVM account the simulated call should be from.
* @param _value the amount of ETH value to send. * @param _value the amount of ETH value to send.
......
...@@ -51,8 +51,10 @@ contract OVM_SafetyChecker is iOVM_SafetyChecker { ...@@ -51,8 +51,10 @@ contract OVM_SafetyChecker is iOVM_SafetyChecker {
uint256(0x0000000000000000000000000000000000000000000000000000000000000000) uint256(0x0000000000000000000000000000000000000000000000000000000000000000)
]; ];
// Mask to gate opcode specific cases // Mask to gate opcode specific cases
// solhint-disable-next-line max-line-length
uint256 opcodeGateMask = ~uint256(0xffffffffffffffffffffffe000000000fffffffff070ffff9c0ffffec000f001); uint256 opcodeGateMask = ~uint256(0xffffffffffffffffffffffe000000000fffffffff070ffff9c0ffffec000f001);
// Halting opcodes // Halting opcodes
// solhint-disable-next-line max-line-length
uint256 opcodeHaltingMask = ~uint256(0x4008000000000000000000000000000000000000004000000000000000000001); uint256 opcodeHaltingMask = ~uint256(0x4008000000000000000000000000000000000000004000000000000000000001);
// PUSH opcodes // PUSH opcodes
uint256 opcodePushMask = ~uint256(0xffffffff000000000000000000000000); uint256 opcodePushMask = ~uint256(0xffffffff000000000000000000000000);
...@@ -67,6 +69,7 @@ contract OVM_SafetyChecker is iOVM_SafetyChecker { ...@@ -67,6 +69,7 @@ contract OVM_SafetyChecker is iOVM_SafetyChecker {
// current opcode: 0x00...0xff // current opcode: 0x00...0xff
uint256 opNum; uint256 opNum;
/* solhint-disable max-line-length */
// inline assembly removes the extra add + bounds check // inline assembly removes the extra add + bounds check
assembly { assembly {
let word := mload(_pc) //load the next 32 bytes at pc into word let word := mload(_pc) //load the next 32 bytes at pc into word
...@@ -86,6 +89,7 @@ contract OVM_SafetyChecker is iOVM_SafetyChecker { ...@@ -86,6 +89,7 @@ contract OVM_SafetyChecker is iOVM_SafetyChecker {
opNum := byte(indexInWord, word) opNum := byte(indexInWord, word)
} }
/* solhint-enable max-line-length */
// + push opcodes // + push opcodes
// + stop opcodes [STOP(0x00),JUMP(0x56),RETURN(0xf3),INVALID(0xfe)] // + stop opcodes [STOP(0x00),JUMP(0x56),RETURN(0xf3),INVALID(0xfe)]
...@@ -96,11 +100,12 @@ contract OVM_SafetyChecker is iOVM_SafetyChecker { ...@@ -96,11 +100,12 @@ contract OVM_SafetyChecker is iOVM_SafetyChecker {
if (opBit & opcodePushMask == 0) { if (opBit & opcodePushMask == 0) {
// all pushes are valid opcodes // all pushes are valid opcodes
// subsequent bytes are not opcodes. Skip them. // subsequent bytes are not opcodes. Skip them.
_pc += (opNum - 0x5e); // PUSH1 is 0x60, so opNum-0x5f = PUSHed bytes and we +1 to _pc += (opNum - 0x5e); // PUSH1 is 0x60, so opNum-0x5f = PUSHed bytes and we
// skip the _pc++; line below in order to save gas ((-0x5f + 1) = -0x5e) // +1 to skip the _pc++; line below in order to save gas ((-0x5f + 1) = -0x5e)
continue; continue;
} else if (opBit & opcodeHaltingMask == 0) { } 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! // We are now inside unreachable code until we hit a JUMPDEST!
do { do {
_pc++; _pc++;
...@@ -110,7 +115,8 @@ contract OVM_SafetyChecker is iOVM_SafetyChecker { ...@@ -110,7 +115,8 @@ contract OVM_SafetyChecker is iOVM_SafetyChecker {
// encountered a JUMPDEST // encountered a JUMPDEST
if (opNum == 0x5b) break; if (opNum == 0x5b) break;
// skip PUSHed bytes // 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); } while (_pc < codeLength);
// opNum is 0x5b, so we don't continue here since the pc++ is fine // opNum is 0x5b, so we don't continue here since the pc++ is fine
} else if (opNum == 0x33) { // Caller opcode } else if (opNum == 0x33) { // Caller opcode
...@@ -129,7 +135,11 @@ contract OVM_SafetyChecker is iOVM_SafetyChecker { ...@@ -129,7 +135,11 @@ contract OVM_SafetyChecker is iOVM_SafetyChecker {
if ((firstOps >> 192) == 0x3350600060045af1) { if ((firstOps >> 192) == 0x3350600060045af1) {
_pc += 8; _pc += 8;
// Call EM and abort execution if instructed // 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) { } else if (firstOps == 0x336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760 && secondOps == 0x016000f35b) {
_pc += 37; _pc += 37;
} else { } else {
......
...@@ -10,8 +10,9 @@ import { iOVM_StateManager } from "../../iOVM/execution/iOVM_StateManager.sol"; ...@@ -10,8 +10,9 @@ import { iOVM_StateManager } from "../../iOVM/execution/iOVM_StateManager.sol";
/** /**
* @title OVM_StateManager * @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 * @dev The State Manager contract holds all storage values for contracts in the OVM. It can only be
* the Execution Manager and State Transitioner. It runs on L1 during the setup and execution of a fraud proof. * 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 * 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). * (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 { ...@@ -24,10 +25,12 @@ contract OVM_StateManager is iOVM_StateManager {
* Constants * * Constants *
*************/ *************/
bytes32 constant internal EMPTY_ACCOUNT_STORAGE_ROOT = 0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421; bytes32 constant internal EMPTY_ACCOUNT_STORAGE_ROOT =
bytes32 constant internal EMPTY_ACCOUNT_CODE_HASH = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; 0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421;
bytes32 constant internal STORAGE_XOR_VALUE = 0xFEEDFACECAFEBEEFFEEDFACECAFEBEEFFEEDFACECAFEBEEFFEEDFACECAFEBEEF; bytes32 constant internal EMPTY_ACCOUNT_CODE_HASH =
0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
bytes32 constant internal STORAGE_XOR_VALUE =
0xFEEDFACECAFEBEEFFEEDFACECAFEBEEFFEEDFACECAFEBEEFFEEDFACECAFEBEEF;
/************* /*************
* Variables * * Variables *
...@@ -42,7 +45,6 @@ contract OVM_StateManager is iOVM_StateManager { ...@@ -42,7 +45,6 @@ contract OVM_StateManager is iOVM_StateManager {
uint256 internal totalUncommittedAccounts; uint256 internal totalUncommittedAccounts;
uint256 internal totalUncommittedContractStorage; uint256 internal totalUncommittedContractStorage;
/*************** /***************
* Constructor * * Constructor *
***************/ ***************/
...@@ -57,13 +59,13 @@ contract OVM_StateManager is iOVM_StateManager { ...@@ -57,13 +59,13 @@ contract OVM_StateManager is iOVM_StateManager {
owner = _owner; owner = _owner;
} }
/********************** /**********************
* Function Modifiers * * 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. * or the OVM_ExecutionManager during transaction execution.
*/ */
modifier authenticated() { modifier authenticated() {
......
// SPDX-License-Identifier: CC0-1.0 // SPDX-License-Identifier: CC0-1.0
/* ERC1820 Pseudo-introspection Registry Contract /* ERC1820 Pseudo-introspection Registry Contract
* This standard defines a universal registry smart contract where any address (contract or regular account) can * This standard defines a universal registry smart contract where any address (contract or regular
* register which interface it supports and which smart contract is responsible for its implementation. * 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 * 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 * To the extent possible under law, the author(s) have dedicated all copyright and related and
* this software to the public domain worldwide. This software is distributed without any warranty. * 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 * You should have received a copy of the CC0 Public Domain Dedication along with this software.
* <http://creativecommons.org/publicdomain/zero/1.0/>. * If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
*/ */
pragma solidity >0.5.0 <0.8.0; pragma solidity >0.5.0 <0.8.0;
/// @dev The interface a contract MUST implement if it is the implementer of /// @dev The interface a contract MUST implement if it is the implementer of
/// some (other) interface for any address other than itself. /// some (other) interface for any address other than itself.
interface ERC1820ImplementerInterface { 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 interfaceHash keccak256 hash of the name of the interface
/// @param addr Address for which the contract will implement 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'. /// @return ERC1820_ACCEPT_MAGIC only if the contract implements 'interfaceHash' for the address
function canImplementInterfaceForAddress(bytes32 interfaceHash, address addr) external view returns(bytes32); /// 'addr'.
function canImplementInterfaceForAddress(bytes32 interfaceHash, address addr) external view
returns(bytes32);
} }
/** /**
...@@ -35,25 +40,31 @@ interface ERC1820ImplementerInterface { ...@@ -35,25 +40,31 @@ interface ERC1820ImplementerInterface {
contract ERC1820Registry { contract ERC1820Registry {
bytes4 constant internal INVALID_ID = 0xffffffff; bytes4 constant internal INVALID_ID = 0xffffffff;
bytes4 constant internal ERC165ID = 0x01ffc9a7; 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 => mapping(bytes32 => address)) internal interfaces;
mapping(address => address) internal managers; mapping(address => address) internal managers;
mapping(address => mapping(bytes4 => bool)) internal erc165Cached; mapping(address => mapping(bytes4 => bool)) internal erc165Cached;
/// @notice Indicates a contract is the 'implementer' of 'interfaceHash' for 'addr'. /// @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'. /// @notice Indicates 'newManager' is the address of the new manager for 'addr'.
event ManagerChanged(address indexed addr, address indexed newManager); event ManagerChanged(address indexed addr, address indexed newManager);
/// @notice Query if an address implements an interface and through which contract. /// @notice Query if an address implements an interface and through which contract.
/// @param _addr Address being queried for the implementer of an interface. /// @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. /// @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'
/// @return The address of the contract which implements the interface '_interfaceHash' for '_addr' // interface.
/// or '0' if '_addr' did not register an implementer for this interface. /// @return The address of the contract which implements the interface '_interfaceHash' for
function getInterfaceImplementer(address _addr, bytes32 _interfaceHash) external view returns (address) { // '_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; address addr = _addr == address(0) ? msg.sender : _addr;
if (isERC165Interface(_interfaceHash)) { if (isERC165Interface(_interfaceHash)) {
bytes4 erc165InterfaceHash = bytes4(_interfaceHash); bytes4 erc165InterfaceHash = bytes4(_interfaceHash);
...@@ -63,14 +74,16 @@ contract ERC1820Registry { ...@@ -63,14 +74,16 @@ contract ERC1820Registry {
} }
/// @notice Sets the contract which implements a specific interface for an address. /// @notice Sets the contract which implements a specific interface for an address.
/// Only the manager defined for that address can set it. // Only the manager defined for that address can set it.
/// (Each address is the manager for itself until it sets a new manager.) // (Each address is the manager for itself until it sets a new manager.)
/// @param _addr Address for which to set the interface. /// @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. /// @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'. /// @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; address addr = _addr == address(0) ? msg.sender : _addr;
require(getManager(addr) == msg.sender, "Not the manager"); require(getManager(addr) == msg.sender, "Not the manager");
...@@ -87,9 +100,10 @@ contract ERC1820Registry { ...@@ -87,9 +100,10 @@ contract ERC1820Registry {
} }
/// @notice Sets '_newManager' as manager for '_addr'. /// @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 _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 { function setManager(address _addr, address _newManager) external {
require(getManager(_addr) == msg.sender, "Not the manager"); require(getManager(_addr) == msg.sender, "Not the manager");
managers[_addr] = _newManager == _addr ? address(0) : _newManager; managers[_addr] = _newManager == _addr ? address(0) : _newManager;
...@@ -129,23 +143,27 @@ contract ERC1820Registry { ...@@ -129,23 +143,27 @@ contract ERC1820Registry {
/// @notice Checks whether a contract implements an ERC165 interface or not. /// @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 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. // 'updateERC165Cache' with the contract address.
/// @param _contract Address of the contract to check. /// @param _contract Address of the contract to check.
/// @param _interfaceId ERC165 interface to check. /// @param _interfaceId ERC165 interface to check.
/// @return True if '_contract' implements '_interfaceId', false otherwise. /// @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]) { if (!erc165Cached[_contract][_interfaceId]) {
return implementsERC165InterfaceNoCache(_contract, _interfaceId); return implementsERC165InterfaceNoCache(_contract, _interfaceId);
} }
return interfaces[_contract][_interfaceId] == _contract; 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 _contract Address of the contract to check.
/// @param _interfaceId ERC165 interface to check. /// @param _interfaceId ERC165 interface to check.
/// @return True if '_contract' implements '_interfaceId', false otherwise. /// @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 success;
uint256 result; uint256 result;
...@@ -168,8 +186,10 @@ contract ERC1820Registry { ...@@ -168,8 +186,10 @@ contract ERC1820Registry {
/// @notice Checks whether the hash is a ERC165 interface (ending with 28 zeroes) or not. /// @notice Checks whether the hash is a ERC165 interface (ending with 28 zeroes) or not.
/// @param _interfaceHash The hash to check. /// @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) { function isERC165Interface(bytes32 _interfaceHash) internal pure returns (bool) {
// solhint-disable-next-line max-line-length
return _interfaceHash & 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0; return _interfaceHash & 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0;
} }
...@@ -180,7 +200,7 @@ contract ERC1820Registry { ...@@ -180,7 +200,7 @@ contract ERC1820Registry {
bytes4 erc165ID = ERC165ID; bytes4 erc165ID = ERC165ID;
assembly { 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(x, erc165ID) // Place signature at beginning of empty storage
mstore(add(x, 0x04), _interfaceId) // Place first argument directly next to signature mstore(add(x, 0x04), _interfaceId) // Place first argument directly next to signature
......
...@@ -7,7 +7,8 @@ import { iOVM_ECDSAContractAccount } from "../../iOVM/predeploys/iOVM_ECDSAContr ...@@ -7,7 +7,8 @@ import { iOVM_ECDSAContractAccount } from "../../iOVM/predeploys/iOVM_ECDSAContr
/* Library Imports */ /* Library Imports */
import { Lib_EIP155Tx } from "../../libraries/codec/Lib_EIP155Tx.sol"; 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"; import { Lib_PredeployAddresses } from "../../libraries/constants/Lib_PredeployAddresses.sol";
/* Contract Imports */ /* Contract Imports */
...@@ -152,9 +153,9 @@ contract OVM_ECDSAContractAccount is iOVM_ECDSAContractAccount { ...@@ -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. // cases, but since this is a contract we'd end up bumping the nonce twice.
Lib_ExecutionManagerWrapper.ovmINCREMENTNONCE(); Lib_ExecutionManagerWrapper.ovmINCREMENTNONCE();
// NOTE: Upgrades are temporarily disabled because users can, in theory, modify their EOA // NOTE: Upgrades are temporarily disabled because users can, in theory, modify their
// so that they don't have to pay any fees to the sequencer. Function will remain disabled // EOA so that they don't have to pay any fees to the sequencer. Function will remain
// until a robust solution is in place. // disabled until a robust solution is in place.
require( require(
_transaction.to != Lib_ExecutionManagerWrapper.ovmADDRESS(), _transaction.to != Lib_ExecutionManagerWrapper.ovmADDRESS(),
"Calls to self are disabled until upgradability is re-enabled." "Calls to self are disabled until upgradability is re-enabled."
......
...@@ -41,17 +41,18 @@ contract OVM_ETH is L2StandardERC20, IWETH9 { ...@@ -41,17 +41,18 @@ contract OVM_ETH is L2StandardERC20, IWETH9 {
/** /**
* Implements the WETH9 deposit() function as a no-op. * Implements the WETH9 deposit() function as a no-op.
* WARNING: this function does NOT have to do with cross-chain asset bridging. The * WARNING: this function does NOT have to do with cross-chain asset bridging. The relevant
* relevant deposit and withdraw functions for that use case can be found at L2StandardBridge.sol. * 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. * This function allows developers to treat OVM_ETH as WETH without any modifications to their
* code.
*/ */
function deposit() function deposit()
public public
payable payable
override override
{ {
// Calling deposit() with nonzero value will send the ETH to this contract address. Once recieved here, // Calling deposit() with nonzero value will send the ETH to this contract address.
// We transfer it back by sending to the msg.sender. // Once received here, we transfer it back by sending to the msg.sender.
_transfer(address(this), msg.sender, msg.value); _transfer(address(this), msg.sender, msg.value);
emit Deposit(msg.sender, msg.value); emit Deposit(msg.sender, msg.value);
...@@ -59,9 +60,10 @@ contract OVM_ETH is L2StandardERC20, IWETH9 { ...@@ -59,9 +60,10 @@ contract OVM_ETH is L2StandardERC20, IWETH9 {
/** /**
* Implements the WETH9 withdraw() function as a no-op. * Implements the WETH9 withdraw() function as a no-op.
* WARNING: this function does NOT have to do with cross-chain asset bridging. The * WARNING: this function does NOT have to do with cross-chain asset bridging. The relevant
* relevant deposit and withdraw functions for that use case can be found at L2StandardBridge.sol. * 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. * This function allows developers to treat OVM_ETH as WETH without any modifications to their
* code.
* @param _wad Amount being withdrawn * @param _wad Amount being withdrawn
*/ */
function withdraw( function withdraw(
...@@ -70,10 +72,12 @@ contract OVM_ETH is L2StandardERC20, IWETH9 { ...@@ -70,10 +72,12 @@ contract OVM_ETH is L2StandardERC20, IWETH9 {
external external
override 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); 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); emit Withdrawal(msg.sender, _wad);
} }
} }
...@@ -36,9 +36,9 @@ contract OVM_L2ToL1MessagePasser is iOVM_L2ToL1MessagePasser { ...@@ -36,9 +36,9 @@ contract OVM_L2ToL1MessagePasser is iOVM_L2ToL1MessagePasser {
override override
public public
{ {
// Note: although this function is public, only messages sent from the OVM_L2CrossDomainMessenger // Note: although this function is public, only messages sent from the
// will be relayed by the OVM_L1CrossDomainMessenger. This is enforced by a check in // OVM_L2CrossDomainMessenger will be relayed by the OVM_L1CrossDomainMessenger.
// OVM_L1CrossDomainMessenger._verifyStorageProof(). // This is enforced by a check in OVM_L1CrossDomainMessenger._verifyStorageProof().
sentMessages[keccak256( sentMessages[keccak256(
abi.encodePacked( abi.encodePacked(
_message, _message,
......
...@@ -4,13 +4,14 @@ pragma solidity >0.5.0 <0.8.0; ...@@ -4,13 +4,14 @@ pragma solidity >0.5.0 <0.8.0;
/* Library Imports */ /* Library Imports */
import { Lib_Bytes32Utils } from "../../libraries/utils/Lib_Bytes32Utils.sol"; import { Lib_Bytes32Utils } from "../../libraries/utils/Lib_Bytes32Utils.sol";
import { Lib_PredeployAddresses } from "../../libraries/constants/Lib_PredeployAddresses.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 * @title OVM_ProxyEOA
* @dev The Proxy EOA contract uses a delegate call to execute the logic in an implementation contract. * @dev The Proxy EOA contract uses a delegate call to execute the logic in an implementation
* In combination with the logic implemented in the ECDSA Contract Account, this enables a form of upgradable * contract. In combination with the logic implemented in the ECDSA Contract Account, this enables
* 'account abstraction' on layer 2. * a form of upgradable 'account abstraction' on layer 2.
* *
* Compiler used: optimistic-solc * Compiler used: optimistic-solc
* Runtime target: OVM * Runtime target: OVM
...@@ -29,10 +30,9 @@ contract OVM_ProxyEOA { ...@@ -29,10 +30,9 @@ contract OVM_ProxyEOA {
/************* /*************
* Constants * * Constants *
*************/ *************/
// solhint-disable-next-line max-line-length
bytes32 constant IMPLEMENTATION_KEY = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; //bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1); bytes32 constant IMPLEMENTATION_KEY = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; //bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1);
/********************* /*********************
* Fallback Function * * Fallback Function *
*********************/ *********************/
......
...@@ -4,7 +4,8 @@ pragma experimental ABIEncoderV2; ...@@ -4,7 +4,8 @@ pragma experimental ABIEncoderV2;
/* Library Imports */ /* Library Imports */
import { Lib_EIP155Tx } from "../../libraries/codec/Lib_EIP155Tx.sol"; 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"; import { iOVM_ECDSAContractAccount } from "../../iOVM/predeploys/iOVM_ECDSAContractAccount.sol";
/** /**
......
...@@ -61,6 +61,7 @@ contract OVM_SequencerFeeVault { ...@@ -61,6 +61,7 @@ contract OVM_SequencerFeeVault {
require( require(
balance >= MIN_WITHDRAWAL_AMOUNT, balance >= MIN_WITHDRAWAL_AMOUNT,
// solhint-disable-next-line max-line-length
"OVM_SequencerFeeVault: withdrawal amount must be greater than minimum withdrawal amount" "OVM_SequencerFeeVault: withdrawal amount must be greater than minimum withdrawal amount"
); );
......
...@@ -13,6 +13,7 @@ abstract contract Abs_FraudContributor is Lib_AddressResolver { ...@@ -13,6 +13,7 @@ abstract contract Abs_FraudContributor is Lib_AddressResolver {
uint256 startGas = gasleft(); uint256 startGas = gasleft();
_; _;
uint256 gasSpent = 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 { ...@@ -75,9 +75,12 @@ contract OVM_BondManager is iOVM_BondManager, Lib_AddressResolver {
********************/ ********************/
/// Adds `who` to the list of witnessProviders for the provided `preStateRoot`. /// 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 // 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); require(transitioner == msg.sender, Errors.ONLY_TRANSITIONER);
witnessProviders[_preStateRoot].total += gasSpent; witnessProviders[_preStateRoot].total += gasSpent;
......
...@@ -9,10 +9,12 @@ import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolve ...@@ -9,10 +9,12 @@ import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolve
/* Interface Imports */ /* Interface Imports */
import { iOVM_FraudVerifier } from "../../iOVM/verification/iOVM_FraudVerifier.sol"; import { iOVM_FraudVerifier } from "../../iOVM/verification/iOVM_FraudVerifier.sol";
import { iOVM_StateTransitioner } from "../../iOVM/verification/iOVM_StateTransitioner.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_BondManager } from "../../iOVM/verification/iOVM_BondManager.sol";
import { iOVM_StateCommitmentChain } from "../../iOVM/chain/iOVM_StateCommitmentChain.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 */ /* Contract Imports */
import { Abs_FraudContributor } from "./Abs_FraudContributor.sol"; import { Abs_FraudContributor } from "./Abs_FraudContributor.sol";
...@@ -108,8 +110,10 @@ contract OVM_FraudVerifier is Lib_AddressResolver, Abs_FraudContributor, iOVM_Fr ...@@ -108,8 +110,10 @@ contract OVM_FraudVerifier is Lib_AddressResolver, Abs_FraudContributor, iOVM_Fr
return; return;
} }
iOVM_StateCommitmentChain ovmStateCommitmentChain = iOVM_StateCommitmentChain(resolve("OVM_StateCommitmentChain")); iOVM_StateCommitmentChain ovmStateCommitmentChain =
iOVM_CanonicalTransactionChain ovmCanonicalTransactionChain = iOVM_CanonicalTransactionChain(resolve("OVM_CanonicalTransactionChain")); iOVM_StateCommitmentChain(resolve("OVM_StateCommitmentChain"));
iOVM_CanonicalTransactionChain ovmCanonicalTransactionChain =
iOVM_CanonicalTransactionChain(resolve("OVM_CanonicalTransactionChain"));
require( require(
ovmStateCommitmentChain.verifyStateCommitment( ovmStateCommitmentChain.verifyStateCommitment(
...@@ -131,6 +135,7 @@ contract OVM_FraudVerifier is Lib_AddressResolver, Abs_FraudContributor, iOVM_Fr ...@@ -131,6 +135,7 @@ contract OVM_FraudVerifier is Lib_AddressResolver, Abs_FraudContributor, iOVM_Fr
); );
require ( require (
// solhint-disable-next-line max-line-length
_preStateRootBatchHeader.prevTotalElements + _preStateRootProof.index + 1 == _transactionBatchHeader.prevTotalElements + _transactionProof.index, _preStateRootBatchHeader.prevTotalElements + _preStateRootProof.index + 1 == _transactionBatchHeader.prevTotalElements + _transactionProof.index,
"Pre-state root global index must equal to the transaction root global 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 ...@@ -169,7 +174,8 @@ contract OVM_FraudVerifier is Lib_AddressResolver, Abs_FraudContributor, iOVM_Fr
contributesToFraudProof(_preStateRoot, _txHash) contributesToFraudProof(_preStateRoot, _txHash)
{ {
iOVM_StateTransitioner transitioner = getStateTransitioner(_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( require(
transitioner.isComplete() == true, transitioner.isComplete() == true,
...@@ -177,6 +183,7 @@ contract OVM_FraudVerifier is Lib_AddressResolver, Abs_FraudContributor, iOVM_Fr ...@@ -177,6 +183,7 @@ contract OVM_FraudVerifier is Lib_AddressResolver, Abs_FraudContributor, iOVM_Fr
); );
require ( require (
// solhint-disable-next-line max-line-length
_postStateRootBatchHeader.prevTotalElements + _postStateRootProof.index == _preStateRootBatchHeader.prevTotalElements + _preStateRootProof.index + 1, _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." "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 ...@@ -208,7 +215,8 @@ contract OVM_FraudVerifier is Lib_AddressResolver, Abs_FraudContributor, iOVM_Fr
_cancelStateTransition(_postStateRootBatchHeader, _preStateRoot); _cancelStateTransition(_postStateRootBatchHeader, _preStateRoot);
// TEMPORARY: Remove the transitioner; for minnet. // 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( emit FraudProofFinalized(
_preStateRoot, _preStateRoot,
...@@ -254,14 +262,15 @@ contract OVM_FraudVerifier is Lib_AddressResolver, Abs_FraudContributor, iOVM_Fr ...@@ -254,14 +262,15 @@ contract OVM_FraudVerifier is Lib_AddressResolver, Abs_FraudContributor, iOVM_Fr
) )
internal internal
{ {
transitioners[keccak256(abi.encodePacked(_preStateRoot, _txHash))] = iOVM_StateTransitionerFactory( transitioners[keccak256(abi.encodePacked(_preStateRoot, _txHash))] =
resolve("OVM_StateTransitionerFactory") iOVM_StateTransitionerFactory(
).create( resolve("OVM_StateTransitionerFactory")
address(libAddressManager), ).create(
_stateTransitionIndex, address(libAddressManager),
_preStateRoot, _stateTransitionIndex,
_txHash _preStateRoot,
); _txHash
);
} }
/** /**
...@@ -275,7 +284,8 @@ contract OVM_FraudVerifier is Lib_AddressResolver, Abs_FraudContributor, iOVM_Fr ...@@ -275,7 +284,8 @@ contract OVM_FraudVerifier is Lib_AddressResolver, Abs_FraudContributor, iOVM_Fr
) )
internal 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")); iOVM_BondManager ovmBondManager = iOVM_BondManager(resolve("OVM_BondManager"));
// Delete the state batch. // Delete the state batch.
...@@ -284,7 +294,8 @@ contract OVM_FraudVerifier is Lib_AddressResolver, Abs_FraudContributor, iOVM_Fr ...@@ -284,7 +294,8 @@ contract OVM_FraudVerifier is Lib_AddressResolver, Abs_FraudContributor, iOVM_Fr
); );
// Get the timestamp and publisher for that block. // 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. // Slash the bonds at the bond manager.
ovmBondManager.finalize( ovmBondManager.finalize(
......
...@@ -25,19 +25,20 @@ import { Abs_FraudContributor } from "./Abs_FraudContributor.sol"; ...@@ -25,19 +25,20 @@ import { Abs_FraudContributor } from "./Abs_FraudContributor.sol";
/** /**
* @title OVM_StateTransitioner * @title OVM_StateTransitioner
* @dev The State Transitioner coordinates the execution of a state transition during the evaluation of a * @dev The State Transitioner coordinates the execution of a state transition during the evaluation
* fraud proof. It feeds verified input to the Execution Manager's run(), and controls a State Manager (which is * of a fraud proof. It feeds verified input to the Execution Manager's run(), and controls a
* uniquely created for each fraud proof). * 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 * Once a fraud proof has been initialized, this contract is provided with the pre-state root and
* that the OVM storage slots committed to the State Mangager are contained in that state * 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 * 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 * post-state root by applying the transaction. The Fraud Verifier can then check for fraud by
* the calculated post-state root with the proposed post-state root. * comparing the calculated post-state root with the proposed post-state root.
* *
* Compiler used: solc * Compiler used: solc
* Runtime target: EVM * 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 * * Data Structures *
...@@ -72,7 +73,9 @@ contract OVM_StateTransitioner is Lib_AddressResolver, Abs_FraudContributor, iOV ...@@ -72,7 +73,9 @@ contract OVM_StateTransitioner is Lib_AddressResolver, Abs_FraudContributor, iOV
* Constants * * Constants *
*************/ *************/
// solhint-disable-next-line max-line-length
bytes32 internal constant EMPTY_ACCOUNT_CODE_HASH = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; bytes32 internal constant EMPTY_ACCOUNT_CODE_HASH = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
// solhint-disable-next-line max-line-length
bytes32 internal constant EMPTY_ACCOUNT_STORAGE_ROOT = 0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421; bytes32 internal constant EMPTY_ACCOUNT_STORAGE_ROOT = 0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421;
...@@ -99,7 +102,8 @@ contract OVM_StateTransitioner is Lib_AddressResolver, Abs_FraudContributor, iOV ...@@ -99,7 +102,8 @@ contract OVM_StateTransitioner is Lib_AddressResolver, Abs_FraudContributor, iOV
postStateRoot = _preStateRoot; postStateRoot = _preStateRoot;
transactionHash = _transactionHash; 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 ...@@ -227,6 +231,7 @@ contract OVM_StateTransitioner is Lib_AddressResolver, Abs_FraudContributor, iOV
// of the code stored on L2. // of the code stored on L2.
require( require(
Lib_EthUtils.getCodeHash(ethContractAddress) == account.codeHash, 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." "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 ...@@ -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 // 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). // going into EM, then going into the code contract).
require( 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." "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 // 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 // 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 ...@@ -7,7 +7,8 @@ import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolve
/* Interface Imports */ /* Interface Imports */
import { iOVM_StateTransitioner } from "../../iOVM/verification/iOVM_StateTransitioner.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_FraudVerifier } from "../../iOVM/verification/iOVM_FraudVerifier.sol"; import { iOVM_FraudVerifier } from "../../iOVM/verification/iOVM_FraudVerifier.sol";
/* Contract Imports */ /* Contract Imports */
......
...@@ -3,7 +3,9 @@ pragma solidity >0.5.0 <0.8.0; ...@@ -3,7 +3,9 @@ pragma solidity >0.5.0 <0.8.0;
pragma experimental ABIEncoderV2; pragma experimental ABIEncoderV2;
/* Interface Imports */ /* 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 { interface iOVM_L1MultiMessageRelayer {
struct L2ToL1Message { struct L2ToL1Message {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
pragma solidity >0.5.0; pragma solidity >0.5.0;
pragma experimental ABIEncoderV2; pragma experimental ABIEncoderV2;
import './iOVM_L1ERC20Bridge.sol'; import "./iOVM_L1ERC20Bridge.sol";
/** /**
* @title iOVM_L1StandardBridge * @title iOVM_L1StandardBridge
...@@ -29,7 +29,7 @@ interface iOVM_L1StandardBridge is iOVM_L1ERC20Bridge { ...@@ -29,7 +29,7 @@ interface iOVM_L1StandardBridge is iOVM_L1ERC20Bridge {
/******************** /********************
* Public Functions * * Public Functions *
********************/ ********************/
/** /**
* @dev Deposit an amount of the ETH to the caller's balance on L2. * @dev Deposit an amount of the ETH to the caller's balance on L2.
* @param _l2Gas Gas limit required to complete the deposit on L2. * @param _l2Gas Gas limit required to complete the deposit on L2.
...@@ -66,8 +66,8 @@ interface iOVM_L1StandardBridge is iOVM_L1ERC20Bridge { ...@@ -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 * @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the
* L1 ETH token. * L1 ETH token. Since only the xDomainMessenger can call this function, it will never be called
* Since only the xDomainMessenger can call this function, it will never be called before the withdrawal is finalized. * before the withdrawal is finalized.
* @param _from L2 address initiating the transfer. * @param _from L2 address initiating the transfer.
* @param _to L1 address to credit the withdrawal to. * @param _to L1 address to credit the withdrawal to.
* @param _amount Amount of the ERC20 to deposit. * @param _amount Amount of the ERC20 to deposit.
......
...@@ -85,8 +85,8 @@ interface iOVM_L2ERC20Bridge { ...@@ -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 * @dev Complete a deposit from L1 to L2, and credits funds to the recipient's balance of this
* L2 token. * L2 token. This call will fail if it did not originate from a corresponding deposit in
* This call will fail if it did not originate from a corresponding deposit in OVM_l1TokenGateway. * OVM_l1TokenGateway.
* @param _l1Token Address for the l1 token this is called with * @param _l1Token Address for the l1 token this is called with
* @param _l2Token Address for the l2 token this is called with * @param _l2Token Address for the l2 token this is called with
* @param _from Account to pull the deposit from on L2. * @param _from Account to pull the deposit from on L2.
......
...@@ -119,8 +119,10 @@ interface iOVM_ExecutionManager { ...@@ -119,8 +119,10 @@ interface iOVM_ExecutionManager {
* Contract Creation Opcodes * * Contract Creation Opcodes *
*****************************/ *****************************/
function ovmCREATE(bytes memory _bytecode) external returns (address _contract, bytes memory _revertdata); function ovmCREATE(bytes memory _bytecode) external
function ovmCREATE2(bytes memory _bytecode, bytes32 _salt) external returns (address _contract, bytes memory _revertdata); 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 { ...@@ -137,10 +139,14 @@ interface iOVM_ExecutionManager {
****************************/ ****************************/
// Valueless ovmCALL for maintaining backwards compatibility with legacy OVM bytecode. // 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, bytes memory _calldata) external
function ovmCALL(uint256 _gasLimit, address _address, uint256 _value, bytes memory _calldata) external returns (bool _success, bytes memory _returndata); returns (bool _success, bytes memory _returndata);
function ovmSTATICCALL(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)
function ovmDELEGATECALL(uint256 _gasLimit, address _address, bytes memory _calldata) external returns (bool _success, bytes memory _returndata); 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 { ...@@ -155,7 +161,8 @@ interface iOVM_ExecutionManager {
* Contract Code Opcodes * * 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 ovmEXTCODESIZE(address _contract) external returns (uint256 _size);
function ovmEXTCODEHASH(address _contract) external returns (bytes32 _hash); function ovmEXTCODEHASH(address _contract) external returns (bytes32 _hash);
......
...@@ -42,7 +42,8 @@ interface iOVM_StateManager { ...@@ -42,7 +42,8 @@ interface iOVM_StateManager {
function putAccount(address _address, Lib_OVMCodec.Account memory _account) external; function putAccount(address _address, Lib_OVMCodec.Account memory _account) external;
function putEmptyAccount(address _address) 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 hasAccount(address _address) external view returns (bool _exists);
function hasEmptyAccount(address _address) external view returns (bool _exists); function hasEmptyAccount(address _address) external view returns (bool _exists);
function setAccountNonce(address _address, uint256 _nonce) external; function setAccountNonce(address _address, uint256 _nonce) external;
...@@ -50,9 +51,12 @@ interface iOVM_StateManager { ...@@ -50,9 +51,12 @@ interface iOVM_StateManager {
function getAccountEthAddress(address _address) external view returns (address _ethAddress); function getAccountEthAddress(address _address) external view returns (address _ethAddress);
function getAccountStorageRoot(address _address) external view returns (bytes32 _storageRoot); function getAccountStorageRoot(address _address) external view returns (bytes32 _storageRoot);
function initPendingAccount(address _address) external; function initPendingAccount(address _address) external;
function commitPendingAccount(address _address, address _ethAddress, bytes32 _codeHash) external; function commitPendingAccount(address _address, address _ethAddress, bytes32 _codeHash)
function testAndSetAccountLoaded(address _address) external returns (bool _wasAccountAlreadyLoaded); external;
function testAndSetAccountChanged(address _address) external returns (bool _wasAccountAlreadyChanged); 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 commitAccount(address _address) external returns (bool _wasAccountCommitted);
function incrementTotalUncommittedAccounts() external; function incrementTotalUncommittedAccounts() external;
function getTotalUncommittedAccounts() external view returns (uint256 _total); function getTotalUncommittedAccounts() external view returns (uint256 _total);
...@@ -65,13 +69,20 @@ interface iOVM_StateManager { ...@@ -65,13 +69,20 @@ interface iOVM_StateManager {
************************************/ ************************************/
function putContractStorage(address _contract, bytes32 _key, bytes32 _value) external; function putContractStorage(address _contract, bytes32 _key, bytes32 _value) external;
function getContractStorage(address _contract, bytes32 _key) external view returns (bytes32 _value); function getContractStorage(address _contract, bytes32 _key) external view
function hasContractStorage(address _contract, bytes32 _key) external view returns (bool _exists); returns (bytes32 _value);
function testAndSetContractStorageLoaded(address _contract, bytes32 _key) external returns (bool _wasContractStorageAlreadyLoaded); function hasContractStorage(address _contract, bytes32 _key) external view
function testAndSetContractStorageChanged(address _contract, bytes32 _key) external returns (bool _wasContractStorageAlreadyChanged); returns (bool _exists);
function commitContractStorage(address _contract, bytes32 _key) external returns (bool _wasContractStorageCommitted); 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 incrementTotalUncommittedContractStorage() external;
function getTotalUncommittedContractStorage() external view returns (uint256 _total); function getTotalUncommittedContractStorage() external view returns (uint256 _total);
function wasContractStorageChanged(address _contract, bytes32 _key) external view returns (bool); function wasContractStorageChanged(address _contract, bytes32 _key) external view
function wasContractStorageCommitted(address _contract, bytes32 _key) external view returns (bool); returns (bool);
function wasContractStorageCommitted(address _contract, bytes32 _key) external view
returns (bool);
} }
...@@ -9,6 +9,7 @@ interface ERC20 { ...@@ -9,6 +9,7 @@ interface ERC20 {
/// All the errors which may be encountered on the bond manager /// All the errors which may be encountered on the bond manager
library Errors { library Errors {
string constant ERC20_ERR = "BondManager: Could not post bond"; 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 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 SLASHED = "BondManager: Cannot finalize withdrawal, you probably got slashed";
string constant WRONG_STATE = "BondManager: Wrong bond state for proposer"; string constant WRONG_STATE = "BondManager: Wrong bond state for proposer";
...@@ -16,9 +17,11 @@ library Errors { ...@@ -16,9 +17,11 @@ library Errors {
string constant WITHDRAWAL_PENDING = "BondManager: Withdrawal already pending"; string constant WITHDRAWAL_PENDING = "BondManager: Withdrawal already pending";
string constant TOO_EARLY = "BondManager: Too early to finalize your withdrawal"; 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"; 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"; 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 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"; string constant WAIT_FOR_DISPUTES = "BondManager: Wait for other potential disputes";
} }
......
...@@ -36,7 +36,8 @@ interface iOVM_FraudVerifier { ...@@ -36,7 +36,8 @@ interface iOVM_FraudVerifier {
* Public Functions: Transition Status * * 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 @@ ...@@ -2,7 +2,8 @@
pragma solidity >0.5.0 <0.8.0; pragma solidity >0.5.0 <0.8.0;
/* Interface Imports */ /* 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 * @title OVM_CrossDomainEnabled
......
...@@ -138,7 +138,7 @@ library Lib_EIP155Tx { ...@@ -138,7 +138,7 @@ library Lib_EIP155Tx {
// We write the encoding of empty bytes when the transaction is a creation, *not* the zero // We write the encoding of empty bytes when the transaction is a creation, *not* the zero
// address as one might assume. // address as one might assume.
if (_transaction.isCreate) { if (_transaction.isCreate) {
raw[3] = Lib_RLPWriter.writeBytes(''); raw[3] = Lib_RLPWriter.writeBytes("");
} else { } else {
raw[3] = Lib_RLPWriter.writeAddress(_transaction.to); raw[3] = Lib_RLPWriter.writeAddress(_transaction.to);
} }
...@@ -153,8 +153,8 @@ library Lib_EIP155Tx { ...@@ -153,8 +153,8 @@ library Lib_EIP155Tx {
} else { } else {
// Chain ID *is* included in the unsigned transaction. // Chain ID *is* included in the unsigned transaction.
raw[6] = Lib_RLPWriter.writeUint(_transaction.chainId); raw[6] = Lib_RLPWriter.writeUint(_transaction.chainId);
raw[7] = Lib_RLPWriter.writeBytes(''); raw[7] = Lib_RLPWriter.writeBytes("");
raw[8] = Lib_RLPWriter.writeBytes(''); raw[8] = Lib_RLPWriter.writeBytes("");
} }
return Lib_RLPWriter.writeList(raw); return Lib_RLPWriter.writeList(raw);
......
...@@ -11,9 +11,11 @@ library Lib_PredeployAddresses { ...@@ -11,9 +11,11 @@ library Lib_PredeployAddresses {
address internal constant ECDSA_CONTRACT_ACCOUNT = 0x4200000000000000000000000000000000000003; address internal constant ECDSA_CONTRACT_ACCOUNT = 0x4200000000000000000000000000000000000003;
address internal constant SEQUENCER_ENTRYPOINT = 0x4200000000000000000000000000000000000005; address internal constant SEQUENCER_ENTRYPOINT = 0x4200000000000000000000000000000000000005;
address payable internal constant OVM_ETH = 0x4200000000000000000000000000000000000006; 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 L2_CROSS_DOMAIN_MESSENGER = 0x4200000000000000000000000000000000000007;
address internal constant LIB_ADDRESS_MANAGER = 0x4200000000000000000000000000000000000008; address internal constant LIB_ADDRESS_MANAGER = 0x4200000000000000000000000000000000000008;
address internal constant PROXY_EOA = 0x4200000000000000000000000000000000000009; address internal constant PROXY_EOA = 0x4200000000000000000000000000000000000009;
// solhint-disable-next-line max-line-length
address internal constant EXECUTION_MANAGER_WRAPPER = 0x420000000000000000000000000000000000000B; address internal constant EXECUTION_MANAGER_WRAPPER = 0x420000000000000000000000000000000000000B;
address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011; address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011;
address internal constant ERC1820_REGISTRY = 0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24; address internal constant ERC1820_REGISTRY = 0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24;
......
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity =0.7.6; 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 { interface IWETH9 is IERC20 {
event Deposit(address indexed dst, uint256 wad); event Deposit(address indexed dst, uint256 wad);
event Withdrawal(address indexed src, uint256 wad); event Withdrawal(address indexed src, uint256 wad);
......
...@@ -3,7 +3,7 @@ pragma solidity >=0.5.16 <0.8.0; ...@@ -3,7 +3,7 @@ pragma solidity >=0.5.16 <0.8.0;
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import './IL2StandardERC20.sol'; import "./IL2StandardERC20.sol";
contract L2StandardERC20 is IL2StandardERC20, ERC20 { contract L2StandardERC20 is IL2StandardERC20, ERC20 {
address public override l1Token; address public override l1Token;
......
...@@ -148,7 +148,8 @@ library Lib_MerkleTrie { ...@@ -148,7 +148,8 @@ library Lib_MerkleTrie {
) )
{ {
TrieNode[] memory proof = _parseProof(_proof); 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; bool exists = keyRemainder.length == 0;
...@@ -157,7 +158,7 @@ library Lib_MerkleTrie { ...@@ -157,7 +158,7 @@ library Lib_MerkleTrie {
"Provided proof is invalid." "Provided proof is invalid."
); );
bytes memory value = exists ? _getNodeValue(proof[pathLength - 1]) : bytes(''); bytes memory value = exists ? _getNodeValue(proof[pathLength - 1]) : bytes("");
return ( return (
exists, exists,
...@@ -253,7 +254,8 @@ library Lib_MerkleTrie { ...@@ -253,7 +254,8 @@ library Lib_MerkleTrie {
if (currentNode.decoded.length == BRANCH_NODE_LENGTH) { if (currentNode.decoded.length == BRANCH_NODE_LENGTH) {
if (currentKeyIndex == key.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; break;
} else { } else {
// We're not at the end of the key yet. // We're not at the end of the key yet.
...@@ -288,7 +290,8 @@ library Lib_MerkleTrie { ...@@ -288,7 +290,8 @@ library Lib_MerkleTrie {
} else if (prefix == PREFIX_EXTENSION_EVEN || prefix == PREFIX_EXTENSION_ODD) { } else if (prefix == PREFIX_EXTENSION_EVEN || prefix == PREFIX_EXTENSION_ODD) {
if (sharedNibbleLength != pathRemainder.length) { if (sharedNibbleLength != pathRemainder.length) {
// Our extension node is not identical to the remainder. // 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); currentNodeID = bytes32(RLP_NULL);
break; break;
} else { } else {
...@@ -348,6 +351,7 @@ library Lib_MerkleTrie { ...@@ -348,6 +351,7 @@ library Lib_MerkleTrie {
TrieNode[] memory newNodes = new TrieNode[](3); TrieNode[] memory newNodes = new TrieNode[](3);
uint256 totalNewNodes = 0; 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 // Reference: https://github.com/ethereumjs/merkle-patricia-tree/blob/c0a10395aab37d42c175a47114ebfcbd7efcf059/src/baseTrie.ts#L294-L313
bool matchLeaf = false; bool matchLeaf = false;
if (lastNodeType == NodeType.LeafNode) { if (lastNodeType == NodeType.LeafNode) {
...@@ -391,7 +395,8 @@ library Lib_MerkleTrie { ...@@ -391,7 +395,8 @@ library Lib_MerkleTrie {
totalNewNodes += 1; totalNewNodes += 1;
// Create a new leaf node, slicing our remainder since the first byte points // Create a new leaf node, slicing our remainder since the first byte points
// to our branch node. // to our branch node.
newNodes[totalNewNodes] = _makeLeafNode(Lib_BytesUtils.slice(keyRemainder, 1), _value); newNodes[totalNewNodes] =
_makeLeafNode(Lib_BytesUtils.slice(keyRemainder, 1), _value);
totalNewNodes += 1; totalNewNodes += 1;
} }
} else { } else {
...@@ -429,13 +434,23 @@ library Lib_MerkleTrie { ...@@ -429,13 +434,23 @@ library Lib_MerkleTrie {
if (lastNodeType == NodeType.LeafNode) { if (lastNodeType == NodeType.LeafNode) {
// We're dealing with a leaf node. // We're dealing with a leaf node.
// We'll modify the key and insert the old leaf node into the branch index. // We'll modify the key and insert the old leaf node into the branch index.
TrieNode memory modifiedLastNode = _makeLeafNode(lastNodeKey, _getNodeValue(lastNode)); TrieNode memory modifiedLastNode =
newBranch = _editBranchIndex(newBranch, branchKey, _getNodeHash(modifiedLastNode.encoded)); _makeLeafNode(lastNodeKey, _getNodeValue(lastNode));
newBranch =
_editBranchIndex(
newBranch,
branchKey,
_getNodeHash(modifiedLastNode.encoded));
} else if (lastNodeKey.length != 0) { } else if (lastNodeKey.length != 0) {
// We're dealing with a shrinking extension node. // We're dealing with a shrinking extension node.
// We need to modify the node to decrease the size of the key. // We need to modify the node to decrease the size of the key.
TrieNode memory modifiedLastNode = _makeExtensionNode(lastNodeKey, _getNodeValue(lastNode)); TrieNode memory modifiedLastNode =
newBranch = _editBranchIndex(newBranch, branchKey, _getNodeHash(modifiedLastNode.encoded)); _makeExtensionNode(lastNodeKey, _getNodeValue(lastNode));
newBranch =
_editBranchIndex(
newBranch,
branchKey,
_getNodeHash(modifiedLastNode.encoded));
} else { } else {
// We're dealing with an unnecessary extension node. // We're dealing with an unnecessary extension node.
// We're going to delete the node entirely. // We're going to delete the node entirely.
......
...@@ -246,7 +246,9 @@ library Lib_Buffer { ...@@ -246,7 +246,9 @@ library Lib_Buffer {
uint40 length; uint40 length;
bytes27 extraData; bytes27 extraData;
assembly { assembly {
// solhint-disable-next-line max-line-length
length := and(context, 0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF) length := and(context, 0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF)
// solhint-disable-next-line max-line-length
extraData := and(context, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000) extraData := and(context, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000)
} }
......
...@@ -94,7 +94,7 @@ library Lib_BytesUtils { ...@@ -94,7 +94,7 @@ library Lib_BytesUtils {
) )
{ {
if (_start >= _bytes.length) { if (_start >= _bytes.length) {
return bytes(''); return bytes("");
} }
return slice(_bytes, _start, _bytes.length - _start); return slice(_bytes, _start, _bytes.length - _start);
......
...@@ -14,7 +14,8 @@ library Lib_ErrorUtils { ...@@ -14,7 +14,8 @@ library Lib_ErrorUtils {
/** /**
* Encodes an error string into raw solidity-style revert data. * Encodes an error string into raw solidity-style revert data.
* (i.e. ascii bytes, prefixed with bytes4(keccak("Error(string))")) * (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. * @param _reason Reason for the reversion.
* @return Standard solidity revert data for the given reason. * @return Standard solidity revert data for the given reason.
*/ */
......
...@@ -14,8 +14,8 @@ library Lib_MerkleTree { ...@@ -14,8 +14,8 @@ library Lib_MerkleTree {
/** /**
* Calculates a merkle root for a list of 32-byte leaf hashes. WARNING: If the number * 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. * 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, * If you do not know the original length of elements for the tree you are verifying, then
* then this may allow empty leaves past _elements.length to pass a verification check down the line. * 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 * 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. * @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). * @return Merkle root of the leaves, with zero hashes for non-powers-of-two (see above).
...@@ -114,7 +114,8 @@ library Lib_MerkleTree { ...@@ -114,7 +114,8 @@ library Lib_MerkleTree {
* @param _root The Merkle root to verify against. * @param _root The Merkle root to verify against.
* @param _leaf The leaf hash to verify inclusion of. * @param _leaf The leaf hash to verify inclusion of.
* @param _index The index in the tree of this leaf. * @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. * @param _totalLeaves The total number of leaves originally passed into.
* @return Whether or not the merkle branch and leaf passes verification. * @return Whether or not the merkle branch and leaf passes verification.
*/ */
......
...@@ -253,7 +253,8 @@ library Lib_ExecutionManagerWrapper { ...@@ -253,7 +253,8 @@ library Lib_ExecutionManagerWrapper {
bytes memory 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) { if (success == true) {
return returndata; return returndata;
......
...@@ -45,6 +45,9 @@ const config: HardhatUserConfig = { ...@@ -45,6 +45,9 @@ const config: HardhatUserConfig = {
version: '0.7.6', version: '0.7.6',
settings: { settings: {
optimizer: { enabled: true, runs: 200 }, optimizer: { enabled: true, runs: 200 },
metadata: {
bytecodeHash: 'none',
},
outputSelection: { outputSelection: {
'*': { '*': {
'*': ['storageLayout'], '*': ['storageLayout'],
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
"posttest:slither": "rm -f @openzeppelin && rm -f @ens && rm -f hardhat", "posttest:slither": "rm -f @openzeppelin && rm -f @ens && rm -f hardhat",
"lint:check": "eslint .", "lint:check": "eslint .",
"lint:fix": "yarn lint:check --fix", "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", "clean": "rm -rf ./dist ./artifacts ./artifacts-ovm ./cache ./cache-ovm ./tsconfig.build.tsbuildinfo",
"deploy": "ts-node \"./bin/deploy.ts\" && yarn generate-markdown", "deploy": "ts-node \"./bin/deploy.ts\" && yarn generate-markdown",
"serve": "./bin/serve_dump.sh", "serve": "./bin/serve_dump.sh",
...@@ -105,6 +106,7 @@ ...@@ -105,6 +106,7 @@
"lint-staged": "11.0.0", "lint-staged": "11.0.0",
"random-bytes-seed": "^1.0.3", "random-bytes-seed": "^1.0.3",
"rlp": "^2.2.6", "rlp": "^2.2.6",
"solhint": "^3.3.6",
"solidity-coverage": "^0.7.16", "solidity-coverage": "^0.7.16",
"ts-generator": "0.0.8", "ts-generator": "0.0.8",
"ts-node": "^9.1.1", "ts-node": "^9.1.1",
......
...@@ -10,7 +10,7 @@ import { getContractDefinition } from '../../src/contract-defs' ...@@ -10,7 +10,7 @@ import { getContractDefinition } from '../../src/contract-defs'
export const DEFAULT_ACCOUNTS = defaultAccounts export const DEFAULT_ACCOUNTS = defaultAccounts
export const DEFAULT_ACCOUNTS_HARDHAT = defaultAccounts.map((account) => { export const DEFAULT_ACCOUNTS_HARDHAT = defaultAccounts.map((account) => {
return { return {
balance: ethers.BigNumber.from(account.balance).toHexString(), balance: account.balance,
privateKey: account.secretKey, privateKey: account.secretKey,
} }
}) })
......
...@@ -14,7 +14,12 @@ try { ...@@ -14,7 +14,12 @@ try {
ReturnData, ReturnData,
} = require('hardhat/internal/hardhat-network/provider/return-data') } = require('hardhat/internal/hardhat-network/provider/return-data')
decodeRevertReason = (value: Buffer) => { 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 // 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