Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Standard RLP transactions #481

Closed
wants to merge 1 commit into from
Closed
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,21 +6,22 @@ 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";

/**
* @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
* ovmCREATEEOA operation. It enables backwards compatibility with Ethereum's Layer 1, by
* providing eth_sign and EIP155 formatted transaction encodings.
*
* Compiler used: solc
* 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,31 +53,29 @@ contract OVM_ECDSAContractAccount is iOVM_ECDSAContractAccount {
bytes memory
)
{
bool isEthSign = _signatureType == Lib_OVMCodec.EOASignatureType.ETH_SIGNED_MESSAGE;
Lib_EIP155Tx.EIP155Tx memory decodedTx = 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(
decodedTx.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(),
decodedTx.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(),
Expand All @@ -98,7 +89,8 @@ 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);
(bool success, ) = Lib_SafeExecutionManagerWrapper.safeCALL(
Expand Down
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";
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 @@ -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