Skip to content

l2geth + contracts: standard interface for systems contracts and userland contracts#721

Merged
tynes merged 6 commits intov0.3.0-rcfrom
l2geth/fix-returndata
May 3, 2021
Merged

l2geth + contracts: standard interface for systems contracts and userland contracts#721
tynes merged 6 commits intov0.3.0-rcfrom
l2geth/fix-returndata

Conversation

@tynes
Copy link
Contributor

@tynes tynes commented May 1, 2021

Description
This PR ABI decodes the results from the EVM execution. Previously we were just slicing bytes, which worked in some cases. Once we started to return different ABIs, the slicing no longer worked. I observed some pretty unexpected results being assigned to ret and success with just the slicing.

Additional context
There have been problems around eth_estimateGas failing - I believe this is due to the fact that simulateMessage() and run() return different ABI encoded types and the parsing was the same for both. This is an attempt to solve the problem once and for all, so that eth_call and eth_estimateGas are stable and work the same as eth_sendRawTransaction

@changeset-bot
Copy link

changeset-bot bot commented May 1, 2021

🦋 Changeset detected

Latest commit: c98c811

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@eth-optimism/l2geth Patch
@eth-optimism/contracts Patch

Not sure what this means? Click here to learn what changesets are.

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

Comment on lines 387 to 392
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe there is a reason to leave it, but notably these code paths are duplicate in practice with the return types currently laid out, and either would work in both cases.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am not super opinionated on leaving both or using a custom coder that has the exact methods, my intention was to be explicit

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This would be cleaner to use the codec and unpack a method that will abi decode bytes

Copy link
Contributor

Choose a reason for hiding this comment

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

IMO better to use both since they're separate functions and may change.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We need to standardize these 2 methods such that they are the same, they should never change

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.

This LGTM to merge into the RC. I have some integration tests I recently wrote locally which I can check against this that were failing against the RC before. :)

Copy link
Collaborator

Choose a reason for hiding this comment

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

Would note somehow here that this is a convention followed by our contracts, and may not necessarily be the case for arbitrary enqueues.

On the plus side, this return type will let us finally crack #497 by adding the same return type to the OVM_L2CrossDomainMessenger. :)

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should actually talk more about this one -- I don't think it should be necessary for us to return abi.encode(true, bytes("")) in OVM_L2CrossDomainMessenger. If we add that requirement then we're gonna get a lot of L2 contracts that weirdly return the same thing (just to make the receipts work).

Copy link
Contributor

Choose a reason for hiding this comment

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

@tynes this is what I wanted to talk to you about earlier

Copy link
Contributor

Choose a reason for hiding this comment

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

A bit confused, does this change imply that consuming contracts would need to follow a specific return value convention? My understanding was that this change only concerns the executionManager's returned values.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There needs to be a strictly defined interface between the system contracts and the userland contracts for consistency purposes. Before this PR, there was not a consistent ABI - two examples are ExecutionManger.run(...)(bytes) and ExecutionManager.simulateMessage(...)(bool,bytes). The run() bytes had a nested ABI encoded (bool,bytes).

We want to index information about the userland contracts and not the system contracts so that when users query for receipt or transaction they get the from to be the ESCDA Contract Account. We enforce that a specific ABI encoding is returned from the userland contracts and passed through the system contracts such that geth can receive the data here and parse it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is anybody opinionated on what this should be named? It needs a name for the geth ABI package to work

Copy link
Contributor

@karlfloersch karlfloersch May 2, 2021

Choose a reason for hiding this comment

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

The value you added here isn't currently being used. You'd ether want to update the variable below from returndata to _returndata or just remove the variable declaration in generally. Personally I'd lean towards removing the variable declaration to keep this PR from changing any code in the run(...) function.

Oh and not opinionated about the name of this variable

Copy link
Contributor

@smartcontracts smartcontracts left a comment

Choose a reason for hiding this comment

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

I'm gonna block this for now because I think we need to be careful with how we proceed here. I'm gonna write down my thoughts in a longer comment in a bit.

@tynes tynes force-pushed the l2geth/fix-returndata branch from 022b277 to 16bd8fd Compare May 1, 2021 01:22
@tynes
Copy link
Contributor Author

tynes commented May 1, 2021

I'm gonna block this for now because I think we need to be careful with how we proceed here. I'm gonna write down my thoughts in a longer comment in a bit.

