-
Notifications
You must be signed in to change notification settings - Fork 2.9k
/
OVM_ECDSAContractAccount.sol
146 lines (126 loc) · 5.22 KB
/
OVM_ECDSAContractAccount.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// SPDX-License-Identifier: MIT
// @unsupported: evm
pragma solidity >0.5.0 <0.8.0;
pragma experimental ABIEncoderV2;
/* Interface Imports */
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_ExecutionManagerWrapper } from "../../libraries/wrappers/Lib_ExecutionManagerWrapper.sol";
/* Contract Imports */
import { OVM_ETH } from "../predeploys/OVM_ETH.sol";
/* External Imports */
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.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 eth_sign and EIP155 formatted transaction encodings.
*
* Compiler used: optimistic-solc
* Runtime target: OVM
*/
contract OVM_ECDSAContractAccount is iOVM_ECDSAContractAccount {
/*************
* 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;
OVM_ETH constant ovmETH = OVM_ETH(0x4200000000000000000000000000000000000006);
/********************
* Public Functions *
********************/
/**
* 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.
* @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
)
override
public
returns (
bool,
bytes memory
)
{
bool isEthSign = _signatureType == Lib_OVMCodec.EOASignatureType.ETH_SIGNED_MESSAGE;
// 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.
require(
Lib_ECDSAUtils.recover(
_transaction,
isEthSign,
_v,
_r,
_s
) == address(this),
"Signature provided for EOA transaction execution is invalid."
);
Lib_OVMCodec.EIP155Transaction memory decodedTx = Lib_OVMCodec.decodeEIP155Transaction(
_transaction,
isEthSign
);
// Grab the chain ID of the current network.
uint256 chainId;
assembly {
chainId := chainid()
}
// Need to make sure that the transaction chainId is correct.
require(
decodedTx.chainId == chainId,
"Transaction chainId does not match expected OVM chainId."
);
// Need to make sure that the transaction nonce is right.
require(
decodedTx.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(decodedTx.gasLimit, EXECUTION_VALIDATION_GAS_OVERHEAD),
// "Gas is not sufficient to execute the transaction."
// );
// Transfer fee to relayer.
require(
ovmETH.transfer(
msg.sender,
SafeMath.mul(decodedTx.gasLimit, decodedTx.gasPrice)
),
"Fee was not transferred to relayer."
);
// Contract creations are signalled by sending a transaction to the zero address.
if (decodedTx.to == address(0)) {
(address created, bytes memory revertdata) = Lib_ExecutionManagerWrapper.ovmCREATE(
decodedTx.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();
return decodedTx.to.call(decodedTx.data);
}
}
}