Skip to content

Conversation

@smartcontracts
Copy link
Contributor

@smartcontracts smartcontracts commented Apr 15, 2021

>>> Not ready for review <<<

Description
Working on this in a draft PR so I can have CI run.

Fixes #495

@changeset-bot
Copy link

changeset-bot bot commented Apr 15, 2021

⚠️ No Changeset found

Latest commit: 7881bc6

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@smartcontracts smartcontracts changed the title feat: Have predeploys use OVM solc only [WIP] feat: Have predeploys use OVM solc only Apr 15, 2021
@smartcontracts
Copy link
Contributor Author

Integration tests are just hanging and I have no clue how to debug that... @gakonst or @tynes?

@tynes
Copy link
Contributor

tynes commented Apr 17, 2021

Integration tests are just hanging and I have no clue how to debug that... @gakonst or @tynes?

I think the key will be to run the tests locally since docker-compose up is ran in the background

@tynes
Copy link
Contributor

tynes commented Apr 17, 2021

When building locally:

$ /optimism/node_modules/.bin/ts-node bin/take-dump.ts
(node:28) UnhandledPromiseRejectionWarning: Error: Unable to find artifact for contract: OVM_L2CrossDomainMessenger
    at Object.getContractDefinition (/optimism/packages/contracts/src/contract-defs.ts:33:15)
    at Object.getContractFactory (/optimism/packages/contracts/src/contract-defs.ts:43:32)
    at Object.makeContractDeployConfig (/optimism/packages/contracts/src/contract-deployment/config.ts:15:38)
    at Object.deploy (/optimism/packages/contracts/src/contract-deployment/deploy.ts:17:49)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
    at Object.makeStateDump (/optimism/packages/contracts/src/contract-dumps.ts:135:30)
    at /optimism/packages/contracts/bin/take-dump.ts:37:18
(Use `node --trace-warnings ...` to show where the warning was created)
(node:28) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 5)
(node:28) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

@tynes
Copy link
Contributor

tynes commented Apr 17, 2021

Running it locally found:

