Skip to content

Commit

Permalink
Refactor L1 user deposit processing in x/rollup module (#208)
Browse files Browse the repository at this point in the history
  • Loading branch information
AnkushinDaniil authored Sep 18, 2024
1 parent c998a26 commit a0e529b
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 42 deletions.
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

0 comments on commit a0e529b

Please sign in to comment.