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

Commit 425ffd5

Browse files
Port SequencerEntrypoint to use ovm solc (#535)
* port SequencerEntrypoint to use ovm solc * Minor tweaks and comments * have hardhat-ovm invalidate cache on commit to solc-bin * remove temporary solc version override * have cache invalidation on a per-version basis * remove ethereumjs-util dep * fix lint error * use allow_kall_2 compiler until build is fixed * add changeset
1 parent 1daabdc commit 425ffd5

12 files changed

Lines changed: 312 additions & 64 deletions

File tree

.changeset/pink-cameras-reflect.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@eth-optimism/contracts": patch
3+
"@eth-optimism/hardhat-ovm": patch
4+
---
5+
6+
Use optimistic-solc to compile the SequencerEntrypoint. Also introduces a cache invalidation mechanism for hardhat-ovm so that we can push new compiler versions.

packages/contracts/contracts/optimistic-ethereum/OVM/predeploys/OVM_SequencerEntrypoint.sol

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
// SPDX-License-Identifier: MIT
2+
// @unsupported: evm
23
pragma solidity >0.5.0 <0.8.0;
34

5+
/* Interface Imports */
6+
import { iOVM_ECDSAContractAccount } from "../../iOVM/accounts/iOVM_ECDSAContractAccount.sol";
7+
48
/* Library Imports */
59
import { Lib_BytesUtils } from "../../libraries/utils/Lib_BytesUtils.sol";
610
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
711
import { Lib_ECDSAUtils } from "../../libraries/utils/Lib_ECDSAUtils.sol";
8-
import { Lib_SafeExecutionManagerWrapper } from "../../libraries/wrappers/Lib_SafeExecutionManagerWrapper.sol";
12+
import { Lib_ExecutionManagerWrapper } from "../../libraries/wrappers/Lib_ExecutionManagerWrapper.sol";
913

1014
/**
1115
* @title OVM_SequencerEntrypoint
@@ -15,7 +19,7 @@ import { Lib_SafeExecutionManagerWrapper } from "../../libraries/wrappers/Lib_Sa
1519
* This contract is the implementation referenced by the Proxy Sequencer Entrypoint, thus enabling
1620
* the Optimism team to upgrade the decompression of calldata from the Sequencer.
1721
*
18-
* Compiler used: solc
22+
* Compiler used: optimistic-solc
1923
* Runtime target: OVM
2024
*/
2125
contract OVM_SequencerEntrypoint {
@@ -59,43 +63,56 @@ contract OVM_SequencerEntrypoint {
5963
bytes memory compressedTx = Lib_BytesUtils.slice(msg.data, 66);
6064
bool isEthSignedMessage = transactionType == TransactionType.ETH_SIGNED_MESSAGE;
6165

66+
// Grab the chain ID for the current network.
67+
uint256 chainId;
68+
assembly {
69+
chainId := chainid()
70+
}
71+
6272
// Need to decompress and then re-encode the transaction based on the original encoding.
6373
bytes memory encodedTx = Lib_OVMCodec.encodeEIP155Transaction(
64-
Lib_OVMCodec.decompressEIP155Transaction(compressedTx),
74+
Lib_OVMCodec.decompressEIP155Transaction(
75+
compressedTx,
76+
chainId
77+
),
6578
isEthSignedMessage
6679
);
6780

6881
address target = Lib_ECDSAUtils.recover(
6982
encodedTx,
7083
isEthSignedMessage,
71-
uint8(v),
84+
v,
7285
r,
7386
s
7487
);
7588

76-
if (Lib_SafeExecutionManagerWrapper.safeEXTCODESIZE(target) == 0) {
89+
bool isEmptyContract;
90+
assembly {
91+
isEmptyContract := iszero(extcodesize(target))
92+
}
93+
94+
if (isEmptyContract) {
7795
// ProxyEOA has not yet been deployed for this EOA.
7896
bytes32 messageHash = Lib_ECDSAUtils.getMessageHash(encodedTx, isEthSignedMessage);
79-
Lib_SafeExecutionManagerWrapper.safeCREATEEOA(messageHash, uint8(v), r, s);
97+
Lib_ExecutionManagerWrapper.ovmCREATEEOA(messageHash, v, r, s);
8098
}
8199

82-
// ProxyEOA has been deployed for this EOA, continue to CALL.
83-
bytes memory callbytes = abi.encodeWithSignature(
84-
"execute(bytes,uint8,uint8,bytes32,bytes32)",
100+
Lib_OVMCodec.EOASignatureType sigtype;
101+
if (isEthSignedMessage) {
102+
sigtype = Lib_OVMCodec.EOASignatureType.ETH_SIGNED_MESSAGE;
103+
} else {
104+
sigtype = Lib_OVMCodec.EOASignatureType.EIP155_TRANSACTION;
105+
}
106+
107+
iOVM_ECDSAContractAccount(target).execute(
85108
encodedTx,
86-
isEthSignedMessage,
87-
uint8(v),
109+
sigtype,
110+
v,
88111
r,
89112
s
90113
);
91-
92-
Lib_SafeExecutionManagerWrapper.safeCALL(
93-
gasleft(),
94-
target,
95-
callbytes
96-
);
97114
}
98-
115+
99116

100117
/**********************
101118
* Internal Functions *
@@ -119,9 +136,7 @@ contract OVM_SequencerEntrypoint {
119136
} if (_transactionType == 2) {
120137
return TransactionType.ETH_SIGNED_MESSAGE;
121138
} else {
122-
Lib_SafeExecutionManagerWrapper.safeREVERT(
123-
"Transaction type must be 0 or 2"
124-
);
139+
revert("Transaction type must be 0 or 2");
125140
}
126141
}
127142
}

packages/contracts/contracts/optimistic-ethereum/libraries/codec/Lib_OVMCodec.sol

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,12 @@ library Lib_OVMCodec {
155155
/**
156156
* Decompresses a compressed EIP155 transaction.
157157
* @param _transaction Compressed EIP155 transaction bytes.
158+
* @param _chainId Chain ID this transaction was signed with.
158159
* @return Transaction parsed into a struct.
159160
*/
160161
function decompressEIP155Transaction(
161-
bytes memory _transaction
162+
bytes memory _transaction,
163+
uint256 _chainId
162164
)
163165
internal
164166
returns (
@@ -171,7 +173,7 @@ library Lib_OVMCodec {
171173
nonce: Lib_BytesUtils.toUint24(_transaction, 6),
172174
to: Lib_BytesUtils.toAddress(_transaction, 9),
173175
data: Lib_BytesUtils.slice(_transaction, 29),
174-
chainId: Lib_SafeExecutionManagerWrapper.safeCHAINID(),
176+
chainId: _chainId,
175177
value: 0
176178
});
177179
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// SPDX-License-Identifier: MIT
2+
// @unsupported: evm
3+
pragma solidity >0.5.0 <0.8.0;
4+
5+
/* Library Imports */
6+
import { Lib_ErrorUtils } from "../utils/Lib_ErrorUtils.sol";
7+
8+
/**
9+
* @title Lib_ExecutionManagerWrapper
10+
*
11+
* Compiler used: solc
12+
* Runtime target: OVM
13+
*/
14+
library Lib_ExecutionManagerWrapper {
15+
16+
/**********************
17+
* Internal Functions *
18+
**********************/
19+
20+
/**
21+
* Performs a safe ovmGETNONCE call.
22+
* @return _nonce Result of calling ovmGETNONCE.
23+
*/
24+
function ovmGETNONCE()
25+
internal
26+
returns (
27+
uint256 _nonce
28+
)
29+
{
30+
bytes memory returndata = _safeExecutionManagerInteraction(
31+
abi.encodeWithSignature(
32+
"ovmGETNONCE()"
33+
)
34+
);
35+
36+
return abi.decode(returndata, (uint256));
37+
}
38+
39+
/**
40+
* Performs a safe ovmINCREMENTNONCE call.
41+
*/
42+
function ovmINCREMENTNONCE()
43+
internal
44+
{
45+
_safeExecutionManagerInteraction(
46+
abi.encodeWithSignature(
47+
"ovmINCREMENTNONCE()"
48+
)
49+
);
50+
}
51+
52+
/**
53+
* Performs a safe ovmCREATEEOA call.
54+
* @param _messageHash Message hash which was signed by EOA
55+
* @param _v v value of signature (0 or 1)
56+
* @param _r r value of signature
57+
* @param _s s value of signature
58+
*/
59+
function ovmCREATEEOA(
60+
bytes32 _messageHash,
61+
uint8 _v,
62+
bytes32 _r,
63+
bytes32 _s
64+
)
65+
internal
66+
{
67+
_safeExecutionManagerInteraction(
68+
abi.encodeWithSignature(
69+
"ovmCREATEEOA(bytes32,uint8,bytes32,bytes32)",
70+
_messageHash,
71+
_v,
72+
_r,
73+
_s
74+
)
75+
);
76+
}
77+
78+
/**
79+
* Calls the ovmL1TXORIGIN opcode.
80+
* @return Address that sent this message from L1.
81+
*/
82+
function ovmL1TXORIGIN()
83+
internal
84+
returns (
85+
address
86+
)
87+
{
88+
bytes memory returndata = _safeExecutionManagerInteraction(
89+
abi.encodeWithSignature(
90+
"ovmL1TXORIGIN()"
91+
)
92+
);
93+
94+
return abi.decode(returndata, (address));
95+
}
96+
97+
98+
/*********************
99+
* Private Functions *
100+
*********************/
101+
102+
/**
103+
* Performs an ovm interaction and the necessary safety checks.
104+
* @param _calldata Data to send to the OVM_ExecutionManager (encoded with sighash).
105+
* @return _returndata Data sent back by the OVM_ExecutionManager.
106+
*/
107+
function _safeExecutionManagerInteraction(
108+
bytes memory _calldata
109+
)
110+
private
111+
returns (
112+
bytes memory
113+
)
114+
{
115+
bytes memory returndata;
116+
assembly {
117+
// kall is a custom yul builtin within optimistic-solc that allows us to directly call
118+
// the execution manager (since `call` would be compiled).
119+
kall(add(_calldata, 0x20), mload(_calldata), 0x0, 0x0)
120+
let size := returndatasize()
121+
returndata := mload(0x40)
122+
mstore(0x40, add(returndata, and(add(add(size, 0x20), 0x1f), not(0x1f))))
123+
mstore(returndata, size)
124+
returndatacopy(add(returndata, 0x20), 0x0, size)
125+
}
126+
return returndata;
127+
}
128+
}

packages/contracts/contracts/test-libraries/codec/TestLib_OVMCodec.sol

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,17 @@ contract TestLib_OVMCodec {
4848
}
4949

5050
function decompressEIP155Transaction(
51-
bytes memory _transaction
51+
bytes memory _transaction,
52+
uint256 _chainId
5253
)
5354
public
5455
returns (
5556
Lib_OVMCodec.EIP155Transaction memory _decompressed
5657
)
5758
{
58-
return Lib_OVMCodec.decompressEIP155Transaction(_transaction);
59+
return Lib_OVMCodec.decompressEIP155Transaction(
60+
_transaction,
61+
_chainId
62+
);
5963
}
6064
}

packages/contracts/hardhat.config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ const config: HardhatUserConfig = {
4848
},
4949
},
5050
},
51+
ovm: {
52+
solcVersion: '0.7.6-allow_kall_2', // temporary until we fix the build for 0.7.6
53+
},
5154
typechain: {
5255
outDir: 'dist/types',
5356
target: 'ethers-v5',

packages/contracts/src/contract-deployment/config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ export const makeContractDeployConfig = async (
220220
factory: getContractFactory('OVM_ECDSAContractAccount'),
221221
},
222222
OVM_SequencerEntrypoint: {
223-
factory: getContractFactory('OVM_SequencerEntrypoint'),
223+
factory: getContractFactory('OVM_SequencerEntrypoint', undefined, true),
224224
},
225225
OVM_ProxySequencerEntrypoint: {
226226
factory: getContractFactory('OVM_ProxySequencerEntrypoint'),

packages/contracts/src/contract-dumps.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ export const makeStateDump = async (cfg: RollupDeployConfig): Promise<any> => {
164164
const ovmCompiled = [
165165
'OVM_L2ToL1MessagePasser',
166166
'OVM_L2CrossDomainMessenger',
167+
'OVM_SequencerEntrypoint',
167168
'Lib_AddressManager',
168169
'OVM_ETH',
169170
]
@@ -211,12 +212,19 @@ export const makeStateDump = async (cfg: RollupDeployConfig): Promise<any> => {
211212
predeploys[name] ||
212213
`0xdeaddeaddeaddeaddeaddeaddeaddeaddead${i.toString(16).padStart(4, '0')}`
213214

215+
let def: any
216+
try {
217+
def = getContractDefinition(name.replace('Proxy__', ''))
218+
} catch (err) {
219+
def = getContractDefinition(name.replace('Proxy__', ''), true)
220+
}
221+
214222
dump.accounts[name] = {
215223
address: deadAddress,
216224
code,
217225
codeHash: keccak256(code),
218226
storage: await getStorageDump(cStateManager, contract.address),
219-
abi: getContractDefinition(name.replace('Proxy__', '')).abi,
227+
abi: def.abi,
220228
}
221229
}
222230

packages/contracts/test/contracts/OVM/precompiles/OVM_ProxySequencerEntrypoint.spec.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { remove0x } from '@eth-optimism/core-utils'
88

99
/* Internal Imports */
1010
import { decodeSolidityError } from '../../../helpers'
11+
import { getContractFactory } from '../../../../src'
1112

1213
const callPredeploy = async (
1314
Helper_PredeployCaller: Contract,
@@ -59,8 +60,10 @@ describe('OVM_ProxySequencerEntrypoint', () => {
5960

6061
Helper_PredeployCaller.setTarget(Mock__OVM_ExecutionManager.address)
6162

62-
OVM_SequencerEntrypoint = await (
63-
await ethers.getContractFactory('OVM_SequencerEntrypoint')
63+
OVM_SequencerEntrypoint = await getContractFactory(
64+
'OVM_SequencerEntrypoint',
65+
wallet,
66+
true
6467
).deploy()
6568
})
6669

0 commit comments

Comments
 (0)