Commit ac03c25f authored by Kelvin Fichter's avatar Kelvin Fichter

refactor: remove unused contracts

parent 3e2aa16a
...@@ -323,120 +323,5 @@ describe('Native ETH value integration tests', () => { ...@@ -323,120 +323,5 @@ describe('Native ETH value integration tests', () => {
expect(delegatedSuccess).to.be.true expect(delegatedSuccess).to.be.true
expect(delegatedReturndata).to.deep.eq(BigNumber.from(value)) expect(delegatedReturndata).to.deep.eq(BigNumber.from(value))
}) })
describe('Intrinsic gas for ovmCALL types', async () => {
let CALL_WITH_VALUE_INTRINSIC_GAS
let ValueGasMeasurer: Contract
before(async () => {
// Grab public variable from the EM
const OVM_ExecutionManager = new Contract(
await env.addressManager.getAddress('OVM_ExecutionManager'),
getContractInterface('OVM_ExecutionManager'),
env.l1Wallet.provider
)
const CALL_WITH_VALUE_INTRINSIC_GAS_BIGNUM =
await OVM_ExecutionManager.CALL_WITH_VALUE_INTRINSIC_GAS()
CALL_WITH_VALUE_INTRINSIC_GAS =
CALL_WITH_VALUE_INTRINSIC_GAS_BIGNUM.toNumber()
const Factory__ValueGasMeasurer = await ethers.getContractFactory(
'ValueGasMeasurer',
wallet
)
ValueGasMeasurer = await Factory__ValueGasMeasurer.deploy()
await ValueGasMeasurer.deployTransaction.wait()
})
it('a call with value to an empty account consumes <= the intrinsic gas including a buffer', async () => {
const value = 1
const gasLimit = 1_000_000
const minimalSendGas =
await ValueGasMeasurer.callStatic.measureGasOfTransferingEthViaCall(
ethers.constants.AddressZero,
value,
gasLimit,
{
gasLimit: 2_000_000,
}
)
const buffer = 1.2
expect(minimalSendGas * buffer).to.be.lte(CALL_WITH_VALUE_INTRINSIC_GAS)
})
it('a call with value to an reverting account consumes <= the intrinsic gas including a buffer', async () => {
// [magic deploy prefix] . [MSTORE] (will throw exception from no stack args)
const AutoRevertInitcode = '0x600D380380600D6000396000f3' + '52'
const Factory__AutoRevert = new ContractFactory(
new Interface([]),
AutoRevertInitcode,
wallet
)
const AutoRevert: Contract = await Factory__AutoRevert.deploy()
await AutoRevert.deployTransaction.wait()
const value = 1
const gasLimit = 1_000_000
// A revert, causing the ETH to be sent back, should consume the minimal possible gas for a nonzero ETH send
const minimalSendGas =
await ValueGasMeasurer.callStatic.measureGasOfTransferingEthViaCall(
AutoRevert.address,
value,
gasLimit,
{
gasLimit: 2_000_000,
}
)
const buffer = 1.2
expect(minimalSendGas * buffer).to.be.lte(CALL_WITH_VALUE_INTRINSIC_GAS)
})
it('a value call passing less than the intrinsic gas should appear to revert', async () => {
const Factory__PayableConstant: ContractFactory =
await ethers.getContractFactory('PayableConstant', wallet)
const PayableConstant: Contract =
await Factory__PayableConstant.deploy()
await PayableConstant.deployTransaction.wait()
const sendAmount = 15
const [success, returndata] =
await ValueCalls0.callStatic.sendWithDataAndGas(
PayableConstant.address,
sendAmount,
PayableConstant.interface.encodeFunctionData('returnValue'),
CALL_WITH_VALUE_INTRINSIC_GAS - 1,
{
gasLimit: 2_000_000,
}
)
expect(success).to.eq(false)
expect(returndata).to.eq('0x')
})
it('a value call which runs out of gas does not out-of-gas the parent', async () => {
const Factory__TestOOG: ContractFactory =
await ethers.getContractFactory('TestOOG', wallet)
const TestOOG: Contract = await Factory__TestOOG.deploy()
await TestOOG.deployTransaction.wait()
const sendAmount = 15
// Implicitly test that this call is not rejected
const [success, returndata] =
await ValueCalls0.callStatic.sendWithDataAndGas(
TestOOG.address,
sendAmount,
TestOOG.interface.encodeFunctionData('runOutOfGas'),
CALL_WITH_VALUE_INTRINSIC_GAS * 2,
{
gasLimit: 2_000_000,
}
)
expect(success).to.eq(false)
expect(returndata).to.eq('0x')
})
})
}) })
}) })
...@@ -314,20 +314,6 @@ func ApplyOvmStateToState(statedb *state.StateDB, stateDump *dump.OvmDump, l1XDo ...@@ -314,20 +314,6 @@ func ApplyOvmStateToState(statedb *state.StateDB, stateDump *dump.OvmDump, l1XDo
l1BridgeValue := common.BytesToHash(l1StandardBridgeAddress.Bytes()) l1BridgeValue := common.BytesToHash(l1StandardBridgeAddress.Bytes())
statedb.SetState(OVM_L2StandardBridge.Address, l1BridgeSlot, l1BridgeValue) statedb.SetState(OVM_L2StandardBridge.Address, l1BridgeSlot, l1BridgeValue)
} }
ExecutionManager, ok := stateDump.Accounts["OVM_ExecutionManager"]
if ok {
if chainID == nil {
chainID = new(big.Int)
}
log.Info("Setting ovmCHAINID in ExecutionManager", "chain-id", chainID.Uint64())
chainIdSlot := common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000007")
chainIdValue := common.BytesToHash(chainID.Bytes())
statedb.SetState(ExecutionManager.Address, chainIdSlot, chainIdValue)
log.Info("Setting maxTransactionGasLimit in ExecutionManager", "gas-limit", gasLimit)
maxTxGasLimitSlot := common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000004")
maxTxGasLimitValue := common.BytesToHash(new(big.Int).SetUint64(gasLimit).Bytes())
statedb.SetState(ExecutionManager.Address, maxTxGasLimitSlot, maxTxGasLimitValue)
}
OVM_SequencerFeeVault, ok := stateDump.Accounts["OVM_SequencerFeeVault"] OVM_SequencerFeeVault, ok := stateDump.Accounts["OVM_SequencerFeeVault"]
if ok { if ok {
log.Info("Setting l1FeeWallet in OVM_SequencerFeeVault", "wallet", l1FeeWalletAddress.Hex()) log.Info("Setting l1FeeWallet in OVM_SequencerFeeVault", "wallet", l1FeeWalletAddress.Hex())
...@@ -514,18 +500,6 @@ func DeveloperGenesisBlock(period uint64, faucet, l1XDomainMessengerAddress comm ...@@ -514,18 +500,6 @@ func DeveloperGenesisBlock(period uint64, faucet, l1XDomainMessengerAddress comm
if !ok { if !ok {
panic("Lib_AddressManager not in state dump") panic("Lib_AddressManager not in state dump")
} }
_, ok = stateDump.Accounts["OVM_StateManager"]
if !ok {
panic("OVM_StateManager not in state dump")
}
_, ok = stateDump.Accounts["OVM_ExecutionManager"]
if !ok {
panic("OVM_ExecutionManager not in state dump")
}
_, ok = stateDump.Accounts["OVM_SequencerEntrypoint"]
if !ok {
panic("OVM_SequencerEntrypoint not in state dump")
}
} }
config.StateDump = &stateDump config.StateDump = &stateDump
......
...@@ -96,10 +96,6 @@ describe('BatchSubmitter', () => { ...@@ -96,10 +96,6 @@ describe('BatchSubmitter', () => {
'OVM_Sequencer', 'OVM_Sequencer',
await sequencer.getAddress() await sequencer.getAddress()
) )
await AddressManager.setAddress(
'OVM_DecompressionPrecompileAddress',
predeploys.OVM_SequencerEntrypoint
)
Mock__OVM_ExecutionManager = await smockit( Mock__OVM_ExecutionManager = await smockit(
await getContractFactory('OVM_ExecutionManager') await getContractFactory('OVM_ExecutionManager')
......
...@@ -36,11 +36,6 @@ const parseEnv = () => { ...@@ -36,11 +36,6 @@ const parseEnv = () => {
'number' 'number'
), ),
ctcMaxTransactionGasLimit: ensure('MAX_TRANSACTION_GAS_LIMIT', 'number'), ctcMaxTransactionGasLimit: ensure('MAX_TRANSACTION_GAS_LIMIT', 'number'),
emMinTransactionGasLimit: ensure('MIN_TRANSACTION_GAS_LIMIT', 'number'),
emMaxtransactionGasLimit: ensure('MAX_TRANSACTION_GAS_LIMIT', 'number'),
emMaxGasPerQueuePerEpoch: ensure('MAX_GAS_PER_QUEUE_PER_EPOCH', 'number'),
emSecondsPerEpoch: ensure('ECONDS_PER_EPOCH', 'number'),
emOvmChainId: ensure('CHAIN_ID', 'number'),
sccFraudProofWindow: ensure('FRAUD_PROOF_WINDOW_SECONDS', 'number'), sccFraudProofWindow: ensure('FRAUD_PROOF_WINDOW_SECONDS', 'number'),
sccSequencerPublishWindow: ensure( sccSequencerPublishWindow: ensure(
'SEQUENCER_PUBLISH_WINDOW_SECONDS', 'SEQUENCER_PUBLISH_WINDOW_SECONDS',
...@@ -56,16 +51,10 @@ const main = async () => { ...@@ -56,16 +51,10 @@ const main = async () => {
l1BlockTimeSeconds: config.l1BlockTimeSeconds, l1BlockTimeSeconds: config.l1BlockTimeSeconds,
ctcForceInclusionPeriodSeconds: config.ctcForceInclusionPeriodSeconds, ctcForceInclusionPeriodSeconds: config.ctcForceInclusionPeriodSeconds,
ctcMaxTransactionGasLimit: config.ctcMaxTransactionGasLimit, ctcMaxTransactionGasLimit: config.ctcMaxTransactionGasLimit,
emMinTransactionGasLimit: config.emMinTransactionGasLimit,
emMaxtransactionGasLimit: config.emMaxtransactionGasLimit,
emMaxGasPerQueuePerEpoch: config.emMaxGasPerQueuePerEpoch,
emSecondsPerEpoch: config.emSecondsPerEpoch,
emOvmChainId: config.emOvmChainId,
sccFraudProofWindow: config.sccFraudProofWindow, sccFraudProofWindow: config.sccFraudProofWindow,
sccSequencerPublishWindow: config.sccFraudProofWindow, sccSequencerPublishWindow: config.sccFraudProofWindow,
ovmSequencerAddress: sequencer.address, ovmSequencerAddress: sequencer.address,
ovmProposerAddress: sequencer.address, ovmProposerAddress: sequencer.address,
ovmRelayerAddress: sequencer.address,
ovmAddressManagerOwner: deployer.address, ovmAddressManagerOwner: deployer.address,
noCompile: process.env.NO_COMPILE ? true : false, noCompile: process.env.NO_COMPILE ? true : false,
}) })
...@@ -75,7 +64,6 @@ const main = async () => { ...@@ -75,7 +64,6 @@ const main = async () => {
// get the hardhat-deploy stuff merged. Woot. // get the hardhat-deploy stuff merged. Woot.
const nicknames = { const nicknames = {
Lib_AddressManager: 'AddressManager', Lib_AddressManager: 'AddressManager',
mockOVM_BondManager: 'OVM_BondManager',
} }
const contracts: any = dirtree( const contracts: any = dirtree(
......
#!/usr/bin/env python3
# pip3 install pyevmasm
from pyevmasm import instruction_tables
#print(instruction_tables.keys())
def asm(x):
return [instruction_tables['istanbul'][i].opcode for i in x]
push_opcodes = asm(["PUSH%d" % i for i in range(1,33)])
stop_opcodes = asm(["STOP", "JUMP", "RETURN", "INVALID"])
caller_opcodes = asm(["CALLER"])
blacklist_ops = set([
"ADDRESS", "BALANCE", "BLOCKHASH",
"CALL", "CALLCODE", "CHAINID", "COINBASE",
"CREATE", "CREATE2", "DELEGATECALL", "DIFFICULTY",
"EXTCODESIZE", "EXTCODECOPY", "EXTCODEHASH",
"GASLIMIT", "GASPRICE", "NUMBER",
"ORIGIN", "REVERT", "SELFBALANCE", "SELFDESTRUCT",
"SLOAD", "SSTORE", "STATICCALL", "TIMESTAMP"])
whitelist_opcodes = []
for x in instruction_tables['istanbul']:
if x.name not in blacklist_ops:
whitelist_opcodes.append(x.opcode)
pushmask = 0
for x in push_opcodes:
pushmask |= 1 << x
stopmask = 0
for x in stop_opcodes:
stopmask |= 1 << x
stoplist = [0]*256
procmask = 0
for i in range(256):
if i in whitelist_opcodes and \
i not in push_opcodes and \
i not in stop_opcodes and \
i not in caller_opcodes:
# can skip this opcode
stoplist[i] = 1
else:
procmask |= 1 << i
# PUSH1 through PUSH4, can't skip in slow
for i in range(0x60, 0x64):
stoplist[i] = i-0x5e
rr = "uint256[8] memory opcodeSkippableBytes = [\n"
for i in range(0, 0x100, 0x20):
ret = "uint256(0x"
for j in range(i, i+0x20, 1):
ret += ("%02X" % stoplist[j])
rr += ret+"),\n"
rr = rr[:-2] + "];"
print(rr)
print("// Mask to gate opcode specific cases")
print("uint256 opcodeGateMask = ~uint256(0x%x);" % procmask)
print("// Halting opcodes")
print("uint256 opcodeHaltingMask = ~uint256(0x%x);" % stopmask)
print("// PUSH opcodes")
print("uint256 opcodePushMask = ~uint256(0x%x);" % pushmask)
...@@ -4,7 +4,6 @@ import * as path from 'path' ...@@ -4,7 +4,6 @@ import * as path from 'path'
import * as mkdirp from 'mkdirp' import * as mkdirp from 'mkdirp'
const env = process.env const env = process.env
const CHAIN_ID = env.CHAIN_ID || '420'
const GAS_PRICE_ORACLE_OWNER = const GAS_PRICE_ORACLE_OWNER =
env.GAS_PRICE_ORACLE_OWNER || '0x' + 'FF'.repeat(20) env.GAS_PRICE_ORACLE_OWNER || '0x' + 'FF'.repeat(20)
...@@ -17,9 +16,6 @@ import { RollupDeployConfig } from '../src/contract-deployment' ...@@ -17,9 +16,6 @@ import { RollupDeployConfig } from '../src/contract-deployment'
mkdirp.sync(outdir) mkdirp.sync(outdir)
const config = { const config = {
ovmGlobalContext: {
ovmCHAINID: parseInt(CHAIN_ID, 10),
},
gasPriceOracleConfig: { gasPriceOracleConfig: {
owner: GAS_PRICE_ORACLE_OWNER, owner: GAS_PRICE_ORACLE_OWNER,
initialGasPrice: 0, initialGasPrice: 0,
......
...@@ -31,7 +31,6 @@ import { ReentrancyGuardUpgradeable } from ...@@ -31,7 +31,6 @@ import { ReentrancyGuardUpgradeable } from
* from L2 onto L1. In the event that a message sent from L1 to L2 is rejected for exceeding the L2 * from L2 onto L1. In the event that a message sent from L1 to L2 is rejected for exceeding the L2
* epoch gas limit, it can be resubmitted via this contract's replay function. * epoch gas limit, it can be resubmitted via this contract's replay function.
* *
* Compiler used: solc
* Runtime target: EVM * Runtime target: EVM
*/ */
contract OVM_L1CrossDomainMessenger is contract OVM_L1CrossDomainMessenger is
...@@ -209,13 +208,12 @@ contract OVM_L1CrossDomainMessenger is ...@@ -209,13 +208,12 @@ contract OVM_L1CrossDomainMessenger is
nonce nonce
); );
address l2CrossDomainMessenger = resolve("OVM_L2CrossDomainMessenger");
_sendXDomainMessage( _sendXDomainMessage(
ovmCanonicalTransactionChain, ovmCanonicalTransactionChain,
l2CrossDomainMessenger,
xDomainCalldata, xDomainCalldata,
_gasLimit _gasLimit
); );
emit SentMessage(xDomainCalldata); emit SentMessage(xDomainCalldata);
} }
...@@ -312,12 +310,11 @@ contract OVM_L1CrossDomainMessenger is ...@@ -312,12 +310,11 @@ contract OVM_L1CrossDomainMessenger is
Lib_OVMCodec.QueueElement memory element = Lib_OVMCodec.QueueElement memory element =
iOVM_CanonicalTransactionChain(canonicalTransactionChain).getQueueElement(_queueIndex); iOVM_CanonicalTransactionChain(canonicalTransactionChain).getQueueElement(_queueIndex);
address l2CrossDomainMessenger = resolve("OVM_L2CrossDomainMessenger");
// Compute the transactionHash // Compute the transactionHash
bytes32 transactionHash = keccak256( bytes32 transactionHash = keccak256(
abi.encode( abi.encode(
address(this), address(this),
l2CrossDomainMessenger, Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER,
_gasLimit, _gasLimit,
_message _message
) )
...@@ -337,7 +334,6 @@ contract OVM_L1CrossDomainMessenger is ...@@ -337,7 +334,6 @@ contract OVM_L1CrossDomainMessenger is
_sendXDomainMessage( _sendXDomainMessage(
canonicalTransactionChain, canonicalTransactionChain,
l2CrossDomainMessenger,
xDomainCalldata, xDomainCalldata,
_gasLimit _gasLimit
); );
...@@ -419,7 +415,7 @@ contract OVM_L1CrossDomainMessenger is ...@@ -419,7 +415,7 @@ contract OVM_L1CrossDomainMessenger is
keccak256( keccak256(
abi.encodePacked( abi.encodePacked(
_xDomainCalldata, _xDomainCalldata,
resolve("OVM_L2CrossDomainMessenger") Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER
) )
), ),
uint256(0) uint256(0)
...@@ -455,20 +451,18 @@ contract OVM_L1CrossDomainMessenger is ...@@ -455,20 +451,18 @@ contract OVM_L1CrossDomainMessenger is
/** /**
* Sends a cross domain message. * Sends a cross domain message.
* @param _canonicalTransactionChain Address of the OVM_CanonicalTransactionChain instance. * @param _canonicalTransactionChain Address of the OVM_CanonicalTransactionChain instance.
* @param _l2CrossDomainMessenger Address of the OVM_L2CrossDomainMessenger instance.
* @param _message Message to send. * @param _message Message to send.
* @param _gasLimit OVM gas limit for the message. * @param _gasLimit OVM gas limit for the message.
*/ */
function _sendXDomainMessage( function _sendXDomainMessage(
address _canonicalTransactionChain, address _canonicalTransactionChain,
address _l2CrossDomainMessenger,
bytes memory _message, bytes memory _message,
uint256 _gasLimit uint256 _gasLimit
) )
internal internal
{ {
iOVM_CanonicalTransactionChain(_canonicalTransactionChain).enqueue( iOVM_CanonicalTransactionChain(_canonicalTransactionChain).enqueue(
_l2CrossDomainMessenger, Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER,
_gasLimit, _gasLimit,
_message _message
); );
......
// SPDX-License-Identifier: MIT
// @unsupported: ovm
pragma solidity >0.5.0 <0.8.0;
pragma experimental ABIEncoderV2;
/* Interface Imports */
import { iOVM_L1CrossDomainMessenger } from
"../../../iOVM/bridge/messaging/iOVM_L1CrossDomainMessenger.sol";
import { iOVM_L1MultiMessageRelayer } from
"../../../iOVM/bridge/messaging/iOVM_L1MultiMessageRelayer.sol";
/* Library Imports */
import { Lib_AddressResolver } from "../../../libraries/resolver/Lib_AddressResolver.sol";
/**
* @title OVM_L1MultiMessageRelayer
* @dev The L1 Multi-Message Relayer contract is a gas efficiency optimization which enables the
* relayer to submit multiple messages in a single transaction to be relayed by the L1 Cross Domain
* Message Sender.
*
* Compiler used: solc
* Runtime target: EVM
*/
contract OVM_L1MultiMessageRelayer is iOVM_L1MultiMessageRelayer, Lib_AddressResolver {
/***************
* Constructor *
***************/
/**
* @param _libAddressManager Address of the Address Manager.
*/
constructor(
address _libAddressManager
)
Lib_AddressResolver(_libAddressManager)
{}
/**********************
* Function Modifiers *
**********************/
modifier onlyBatchRelayer() {
require(
msg.sender == resolve("OVM_L2BatchMessageRelayer"),
// solhint-disable-next-line max-line-length
"OVM_L1MultiMessageRelayer: Function can only be called by the OVM_L2BatchMessageRelayer"
);
_;
}
/********************
* Public Functions *
********************/
/**
* @notice Forwards multiple cross domain messages to the L1 Cross Domain Messenger for relaying
* @param _messages An array of L2 to L1 messages
*/
function batchRelayMessages(
L2ToL1Message[] calldata _messages
)
override
external
onlyBatchRelayer
{
iOVM_L1CrossDomainMessenger messenger = iOVM_L1CrossDomainMessenger(
resolve("Proxy__OVM_L1CrossDomainMessenger")
);
for (uint256 i = 0; i < _messages.length; i++) {
L2ToL1Message memory message = _messages[i];
messenger.relayMessage(
message.target,
message.sender,
message.message,
message.messageNonce,
message.proof
);
}
}
}
...@@ -23,7 +23,6 @@ import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.s ...@@ -23,7 +23,6 @@ import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.s
* @dev The L2 Cross Domain Messenger contract sends messages from L2 to L1, and is the entry point * @dev The L2 Cross Domain Messenger contract sends messages from L2 to L1, and is the entry point
* for L2 messages sent via the L1 Cross Domain Messenger. * for L2 messages sent via the L1 Cross Domain Messenger.
* *
* Compiler used: optimistic-solc
* Runtime target: OVM * Runtime target: OVM
*/ */
contract OVM_L2CrossDomainMessenger is contract OVM_L2CrossDomainMessenger is
......
...@@ -22,7 +22,6 @@ import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; ...@@ -22,7 +22,6 @@ import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
* tokens that are in use on L2. It synchronizes a corresponding L2 Bridge, informing it of deposits * 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. * and listening to it for newly finalized withdrawals.
* *
* Compiler used: solc
* Runtime target: EVM * Runtime target: EVM
*/ */
contract OVM_L1StandardBridge is iOVM_L1StandardBridge, OVM_CrossDomainEnabled { contract OVM_L1StandardBridge is iOVM_L1StandardBridge, OVM_CrossDomainEnabled {
......
...@@ -24,7 +24,6 @@ import { IL2StandardERC20 } from "../../../libraries/standards/IL2StandardERC20. ...@@ -24,7 +24,6 @@ import { IL2StandardERC20 } from "../../../libraries/standards/IL2StandardERC20.
* This contract also acts as a burner of the tokens intended for withdrawal, informing the L1 * This contract also acts as a burner of the tokens intended for withdrawal, informing the L1
* bridge to release L1 funds. * bridge to release L1 funds.
* *
* Compiler used: optimistic-solc
* Runtime target: OVM * Runtime target: OVM
*/ */
contract OVM_L2StandardBridge is iOVM_L2ERC20Bridge, OVM_CrossDomainEnabled { contract OVM_L2StandardBridge is iOVM_L2ERC20Bridge, OVM_CrossDomainEnabled {
......
...@@ -10,7 +10,7 @@ import { Lib_PredeployAddresses } from "../../../libraries/constants/Lib_Predepl ...@@ -10,7 +10,7 @@ import { Lib_PredeployAddresses } from "../../../libraries/constants/Lib_Predepl
* @title OVM_L2StandardTokenFactory * @title OVM_L2StandardTokenFactory
* @dev Factory contract for creating standard L2 token representations of L1 ERC20s * @dev Factory contract for creating standard L2 token representations of L1 ERC20s
* compatible with and working on the standard bridge. * compatible with and working on the standard bridge.
* Compiler used: optimistic-solc *
* Runtime target: OVM * Runtime target: OVM
*/ */
contract OVM_L2StandardTokenFactory { contract OVM_L2StandardTokenFactory {
......
...@@ -13,9 +13,6 @@ import { iOVM_CanonicalTransactionChain } from ...@@ -13,9 +13,6 @@ import { iOVM_CanonicalTransactionChain } from
"../../iOVM/chain/iOVM_CanonicalTransactionChain.sol"; "../../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 */
import { OVM_ExecutionManager } from "../execution/OVM_ExecutionManager.sol";
/* External Imports */ /* External Imports */
import { Math } from "@openzeppelin/contracts/math/Math.sol"; import { Math } from "@openzeppelin/contracts/math/Math.sol";
...@@ -29,7 +26,6 @@ import { Math } from "@openzeppelin/contracts/math/Math.sol"; ...@@ -29,7 +26,6 @@ import { Math } from "@openzeppelin/contracts/math/Math.sol";
* 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().
* *
* Compiler used: solc
* Runtime target: EVM * Runtime target: EVM
*/ */
contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_AddressResolver { contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_AddressResolver {
...@@ -1140,9 +1136,6 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad ...@@ -1140,9 +1136,6 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
bool bool
) )
{ {
OVM_ExecutionManager ovmExecutionManager =
OVM_ExecutionManager(resolve("OVM_ExecutionManager"));
uint256 gasLimit = ovmExecutionManager.getMaxTransactionGasLimit();
bytes32 leafHash = _getSequencerLeafHash(_txChainElement); bytes32 leafHash = _getSequencerLeafHash(_txChainElement);
require( require(
...@@ -1157,8 +1150,8 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad ...@@ -1157,8 +1150,8 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, Lib_Ad
require( require(
_transaction.blockNumber == _txChainElement.blockNumber _transaction.blockNumber == _txChainElement.blockNumber
&& _transaction.timestamp == _txChainElement.timestamp && _transaction.timestamp == _txChainElement.timestamp
&& _transaction.entrypoint == resolve("OVM_DecompressionPrecompileAddress") && _transaction.entrypoint == address(0)
&& _transaction.gasLimit == gasLimit && _transaction.gasLimit == maxTransactionGasLimit
&& _transaction.l1TxOrigin == address(0) && _transaction.l1TxOrigin == address(0)
&& _transaction.l1QueueOrigin == Lib_OVMCodec.QueueOrigin.SEQUENCER_QUEUE && _transaction.l1QueueOrigin == Lib_OVMCodec.QueueOrigin.SEQUENCER_QUEUE
&& keccak256(_transaction.data) == keccak256(_txChainElement.txData), && keccak256(_transaction.data) == keccak256(_txChainElement.txData),
......
...@@ -19,7 +19,6 @@ import { iOVM_ChainStorageContainer } from "../../iOVM/chain/iOVM_ChainStorageCo ...@@ -19,7 +19,6 @@ import { iOVM_ChainStorageContainer } from "../../iOVM/chain/iOVM_ChainStorageCo
* 2. Stores queued transactions for the Canonical Transaction Chain * 2. Stores queued transactions for the Canonical Transaction Chain
* 3. Stores chain state batches for the State Commitment Chain * 3. Stores chain state batches for the State Commitment Chain
* *
* Compiler used: solc
* Runtime target: EVM * Runtime target: EVM
*/ */
contract OVM_ChainStorageContainer is iOVM_ChainStorageContainer, Lib_AddressResolver { contract OVM_ChainStorageContainer is iOVM_ChainStorageContainer, Lib_AddressResolver {
......
...@@ -8,7 +8,6 @@ import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolve ...@@ -8,7 +8,6 @@ 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_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 import { iOVM_CanonicalTransactionChain } from
"../../iOVM/chain/iOVM_CanonicalTransactionChain.sol"; "../../iOVM/chain/iOVM_CanonicalTransactionChain.sol";
...@@ -25,7 +24,6 @@ import "@openzeppelin/contracts/math/SafeMath.sol"; ...@@ -25,7 +24,6 @@ import "@openzeppelin/contracts/math/SafeMath.sol";
* Elements here have a 1:1 correspondence with transactions in the CTC, and should be the unique * Elements here have a 1:1 correspondence with transactions in the CTC, and should be the unique
* state root calculated off-chain by applying the canonical transactions one by one. * state root calculated off-chain by applying the canonical transactions one by one.
* *
* Compiler used: solc
* Runtime target: EVM * Runtime target: EVM
*/ */
contract OVM_StateCommitmentChain is iOVM_StateCommitmentChain, Lib_AddressResolver { contract OVM_StateCommitmentChain is iOVM_StateCommitmentChain, Lib_AddressResolver {
......
// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.8.0;
/* Interface Imports */
import { iOVM_SafetyChecker } from "../../iOVM/execution/iOVM_SafetyChecker.sol";
/**
* @title OVM_SafetyChecker
* @dev The Safety Checker verifies that contracts deployed on L2 do not contain any
* "unsafe" operations. An operation is considered unsafe if it would access state variables which
* are specific to the environment (ie. L1 or L2) in which it is executed, as this could be used
* to "escape the sandbox" of the OVM, resulting in non-deterministic fraud proofs.
* That is, an attacker would be able to "prove fraud" on an honestly applied transaction.
* Note that a "safe" contract requires opcodes to appear in a particular pattern;
* omission of "unsafe" opcodes is necessary, but not sufficient.
*
* Compiler used: solc
* Runtime target: EVM
*/
contract OVM_SafetyChecker is iOVM_SafetyChecker {
/********************
* Public Functions *
********************/
/**
* Returns whether or not all of the provided bytecode is safe.
* @param _bytecode The bytecode to safety check.
* @return `true` if the bytecode is safe, `false` otherwise.
*/
function isBytecodeSafe(
bytes memory _bytecode
)
override
external
pure
returns (
bool
)
{
// autogenerated by gen_safety_checker_constants.py
// number of bytes to skip for each opcode
uint256[8] memory opcodeSkippableBytes = [
uint256(0x0001010101010101010101010000000001010101010101010101010101010000),
uint256(0x0100000000000000000000000000000000000000010101010101000000010100),
uint256(0x0000000000000000000000000000000001010101000000010101010100000000),
uint256(0x0203040500000000000000000000000000000000000000000000000000000000),
uint256(0x0101010101010101010101010101010101010101010101010101010101010101),
uint256(0x0101010101000000000000000000000000000000000000000000000000000000),
uint256(0x0000000000000000000000000000000000000000000000000000000000000000),
uint256(0x0000000000000000000000000000000000000000000000000000000000000000)
];
// Mask to gate opcode specific cases
// solhint-disable-next-line max-line-length
uint256 opcodeGateMask = ~uint256(0xffffffffffffffffffffffe000000000fffffffff070ffff9c0ffffec000f001);
// Halting opcodes
// solhint-disable-next-line max-line-length
uint256 opcodeHaltingMask = ~uint256(0x4008000000000000000000000000000000000000004000000000000000000001);
// PUSH opcodes
uint256 opcodePushMask = ~uint256(0xffffffff000000000000000000000000);
uint256 codeLength;
uint256 _pc;
assembly {
_pc := add(_bytecode, 0x20)
}
codeLength = _pc + _bytecode.length;
do {
// current opcode: 0x00...0xff
uint256 opNum;
/* solhint-disable max-line-length */
// inline assembly removes the extra add + bounds check
assembly {
let word := mload(_pc) //load the next 32 bytes at pc into word
// Look up number of bytes to skip from opcodeSkippableBytes and then update indexInWord
// E.g. the 02030405 in opcodeSkippableBytes is the number of bytes to skip for PUSH1->4
// We repeat this 6 times, thus we can only skip bytes for up to PUSH4 ((1+4) * 6 = 30 < 32).
// If we see an opcode that is listed as 0 skippable bytes e.g. PUSH5,
// then we will get stuck on that indexInWord and then opNum will be set to the PUSH5 opcode.
let indexInWord := byte(0, mload(add(opcodeSkippableBytes, byte(0, word))))
indexInWord := add(indexInWord, byte(0, mload(add(opcodeSkippableBytes, byte(indexInWord, word)))))
indexInWord := add(indexInWord, byte(0, mload(add(opcodeSkippableBytes, byte(indexInWord, word)))))
indexInWord := add(indexInWord, byte(0, mload(add(opcodeSkippableBytes, byte(indexInWord, word)))))
indexInWord := add(indexInWord, byte(0, mload(add(opcodeSkippableBytes, byte(indexInWord, word)))))
indexInWord := add(indexInWord, byte(0, mload(add(opcodeSkippableBytes, byte(indexInWord, word)))))
_pc := add(_pc, indexInWord)
opNum := byte(indexInWord, word)
}
/* solhint-enable max-line-length */
// + push opcodes
// + stop opcodes [STOP(0x00),JUMP(0x56),RETURN(0xf3),INVALID(0xfe)]
// + caller opcode CALLER(0x33)
// + blacklisted opcodes
uint256 opBit = 1 << opNum;
if (opBit & opcodeGateMask == 0) {
if (opBit & opcodePushMask == 0) {
// all pushes are valid opcodes
// subsequent bytes are not opcodes. Skip them.
_pc += (opNum - 0x5e); // PUSH1 is 0x60, so opNum-0x5f = PUSHed bytes and we
// +1 to skip the _pc++; line below in order to save gas ((-0x5f + 1) = -0x5e)
continue;
} else if (opBit & opcodeHaltingMask == 0) {
// STOP or JUMP or RETURN or INVALID (Note: REVERT is blacklisted, so not
// included here)
// We are now inside unreachable code until we hit a JUMPDEST!
do {
_pc++;
assembly {
opNum := byte(0, mload(_pc))
}
// encountered a JUMPDEST
if (opNum == 0x5b) break;
// skip PUSHed bytes
// opNum-0x5f = PUSHed bytes (PUSH1 is 0x60)
if ((1 << opNum) & opcodePushMask == 0) _pc += (opNum - 0x5f);
} while (_pc < codeLength);
// opNum is 0x5b, so we don't continue here since the pc++ is fine
} else if (opNum == 0x33) { // Caller opcode
uint256 firstOps; // next 32 bytes of bytecode
uint256 secondOps; // following 32 bytes of bytecode
assembly {
firstOps := mload(_pc)
// 37 bytes total, 5 left over --> 32 - 5 bytes = 27 bytes = 216 bits
secondOps := shr(216, mload(add(_pc, 0x20)))
}
// Call identity precompile
// CALLER POP PUSH1 0x00 PUSH1 0x04 GAS CALL
// 32 - 8 bytes = 24 bytes = 192
if ((firstOps >> 192) == 0x3350600060045af1) {
_pc += 8;
// Call EM and abort execution if instructed
// CALLER PUSH1 0x00 SWAP1 GAS CALL PC PUSH1 0x0E ADD JUMPI RETURNDATASIZE
// PUSH1 0x00 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x00 REVERT JUMPDEST
// RETURNDATASIZE PUSH1 0x01 EQ ISZERO PC PUSH1 0x0a ADD JUMPI PUSH1 0x01 PUSH1
// 0x00 RETURN JUMPDEST
// solhint-disable-next-line max-line-length
} else if (firstOps == 0x336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760 && secondOps == 0x016000f35b) {
_pc += 37;
} else {
return false;
}
continue;
} else {
// encountered a non-whitelisted opcode!
return false;
}
}
_pc++;
} while (_pc < codeLength);
return true;
}
}
// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.8.0;
/* Interface Imports */
import { iOVM_StateManager } from "../../iOVM/execution/iOVM_StateManager.sol";
import { iOVM_StateManagerFactory } from "../../iOVM/execution/iOVM_StateManagerFactory.sol";
/* Contract Imports */
import { OVM_StateManager } from "./OVM_StateManager.sol";
/**
* @title OVM_StateManagerFactory
* @dev The State Manager Factory is called by a State Transitioner's init code, to create a new
* State Manager for use in the Fraud Verification process.
*
* Compiler used: solc
* Runtime target: EVM
*/
contract OVM_StateManagerFactory is iOVM_StateManagerFactory {
/********************
* Public Functions *
********************/
/**
* Creates a new OVM_StateManager
* @param _owner Owner of the created contract.
* @return New OVM_StateManager instance.
*/
function create(
address _owner
)
override
public
returns (
iOVM_StateManager
)
{
return new OVM_StateManager(_owner);
}
}
...@@ -11,7 +11,6 @@ import { iOVM_DeployerWhitelist } from "../../iOVM/predeploys/iOVM_DeployerWhite ...@@ -11,7 +11,6 @@ import { iOVM_DeployerWhitelist } from "../../iOVM/predeploys/iOVM_DeployerWhite
* which are allowed to deploy contracts on Layer2. The Execution Manager will only allow an * which are allowed to deploy contracts on Layer2. The Execution Manager will only allow an
* ovmCREATE or ovmCREATE2 operation to proceed if the deployer's address whitelisted. * ovmCREATE or ovmCREATE2 operation to proceed if the deployer's address whitelisted.
* *
* Compiler used: optimistic-solc
* Runtime target: OVM * Runtime target: OVM
*/ */
contract OVM_DeployerWhitelist is iOVM_DeployerWhitelist { contract OVM_DeployerWhitelist is iOVM_DeployerWhitelist {
......
// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.8.0;
pragma experimental ABIEncoderV2;
/* Interface Imports */
import { iOVM_ECDSAContractAccount } from "../../iOVM/predeploys/iOVM_ECDSAContractAccount.sol";
/* Library Imports */
import { Lib_EIP155Tx } from "../../libraries/codec/Lib_EIP155Tx.sol";
import { Lib_ExecutionManagerWrapper } from
"../../libraries/wrappers/Lib_ExecutionManagerWrapper.sol";
import { Lib_PredeployAddresses } from "../../libraries/constants/Lib_PredeployAddresses.sol";
/* Contract Imports */
import { OVM_ETH } from "../predeploys/OVM_ETH.sol";
/* External Imports */
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol";
import { ECDSA } from "@openzeppelin/contracts/cryptography/ECDSA.sol";
/**
* @title OVM_ECDSAContractAccount
* @dev The ECDSA Contract Account can be used as the implementation for a ProxyEOA deployed by the
* ovmCREATEEOA operation. It enables backwards compatibility with Ethereum's Layer 1, by
* providing EIP155 formatted transaction encodings.
*
* Compiler used: optimistic-solc
* Runtime target: OVM
*/
contract OVM_ECDSAContractAccount is iOVM_ECDSAContractAccount {
/*************
* Libraries *
*************/
using Lib_EIP155Tx for Lib_EIP155Tx.EIP155Tx;
/*************
* Constants *
*************/
// TODO: should be the amount sufficient to cover the gas costs of all of the transactions up
// to and including the CALL/CREATE which forms the entrypoint of the transaction.
uint256 constant EXECUTION_VALIDATION_GAS_OVERHEAD = 25000;
/********************
* Public Functions *
********************/
/**
* No-op fallback mirrors behavior of calling an EOA on L1.
*/
fallback()
external
payable
{
return;
}
/**
* @dev Should return whether the signature provided is valid for the provided data
* @param hash Hash of the data to be signed
* @param signature Signature byte array associated with _data
*/
function isValidSignature(
bytes32 hash,
bytes memory signature
)
public
view
returns (
bytes4 magicValue
)
{
return ECDSA.recover(hash, signature) == address(this) ?
this.isValidSignature.selector :
bytes4(0);
}
/**
* Executes a signed transaction.
* @param _transaction Signed EIP155 transaction.
* @return Whether or not the call returned (rather than reverted).
* @return Data returned by the call.
*/
function execute(
Lib_EIP155Tx.EIP155Tx memory _transaction
)
override
public
returns (
bool,
bytes memory
)
{
// Address of this contract within the ovm (ovmADDRESS) should be the same as the
// recovered address of the user who signed this message. This is how we manage to shim
// account abstraction even though the user isn't a contract.
require(
_transaction.sender() == Lib_ExecutionManagerWrapper.ovmADDRESS(),
"Signature provided for EOA transaction execution is invalid."
);
require(
_transaction.chainId == Lib_ExecutionManagerWrapper.ovmCHAINID(),
"Transaction signed with wrong chain ID"
);
// Need to make sure that the transaction nonce is right.
require(
_transaction.nonce == Lib_ExecutionManagerWrapper.ovmGETNONCE(),
"Transaction nonce does not match the expected nonce."
);
// TEMPORARY: Disable gas checks for mainnet.
// // Need to make sure that the gas is sufficient to execute the transaction.
// require(
// gasleft() >= SafeMath.add(transaction.gasLimit, EXECUTION_VALIDATION_GAS_OVERHEAD),
// "Gas is not sufficient to execute the transaction."
// );
// Transfer fee to relayer.
require(
OVM_ETH(Lib_PredeployAddresses.OVM_ETH).transfer(
Lib_PredeployAddresses.SEQUENCER_FEE_WALLET,
SafeMath.mul(_transaction.gasLimit, _transaction.gasPrice)
),
"Fee was not transferred to relayer."
);
if (_transaction.isCreate) {
// TEMPORARY: Disable value transfer for contract creations.
require(
_transaction.value == 0,
"Value transfer in contract creation not supported."
);
(address created, bytes memory revertdata) = Lib_ExecutionManagerWrapper.ovmCREATE(
_transaction.data
);
// Return true if the contract creation succeeded, false w/ revertdata otherwise.
if (created != address(0)) {
return (true, abi.encode(created));
} else {
return (false, revertdata);
}
} else {
// We only want to bump the nonce for `ovmCALL` because `ovmCREATE` automatically bumps
// the nonce of the calling account. Normally an EOA would bump the nonce for both
// cases, but since this is a contract we'd end up bumping the nonce twice.
Lib_ExecutionManagerWrapper.ovmINCREMENTNONCE();
// NOTE: Upgrades are temporarily disabled because users can, in theory, modify their
// EOA so that they don't have to pay any fees to the sequencer. Function will remain
// disabled until a robust solution is in place.
require(
_transaction.to != Lib_ExecutionManagerWrapper.ovmADDRESS(),
"Calls to self are disabled until upgradability is re-enabled."
);
return _transaction.to.call{value: _transaction.value}(_transaction.data);
}
}
}
...@@ -13,7 +13,6 @@ import { IWETH9 } from "../../libraries/standards/IWETH9.sol"; ...@@ -13,7 +13,6 @@ import { IWETH9 } from "../../libraries/standards/IWETH9.sol";
* @dev The ETH predeploy provides an ERC20 interface for ETH deposited to Layer 2. Note that * @dev The ETH predeploy provides an ERC20 interface for ETH deposited to Layer 2. Note that
* unlike on Layer 1, Layer 2 accounts do not have a balance field. * unlike on Layer 1, Layer 2 accounts do not have a balance field.
* *
* Compiler used: optimistic-solc
* Runtime target: OVM * Runtime target: OVM
*/ */
contract OVM_ETH is L2StandardERC20, IWETH9 { contract OVM_ETH is L2StandardERC20, IWETH9 {
......
// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.8.0;
/* Library Imports */
import { Lib_ErrorUtils } from "../../libraries/utils/Lib_ErrorUtils.sol";
/**
* @title OVM_ExecutionManagerWrapper
* @dev This contract is a thin wrapper around the `kall` builtin. By making this contract a
* predeployed contract, we can restrict evm solc incompatibility to this one contract. Other
* contracts will typically call this contract via `Lib_ExecutionManagerWrapper`.
*
* Compiler used: optimistic-solc
* Runtime target: OVM
*/
contract OVM_ExecutionManagerWrapper {
/*********************
* Fallback Function *
*********************/
fallback()
external
payable
{
// DO NOTHING FOR NOW
}
}
...@@ -11,7 +11,6 @@ import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; ...@@ -11,7 +11,6 @@ import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
* transactions. When the system is more congested, the l2 gas price will increase and fees * transactions. When the system is more congested, the l2 gas price will increase and fees
* will also increase as a result. * will also increase as a result.
* *
* Compiler used: optimistic-solc
* Runtime target: OVM * Runtime target: OVM
*/ */
contract OVM_GasPriceOracle is Ownable { contract OVM_GasPriceOracle is Ownable {
......
...@@ -13,8 +13,6 @@ pragma solidity >0.5.0 <0.8.0; ...@@ -13,8 +13,6 @@ pragma solidity >0.5.0 <0.8.0;
* because there is no corresponding operation in the EVM which the the optimistic solidity compiler * because there is no corresponding operation in the EVM which the the optimistic solidity compiler
* can be replaced with a call to the ExecutionManager's ovmL1TXORIGIN() function. * can be replaced with a call to the ExecutionManager's ovmL1TXORIGIN() function.
* *
*
* Compiler used: solc
* Runtime target: OVM * Runtime target: OVM
*/ */
contract OVM_L1MessageSender { contract OVM_L1MessageSender {
......
...@@ -11,7 +11,6 @@ import { iOVM_L2ToL1MessagePasser } from "../../iOVM/predeploys/iOVM_L2ToL1Messa ...@@ -11,7 +11,6 @@ import { iOVM_L2ToL1MessagePasser } from "../../iOVM/predeploys/iOVM_L2ToL1Messa
* _verifyStorageProof function, which verifies the existence of the transaction hash in this * _verifyStorageProof function, which verifies the existence of the transaction hash in this
* contract's `sentMessages` mapping. * contract's `sentMessages` mapping.
* *
* Compiler used: optimistic-solc
* Runtime target: OVM * Runtime target: OVM
*/ */
contract OVM_L2ToL1MessagePasser is iOVM_L2ToL1MessagePasser { contract OVM_L2ToL1MessagePasser is iOVM_L2ToL1MessagePasser {
......
// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.8.0;
/* Library Imports */
import { Lib_Bytes32Utils } from "../../libraries/utils/Lib_Bytes32Utils.sol";
import { Lib_PredeployAddresses } from "../../libraries/constants/Lib_PredeployAddresses.sol";
import { Lib_ExecutionManagerWrapper } from
"../../libraries/wrappers/Lib_ExecutionManagerWrapper.sol";
/**
* @title OVM_ProxyEOA
* @dev The Proxy EOA contract uses a delegate call to execute the logic in an implementation
* contract. In combination with the logic implemented in the ECDSA Contract Account, this enables
* a form of upgradable 'account abstraction' on layer 2.
*
* Compiler used: optimistic-solc
* Runtime target: OVM
*/
contract OVM_ProxyEOA {
/**********
* Events *
**********/
event Upgraded(
address indexed implementation
);
/*************
* Constants *
*************/
// solhint-disable-next-line max-line-length
bytes32 constant IMPLEMENTATION_KEY = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; //bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1);
/*********************
* Fallback Function *
*********************/
fallback()
external
payable
{
(bool success, bytes memory returndata) = getImplementation().delegatecall(msg.data);
if (success) {
assembly {
return(add(returndata, 0x20), mload(returndata))
}
} else {
assembly {
revert(add(returndata, 0x20), mload(returndata))
}
}
}
// WARNING: We use the deployed bytecode of this contract as a template to create ProxyEOA
// contracts. As a result, we must *not* perform any constructor logic. Use initialization
// functions if necessary.
/********************
* Public Functions *
********************/
/**
* Changes the implementation address.
* @param _implementation New implementation address.
*/
function upgrade(
address _implementation
)
external
{
require(
msg.sender == Lib_ExecutionManagerWrapper.ovmADDRESS(),
"EOAs can only upgrade their own EOA implementation."
);
_setImplementation(_implementation);
emit Upgraded(_implementation);
}
/**
* Gets the address of the current implementation.
* @return Current implementation address.
*/
function getImplementation()
public
view
returns (
address
)
{
bytes32 addr32;
assembly {
addr32 := sload(IMPLEMENTATION_KEY)
}
address implementation = Lib_Bytes32Utils.toAddress(addr32);
if (implementation == address(0)) {
return Lib_PredeployAddresses.ECDSA_CONTRACT_ACCOUNT;
} else {
return implementation;
}
}
/**********************
* Internal Functions *
**********************/
function _setImplementation(
address _implementation
)
internal
{
bytes32 addr32 = Lib_Bytes32Utils.fromAddress(_implementation);
assembly {
sstore(IMPLEMENTATION_KEY, addr32)
}
}
}
// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.8.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_EIP155Tx } from "../../libraries/codec/Lib_EIP155Tx.sol";
import { Lib_ExecutionManagerWrapper } from
"../../libraries/wrappers/Lib_ExecutionManagerWrapper.sol";
import { iOVM_ECDSAContractAccount } from "../../iOVM/predeploys/iOVM_ECDSAContractAccount.sol";
/**
* @title OVM_SequencerEntrypoint
* @dev The Sequencer Entrypoint is a predeploy which, despite its name, can in fact be called by
* any account. It accepts a more efficient compressed calldata format, which it decompresses and
* encodes to the standard EIP155 transaction format.
* Compiler used: optimistic-solc
* Runtime target: OVM
*/
contract OVM_SequencerEntrypoint {
/*************
* Libraries *
*************/
using Lib_EIP155Tx for Lib_EIP155Tx.EIP155Tx;
/*********************
* Fallback Function *
*********************/
/**
* Expects an RLP-encoded EIP155 transaction as input. See the EIP for a more detailed
* description of this transaction format:
* https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md
*/
fallback()
external
{
// We use this twice, so it's more gas efficient to store a copy of it (barely).
bytes memory encodedTx = msg.data;
// Decode the tx with the correct chain ID.
Lib_EIP155Tx.EIP155Tx memory transaction = Lib_EIP155Tx.decode(
encodedTx,
Lib_ExecutionManagerWrapper.ovmCHAINID()
);
// Value is computed on the fly. Keep it in the stack to save some gas.
address target = transaction.sender();
bool isEmptyContract;
assembly {
isEmptyContract := iszero(extcodesize(target))
}
// If the account is empty, deploy the default EOA to that address.
if (isEmptyContract) {
Lib_ExecutionManagerWrapper.ovmCREATEEOA(
transaction.hash(),
transaction.recoveryParam,
transaction.r,
transaction.s
);
}
// Forward the transaction over to the EOA.
(bool success, bytes memory returndata) = target.call(
abi.encodeWithSelector(iOVM_ECDSAContractAccount.execute.selector, transaction)
);
if (success) {
assembly {
return(add(returndata, 0x20), mload(returndata))
}
} else {
assembly {
revert(add(returndata, 0x20), mload(returndata))
}
}
}
}
...@@ -13,7 +13,6 @@ import { OVM_L2StandardBridge } from "../bridge/tokens/OVM_L2StandardBridge.sol" ...@@ -13,7 +13,6 @@ import { OVM_L2StandardBridge } from "../bridge/tokens/OVM_L2StandardBridge.sol"
* @dev Simple holding contract for fees paid to the Sequencer. Likely to be replaced in the future * @dev Simple holding contract for fees paid to the Sequencer. Likely to be replaced in the future
* but "good enough for now". * but "good enough for now".
* *
* Compiler used: optimistic-solc
* Runtime target: OVM * Runtime target: OVM
*/ */
contract OVM_SequencerFeeVault { contract OVM_SequencerFeeVault {
......
// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.8.0;
import { iOVM_BondManager } from "../../iOVM/verification/iOVM_BondManager.sol";
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
/// Minimal contract to be inherited by contracts consumed by users that provide
/// data for fraud proofs
abstract contract Abs_FraudContributor is Lib_AddressResolver {
/// Decorate your functions with this modifier to store how much total gas was
/// consumed by the sender, to reward users fairly
modifier contributesToFraudProof(bytes32 preStateRoot, bytes32 txHash) {
uint256 startGas = gasleft();
_;
uint256 gasSpent = startGas - gasleft();
iOVM_BondManager(resolve("OVM_BondManager"))
.recordGasSpent(preStateRoot, txHash, msg.sender, gasSpent);
}
}
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.8.0; pragma solidity >0.5.0 <0.8.0;
/* Library Imports */
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
/* Interface Imports */ /* Interface Imports */
import { iOVM_BondManager, Errors, ERC20 } from "../../iOVM/verification/iOVM_BondManager.sol"; import { iOVM_BondManager } from "../../iOVM/verification/iOVM_BondManager.sol";
import { iOVM_FraudVerifier } from "../../iOVM/verification/iOVM_FraudVerifier.sol";
/* Contract Imports */
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
/** /**
* @title OVM_BondManager * @title OVM_BondManager
* @dev The Bond Manager contract handles deposits in the form of an ERC20 token from bonded * @dev This contract is, for now, a stub of the "real" OVM_BondManager that does nothing but
* Proposers. It also handles the accounting of gas costs spent by a Verifier during the course of a * allow the "OVM_Proposer" to submit state root batches.
* fraud proof. In the event of a successful fraud proof, the fraudulent Proposer's bond is slashed,
* and the Verifier's gas costs are refunded.
* *
* Compiler used: solc
* Runtime target: EVM * Runtime target: EVM
*/ */
contract OVM_BondManager is iOVM_BondManager, Lib_AddressResolver { contract OVM_BondManager is iOVM_BondManager, Lib_AddressResolver {
/****************************
* Constants and Parameters *
****************************/
/// The period to find the earliest fraud proof for a publisher
uint256 public constant multiFraudProofPeriod = 7 days;
/// The dispute period
uint256 public constant disputePeriodSeconds = 7 days;
/// The minimum collateral a sequencer must post
uint256 public constant requiredCollateral = 1 ether;
/*******************************************
* Contract Variables: Contract References *
*******************************************/
/// The bond token
ERC20 immutable public token;
/********************************************
* Contract Variables: Internal Accounting *
*******************************************/
/// The bonds posted by each proposer
mapping(address => Bond) public bonds;
/// For each pre-state root, there's an array of witnessProviders that must be rewarded
/// for posting witnesses
mapping(bytes32 => Rewards) public witnessProviders;
/***************
* Constructor *
***************/
/// Initializes with a ERC20 token to be used for the fidelity bonds
/// and with the Address Manager
constructor( constructor(
ERC20 _token,
address _libAddressManager address _libAddressManager
) )
Lib_AddressResolver(_libAddressManager) Lib_AddressResolver(_libAddressManager)
{ {}
token = _token;
}
/********************
* Public Functions *
********************/
/// Adds `who` to the list of witnessProviders for the provided `preStateRoot`.
function recordGasSpent(bytes32 _preStateRoot, bytes32 _txHash, address who, uint256 gasSpent)
override public {
// The sender must be the transitioner that corresponds to the claimed pre-state root
address transitioner =
address(iOVM_FraudVerifier(resolve("OVM_FraudVerifier"))
.getStateTransitioner(_preStateRoot, _txHash));
require(transitioner == msg.sender, Errors.ONLY_TRANSITIONER);
witnessProviders[_preStateRoot].total += gasSpent;
witnessProviders[_preStateRoot].gasSpent[who] += gasSpent;
}
/// Slashes + distributes rewards or frees up the sequencer's bond, only called by
/// `FraudVerifier.finalizeFraudVerification`
function finalize(bytes32 _preStateRoot, address publisher, uint256 timestamp) override public {
require(msg.sender == resolve("OVM_FraudVerifier"), Errors.ONLY_FRAUD_VERIFIER);
require(witnessProviders[_preStateRoot].canClaim == false, Errors.ALREADY_FINALIZED);
// allow users to claim from that state root's
// pool of collateral (effectively slashing the sequencer)
witnessProviders[_preStateRoot].canClaim = true;
Bond storage bond = bonds[publisher];
if (bond.firstDisputeAt == 0) {
bond.firstDisputeAt = block.timestamp;
bond.earliestDisputedStateRoot = _preStateRoot;
bond.earliestTimestamp = timestamp;
} else if (
// only update the disputed state root for the publisher if it's within
// the dispute period _and_ if it's before the previous one
block.timestamp < bond.firstDisputeAt + multiFraudProofPeriod &&
timestamp < bond.earliestTimestamp
) {
bond.earliestDisputedStateRoot = _preStateRoot;
bond.earliestTimestamp = timestamp;
}
// if the fraud proof's dispute period does not intersect with the
// withdrawal's timestamp, then the user should not be slashed
// e.g if a user at day 10 submits a withdrawal, and a fraud proof
// from day 1 gets published, the user won't be slashed since day 8 (1d + 7d)
// is before the user started their withdrawal. on the contrary, if the user
// had started their withdrawal at, say, day 6, they would be slashed
if (
bond.withdrawalTimestamp != 0 &&
uint256(bond.withdrawalTimestamp) > timestamp + disputePeriodSeconds &&
bond.state == State.WITHDRAWING
) {
return;
}
// slash!
bond.state = State.NOT_COLLATERALIZED;
}
/// Sequencers call this function to post collateral which will be used for
/// the `appendBatch` call
function deposit() override public {
require(
token.transferFrom(msg.sender, address(this), requiredCollateral),
Errors.ERC20_ERR
);
// This cannot overflow
bonds[msg.sender].state = State.COLLATERALIZED;
}
/// Starts the withdrawal for a publisher
function startWithdrawal() override public {
Bond storage bond = bonds[msg.sender];
require(bond.withdrawalTimestamp == 0, Errors.WITHDRAWAL_PENDING);
require(bond.state == State.COLLATERALIZED, Errors.WRONG_STATE);
bond.state = State.WITHDRAWING;
bond.withdrawalTimestamp = uint32(block.timestamp);
}
/// Finalizes a pending withdrawal from a publisher
function finalizeWithdrawal() override public {
Bond storage bond = bonds[msg.sender];
require(
block.timestamp >= uint256(bond.withdrawalTimestamp) + disputePeriodSeconds,
Errors.TOO_EARLY
);
require(bond.state == State.WITHDRAWING, Errors.SLASHED);
// refunds!
bond.state = State.NOT_COLLATERALIZED;
bond.withdrawalTimestamp = 0;
require(
token.transfer(msg.sender, requiredCollateral),
Errors.ERC20_ERR
);
}
/// Claims the user's reward for the witnesses they provided for the earliest
/// disputed state root of the designated publisher
function claim(address who) override public {
Bond storage bond = bonds[who];
require(
block.timestamp >= bond.firstDisputeAt + multiFraudProofPeriod,
Errors.WAIT_FOR_DISPUTES
);
// reward the earliest state root for this publisher function recordGasSpent(
bytes32 _preStateRoot = bond.earliestDisputedStateRoot; bytes32 _preStateRoot,
Rewards storage rewards = witnessProviders[_preStateRoot]; bytes32 _txHash,
address _who,
// only allow claiming if fraud was proven in `finalize` uint256 _gasSpent
require(rewards.canClaim, Errors.CANNOT_CLAIM); )
override
// proportional allocation - only reward 50% (rest gets locked in the public
// contract forever {}
uint256 amount = (requiredCollateral * rewards.gasSpent[msg.sender]) / (2 * rewards.total);
function finalize(
// reset the user's spent gas so they cannot double claim bytes32 _preStateRoot,
rewards.gasSpent[msg.sender] = 0; address _publisher,
uint256 _timestamp
// transfer )
require(token.transfer(msg.sender, amount), Errors.ERC20_ERR); override
} public
{}
function deposit()
override
public
{}
function startWithdrawal()
override
public
{}
function finalizeWithdrawal()
override
public
{}
function claim(
address _who
)
override
public
{}
/// Checks if the user is collateralized function isCollateralized(
function isCollateralized(address who) override public view returns (bool) { address _who
return bonds[who].state == State.COLLATERALIZED; )
override
public
view
returns (
bool
)
{
// Only authenticate sequencer to submit state root batches.
return _who == resolve("OVM_Proposer");
} }
/// Gets how many witnesses the user has provided for the state root function getGasSpent(
function getGasSpent(bytes32 preStateRoot, address who) override public view returns (uint256) { bytes32 _preStateRoot,
return witnessProviders[preStateRoot].gasSpent[who]; address _who
)
override
public
pure
returns (
uint256
)
{
return 0;
} }
} }
// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.8.0;
/**
* @title iOVM_SafetyChecker
*/
interface iOVM_SafetyChecker {
/********************
* Public Functions *
********************/
function isBytecodeSafe(bytes calldata _bytecode) external pure returns (bool);
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment