@@ -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,8 @@ contract OVM_L1StandardBridge is iOVM_L1StandardBridge, OVM_CrossDomainEnabled {
...
@@ -69,7 +70,8 @@ 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 +138,8 @@ contract OVM_L1StandardBridge is iOVM_L1StandardBridge, OVM_CrossDomainEnabled {
...
@@ -136,7 +138,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 +238,9 @@ contract OVM_L1StandardBridge is iOVM_L1StandardBridge, OVM_CrossDomainEnabled {
...
@@ -235,8 +238,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),
...
@@ -306,7 +310,7 @@ contract OVM_L1StandardBridge is iOVM_L1StandardBridge, OVM_CrossDomainEnabled {
...
@@ -306,7 +310,7 @@ contract OVM_L1StandardBridge is iOVM_L1StandardBridge, OVM_CrossDomainEnabled {
// 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 {
// 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,7 +1319,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
...
@@ -1296,7 +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,
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?") // solhint-disable-line max-line-length
);
);
}
}
...
@@ -1304,12 +1327,13 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
...
@@ -1304,12 +1327,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
// 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,7 +1346,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
...
@@ -1322,7 +1346,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,
Lib_ErrorUtils.encodeRevertString("Constructor attempted to deploy unsafe bytecode.")
Lib_ErrorUtils.encodeRevertString("Constructor attempted to deploy unsafe bytecode.") // solhint-disable-line max-line-length
);
);
}
}
...
@@ -1340,8 +1364,10 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
...
@@ -1340,8 +1364,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 +1388,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
...
@@ -1362,8 +1388,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 +1602,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
...
@@ -1576,7 +1602,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {