// EVM does not return data in the success case, see: https://github.com/ethereum/go-ethereum/blob/aae7660410f0ef90279e14afaaf2f429fdc2a186/core/vm/instructions.go#L600-L604
return (true, hex'');
}
// Both 0x0000... and the EVM precompiles have the same address on L1 and L2 -->
// no trie lookup needed.
address codeContractAddress =
uint(_contract) < 100
? _contract
: _getAccountEthAddress(_contract);
return _handleExternalMessage(
_nextMessageContext,
_gasLimit,
codeContractAddress,
_calldata,
_messageType
);
}
/**
* Handles all interactions which involve the execution manager calling out to untrusted code
* (both calls and creates). Ensures that OVM-related measures are enforced, including L2 gas
* refunds, nuisance gas, and flagged reversions.
*
* @param _nextMessageContext Message context to be used for the external message.
* @param _gasLimit Amount of gas to be passed into this message. NOTE: this argument is
* overwritten in some cases to avoid stack-too-deep.
* @param _contract OVM address being called or deployed to
* @param _data Data for the message (either calldata or creation code)
* @param _messageType What type of ovmOPCODE this message corresponds to.
* @return Whether or not the message (either a call or deployment) succeeded.
* @return Data returned by the message.
*/
function _handleExternalMessage(
MessageContext memory _nextMessageContext,
// NOTE: this argument is overwritten in some cases to avoid stack-too-deep.
* Handles the creation-specific safety measures required for OVM contract deployment.
* This function sanitizes the return types for creation messages to match calls (bool, bytes),
* by being an external function which the EM can call, that mimics the success/fail case of the
* CREATE.
* This allows for consistent handling of both types of messages in _handleExternalMessage().
* Having this step occur as a separate call frame also allows us to easily revert the
* contract deployment in the event that the code is unsafe.
*
* @param _creationCode Code to pass into CREATE for deployment.
* @param _address OVM address being deployed to.
*/
function safeCREATE(
bytes memory _creationCode,
address _address
)
external
{
// The only way this should callable is from within _createContract(),
// and it should DEFINITELY not be callable by a non-EM code contract.
if (msg.sender != address(this)) {
return;
}
// Check that there is not already code at this address.
if (_hasEmptyAccount(_address) == false) {
// Note: in the EVM, this case burns all allotted gas. For improved
// developer experience, we do return the remaining gas.
_revertWithFlag(
RevertFlag.CREATE_COLLISION
);
}
// Check the creation bytecode against the OVM_SafetyChecker.
if (ovmSafetyChecker.isBytecodeSafe(_creationCode) == false) {
// Note: in the EVM, this case burns all allotted gas. For improved
// developer experience, we do return the remaining gas.
_revertWithFlag(
RevertFlag.UNSAFE_BYTECODE,
// solhint-disable-next-line max-line-length
Lib_ErrorUtils.encodeRevertString("Contract creation code contains unsafe opcodes. Did you use the right compiler or pass an unsafe constructor argument?")
);
}
// We always need to initialize the contract with the default account values.
_initPendingAccount(_address);
// Actually execute the EVM create message.
// NOTE: The inline assembly below means we can NOT make any evm calls between here and then