diff --git a/arbnode/inbox_test.go b/arbnode/inbox_test.go index e979979dea..5c879743a4 100644 --- a/arbnode/inbox_test.go +++ b/arbnode/inbox_test.go @@ -233,7 +233,7 @@ func TestTransactionStreamer(t *testing.T) { Fail(t, "error getting block state", err) } haveBalance := state.GetBalance(acct) - if balance.Cmp(haveBalance) != 0 { + if balance.Cmp(haveBalance.ToBig()) != 0 { t.Error("unexpected balance for account", acct, "; expected", balance, "got", haveBalance) } } diff --git a/arbos/arbosState/arbosstate.go b/arbos/arbosState/arbosstate.go index f7b7f0e7f6..e84c350538 100644 --- a/arbos/arbosState/arbosstate.go +++ b/arbos/arbosState/arbosstate.go @@ -303,7 +303,7 @@ func (state *ArbosState) UpgradeArbosVersion( case 10: ensure(state.l1PricingState.SetL1FeesAvailable(stateDB.GetBalance( l1pricing.L1PricerFundsPoolAddress, - ))) + ).ToBig())) case 11: // Update the PerBatchGasCost to a more accurate value compared to the old v6 default. ensure(state.l1PricingState.SetPerBatchGasCost(l1pricing.InitialPerBatchGasCostV12)) @@ -324,9 +324,22 @@ func (state *ArbosState) UpgradeArbosVersion( case 20: // Update Brotli compression level for fast compression from 0 to 1 ensure(state.SetBrotliCompressionLevel(1)) + // ArbOS versions 21 through 29 are left to Orbit chains for custom upgrades. + case 30: + if !chainConfig.DebugMode() { + // This upgrade isn't finalized so we only want to support it for testing + return fmt.Errorf( + "the chain is upgrading to unsupported ArbOS version %v, %w", + nextArbosVersion, + ErrFatalNodeOutOfDate, + ) + } + // no state changes needed default: if nextArbosVersion >= 12 && nextArbosVersion <= 19 { // ArbOS versions 12 through 19 are left to Orbit chains for custom upgrades. + } else if nextArbosVersion >= 21 && nextArbosVersion <= 29 { + // ArbOS versions 21 through 29 are left to Orbit chains for custom upgrades. } else { return fmt.Errorf( "the chain is upgrading to unsupported ArbOS version %v, %w", diff --git a/arbos/arbosState/initialization_test.go b/arbos/arbosState/initialization_test.go index 3de1fc5d38..0ef9cea4c5 100644 --- a/arbos/arbosState/initialization_test.go +++ b/arbos/arbosState/initialization_test.go @@ -151,7 +151,7 @@ func checkAccounts(db *state.StateDB, arbState *ArbosState, accts []statetransfe if db.GetNonce(addr) != acct.Nonce { t.Fatal() } - if db.GetBalance(addr).Cmp(acct.EthBalance) != 0 { + if db.GetBalance(addr).ToBig().Cmp(acct.EthBalance) != 0 { t.Fatal() } if acct.ContractInfo != nil { diff --git a/arbos/arbosState/initialize.go b/arbos/arbosState/initialize.go index 56d8172ee8..486c6ae33a 100644 --- a/arbos/arbosState/initialize.go +++ b/arbos/arbosState/initialize.go @@ -15,6 +15,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" + "github.com/holiman/uint256" "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbos/burn" "github.com/offchainlabs/nitro/arbos/l2pricing" @@ -142,7 +143,7 @@ func InitializeArbosInDatabase(db ethdb.Database, initData statetransfer.InitDat if err != nil { return common.Hash{}, err } - statedb.SetBalance(account.Addr, account.EthBalance) + statedb.SetBalance(account.Addr, uint256.MustFromBig(account.EthBalance)) statedb.SetNonce(account.Addr, account.Nonce) if account.ContractInfo != nil { statedb.SetCode(account.Addr, account.ContractInfo.Code) @@ -173,7 +174,7 @@ func initializeRetryables(statedb *state.StateDB, rs *retryables.RetryableState, return err } if r.Timeout <= currentTimestamp { - statedb.AddBalance(r.Beneficiary, r.Callvalue) + statedb.AddBalance(r.Beneficiary, uint256.MustFromBig(r.Callvalue)) continue } retryablesList = append(retryablesList, r) @@ -192,7 +193,7 @@ func initializeRetryables(statedb *state.StateDB, rs *retryables.RetryableState, addr := r.To to = &addr } - statedb.AddBalance(retryables.RetryableEscrowAddress(r.Id), r.Callvalue) + statedb.AddBalance(retryables.RetryableEscrowAddress(r.Id), uint256.MustFromBig(r.Callvalue)) _, err := rs.CreateRetryable(r.Id, r.Timeout, r.From, to, r.Callvalue, r.Beneficiary, r.Calldata) if err != nil { return err diff --git a/arbos/l1pricing/l1PricingOldVersions.go b/arbos/l1pricing/l1PricingOldVersions.go index 5c6b6ab7d6..821d743e7d 100644 --- a/arbos/l1pricing/l1PricingOldVersions.go +++ b/arbos/l1pricing/l1PricingOldVersions.go @@ -4,12 +4,13 @@ package l1pricing import ( + "math" + "math/big" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" "github.com/offchainlabs/nitro/arbos/util" am "github.com/offchainlabs/nitro/util/arbmath" - "math" - "math/big" ) func (ps *L1PricingState) _preversion10_UpdateForBatchPosterSpending( @@ -105,8 +106,8 @@ func (ps *L1PricingState) _preversion10_UpdateForBatchPosterSpending( // pay rewards, as much as possible paymentForRewards := am.BigMulByUint(am.UintToBig(perUnitReward), unitsAllocated) availableFunds := statedb.GetBalance(L1PricerFundsPoolAddress) - if am.BigLessThan(availableFunds, paymentForRewards) { - paymentForRewards = availableFunds + if am.BigLessThan(availableFunds.ToBig(), paymentForRewards) { + paymentForRewards = availableFunds.ToBig() } fundsDueForRewards = am.BigSub(fundsDueForRewards, paymentForRewards) if err := ps.SetFundsDueForRewards(fundsDueForRewards); err != nil { @@ -130,8 +131,8 @@ func (ps *L1PricingState) _preversion10_UpdateForBatchPosterSpending( return err } balanceToTransfer := balanceDueToPoster - if am.BigLessThan(availableFunds, balanceToTransfer) { - balanceToTransfer = availableFunds + if am.BigLessThan(availableFunds.ToBig(), balanceToTransfer) { + balanceToTransfer = availableFunds.ToBig() } if balanceToTransfer.Sign() > 0 { addrToPay, err := posterState.PayTo() @@ -166,7 +167,7 @@ func (ps *L1PricingState) _preversion10_UpdateForBatchPosterSpending( if err != nil { return err } - surplus := am.BigSub(statedb.GetBalance(L1PricerFundsPoolAddress), am.BigAdd(totalFundsDue, fundsDueForRewards)) + surplus := am.BigSub(statedb.GetBalance(L1PricerFundsPoolAddress).ToBig(), am.BigAdd(totalFundsDue, fundsDueForRewards)) inertia, err := ps.Inertia() if err != nil { @@ -230,7 +231,7 @@ func (ps *L1PricingState) _preVersion2_UpdateForBatchPosterSpending( if err != nil { return err } - oldSurplus := am.BigSub(statedb.GetBalance(L1PricerFundsPoolAddress), am.BigAdd(totalFundsDue, fundsDueForRewards)) + oldSurplus := am.BigSub(statedb.GetBalance(L1PricerFundsPoolAddress).ToBig(), am.BigAdd(totalFundsDue, fundsDueForRewards)) // compute allocation fraction -- will allocate updateTimeDelta/timeDelta fraction of units and funds to this update lastUpdateTime, err := ps.LastUpdateTime() @@ -280,7 +281,7 @@ func (ps *L1PricingState) _preVersion2_UpdateForBatchPosterSpending( // allocate funds to this update collectedSinceUpdate := statedb.GetBalance(L1PricerFundsPoolAddress) - availableFunds := am.BigDivByUint(am.BigMulByUint(collectedSinceUpdate, allocationNumerator), allocationDenominator) + availableFunds := am.BigDivByUint(am.BigMulByUint(collectedSinceUpdate.ToBig(), allocationNumerator), allocationDenominator) // pay rewards, as much as possible paymentForRewards := am.BigMulByUint(am.UintToBig(perUnitReward), unitsAllocated) @@ -356,7 +357,7 @@ func (ps *L1PricingState) _preVersion2_UpdateForBatchPosterSpending( if err != nil { return err } - surplus := am.BigSub(statedb.GetBalance(L1PricerFundsPoolAddress), am.BigAdd(totalFundsDue, fundsDueForRewards)) + surplus := am.BigSub(statedb.GetBalance(L1PricerFundsPoolAddress).ToBig(), am.BigAdd(totalFundsDue, fundsDueForRewards)) inertia, err := ps.Inertia() if err != nil { diff --git a/arbos/l1pricing_test.go b/arbos/l1pricing_test.go index b23c1747ab..6e2b1b7eec 100644 --- a/arbos/l1pricing_test.go +++ b/arbos/l1pricing_test.go @@ -11,6 +11,7 @@ import ( "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/vm" + "github.com/holiman/uint256" "github.com/offchainlabs/nitro/arbos/arbosState" "github.com/offchainlabs/nitro/arbos/l1pricing" "github.com/offchainlabs/nitro/arbos/util" @@ -171,7 +172,7 @@ func _testL1PricingFundsDue(t *testing.T, testParams *l1PricingTest, expectedRes // create some fake collection balanceAdded := big.NewInt(int64(testParams.fundsCollectedPerSecond * 3)) unitsAdded := testParams.unitsPerSecond * 3 - evm.StateDB.AddBalance(l1pricing.L1PricerFundsPoolAddress, balanceAdded) + evm.StateDB.AddBalance(l1pricing.L1PricerFundsPoolAddress, uint256.MustFromBig(balanceAdded)) err = l1p.SetL1FeesAvailable(balanceAdded) Require(t, err) err = l1p.SetUnitsSinceUpdate(unitsAdded) @@ -187,7 +188,7 @@ func _testL1PricingFundsDue(t *testing.T, testParams *l1PricingTest, expectedRes ) Require(t, err) rewardRecipientBalance := evm.StateDB.GetBalance(rewardAddress) - if !arbmath.BigEquals(rewardRecipientBalance, expectedResults.rewardRecipientBalance) { + if !arbmath.BigEquals(rewardRecipientBalance.ToBig(), expectedResults.rewardRecipientBalance) { Fail(t, rewardRecipientBalance, expectedResults.rewardRecipientBalance) } unitsRemaining, err := l1p.UnitsSinceUpdate() @@ -196,16 +197,16 @@ func _testL1PricingFundsDue(t *testing.T, testParams *l1PricingTest, expectedRes Fail(t, unitsRemaining, expectedResults.unitsRemaining) } fundsReceived := evm.StateDB.GetBalance(firstPayTo) - if !arbmath.BigEquals(fundsReceived, expectedResults.fundsReceived) { + if !arbmath.BigEquals(fundsReceived.ToBig(), expectedResults.fundsReceived) { Fail(t, fundsReceived, expectedResults.fundsReceived) } fundsStillHeld := evm.StateDB.GetBalance(l1pricing.L1PricerFundsPoolAddress) - if !arbmath.BigEquals(fundsStillHeld, expectedResults.fundsStillHeld) { + if !arbmath.BigEquals(fundsStillHeld.ToBig(), expectedResults.fundsStillHeld) { Fail(t, fundsStillHeld, expectedResults.fundsStillHeld) } fundsAvail, err := l1p.L1FeesAvailable() Require(t, err) - if fundsStillHeld.Cmp(fundsAvail) != 0 { + if fundsStillHeld.ToBig().Cmp(fundsAvail) != 0 { Fail(t, fundsStillHeld, fundsAvail) } } diff --git a/arbos/retryables/retryable.go b/arbos/retryables/retryable.go index 6984e41904..e1cfe48bcf 100644 --- a/arbos/retryables/retryable.go +++ b/arbos/retryables/retryable.go @@ -145,7 +145,7 @@ func (rs *RetryableState) DeleteRetryable(id common.Hash, evm *vm.EVM, scenario escrowAddress := RetryableEscrowAddress(id) beneficiaryAddress := common.BytesToAddress(beneficiary[:]) amount := evm.StateDB.GetBalance(escrowAddress) - err = util.TransferBalance(&escrowAddress, &beneficiaryAddress, amount, evm, scenario, "escrow") + err = util.TransferBalance(&escrowAddress, &beneficiaryAddress, amount.ToBig(), evm, scenario, "escrow") if err != nil { return false, err } diff --git a/arbos/tx_processor.go b/arbos/tx_processor.go index 569edb7c63..2eab598b09 100644 --- a/arbos/tx_processor.go +++ b/arbos/tx_processor.go @@ -8,6 +8,7 @@ import ( "fmt" "math/big" + "github.com/holiman/uint256" "github.com/offchainlabs/nitro/arbos/l1pricing" "github.com/offchainlabs/nitro/arbos/util" @@ -143,7 +144,9 @@ func (p *TxProcessor) StartTxHook() (endTxNow bool, gasUsed uint64, err error, r // We intentionally use the variant here that doesn't do tracing, // because this transfer is represented as the outer eth transaction. // This transfer is necessary because we don't actually invoke the EVM. - core.Transfer(evm.StateDB, from, *to, value) + // Since MintBalance already called AddBalance on `from`, + // we don't have EIP-161 concerns around not touching `from`. + core.Transfer(evm.StateDB, from, *to, uint256.MustFromBig(value)) return true, 0, nil, nil case *types.ArbitrumInternalTx: defer (startTracer())() @@ -172,7 +175,7 @@ func (p *TxProcessor) StartTxHook() (endTxNow bool, gasUsed uint64, err error, r // check that the user has enough balance to pay for the max submission fee balanceAfterMint := evm.StateDB.GetBalance(tx.From) - if balanceAfterMint.Cmp(tx.MaxSubmissionFee) < 0 { + if balanceAfterMint.ToBig().Cmp(tx.MaxSubmissionFee) < 0 { err := fmt.Errorf( "insufficient funds for max submission fee: address %v have %v want %v", tx.From, balanceAfterMint, tx.MaxSubmissionFee, @@ -256,7 +259,7 @@ func (p *TxProcessor) StartTxHook() (endTxNow bool, gasUsed uint64, err error, r maxGasCost := arbmath.BigMulByUint(tx.GasFeeCap, usergas) maxFeePerGasTooLow := arbmath.BigLessThan(tx.GasFeeCap, effectiveBaseFee) - if arbmath.BigLessThan(balance, maxGasCost) || usergas < params.TxGas || maxFeePerGasTooLow { + if arbmath.BigLessThan(balance.ToBig(), maxGasCost) || usergas < params.TxGas || maxFeePerGasTooLow { // User either specified too low of a gas fee cap, didn't have enough balance to pay for gas, // or the specified gas limit is below the minimum transaction gas cost. // Either way, attempt to refund the gas costs, since we're not doing the auto-redeem. diff --git a/arbos/util/tracing.go b/arbos/util/tracing.go index e4cde0f42b..49b82d6d64 100644 --- a/arbos/util/tracing.go +++ b/arbos/util/tracing.go @@ -42,7 +42,7 @@ func NewTracingInfo(evm *vm.EVM, from, to common.Address, scenario TracingScenar return &TracingInfo{ Tracer: evm.Config.Tracer, Scenario: scenario, - Contract: vm.NewContract(addressHolder{to}, addressHolder{from}, big.NewInt(0), 0), + Contract: vm.NewContract(addressHolder{to}, addressHolder{from}, uint256.NewInt(0), 0), Depth: evm.Depth(), } } @@ -79,7 +79,7 @@ func (info *TracingInfo) MockCall(input []byte, gas uint64, from, to common.Addr tracer := info.Tracer depth := info.Depth - contract := vm.NewContract(addressHolder{to}, addressHolder{from}, amount, gas) + contract := vm.NewContract(addressHolder{to}, addressHolder{from}, uint256.MustFromBig(amount), gas) scope := &vm.ScopeContext{ Memory: TracingMemoryFromBytes(input), diff --git a/arbos/util/transfer.go b/arbos/util/transfer.go index 3a81181200..e293ef13c3 100644 --- a/arbos/util/transfer.go +++ b/arbos/util/transfer.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/log" + "github.com/holiman/uint256" "github.com/offchainlabs/nitro/util/arbmath" ) @@ -29,13 +30,17 @@ func TransferBalance( } if from != nil { balance := evm.StateDB.GetBalance(*from) - if arbmath.BigLessThan(balance, amount) { + if arbmath.BigLessThan(balance.ToBig(), amount) { return fmt.Errorf("%w: addr %v have %v want %v", vm.ErrInsufficientBalance, *from, balance, amount) } - evm.StateDB.SubBalance(*from, amount) + evm.StateDB.SubBalance(*from, uint256.MustFromBig(amount)) + if evm.Context.ArbOSVersion >= 30 { + // ensure the from account is "touched" for EIP-161 + evm.StateDB.AddBalance(*from, &uint256.Int{}) + } } if to != nil { - evm.StateDB.AddBalance(*to, amount) + evm.StateDB.AddBalance(*to, uint256.MustFromBig(amount)) } if tracer := evm.Config.Tracer; tracer != nil { if evm.Depth() != 0 && scenario != TracingDuringEVM { @@ -59,7 +64,7 @@ func TransferBalance( info := &TracingInfo{ Tracer: evm.Config.Tracer, Scenario: scenario, - Contract: vm.NewContract(addressHolder{*to}, addressHolder{*from}, big.NewInt(0), 0), + Contract: vm.NewContract(addressHolder{*to}, addressHolder{*from}, uint256.NewInt(0), 0), Depth: evm.Depth(), } info.MockCall([]byte{}, 0, *from, *to, amount) diff --git a/execution/gethexec/tx_pre_checker.go b/execution/gethexec/tx_pre_checker.go index cff8b04d32..1a48d75fda 100644 --- a/execution/gethexec/tx_pre_checker.go +++ b/execution/gethexec/tx_pre_checker.go @@ -187,7 +187,7 @@ func PreCheckTx(bc *core.BlockChain, chainConfig *params.ChainConfig, header *ty } balance := statedb.GetBalance(sender) cost := tx.Cost() - if arbmath.BigLessThan(balance, cost) { + if arbmath.BigLessThan(balance.ToBig(), cost) { return fmt.Errorf("%w: address %v have %v want %v", core.ErrInsufficientFunds, sender, balance, cost) } if config.Strictness >= TxPreCheckerStrictnessFullValidation && tx.Nonce() > stateNonce { diff --git a/gethhook/geth_test.go b/gethhook/geth_test.go index 6274a54119..99bfa4ae1c 100644 --- a/gethhook/geth_test.go +++ b/gethhook/geth_test.go @@ -110,7 +110,7 @@ func TestEthDepositMessage(t *testing.T) { RunMessagesThroughAPI(t, [][]byte{serialized, serialized2}, statedb) - balanceAfter := statedb.GetBalance(addr) + balanceAfter := statedb.GetBalance(addr).ToBig() if balanceAfter.Cmp(new(big.Int).Add(balance.Big(), balance2.Big())) != 0 { Fail(t) } diff --git a/go-ethereum b/go-ethereum index f041492a6c..92b91d3fac 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit f041492a6ceaea355b29de36c55b56abb60b2660 +Subproject commit 92b91d3fac58e7aed688f685aa8d27665f4cd47c diff --git a/go.mod b/go.mod index ded1fced70..652c5ed02d 100644 --- a/go.mod +++ b/go.mod @@ -316,7 +316,7 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect - github.com/go-ole/go-ole v1.2.5 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-redis/redis/v8 v8.11.4 github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/uuid v1.3.1 diff --git a/go.sum b/go.sum index 8be44da749..72d78ba497 100644 --- a/go.sum +++ b/go.sum @@ -418,8 +418,9 @@ github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbV github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= -github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= @@ -2023,6 +2024,7 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/precompiles/ArbGasInfo.go b/precompiles/ArbGasInfo.go index cb0045c49f..25801109c7 100644 --- a/precompiles/ArbGasInfo.go +++ b/precompiles/ArbGasInfo.go @@ -187,7 +187,7 @@ func (con ArbGasInfo) GetGasBacklog(c ctx, evm mech) (uint64, error) { return c.State.L2PricingState().GasBacklog() } -// GetPricingInertia gets the L2 basefee in response to backlogged gas +// GetPricingInertia gets how slowly ArbOS updates the L2 basefee in response to backlogged gas func (con ArbGasInfo) GetPricingInertia(c ctx, evm mech) (uint64, error) { return c.State.L2PricingState().PricingInertia() } @@ -197,6 +197,7 @@ func (con ArbGasInfo) GetGasBacklogTolerance(c ctx, evm mech) (uint64, error) { return c.State.L2PricingState().BacklogTolerance() } +// GetL1PricingSurplus gets the surplus of funds for L1 batch posting payments (may be negative) func (con ArbGasInfo) GetL1PricingSurplus(c ctx, evm mech) (*big.Int, error) { if c.State.ArbOSVersion() < 10 { return con._preversion10_GetL1PricingSurplus(c, evm) @@ -217,37 +218,45 @@ func (con ArbGasInfo) _preversion10_GetL1PricingSurplus(c ctx, evm mech) (*big.I } haveFunds := evm.StateDB.GetBalance(l1pricing.L1PricerFundsPoolAddress) needFunds := arbmath.BigAdd(fundsDueForRefunds, fundsDueForRewards) - return arbmath.BigSub(haveFunds, needFunds), nil + return arbmath.BigSub(haveFunds.ToBig(), needFunds), nil } +// GetPerBatchGasCharge gets the base charge (in L1 gas) attributed to each data batch in the calldata pricer func (con ArbGasInfo) GetPerBatchGasCharge(c ctx, evm mech) (int64, error) { return c.State.L1PricingState().PerBatchGasCost() } +// GetAmortizedCostCapBips gets the cost amortization cap in basis points func (con ArbGasInfo) GetAmortizedCostCapBips(c ctx, evm mech) (uint64, error) { return c.State.L1PricingState().AmortizedCostCapBips() } +// GetL1FeesAvailable gets the available funds from L1 fees func (con ArbGasInfo) GetL1FeesAvailable(c ctx, evm mech) (huge, error) { return c.State.L1PricingState().L1FeesAvailable() } +// GetL1PricingEquilibrationUnits gets the equilibration units parameter for L1 price adjustment algorithm func (con ArbGasInfo) GetL1PricingEquilibrationUnits(c ctx, evm mech) (*big.Int, error) { return c.State.L1PricingState().EquilibrationUnits() } +// GetLastL1PricingUpdateTime gets the last time the L1 calldata pricer was updated func (con ArbGasInfo) GetLastL1PricingUpdateTime(c ctx, evm mech) (uint64, error) { return c.State.L1PricingState().LastUpdateTime() } +// GetL1PricingFundsDueForRewards gets the amount of L1 calldata payments due for rewards (per the L1 reward rate) func (con ArbGasInfo) GetL1PricingFundsDueForRewards(c ctx, evm mech) (*big.Int, error) { return c.State.L1PricingState().FundsDueForRewards() } +// GetL1PricingUnitsSinceUpdate gets the amount of L1 calldata posted since the last update func (con ArbGasInfo) GetL1PricingUnitsSinceUpdate(c ctx, evm mech) (uint64, error) { return c.State.L1PricingState().UnitsSinceUpdate() } +// GetLastL1PricingSurplus gets the L1 pricing surplus as of the last update (may be negative) func (con ArbGasInfo) GetLastL1PricingSurplus(c ctx, evm mech) (*big.Int, error) { return c.State.L1PricingState().LastSurplus() } diff --git a/precompiles/ArbInfo.go b/precompiles/ArbInfo.go index a260f7e7a4..9f8cf34532 100644 --- a/precompiles/ArbInfo.go +++ b/precompiles/ArbInfo.go @@ -18,7 +18,7 @@ func (con ArbInfo) GetBalance(c ctx, evm mech, account addr) (huge, error) { if err := c.Burn(params.BalanceGasEIP1884); err != nil { return nil, err } - return evm.StateDB.GetBalance(account), nil + return evm.StateDB.GetBalance(account).ToBig(), nil } // GetCode retrieves a contract's deployed code diff --git a/precompiles/ArbOwner.go b/precompiles/ArbOwner.go index 166768940b..f718a99f3e 100644 --- a/precompiles/ArbOwner.go +++ b/precompiles/ArbOwner.go @@ -153,7 +153,7 @@ func (con ArbOwner) ReleaseL1PricerSurplusFunds(c ctx, evm mech, maxWeiToRelease if err != nil { return nil, err } - weiToTransfer := new(big.Int).Sub(balance, recognized) + weiToTransfer := new(big.Int).Sub(balance.ToBig(), recognized) if weiToTransfer.Sign() < 0 { return common.Big0, nil } diff --git a/precompiles/ArbOwner_test.go b/precompiles/ArbOwner_test.go index ab128a8cb2..1f8c7ae4cd 100644 --- a/precompiles/ArbOwner_test.go +++ b/precompiles/ArbOwner_test.go @@ -14,6 +14,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" + "github.com/holiman/uint256" "github.com/offchainlabs/nitro/arbos/arbosState" "github.com/offchainlabs/nitro/arbos/burn" @@ -113,7 +114,7 @@ func TestArbOwner(t *testing.T) { Fail(t, avail) } deposited := big.NewInt(1000000) - evm.StateDB.AddBalance(l1pricing.L1PricerFundsPoolAddress, deposited) + evm.StateDB.AddBalance(l1pricing.L1PricerFundsPoolAddress, uint256.MustFromBig(deposited)) avail, err = gasInfo.GetL1FeesAvailable(callCtx, evm) Require(t, err) if avail.Sign() != 0 { diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 8c8b941f2e..ad9c6fbdf2 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -188,6 +188,13 @@ func (b *NodeBuilder) DefaultConfig(t *testing.T, withL1 bool) *NodeBuilder { return b } +func (b *NodeBuilder) WithArbOSVersion(arbosVersion uint64) *NodeBuilder { + newChainConfig := *b.chainConfig + newChainConfig.ArbitrumChainParams.InitialArbOSVersion = arbosVersion + b.chainConfig = &newChainConfig + return b +} + func (b *NodeBuilder) Build(t *testing.T) func() { if b.execConfig.RPC.MaxRecreateStateDepth == arbitrum.UninitializedMaxRecreateStateDepth { if b.execConfig.Caching.Archive { diff --git a/system_tests/retryable_test.go b/system_tests/retryable_test.go index 132f2e7555..1abf9f2162 100644 --- a/system_tests/retryable_test.go +++ b/system_tests/retryable_test.go @@ -32,7 +32,7 @@ import ( "github.com/offchainlabs/nitro/util/colors" ) -func retryableSetup(t *testing.T) ( +func retryableSetup(t *testing.T, modifyNodeConfig ...func(*NodeBuilder)) ( *NodeBuilder, *bridgegen.Inbox, func(*types.Receipt) *types.Transaction, @@ -41,6 +41,9 @@ func retryableSetup(t *testing.T) ( ) { ctx, cancel := context.WithCancel(context.Background()) builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + for _, f := range modifyNodeConfig { + f(builder) + } builder.Build(t) builder.L2Info.GenerateAccount("User2") @@ -205,9 +208,11 @@ func TestSubmitRetryableImmediateSuccess(t *testing.T) { } } -func TestSubmitRetryableEmptyEscrow(t *testing.T) { +func testSubmitRetryableEmptyEscrow(t *testing.T, arbosVersion uint64) { t.Parallel() - builder, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + builder, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t, func(builder *NodeBuilder) { + builder.WithArbOSVersion(arbosVersion) + }) defer teardown() user2Address := builder.L2Info.GetAddress("User2") @@ -278,14 +283,20 @@ func TestSubmitRetryableEmptyEscrow(t *testing.T) { escrowAccount := retryables.RetryableEscrowAddress(l2Tx.Hash()) state, err := builder.L2.ExecNode.ArbInterface.BlockChain().State() Require(t, err) - escrowCodeHash := state.GetCodeHash(escrowAccount) - if escrowCodeHash == (common.Hash{}) { - Fatal(t, "Escrow account deleted (or not created)") - } else if escrowCodeHash != types.EmptyCodeHash { - Fatal(t, "Escrow account has unexpected code hash", escrowCodeHash) + escrowExists := state.Exist(escrowAccount) + if escrowExists != (arbosVersion < 30) { + Fatal(t, "Escrow account existance", escrowExists, "doesn't correspond to ArbOS version", arbosVersion) } } +func TestSubmitRetryableEmptyEscrowArbOS20(t *testing.T) { + testSubmitRetryableEmptyEscrow(t, 20) +} + +func TestSubmitRetryableEmptyEscrowArbOS30(t *testing.T) { + testSubmitRetryableEmptyEscrow(t, 30) +} + func TestSubmitRetryableFailThenRetry(t *testing.T) { t.Parallel() builder, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) diff --git a/system_tests/seqinbox_test.go b/system_tests/seqinbox_test.go index 81dd2ad0d7..1b2701c2df 100644 --- a/system_tests/seqinbox_test.go +++ b/system_tests/seqinbox_test.go @@ -171,7 +171,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { var blockStates []blockTestState blockStates = append(blockStates, blockTestState{ balances: map[common.Address]*big.Int{ - ownerAddress: startOwnerBalance, + ownerAddress: startOwnerBalance.ToBig(), }, nonces: map[common.Address]uint64{ ownerAddress: startOwnerNonce, @@ -392,7 +392,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { } if batchCount.Cmp(big.NewInt(int64(len(blockStates)))) == 0 { break - } else if i >= 100 { + } else if i >= 140 { Fatal(t, "timed out waiting for l1 batch count update; have", batchCount, "want", len(blockStates)-1) } time.Sleep(10 * time.Millisecond) @@ -433,7 +433,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { Require(t, err) for acct, expectedBalance := range state.balances { haveBalance := stateDb.GetBalance(acct) - if expectedBalance.Cmp(haveBalance) < 0 { + if expectedBalance.Cmp(haveBalance.ToBig()) < 0 { Fatal(t, "unexpected balance for account", acct, "; expected", expectedBalance, "got", haveBalance) } }