deployer_1         | 192.168.192.8 - - [17/Apr/2021 00:26:02] "GET /state-dump.latest.json HTTP/1.1" 404 -
l2geth_1           | panic: Cannot fetch state dump: State dump not found
l2geth_1           |
l2geth_1           | goroutine 1 [running]:
l2geth_1           | github.com/ethereum/go-ethereum/core.DeveloperGenesisBlock(0x0, 0xcdbd24fc22d45828, 0x6a322d4ce8dc026c, 0xe970b65919984a67, 0x20af5177420a9dfa, 0x7b8570a91967671d, 0x260974e5b3be8a99, 0x924707f651b7e52a, 0x3e61331b, 0x0, ...)
l2geth_1           |    /go-ethereum/core/genesis.go:486 +0x1166
l2geth_1           | github.com/ethereum/go-ethereum/cmd/utils.SetEthConfig(0xc00029a6e0, 0xc0002b0280, 0xc00016f200)
l2geth_1           |    /go-ethereum/cmd/utils/flags.go:1731 +0xf19
l2geth_1           | main.makeConfigNode(0xc00029a6e0, 0xc00016ec00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
l2geth_1           |    /go-ethereum/cmd/geth/config.go:129 +0x3cb
l2geth_1           | main.makeFullNode(0xc00029a6e0, 0x127167d)
l2geth_1           |    /go-ethereum/cmd/geth/config.go:149 +0x72
l2geth_1           | main.geth(0xc00029a6e0, 0x0, 0x0)
l2geth_1           |    /go-ethereum/cmd/geth/main.go:324 +0xf7
l2geth_1           | gopkg.in/urfave/cli%2ev1.HandleAction(0x10bf240, 0x134da38, 0xc00029a6e0, 0xc000281ce0, 0x0)
l2geth_1           |    /go/pkg/mod/gopkg.in/urfave/[email protected]/app.go:490 +0xc8
l2geth_1           | gopkg.in/urfave/cli%2ev1.(*App).Run(0xc0002b6000, 0xc000126020, 0x2, 0x2, 0x0, 0x0)
l2geth_1           |    /go/pkg/mod/gopkg.in/urfave/[email protected]/app.go:264 +0x5dd
l2geth_1           | main.main()
l2geth_1           |    /go-ethereum/cmd/geth/main.go:266 +0x55

Nit: the filename should be state-dump-latest.json instead of state-dump.latest.json so that it doesn't confuse things that expect a single dot to mark the file extension

@tynes
Copy link
Contributor

tynes commented Apr 17, 2021

@smartcontracts The state dump file fails to build so it is not created and served to l2geth on startup

@snario
Copy link
Contributor

snario commented Apr 19, 2021

This is the monorepo port of ethereum-optimism/contracts#300

@karlfloersch
Copy link
Contributor

karlfloersch commented Apr 20, 2021

After doing more debugging it seems integration tests are failing due to a bug in the compiler, probably related to kall. You can reproduce a relatively simple case by running this integration test:

it('should return the block and all included transactions', async () => {
// Send a transaction and wait for it to be mined.
const tx = DEFAULT_TRANSACTION
const result = await wallet.sendTransaction(tx)
const receipt = await result.wait()
const block = (await provider.getBlockWithTransactions(
receipt.blockHash
)) as any
expect(block.number).to.not.equal(0)
expect(typeof block.stateRoot).to.equal('string')
expect(block.transactions.length).to.equal(1)
expect(block.transactions[0].txType).to.equal('EIP155')
expect(block.transactions[0].queueOrigin).to.equal('sequencer')
expect(block.transactions[0].l1TxOrigin).to.equal(null)
})

And then observing the L2Geth logs. It should fail at const result = await wallet.sendTransaction(tx)

@ben-chain is going to help look into the compiler issue

Copy link
Collaborator

@ben-chain ben-chain left a comment

Choose a reason for hiding this comment

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

Left a good number of comments; this is looking great! Need to figure out how to get the two deleted tests back, though -- not obvious to me what the dependency problem is there, but I'm assuming that's what it is.

OriginalTargetReached bool
OvmExecutionManager dump.OvmDumpAccount
OvmStateManager dump.OvmDumpAccount
OvmMockAccount dump.OvmDumpAccount
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: this file diff seems unrelated and probably should have been a separate PR

pragma experimental ABIEncoderV2;

/* Interface Imports */
import { iOVM_ERC20 } from "../../iOVM/predeploys/iOVM_ERC20.sol";
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could this be OVM_ETH as we do have a strict assumption that it will be that specific ERC20?

Lib_SafeExecutionManagerWrapper.safeREQUIRE(
decodedTx.chainId == Lib_SafeExecutionManagerWrapper.safeCHAINID(),
require(
decodedTx.chainId == Lib_ExecutionManagerWrapper.ovmCHAINID(),
Copy link
Collaborator

Choose a reason for hiding this comment

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

could alternatively use Yul here now; so real preference from me though.

// // Need to make sure that the gas is sufficient to execute the transaction.
// Lib_SafeExecutionManagerWrapper.safeREQUIRE(
// gasleft() >= Lib_SafeMathWrapper.add(decodedTx.gasLimit, EXECUTION_VALIDATION_GAS_OVERHEAD),
// Lib_ExecutionManagerWrapper.safeREQUIRE(
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: this can be replaced with an explicit require, just like the nonce check above

Comment on lines +121 to +127
if iszero(created) {
let size := returndatasize()
revertdata := mload(0x40)
mstore(0x40, add(revertdata, and(add(add(size, 0x20), 0x1f), not(0x1f))))
mstore(revertdata, size)
returndatacopy(add(revertdata, 0x20), 0x0, size)
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

This block is a little brittle, at minimum I think adding comments is required here. This could have been left as-is though, right? I have mixed feelings--on one hand, this block of assembly would make no sense in the EVM context, so it is a little confusing to read, and the functionality feels very "wrapper-ey" to me. OTOH, I get that it does add overhead to a reviewer's life.

predeploys[name] ||
`0xdeaddeaddeaddeaddeaddeaddeaddeaddead${i.toString(16).padStart(4, '0')}`

let def: any
Copy link
Collaborator

Choose a reason for hiding this comment

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

One problem this just raised for me is that because of unsupported: evm we will now be in the situation that contracts which use kall cannot be referenced by EVM contracts. Solvable with interfaces but we should think about if there's something more clever to be done here.

before(async () => {
Factory__OVM_ECDSAContractAccount = await ethers.getContractFactory(
'OVM_ECDSAContractAccount'
Factory__OVM_ECDSAContractAccount = getContractFactory(
Copy link
Collaborator

Choose a reason for hiding this comment

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

LOL very glad that this works in either runtime

Mock__OVM_ExecutionManager.smocked.ovmCALL.will.return.with([true, '0x'])
Mock__OVM_ExecutionManager.smocked.ovmCALL.will.return.with(
(gasLimit, target, data) => {
if (target === '0x4200000000000000000000000000000000000006') {
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: getting this from the predeploys export would improve readability on this test

)
Mock__OVM_ExecutionManager.smocked.ovmSTATICCALL.will.return.with(
(gasLimit, target, data) => {
if (target === '0x0000000000000000000000000000000000000001') {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
if (target === '0x0000000000000000000000000000000000000001') {
// smock ecrecover precompile
if (target === '0x0000000000000000000000000000000000000001') {

Mock__OVM_ExecutionManager.smocked.ovmCALL.will.return.with([false, '0x'])
Mock__OVM_ExecutionManager.smocked.ovmCALL.will.return.with(
(gasLimit, target, data) => {
if (target === '0x4200000000000000000000000000000000000006') {
Copy link
Collaborator

Choose a reason for hiding this comment

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

ditto on lookup from predeploys

@smartcontracts
Copy link
Contributor Author

Going to be dropping this PR in favor of several smaller PRs. Leaving this up as reference for myself.

@gakonst
Copy link
Contributor

gakonst commented Apr 21, 2021

@smartcontracts closing - can still view this as a closed PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Upgrade the Solidity compiler to simplify pre-deploy contract code

7 participants