Skip to content
This repository was archived by the owner on Apr 12, 2021. It is now read-only.

feat: Use standard RLP transactions #300

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ pragma experimental ABIEncoderV2;
import { iOVM_ECDSAContractAccount } from "../../iOVM/accounts/iOVM_ECDSAContractAccount.sol";

/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
import { Lib_ECDSAUtils } from "../../libraries/utils/Lib_ECDSAUtils.sol";
import { Lib_EIP155Tx } from "../../libraries/codec/Lib_EIP155Tx.sol";
import { Lib_SafeExecutionManagerWrapper } from "../../libraries/wrappers/Lib_SafeExecutionManagerWrapper.sol";
import { Lib_SafeMathWrapper } from "../../libraries/wrappers/Lib_SafeMathWrapper.sol";

Expand All @@ -21,6 +20,8 @@ import { Lib_SafeMathWrapper } from "../../libraries/wrappers/Lib_SafeMathWrappe
* Runtime target: OVM
*/
contract OVM_ECDSAContractAccount is iOVM_ECDSAContractAccount {
using Lib_EIP155Tx for Lib_EIP155Tx.EIP155Tx;


/*************
* Constants *
Expand All @@ -38,20 +39,12 @@ contract OVM_ECDSAContractAccount is iOVM_ECDSAContractAccount {

/**
* Executes a signed transaction.
* @param _transaction Signed EOA transaction.
* @param _signatureType Hashing scheme used for the transaction (e.g., ETH signed message).
* @param _v Signature `v` parameter.
* @param _r Signature `r` parameter.
* @param _s Signature `s` parameter.
* @param _encodedTransaction Signed EIP155 transaction.
* @return Whether or not the call returned (rather than reverted).
* @return Data returned by the call.
*/
function execute(
bytes memory _transaction,
Lib_OVMCodec.EOASignatureType _signatureType,
uint8 _v,
bytes32 _r,
bytes32 _s
bytes memory _encodedTransaction
)
override
public
Expand All @@ -60,34 +53,32 @@ contract OVM_ECDSAContractAccount is iOVM_ECDSAContractAccount {
bytes memory
)
{
bool isEthSign = _signatureType == Lib_OVMCodec.EOASignatureType.ETH_SIGNED_MESSAGE;
Lib_EIP155Tx.EIP155Tx memory transaction = Lib_EIP155Tx.decode(
_encodedTransaction,
Lib_SafeExecutionManagerWrapper.safeCHAINID()
);

// Recovery parameter being something other than 0 or 1 indicates that this transaction was
// signed using the wrong chain ID. We really should have this logic inside of Lib_EIP155Tx
// but I'd prefer not to add the "safeREQUIRE" logic into that library. So it'll live here
// for now.
Lib_SafeExecutionManagerWrapper.safeREQUIRE(
transaction.recoveryParam < 2,
"OVM_ECDSAContractAccount: Transaction was signed with the wrong chain ID."
);

// 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.
// Need to make sure that the transaction nonce is right and bump it if so.
Lib_SafeExecutionManagerWrapper.safeREQUIRE(
Lib_ECDSAUtils.recover(
_transaction,
isEthSign,
_v,
_r,
_s
) == Lib_SafeExecutionManagerWrapper.safeADDRESS(),
transaction.sender() == Lib_SafeExecutionManagerWrapper.safeADDRESS(),
"Signature provided for EOA transaction execution is invalid."
);

Lib_OVMCodec.EIP155Transaction memory decodedTx = Lib_OVMCodec.decodeEIP155Transaction(_transaction, isEthSign);

// Need to make sure that the transaction chainId is correct.
Lib_SafeExecutionManagerWrapper.safeREQUIRE(
decodedTx.chainId == Lib_SafeExecutionManagerWrapper.safeCHAINID(),
"Transaction chainId does not match expected OVM chainId."
);

// Need to make sure that the transaction nonce is right.
Lib_SafeExecutionManagerWrapper.safeREQUIRE(
decodedTx.nonce == Lib_SafeExecutionManagerWrapper.safeGETNONCE(),
transaction.nonce == Lib_SafeExecutionManagerWrapper.safeGETNONCE(),
"Transaction nonce does not match the expected nonce."
);

Expand All @@ -98,24 +89,30 @@ contract OVM_ECDSAContractAccount is iOVM_ECDSAContractAccount {
// "Gas is not sufficient to execute the transaction."
// );

// Transfer fee to relayer.
// Transfer fee to relayer. We assume that whoever called this function is the relayer,
// hence the usage of CALLER. Fee is computed as gasLimit * gasPrice.
address relayer = Lib_SafeExecutionManagerWrapper.safeCALLER();
uint256 fee = Lib_SafeMathWrapper.mul(decodedTx.gasLimit, decodedTx.gasPrice);
uint256 fee = Lib_SafeMathWrapper.mul(transaction.gasLimit, transaction.gasPrice);
(bool success, ) = Lib_SafeExecutionManagerWrapper.safeCALL(
gasleft(),
ETH_ERC20_ADDRESS,
abi.encodeWithSignature("transfer(address,uint256)", relayer, fee)
abi.encodeWithSignature(
"transfer(address,uint256)",
relayer,
fee
)
);

// Make sure the transfer was actually successful.
Lib_SafeExecutionManagerWrapper.safeREQUIRE(
success == true,
"Fee was not transferred to relayer."
);

// Contract creations are signalled by sending a transaction to the zero address.
if (decodedTx.to == address(0)) {
if (transaction.isCreate) {
(address created, bytes memory revertData) = Lib_SafeExecutionManagerWrapper.safeCREATE(
decodedTx.gasLimit,
decodedTx.data
transaction.gasLimit,
transaction.data
);

// Return true if the contract creation succeeded, false w/ revertData otherwise.
Expand All @@ -128,12 +125,12 @@ contract OVM_ECDSAContractAccount is iOVM_ECDSAContractAccount {
// 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_SafeExecutionManagerWrapper.safeSETNONCE(decodedTx.nonce + 1);
Lib_SafeExecutionManagerWrapper.safeSETNONCE(transaction.nonce + 1);

return Lib_SafeExecutionManagerWrapper.safeCALL(
decodedTx.gasLimit,
decodedTx.to,
decodedTx.data
transaction.gasLimit,
transaction.to,
transaction.data
);
}
}
Expand Down
2 changes: 0 additions & 2 deletions contracts/optimistic-ethereum/OVM/accounts/OVM_ProxyEOA.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ pragma solidity >0.5.0 <0.8.0;

/* Library Imports */
import { Lib_Bytes32Utils } from "../../libraries/utils/Lib_Bytes32Utils.sol";
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Files were unused, I removed them.

import { Lib_ECDSAUtils } from "../../libraries/utils/Lib_ECDSAUtils.sol";
import { Lib_SafeExecutionManagerWrapper } from "../../libraries/wrappers/Lib_SafeExecutionManagerWrapper.sol";

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
)
override
public
view
{
_revertWithFlag(RevertFlag.INTENTIONAL_REVERT, _data);
}
Expand Down Expand Up @@ -1538,6 +1539,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver {
RevertFlag _flag
)
internal
view
{
_revertWithFlag(_flag, bytes(''));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
pragma solidity >0.5.0 <0.8.0;

/* Library Imports */
import { Lib_BytesUtils } from "../../libraries/utils/Lib_BytesUtils.sol";
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
import { Lib_ECDSAUtils } from "../../libraries/utils/Lib_ECDSAUtils.sol";
import { Lib_EIP155Tx } from "../../libraries/codec/Lib_EIP155Tx.sol";
import { Lib_SafeExecutionManagerWrapper } from "../../libraries/wrappers/Lib_SafeExecutionManagerWrapper.sol";

/**
Expand All @@ -19,109 +17,55 @@ import { Lib_SafeExecutionManagerWrapper } from "../../libraries/wrappers/Lib_Sa
* Runtime target: OVM
*/
contract OVM_SequencerEntrypoint {

/*********
* Enums *
*********/

enum TransactionType {
NATIVE_ETH_TRANSACTION,
ETH_SIGNED_MESSAGE
}
using Lib_EIP155Tx for Lib_EIP155Tx.EIP155Tx;


/*********************
* Fallback Function *
*********************/

/**
* Uses a custom "compressed" format to save on calldata gas:
* calldata[00:01]: transaction type (0 == EIP 155, 2 == Eth Sign Message)
* calldata[01:33]: signature "r" parameter
* calldata[33:65]: signature "s" parameter
* calldata[65:66]: signature "v" parameter
* calldata[66:69]: transaction gas limit
* calldata[69:72]: transaction gas price
* calldata[72:75]: transaction nonce
* calldata[75:95]: transaction target address
* calldata[95:XX]: transaction data
* 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
{
TransactionType transactionType = _getTransactionType(Lib_BytesUtils.toUint8(msg.data, 0));

bytes32 r = Lib_BytesUtils.toBytes32(Lib_BytesUtils.slice(msg.data, 1, 32));
bytes32 s = Lib_BytesUtils.toBytes32(Lib_BytesUtils.slice(msg.data, 33, 32));
uint8 v = Lib_BytesUtils.toUint8(msg.data, 65);

// Remainder is the transaction to execute.
bytes memory compressedTx = Lib_BytesUtils.slice(msg.data, 66);
bool isEthSignedMessage = transactionType == TransactionType.ETH_SIGNED_MESSAGE;

// Need to decompress and then re-encode the transaction based on the original encoding.
bytes memory encodedTx = Lib_OVMCodec.encodeEIP155Transaction(
Lib_OVMCodec.decompressEIP155Transaction(compressedTx),
isEthSignedMessage
Lib_EIP155Tx.EIP155Tx memory transaction = Lib_EIP155Tx.decode(
msg.data,
Lib_SafeExecutionManagerWrapper.safeCHAINID()
);

address target = Lib_ECDSAUtils.recover(
encodedTx,
isEthSignedMessage,
uint8(v),
r,
s
// Recovery parameter being something other than 0 or 1 indicates that this transaction was
// signed using the wrong chain ID. We really should have this logic inside of the
Lib_SafeExecutionManagerWrapper.safeREQUIRE(
transaction.recoveryParam < 2,
"OVM_SequencerEntrypoint: Transaction was signed with the wrong chain ID."
);

if (Lib_SafeExecutionManagerWrapper.safeEXTCODESIZE(target) == 0) {
// ProxyEOA has not yet been deployed for this EOA.
bytes32 messageHash = Lib_ECDSAUtils.getMessageHash(encodedTx, isEthSignedMessage);
Lib_SafeExecutionManagerWrapper.safeCREATEEOA(messageHash, uint8(v), r, s);
}
// Cache this result since we use it twice. Maybe we could move this caching into
// Lib_EIP155Tx but I'd rather not make optimizations like that right now.
address sender = transaction.sender();

// ProxyEOA has been deployed for this EOA, continue to CALL.
bytes memory callbytes = abi.encodeWithSignature(
"execute(bytes,uint8,uint8,bytes32,bytes32)",
encodedTx,
isEthSignedMessage,
uint8(v),
r,
s
);
// Create an EOA contract for this account if it doesn't already exist.
if (Lib_SafeExecutionManagerWrapper.safeEXTCODESIZE(sender) == 0) {
Lib_SafeExecutionManagerWrapper.safeCREATEEOA(
transaction.hash(),
transaction.recoveryParam,
transaction.r,
transaction.s
);
}

// Now call into the EOA contract (which should definitely exist).
Lib_SafeExecutionManagerWrapper.safeCALL(
gasleft(),
target,
callbytes
sender,
abi.encodeWithSignature(
"execute(bytes)",
msg.data
)
);
}


/**********************
* Internal Functions *
**********************/

/**
* Converts a uint256 into a TransactionType enum.
* @param _transactionType Transaction type index.
* @return _txType Transaction type enum value.
*/
function _getTransactionType(
uint8 _transactionType
)
internal
returns (
TransactionType _txType
)
{
if (_transactionType == 0) {
return TransactionType.NATIVE_ETH_TRANSACTION;
} if (_transactionType == 2) {
return TransactionType.ETH_SIGNED_MESSAGE;
} else {
Lib_SafeExecutionManagerWrapper.safeREVERT(
"Transaction type must be 0 or 2"
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
pragma solidity >0.5.0 <0.8.0;
pragma experimental ABIEncoderV2;

/* Library Imports */
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";

/**
* @title iOVM_ECDSAContractAccount
*/
Expand All @@ -15,10 +12,11 @@ interface iOVM_ECDSAContractAccount {
********************/

function execute(
bytes memory _transaction,
Lib_OVMCodec.EOASignatureType _signatureType,
uint8 _v,
bytes32 _r,
bytes32 _s
) external returns (bool _success, bytes memory _returndata);
bytes memory _encodedTransaction
)
external
returns (
bool,
bytes memory
);
}
Loading