I agree that this should be thought about more before merging

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Rename this to something canonical

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@gakonst I'd like to define a common interface that defines the interaction between system contracts and userland contracts. This ABI would need to decode 2 things. One method decodes bytes and another method decodes bool,bytes.

Methods that need to use the interface:

  • ExecutionManager.run
  • ExecutionManager.simulateMessage
  • OVM_L2CrossDomainMessenger.relayMessage

If this interface is followed, then geth will index the transactions based on the userland contracts instead of the system contracts

Comment on lines 387 to 392
Copy link
Contributor

Choose a reason for hiding this comment

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

IMO better to use both since they're separate functions and may change.

Copy link
Contributor

Choose a reason for hiding this comment

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

Should maybe handle the error anyway?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We want to be sure to not shadow err here so it would have to be:

if err := codec.Unpack(&inner, "call", run.ReturnData); err != nil {
    ...
}

We don't need to log the error and we don't want to return early if there is an error, any suggestions in particular?

Copy link
Contributor

Choose a reason for hiding this comment

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

A bit confused, does this change imply that consuming contracts would need to follow a specific return value convention? My understanding was that this change only concerns the executionManager's returned values.

@tynes
Copy link
Contributor Author

tynes commented May 2, 2021

The estimateGas return values were changed, I can update them to make the tests pass again but I'm not 100% sure why they are changing

@tynes tynes force-pushed the l2geth/fix-returndata branch from 48e9bcc to 3d20b0e Compare May 2, 2021 18:05
Copy link
Contributor

Choose a reason for hiding this comment

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

If you remove _returndata above, probably good to remove it here too.

I think our Solidity style is no longer using these returns variable declarations

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The returned arguments must be named or the geth ABI package will not be able to decode them into a struct

Copy link
Contributor

Choose a reason for hiding this comment

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

Got it! I'd suggest adding a comment in the function about that because it seemed like a code smell to not use the variable that was defined, but I also hear you about not liking to use the variables defined in the returns statement.

I also think we should define our Solidity style guide because right now I believe our style is to not use the returns variables, but I hear you on why it's useful to have them in this case. And then if we ever diverge from the style guide we can add comments for why we did.

Copy link
Contributor

@karlfloersch karlfloersch 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 few notes which should be addressed before merging but overall this LGTM!

Curious what @smartcontracts your concern was

@tynes tynes force-pushed the l2geth/fix-returndata branch from 2ae27e1 to c98c811 Compare May 3, 2021 02:59
@tynes tynes changed the title l2geth + contracts: abi decoding + standard interface l2geth + contracts: standard interface for systems contracts and userland contracts May 3, 2021
var deadPrefix, fortyTwoPrefix, zeroPrefix []byte

