Skip to content
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
1 change: 1 addition & 0 deletions arbos/arbosState/arbosstate.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@ func (state *ArbosState) UpgradeArbosVersion(
} else {
ensure(state.l1PricingState.SetCalldataPrice(big.NewInt(int64(params.TxDataNonZeroGasEIP2028))))
}
ensure(state.l2PricingState.SetMaxPerTxGasLimit(l2pricing.InitialPerTxGasLimitV50))
default:
return fmt.Errorf(
"the chain is upgrading to unsupported ArbOS version %v, %w",
Expand Down
6 changes: 6 additions & 0 deletions arbos/block_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ func ProduceBlockAdvanced(
// Note: blockGasLeft will diverge from the actual gas left during execution in the event of invalid txs,
// but it's only used as block-local representation limiting the amount of work done in a block.
blockGasLeft, _ := arbState.L2PricingState().PerBlockGasLimit()
maxPerTxGasLimit, _ := arbState.L2PricingState().PerTxGasLimit()
l1BlockNum := l1Info.l1BlockNumber

// Prepend a tx before all others to touch up the state (update the L1 block num, pricing pools, etc)
Expand Down Expand Up @@ -346,6 +347,11 @@ func ProduceBlockAdvanced(
}

computeGas := tx.Gas() - dataGas
// Implements EIP-7825. Check activated after arbos_50
if arbState.ArbOSVersion() >= params.ArbosVersion_50 &&
computeGas > maxPerTxGasLimit && isUserTx {
return nil, nil, fmt.Errorf("%w (cap: %d, tx l2Gas: %d)", core.ErrGasLimitTooHigh, maxPerTxGasLimit, computeGas)
}
if computeGas < params.TxGas {
if hooks.DiscardInvalidTxsEarly {
return nil, nil, core.ErrIntrinsicGas
Expand Down
11 changes: 11 additions & 0 deletions arbos/l2pricing/l2pricing.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type L2PricingState struct {
gasBacklog storage.StorageBackedUint64
pricingInertia storage.StorageBackedUint64
backlogTolerance storage.StorageBackedUint64
perTxGasLimit storage.StorageBackedUint64
}

const (
Expand All @@ -28,6 +29,7 @@ const (
gasBacklogOffset
pricingInertiaOffset
backlogToleranceOffset
perTxGasLimitOffset
)

const GethBlockGasLimit = 1 << 50
Expand All @@ -52,6 +54,7 @@ func OpenL2PricingState(sto *storage.Storage) *L2PricingState {
sto.OpenStorageBackedUint64(gasBacklogOffset),
sto.OpenStorageBackedUint64(pricingInertiaOffset),
sto.OpenStorageBackedUint64(backlogToleranceOffset),
sto.OpenStorageBackedUint64(perTxGasLimitOffset),
}
}

Expand Down Expand Up @@ -90,6 +93,14 @@ func (ps *L2PricingState) SetMaxPerBlockGasLimit(limit uint64) error {
return ps.perBlockGasLimit.Set(limit)
}

func (ps *L2PricingState) PerTxGasLimit() (uint64, error) {
return ps.perTxGasLimit.Get()
}

func (ps *L2PricingState) SetMaxPerTxGasLimit(limit uint64) error {
return ps.perTxGasLimit.Set(limit)
}

func (ps *L2PricingState) GasBacklog() (uint64, error) {
return ps.gasBacklog.Get()
}
Expand Down
1 change: 1 addition & 0 deletions arbos/l2pricing/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const InitialMinimumBaseFeeWei = params.GWei / 10
const InitialBaseFeeWei = InitialMinimumBaseFeeWei
const InitialPricingInertia = 102
const InitialBacklogTolerance = 10
const InitialPerTxGasLimitV50 uint64 = 32 * 1000000

func (ps *L2PricingState) AddToGasPool(gas int64) error {
backlog, err := ps.GasBacklog()
Expand Down
2 changes: 1 addition & 1 deletion contracts-local/src/precompiles
3 changes: 3 additions & 0 deletions execution/gethexec/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ type PricingModelHistory struct {
MinBaseFee *big.Int `json:"minBaseFee"`
SpeedLimit uint64 `json:"speedLimit"`
PerBlockGasLimit uint64 `json:"perBlockGasLimit"`
PerTxGasLimit uint64 `json:"perTxGasLimit"`
PricingInertia uint64 `json:"pricingInertia"`
BacklogTolerance uint64 `json:"backlogTolerance"`

Expand Down Expand Up @@ -208,6 +209,7 @@ func (api *ArbDebugAPI) PricingModel(ctx context.Context, start, end rpc.BlockNu
if i == uint64(blocks)-1 {
speedLimit, _ := l2Pricing.SpeedLimitPerSecond()
perBlockGasLimit, _ := l2Pricing.PerBlockGasLimit()
perTxGasLimit, _ := l2Pricing.PerTxGasLimit()
minBaseFee, _ := l2Pricing.MinBaseFeeWei()
pricingInertia, _ := l2Pricing.PricingInertia()
backlogTolerance, _ := l2Pricing.BacklogTolerance()
Expand All @@ -225,6 +227,7 @@ func (api *ArbDebugAPI) PricingModel(ctx context.Context, start, end rpc.BlockNu
history.MinBaseFee = minBaseFee
history.SpeedLimit = speedLimit
history.PerBlockGasLimit = perBlockGasLimit
history.PerTxGasLimit = perTxGasLimit
history.PricingInertia = pricingInertia
history.BacklogTolerance = backlogTolerance
history.L1PricingInertia = l1PricingInertia
Expand Down
13 changes: 10 additions & 3 deletions precompiles/ArbGasInfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,12 +176,19 @@ func (con ArbGasInfo) GetPricesInArbGas(c ctx, evm mech) (huge, huge, huge, erro
return con.GetPricesInArbGasWithAggregator(c, evm, addr{})
}

// GetGasAccountingParams gets the rollup's speed limit, pool size, and tx gas limit
// GetGasAccountingParams gets the rollup's speed limit, pool size, and block gas limit
func (con ArbGasInfo) GetGasAccountingParams(c ctx, evm mech) (huge, huge, huge, error) {
l2pricing := c.State.L2PricingState()
speedLimit, _ := l2pricing.SpeedLimitPerSecond()
maxTxGasLimit, err := l2pricing.PerBlockGasLimit()
return arbmath.UintToBig(speedLimit), arbmath.UintToBig(maxTxGasLimit), arbmath.UintToBig(maxTxGasLimit), err
maxBlockGasLimit, err := l2pricing.PerBlockGasLimit()
return arbmath.UintToBig(speedLimit), arbmath.UintToBig(maxBlockGasLimit), arbmath.UintToBig(maxBlockGasLimit), err
Comment thread
eljobe marked this conversation as resolved.
}

// GetMaxTxGasLimit gets the max tx gas limit
func (con ArbGasInfo) GetMaxTxGasLimit(c ctx, evm mech) (huge, error) {
l2pricing := c.State.L2PricingState()
maxTxGasLimit, err := l2pricing.PerTxGasLimit()
return arbmath.UintToBig(maxTxGasLimit), err
}

// GetMinimumGasPrice gets the minimum gas price needed for a transaction to succeed
Expand Down
10 changes: 9 additions & 1 deletion precompiles/ArbOwner.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,16 @@ func (con ArbOwner) SetSpeedLimit(c ctx, evm mech, limit uint64) error {
return c.State.L2PricingState().SetSpeedLimitPerSecond(limit)
}

// SetMaxTxGasLimit sets the maximum size a tx (and block) can be
// SetMaxTxGasLimit sets the maximum size a tx can be
func (con ArbOwner) SetMaxTxGasLimit(c ctx, evm mech, limit uint64) error {
if c.State.ArbOSVersion() < params.ArbosVersion_50 {
return c.State.L2PricingState().SetMaxPerBlockGasLimit(limit)
}
return c.State.L2PricingState().SetMaxPerTxGasLimit(limit)
}

// SetMaxBlockGasLimit sets the maximum size a block can be
func (con ArbOwner) SetMaxBlockGasLimit(c ctx, evm mech, limit uint64) error {
return c.State.L2PricingState().SetMaxPerBlockGasLimit(limit)
}

Expand Down
2 changes: 2 additions & 0 deletions precompiles/precompile.go
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,7 @@ func Precompiles() map[addr]ArbosPrecompile {
ArbGasInfo.methodsByName["GetL1PricingFundsDueForRewards"].arbosVersion = params.ArbosVersion_20
ArbGasInfo.methodsByName["GetL1PricingUnitsSinceUpdate"].arbosVersion = params.ArbosVersion_20
ArbGasInfo.methodsByName["GetLastL1PricingSurplus"].arbosVersion = params.ArbosVersion_20
ArbGasInfo.methodsByName["GetMaxTxGasLimit"].arbosVersion = params.ArbosVersion_50
insert(MakePrecompile(pgen.ArbAggregatorMetaData, &ArbAggregator{Address: types.ArbAggregatorAddress}))
insert(MakePrecompile(pgen.ArbStatisticsMetaData, &ArbStatistics{Address: types.ArbStatisticsAddress}))

Expand Down Expand Up @@ -643,6 +644,7 @@ func Precompiles() map[addr]ArbosPrecompile {
ArbOwner.methodsByName["IsNativeTokenOwner"].arbosVersion = params.ArbosVersion_41
ArbOwner.methodsByName["GetAllNativeTokenOwners"].arbosVersion = params.ArbosVersion_41
ArbOwner.methodsByName["SetL1CalldataPrice"].arbosVersion = params.ArbosVersion_50
ArbOwner.methodsByName["SetMaxBlockGasLimit"].arbosVersion = params.ArbosVersion_50

ArbOwnerPublic.methodsByName["GetNativeTokenManagementFrom"].arbosVersion = params.ArbosVersion_50

Expand Down
2 changes: 1 addition & 1 deletion precompiles/precompile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ func TestPrecompilesPerArbosVersion(t *testing.T) {
params.ArbosVersion_31: 1,
params.ArbosVersion_40: 3,
params.ArbosVersion_41: 10,
params.ArbosVersion_50: 3,
params.ArbosVersion_50: 5,
}

precompiles := Precompiles()
Expand Down
68 changes: 67 additions & 1 deletion system_tests/precompile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,22 @@ import (
"math/big"
"slices"
"sort"
"strings"
"testing"
"time"

"github.com/google/go-cmp/cmp"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"

"github.com/offchainlabs/nitro/arbos"
"github.com/offchainlabs/nitro/arbos/arbosState"
"github.com/offchainlabs/nitro/arbos/burn"
"github.com/offchainlabs/nitro/arbos/l1pricing"
"github.com/offchainlabs/nitro/cmd/chaininfo"
"github.com/offchainlabs/nitro/solgen/go/localgen"
Expand Down Expand Up @@ -456,8 +460,70 @@ func TestCurrentTxL1GasFees(t *testing.T) {
}
}

func TestArbOwnerMaxTxAndBlockGasLimit(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

builder := NewNodeBuilder(ctx).DefaultConfig(t, false).WithArbOSVersion(params.ArbosVersion_50)
cleanup := builder.Build(t)
defer cleanup()

auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx)

arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), builder.L2.Client)
Require(t, err)
arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), builder.L2.Client)
Require(t, err)

wantTxGasLimit := uint64(3000000)
wantBlockGasLimit := uint64(4000000)
txGasLimitTx, err := arbOwner.SetMaxTxGasLimit(&auth, wantTxGasLimit)
Require(t, err)
_, err = EnsureTxSucceeded(ctx, builder.L2.Client, txGasLimitTx)
Require(t, err)
blockGasLimitTx, err := arbOwner.SetMaxBlockGasLimit(&auth, wantBlockGasLimit)
Require(t, err)
_, err = EnsureTxSucceeded(ctx, builder.L2.Client, blockGasLimitTx)
Require(t, err)

statedb, err := builder.L2.ExecNode.Backend.ArbInterface().BlockChain().State()
Require(t, err)
burner := burn.NewSystemBurner(nil, false)
arbosSt, err := arbosState.OpenArbosState(statedb, burner)
Require(t, err)

haveTxGasLimit, err := arbosSt.L2PricingState().PerTxGasLimit()
Require(t, err)
if haveTxGasLimit != wantTxGasLimit {
t.Fatalf("txGasLimit mismatch. have: %d want: %d", haveTxGasLimit, wantTxGasLimit)
}
haveBlockGasLimit, err := arbosSt.L2PricingState().PerBlockGasLimit()
Require(t, err)
if haveBlockGasLimit != wantBlockGasLimit {
t.Fatalf("blockGasLimit mismatch. have: %d want: %d", haveBlockGasLimit, wantBlockGasLimit)
}

haveTxGasLimitArbGasInfo, err := arbGasInfo.GetMaxTxGasLimit(&bind.CallOpts{Context: ctx})
Require(t, err)
if haveTxGasLimitArbGasInfo.Uint64() != wantTxGasLimit {
t.Fatalf("arbGasInfo txGasLimit mismatch. have: %d want: %d", haveTxGasLimitArbGasInfo.Uint64(), wantTxGasLimit)
}
_, _, haveBlockGasLimitArbGasInfo, err := arbGasInfo.GetGasAccountingParams(&bind.CallOpts{Context: ctx})
Require(t, err)
if haveBlockGasLimitArbGasInfo.Uint64() != wantBlockGasLimit {
t.Fatalf("arbGasInfo blockGasLimit mismatch. have: %d want: %d", haveBlockGasLimitArbGasInfo.Uint64(), wantBlockGasLimit)
}

gas := wantTxGasLimit + 1500000 // as txGasLimit is only on computeGas we need to add more for datagas
tx := builder.L2Info.PrepareTx("Owner", "Faucet", gas, big.NewInt(1e10), nil)
err = builder.L2.Client.SendTransaction(ctx, tx)
if err == nil || !strings.Contains(err.Error(), core.ErrGasLimitTooHigh.Error()) {
t.Fatalf("expected ErrGasLimitTooHigh error but got: %v", err)
}
}

func TestArbNativeTokenManagerThroughSolidityContract(t *testing.T) {
ctx, cancel := context.WithCancel(t.Context())
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

arbOSInit := &params.ArbOSInit{
Expand Down
Loading