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

Refactor L1 user deposit processing in x/rollup module #208

Merged
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
10 changes: 6 additions & 4 deletions builder/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,14 +311,16 @@ func TestBuildRollupTxs(t *testing.T) {
require.Len(t, ethTxs, 2, "Expected two Ethereum transactions: L1 attribute and deposit tx, got %d", len(ethTxs))

depositTxETH := ethTxs[1]
require.NotNil(t, depositTxETH.Value())
require.NotNil(t, depositTxETH.Mint())
require.NotNil(t, depositTxETH.To(), "Deposit transaction must have a 'to' address")

cosmAddr := utils.EvmToCosmosAddress(*depositTxETH.To())
from, err := gethtypes.NewCancunSigner(depositTxETH.ChainId()).Sender(depositTxETH)
require.NoError(t, err)
cosmAddr := utils.EvmToCosmosAddress(from)
withdrawalTx := testapp.ToTx(t, &types.MsgInitiateWithdrawal{
Sender: cosmAddr.String(),
Target: common.HexToAddress("0x12345abcde").String(),
Value: math.NewIntFromBigInt(depositTxETH.Value()),
Value: math.NewIntFromBigInt(depositTxETH.Mint()),
GasLimit: big.NewInt(100_000).Bytes(),
Data: []byte{},
})
Expand Down Expand Up @@ -346,7 +348,7 @@ func TestBuildRollupTxs(t *testing.T) {
builtBlock, preBuildInfo, postBuildInfo := buildBlock(t, b, env.app, payload)

// Test deposit was received
checkDepositTxResult(t, env.txStore, depositTxs, fmt.Sprintf("%sETH", depositTxETH.Value().String()), cosmAddr.String())
checkDepositTxResult(t, env.txStore, depositTxs, fmt.Sprintf("%sETH", depositTxETH.Mint().String()), cosmAddr.String())

withdrawalTxResult, err := env.txStore.Get(bfttypes.Tx(withdrawalTx).Hash())
require.NoError(t, err)
Expand Down
3 changes: 1 addition & 2 deletions e2e/stack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,12 +258,11 @@ func rollupFlow(t *testing.T, stack *e2e.StackConfig) {
require.NoError(t, err)

// send user Deposit Tx
// TODO: the only reason the L1 balance assertions are passing is because depositTx.Value == depositTx.Mint. Once we pivot to using Mint instead of Value in x/rollup we should add separate deposit tx cases with and without a Value field set
depositAmount := big.NewInt(oneEth)
depositTx, err := stack.L1Portal.DepositTransaction(
createL1TransactOpts(t, stack, userPrivKey, l1signer, l1GasLimit, depositAmount),
userAddress,
depositAmount,
big.NewInt(0),
l2GasLimit,
false, // _isCreation
[]byte{}, // no data
Expand Down
3 changes: 1 addition & 2 deletions eth/api_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/polymerdao/monomer"
"github.com/polymerdao/monomer/eth/internal/ethapi"
)

type ethAPIBackend struct {
Expand All @@ -27,7 +26,7 @@ func newEthAPIBackend(db state.Database, blockStore DB) *ethAPIBackend {
}

func (*ethAPIBackend) ChainConfig() *params.ChainConfig {
return ethapi.NewChainConfig(nil)
return monomer.NewChainConfig(nil)
}

func (*ethAPIBackend) GetReceipts(_ context.Context, _ common.Hash) (types.Receipts, error) {
Expand Down
25 changes: 2 additions & 23 deletions eth/internal/ethapi/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/polymerdao/monomer/utils"
"github.com/polymerdao/monomer"
)

type noopBackend struct{}
Expand All @@ -34,27 +34,6 @@ func (noopBackend) StateAndHeaderByNumberOrHash(_ context.Context, _ rpc.BlockNu
return nil, nil, nil
}

func NewChainConfig(chainID *big.Int) *params.ChainConfig {
return &params.ChainConfig{
ChainID: chainID,

ByzantiumBlock: new(big.Int),
ConstantinopleBlock: new(big.Int),
PetersburgBlock: new(big.Int),
IstanbulBlock: new(big.Int),
MuirGlacierBlock: new(big.Int),
BerlinBlock: new(big.Int),
LondonBlock: new(big.Int),
ArrowGlacierBlock: new(big.Int),
GrayGlacierBlock: new(big.Int),
MergeNetsplitBlock: new(big.Int),

BedrockBlock: new(big.Int),
RegolithTime: utils.Ptr(uint64(0)),
CanyonTime: utils.Ptr(uint64(0)),
}
}

func SimpleRPCMarshalBlock(block *types.Block, fullTx bool, chainID *big.Int) (map[string]interface{}, error) {
return RPCMarshalBlock(context.Background(), block, true, fullTx, NewChainConfig(chainID), noopBackend{})
return RPCMarshalBlock(context.Background(), block, true, fullTx, monomer.NewChainConfig(chainID), noopBackend{})
}
23 changes: 23 additions & 0 deletions monomer.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
"github.com/polymerdao/monomer/utils"
)

type Application interface {
Expand Down Expand Up @@ -214,3 +216,24 @@ func ValidForkchoiceUpdateResult(headBlockHash *common.Hash, id *engine.PayloadI
PayloadID: id,
}
}

func NewChainConfig(chainID *big.Int) *params.ChainConfig {
return &params.ChainConfig{
ChainID: chainID,

ByzantiumBlock: new(big.Int),
ConstantinopleBlock: new(big.Int),
PetersburgBlock: new(big.Int),
IstanbulBlock: new(big.Int),
MuirGlacierBlock: new(big.Int),
BerlinBlock: new(big.Int),
LondonBlock: new(big.Int),
ArrowGlacierBlock: new(big.Int),
GrayGlacierBlock: new(big.Int),
MergeNetsplitBlock: new(big.Int),

BedrockBlock: new(big.Int),
RegolithTime: utils.Ptr(uint64(0)),
CanyonTime: utils.Ptr(uint64(0)),
}
}
4 changes: 3 additions & 1 deletion testutils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ func GenerateEthTxs(t *testing.T) (*gethtypes.Transaction, *gethtypes.Transactio
l1InfoTx := gethtypes.NewTx(l1InfoRawTx)

rng := rand.New(rand.NewSource(1234))
depositTx := gethtypes.NewTx(testutils.GenerateDeposit(testutils.RandomHash(rng), rng))
depositRawTx := testutils.GenerateDeposit(testutils.RandomHash(rng), rng)
depositRawTx.Mint = big.NewInt(100)
depositTx := gethtypes.NewTx(depositRawTx)

cosmosEthTx := monomer.AdaptNonDepositCosmosTxToEthTx([]byte{1})
return l1InfoTx, depositTx, cosmosEthTx
Expand Down
29 changes: 23 additions & 6 deletions x/rollup/keeper/deposits.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ package keeper
import (
"encoding/json"
"fmt"
"math/big"

sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum/go-ethereum/common/hexutil"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/polymerdao/monomer"
"github.com/polymerdao/monomer/utils"
"github.com/polymerdao/monomer/x/rollup/types"
"github.com/samber/lo"
Expand Down Expand Up @@ -50,7 +52,11 @@ func (k *Keeper) processL1AttributesTx(ctx sdk.Context, txBytes []byte) (*derive

// processL1UserDepositTxs processes the L1 user deposit txs, mints ETH to the user's cosmos address,
// and returns associated events.
func (k *Keeper) processL1UserDepositTxs(ctx sdk.Context, txs [][]byte) (sdk.Events, error) { //nolint:gocritic // hugeParam
func (k *Keeper) processL1UserDepositTxs(
ctx sdk.Context, //nolint:gocritic // hugeParam
txs [][]byte,
l1blockInfo *derive.L1BlockInfo,
) (sdk.Events, error) {
mintEvents := sdk.Events{}

// skip the first tx - it is the L1 attributes tx
Expand All @@ -70,18 +76,29 @@ func (k *Keeper) processL1UserDepositTxs(ctx sdk.Context, txs [][]byte) (sdk.Eve
return nil, types.WrapError(types.ErrInvalidL1Txs, "L1 tx must be a user deposit tx, type %d", tx.Type())
}
ctx.Logger().Debug("User deposit tx", "index", i, "tx", string(lo.Must(tx.MarshalJSON())))
to := tx.To()
// if the receipient is nil, it means the tx is creating a contract which we don't support, so return an error.
// see https://github.com/ethereum-optimism/op-geth/blob/v1.101301.0-rc.2/core/state_processor.go#L154
if to == nil {
if tx.To() == nil {
ctx.Logger().Error("Contract creation txs are not supported", "index", i)
return nil, types.WrapError(types.ErrInvalidL1Txs, "Contract creation txs are not supported, index:%d", i)
}
cosmAddr := utils.EvmToCosmosAddress(*to)
mintAmount := sdkmath.NewIntFromBigInt(tx.Value())

// Get the sender's address from the transaction
from, err := ethtypes.MakeSigner(
monomer.NewChainConfig(tx.ChainId()),
new(big.Int).SetUint64(l1blockInfo.Number),
l1blockInfo.Time,
).Sender(&tx)
if err != nil {
ctx.Logger().Error("Failed to get sender address", "evmAddress", from, "err", err)
return nil, types.WrapError(types.ErrInvalidL1Txs, "failed to get sender address: %v", err)
}
cosmAddr := utils.EvmToCosmosAddress(from)
mintAmount := sdkmath.NewIntFromBigInt(tx.Mint())

mintEvent, err := k.mintETH(ctx, cosmAddr, mintAmount)
if err != nil {
ctx.Logger().Error("Failed to mint ETH", "evmAddress", to, "cosmosAddress", cosmAddr, "err", err)
ctx.Logger().Error("Failed to mint ETH", "evmAddress", from, "cosmosAddress", cosmAddr, "err", err)
return nil, types.WrapError(types.ErrMintETH, "failed to mint ETH for cosmosAddress: %v; err: %v", cosmAddr, err)
}
mintEvents = append(mintEvents, *mintEvent)
Expand Down
2 changes: 1 addition & 1 deletion x/rollup/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func (k *Keeper) ApplyL1Txs(goCtx context.Context, msg *types.MsgApplyL1Txs) (*t
ctx.Logger().Info("Save L1 block info", "l1blockInfo", string(lo.Must(json.Marshal(l1blockInfo))))

// process L1 user deposit txs
mintEvents, err := k.processL1UserDepositTxs(ctx, msg.TxBytes)
mintEvents, err := k.processL1UserDepositTxs(ctx, msg.TxBytes, l1blockInfo)
if err != nil {
ctx.Logger().Error("Failed to process L1 user deposit txs", "err", err)
return nil, types.WrapError(types.ErrProcessL1UserDepositTxs, "err: %v", err)
Expand Down
10 changes: 7 additions & 3 deletions x/rollup/tests/integration/rollup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ import (
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/ethereum/go-ethereum/common"
gethtypes "github.com/ethereum/go-ethereum/core/types"
monomertestutils "github.com/polymerdao/monomer/testutils"
"github.com/polymerdao/monomer/utils"
"github.com/polymerdao/monomer/x/rollup"
rollupkeeper "github.com/polymerdao/monomer/x/rollup/keeper"
rolluptypes "github.com/polymerdao/monomer/x/rollup/types"
Expand All @@ -40,14 +42,16 @@ func TestRollup(t *testing.T) {
l1AttributesTxBz := monomertestutils.TxToBytes(t, l1AttributesTx)
depositTxBz := monomertestutils.TxToBytes(t, depositTx)

depositAmount := depositTx.Value()
var userAddr sdk.AccAddress = depositTx.To().Bytes()
depositAmount := depositTx.Mint()
from, err := gethtypes.NewCancunSigner(depositTx.ChainId()).Sender(depositTx)
require.NoError(t, err)
userAddr := utils.EvmToCosmosAddress(from)

// query the user's ETH balance and assert it's zero
require.Equal(t, math.ZeroInt(), queryUserETHBalance(t, queryClient, userAddr, integrationApp))

// send an invalid MsgApplyL1Txs and assert error
_, err := integrationApp.RunMsg(&rolluptypes.MsgApplyL1Txs{
_, err = integrationApp.RunMsg(&rolluptypes.MsgApplyL1Txs{
TxBytes: [][]byte{l1AttributesTxBz, l1AttributesTxBz},
FromAddress: monomerSigner,
})
Expand Down
Loading