func init() {
const abidata = `
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This should be defined as an interface in the contracts repo and I should be able to import its ABI

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think that should be possible if we can add it to the spec

@tynes
Copy link
Contributor Author

tynes commented May 3, 2021

The estimateGas return values were changed, I can update them to make the tests pass again but I'm not 100% sure why they are changing

This was due to the merge of master in the v0.3.0-rc branch

@tynes
Copy link
Contributor Author

tynes commented May 3, 2021

A bit confused, does this change imply that consuming contracts would need to follow a specific return value convention? My understanding was that this change only concerns the executionManager's returned values.

The smart contract wallet developers need to be aware of this convention so that l2geth can properly index the transaction as if it originated from the smart contract wallet instead of it originating at ExecutionManager.run. This will make the RPC more similar to the L1 RPC

// If this fails to decode, the nil values will be set in
// `inner`, meaning that it will be interpreted as reverted
// execution with empty returndata
_ = codec.Unpack(&inner, "call", returnData.ReturnData)
Copy link
Contributor

Choose a reason for hiding this comment

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

Currently we decode under the assumption that userland contracts will return (bool, bytes). I'd like to also support (bool) returndata. One way to cheat this is by appending the zero hash to the returndata if you want a hack that will work consistently.

Copy link
Contributor

Choose a reason for hiding this comment

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

Fineeee no hacks. Better just add a second decoding step.

@tynes tynes merged commit 2aaefbe into v0.3.0-rc May 3, 2021
@tynes tynes deleted the l2geth/fix-returndata branch May 3, 2021 23:10
tynes added a commit that referenced this pull request May 10, 2021
* feat: Attempt to decode txs as RLP first (#563)

Co-authored-by: smartcontracts <smartcontracts@doge.org>

* l2geth: remove eth_sendRawEthSignTransaction endpoint (#589)

* feat[contracts]: Use standard RLP transaction format (#566)

* feat[contracts]: Use standard RLP transaction format

* fix[l2geth]: Encode transaction as RLP

* fix: Correct gas estimation in integration tests

* fix: Correct gas estimation in integration tests

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

Co-authored-by: ben-chain <ben@pseudonym.party>

* fix[contracts]: Use isCreate instead of checking target address

* fix[contracts]: Minor optimization in SequencerEntrypoint

* fix[contracts]: Pass max gas to contract call in EOA contract

Co-authored-by: ben-chain <ben@pseudonym.party>

* feat[contracts]: Make ProxyEOA compatible with eip1967 (#592)

* feat[contracts]: Make ProxyEOA compatible with eip1967

* fix[contracts]: Fix bug introduced by indirect constant

* chore[contracts]: Add changeset

* Update .changeset/old-cycles-invite.md

Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>

* l2geth: remove ovmsigner (#591)

* l2geth: remove ovmsigner

Also reduce the diff

Co-authored-by: smartcontracts

* l2geth: add changeset

* l2geth: set rlp encoded tx in txmeta in RPC layer (#644)

* l2geth: set rlp encoded tx in txmeta in RPC layer

* l2geth: remove extra setter of txmeta

* chore: add changeset

* feat: Have ExecutionManager pass data upwards (#643)

* feat[contracts]: Make ExecutionManager return data

* fix[l2geth]: fix linting error

* fix[contracts]: Fix build error

* fix[contracts]: fix failing unit tests

* Add changeset

Co-authored-by: Karl Floersch <karl@karlfloersch.com>

* rpc: only allow txs with no calldata when there is value (#645)

* l2geth: api checks for 0 value

* chore: add changeset

* l2geth: remove check for specific gasprice

* feat[contracts]: Add value transfer support to ECDSAContractAccount (#619)

* feat[contracts]: Use standard RLP transaction format (#566)

* feat[contracts]: Use standard RLP transaction format

* fix[l2geth]: Encode transaction as RLP

* fix: Correct gas estimation in integration tests

* fix: Correct gas estimation in integration tests

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

Co-authored-by: ben-chain <ben@pseudonym.party>

* fix[contracts]: Use isCreate instead of checking target address

* fix[contracts]: Minor optimization in SequencerEntrypoint

* fix[contracts]: Pass max gas to contract call in EOA contract

Co-authored-by: ben-chain <ben@pseudonym.party>

* feat[contracts]: Add value transfer to contract account

* fix[contracts]: Tweak transfer logic and add tests

* fix[geth]: Remove logic that rejects value gt 0 txs

* fix: nonce issue in rpc tests

* fix: use correct wallet in rpc value tests

* Update rpc.spec.ts

* cleanup: remove double definition

* chore: add changeset

* chore: add changeset

* tests: delete dead test

* l2geth: log the tx value

* l2geth: pass through zero value at top level

* test: receipt passes

* test: more specifically set balance

Co-authored-by: ben-chain <ben@pseudonym.party>
Co-authored-by: Mark Tyneway <mark.tyneway@gmail.com>

* dtl: remove legacy encoding (#618)

* dtl: remove legacy decoding

* tests: remove dead test

* chore: add changeset

* Add Goerli v3 deployment (#651)

* Add Goerli v3 deployment

* Add Goerli v3 to README

* dtlL fix syncing off by one (#687)

* dtl: syncing off by one error

* chore: add changeset

* dtl: index the value field (#686)

* chore: add changeset

* chore: add changeset

* dtl: pass through value field

* core-utils: update and test toRpcString

* lint: fix

* l2geth: parse value fields

* chore: add changeset

* rpc: gas fixes (#695)

* l2geth: prevent fees lower than 21000

* l2geth: remove old check for too high tx gaslimit

* tests: update to use new min gas estimated value

* chore: add changeset

* test: update expected values

* test: remove dead test

* examples: fix waffle example + gas changes in tests (#724)

* examples: fix waffle example

* tests: update gas price in assertion

* chore: add changeset

* l2geth: estimate gas assertion in decimal

* test: use configurable key

* ops: delete extra whitespace (#731)

* fix: prevent eth sendtransaction (#725)

* api: prevent unsafe calls

* api: fill in txmeta

* chore: add changeset

* chore: add changeset

* l2geth + contracts:  standard interface for systems contracts and userland contracts (#721)

* l2geth: fix call returndata parsing

* contracts: standardize simulateMessage and run to return bytes

* chore: add changeset

* chore: add changeset

* l2geth: more simple decoding

* contracts: remove named arguments

* chore: fix linter errors

* Add contract deployment to Kovan (#715)

* fix: remove type check in rollup client (#750)

* l2geth: remove tx type check in client

* chore: add changeset

* dtl: prevent null reference in L1 handler (#757)

* dtl: prevent reference of null value

* chore: add changeset

* test: eth_call exceptions (#800)

* feat[l2geth]: Pass up contract revert reasons during DoEstimateGas (#774)

* wip: Starting work on geth revert reasons during estimate gas

fix: error in comment

fix: I got things backwards

fix: Use UnpackValues instead of Unpack

Update l2geth/accounts/abi/abi.go

Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>

* Add integration test for reverts

fix: build error

* chore: Add changeset

Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>

* chore: add changeset (#831)

* Migrate ETH between gateways (#778)

* add migrate ETH functionality

* contracts: add eth gateway docstring (#832)

Co-authored-by: Mark Tyneway <mark.tyneway@gmail.com>

Co-authored-by: smartcontracts <smartcontracts@doge.org>
Co-authored-by: Mark Tyneway <mark.tyneway@gmail.com>
Co-authored-by: smartcontracts <kelvinfichter@gmail.com>
Co-authored-by: ben-chain <ben@pseudonym.party>
Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>
Co-authored-by: Maurelian <maurelian@protonmail.ch>
Co-authored-by: Kevin Ho <kevinjho1996@gmail.com>
InoMurko pushed a commit to omgnetwork/optimism that referenced this pull request May 25, 2021
* feat: Attempt to decode txs as RLP first (#563)

Co-authored-by: smartcontracts <smartcontracts@doge.org>

* l2geth: remove eth_sendRawEthSignTransaction endpoint (#589)

* feat[contracts]: Use standard RLP transaction format (#566)

* feat[contracts]: Use standard RLP transaction format

* fix[l2geth]: Encode transaction as RLP

* fix: Correct gas estimation in integration tests

* fix: Correct gas estimation in integration tests

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

Co-authored-by: ben-chain <ben@pseudonym.party>

* fix[contracts]: Use isCreate instead of checking target address

* fix[contracts]: Minor optimization in SequencerEntrypoint

* fix[contracts]: Pass max gas to contract call in EOA contract

Co-authored-by: ben-chain <ben@pseudonym.party>

* feat[contracts]: Make ProxyEOA compatible with eip1967 (#592)

* feat[contracts]: Make ProxyEOA compatible with eip1967

* fix[contracts]: Fix bug introduced by indirect constant

* chore[contracts]: Add changeset

* Update .changeset/old-cycles-invite.md

Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>

* l2geth: remove ovmsigner (#591)

* l2geth: remove ovmsigner

Also reduce the diff

Co-authored-by: smartcontracts

* l2geth: add changeset

* l2geth: set rlp encoded tx in txmeta in RPC layer (ethereum-optimism#644)

* l2geth: set rlp encoded tx in txmeta in RPC layer

* l2geth: remove extra setter of txmeta

* chore: add changeset

* feat: Have ExecutionManager pass data upwards (ethereum-optimism#643)

* feat[contracts]: Make ExecutionManager return data

* fix[l2geth]: fix linting error

* fix[contracts]: Fix build error

* fix[contracts]: fix failing unit tests

* Add changeset

Co-authored-by: Karl Floersch <karl@karlfloersch.com>

* rpc: only allow txs with no calldata when there is value (ethereum-optimism#645)

* l2geth: api checks for 0 value

* chore: add changeset

* l2geth: remove check for specific gasprice

* feat[contracts]: Add value transfer support to ECDSAContractAccount (ethereum-optimism#619)

* feat[contracts]: Use standard RLP transaction format (#566)

* feat[contracts]: Use standard RLP transaction format

* fix[l2geth]: Encode transaction as RLP

* fix: Correct gas estimation in integration tests

* fix: Correct gas estimation in integration tests

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

Co-authored-by: ben-chain <ben@pseudonym.party>

* fix[contracts]: Use isCreate instead of checking target address

* fix[contracts]: Minor optimization in SequencerEntrypoint

* fix[contracts]: Pass max gas to contract call in EOA contract

Co-authored-by: ben-chain <ben@pseudonym.party>

* feat[contracts]: Add value transfer to contract account

* fix[contracts]: Tweak transfer logic and add tests

* fix[geth]: Remove logic that rejects value gt 0 txs

* fix: nonce issue in rpc tests

* fix: use correct wallet in rpc value tests

* Update rpc.spec.ts

* cleanup: remove double definition

* chore: add changeset

* chore: add changeset

* tests: delete dead test

* l2geth: log the tx value

* l2geth: pass through zero value at top level

* test: receipt passes

* test: more specifically set balance

Co-authored-by: ben-chain <ben@pseudonym.party>
Co-authored-by: Mark Tyneway <mark.tyneway@gmail.com>

* dtl: remove legacy encoding (ethereum-optimism#618)

* dtl: remove legacy decoding

* tests: remove dead test

* chore: add changeset

* Add Goerli v3 deployment (ethereum-optimism#651)

* Add Goerli v3 deployment

* Add Goerli v3 to README

* dtlL fix syncing off by one (ethereum-optimism#687)

* dtl: syncing off by one error

* chore: add changeset

* dtl: index the value field (ethereum-optimism#686)

* chore: add changeset

* chore: add changeset

* dtl: pass through value field

* core-utils: update and test toRpcString

* lint: fix

* l2geth: parse value fields

* chore: add changeset

* rpc: gas fixes (ethereum-optimism#695)

* l2geth: prevent fees lower than 21000

* l2geth: remove old check for too high tx gaslimit

* tests: update to use new min gas estimated value

* chore: add changeset

* test: update expected values

* test: remove dead test

* examples: fix waffle example + gas changes in tests (ethereum-optimism#724)

* examples: fix waffle example

* tests: update gas price in assertion

* chore: add changeset

* l2geth: estimate gas assertion in decimal

* test: use configurable key

* ops: delete extra whitespace (ethereum-optimism#731)

* fix: prevent eth sendtransaction (ethereum-optimism#725)

* api: prevent unsafe calls

* api: fill in txmeta

* chore: add changeset

* chore: add changeset

* l2geth + contracts:  standard interface for systems contracts and userland contracts (ethereum-optimism#721)

* l2geth: fix call returndata parsing

* contracts: standardize simulateMessage and run to return bytes

* chore: add changeset

* chore: add changeset

* l2geth: more simple decoding

* contracts: remove named arguments

* chore: fix linter errors

* Add contract deployment to Kovan (ethereum-optimism#715)

* fix: remove type check in rollup client (ethereum-optimism#750)

* l2geth: remove tx type check in client

* chore: add changeset

* dtl: prevent null reference in L1 handler (ethereum-optimism#757)

* dtl: prevent reference of null value

* chore: add changeset

* test: eth_call exceptions (ethereum-optimism#800)

* feat[l2geth]: Pass up contract revert reasons during DoEstimateGas (ethereum-optimism#774)

* wip: Starting work on geth revert reasons during estimate gas

fix: error in comment

fix: I got things backwards

fix: Use UnpackValues instead of Unpack

Update l2geth/accounts/abi/abi.go

Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>

* Add integration test for reverts

fix: build error

* chore: Add changeset

Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>

* chore: add changeset (ethereum-optimism#831)

* Migrate ETH between gateways (ethereum-optimism#778)

* add migrate ETH functionality

* contracts: add eth gateway docstring (ethereum-optimism#832)

Co-authored-by: Mark Tyneway <mark.tyneway@gmail.com>

Co-authored-by: smartcontracts <smartcontracts@doge.org>
Co-authored-by: Mark Tyneway <mark.tyneway@gmail.com>
Co-authored-by: smartcontracts <kelvinfichter@gmail.com>
Co-authored-by: ben-chain <ben@pseudonym.party>
Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>
Co-authored-by: Maurelian <maurelian@protonmail.ch>
Co-authored-by: Kevin Ho <kevinjho1996@gmail.com>
OptimismBot pushed a commit that referenced this pull request Dec 3, 2025
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.

5 participants

Comments