From fba26335c9e771d854792d5db31073e062e4a826 Mon Sep 17 00:00:00 2001 From: Calin Martinconi Date: Mon, 25 May 2026 17:41:30 +0300 Subject: [PATCH 1/8] refactor: add BzzAddress to ChainConfig and remove LookupERC20Address --- cmd/bee/cmd/cmd.go | 2 + cmd/bee/cmd/start.go | 1 + packaging/bee.yaml | 2 + packaging/homebrew-amd64/bee.yaml | 2 + packaging/homebrew-arm64/bee.yaml | 2 + packaging/scoop/bee.yaml | 2 + pkg/config/chain.go | 5 +- pkg/config/chain_test.go | 76 ++++++++++++++++++++ pkg/node/node.go | 30 ++++---- pkg/postage/postagecontract/contract.go | 26 ------- pkg/postage/postagecontract/contract_test.go | 27 ------- 11 files changed, 108 insertions(+), 67 deletions(-) create mode 100644 pkg/config/chain_test.go diff --git a/cmd/bee/cmd/cmd.go b/cmd/bee/cmd/cmd.go index b4ece436d8d..6b4d2aa4c70 100644 --- a/cmd/bee/cmd/cmd.go +++ b/cmd/bee/cmd/cmd.go @@ -50,6 +50,7 @@ const ( optionNamePaymentEarly = "payment-early-percent" optionNameResolverEndpoints = "resolver-options" optionNameBootnodeMode = "bootnode-mode" + optionNameBzzTokenAddress = "bzz-token-address" optionNameSwapFactoryAddress = "swap-factory-address" optionNameSwapInitialDeposit = "swap-initial-deposit" optionNameSwapEnable = "swap-enable" @@ -298,6 +299,7 @@ func (c *command) setAllFlags(cmd *cobra.Command) { cmd.Flags().Duration(optionNameBlockchainRpcIdleTimeout, 90*time.Second, "blockchain rpc idle connection timeout") cmd.Flags().Duration(optionNameBlockchainRpcKeepalive, 30*time.Second, "blockchain rpc TCP keepalive interval") cmd.Flags().String(optionNameSwapFactoryAddress, "", "swap factory addresses") + cmd.Flags().String(optionNameBzzTokenAddress, "", "bzz token contract address (required on chains without a built-in default)") cmd.Flags().String(optionNameSwapInitialDeposit, "0", "initial deposit if deploying a new chequebook") cmd.Flags().Bool(optionNameSwapEnable, false, "enable swap") cmd.Flags().Bool(optionNameChequebookEnable, true, "enable chequebook") diff --git a/cmd/bee/cmd/start.go b/cmd/bee/cmd/start.go index 5773c4af3e3..7e0ef4c663d 100644 --- a/cmd/bee/cmd/start.go +++ b/cmd/bee/cmd/start.go @@ -278,6 +278,7 @@ func buildBeeNode(ctx context.Context, c *command, cmd *cobra.Command, logger lo BlockchainRpcTLSTimeout: c.config.GetDuration(configKeyBlockchainRpcTLSTimeout), BlockchainRpcIdleTimeout: c.config.GetDuration(configKeyBlockchainRpcIdleTimeout), BlockchainRpcKeepalive: c.config.GetDuration(configKeyBlockchainRpcKeepalive), + BzzTokenAddress: c.config.GetString(optionNameBzzTokenAddress), BlockProfile: c.config.GetBool(optionNamePProfBlock), BlockTime: networkConfig.blockTime, BlockSyncInterval: c.config.GetUint64(optionNameBlockSyncInterval), diff --git a/packaging/bee.yaml b/packaging/bee.yaml index ef04fb716c6..f285445a4cc 100644 --- a/packaging/bee.yaml +++ b/packaging/bee.yaml @@ -19,6 +19,8 @@ # bootnode: ["/dnsaddr/mainnet.ethswarm.org"] ## cause the node to always accept incoming connections # bootnode-mode: false +## bzz token contract address (required on chains without a built-in default) +# bzz-token-address: "" ## cache capacity in chunks, multiply by 4096 to get approximate capacity in bytes # cache-capacity: "1000000" ## enable forwarded content caching diff --git a/packaging/homebrew-amd64/bee.yaml b/packaging/homebrew-amd64/bee.yaml index 2aac12016fe..196f51e6a0c 100644 --- a/packaging/homebrew-amd64/bee.yaml +++ b/packaging/homebrew-amd64/bee.yaml @@ -19,6 +19,8 @@ # bootnode: ["/dnsaddr/mainnet.ethswarm.org"] ## cause the node to always accept incoming connections # bootnode-mode: false +## bzz token contract address (required on chains without a built-in default) +# bzz-token-address: "" ## cache capacity in chunks, multiply by 4096 to get approximate capacity in bytes # cache-capacity: "1000000" ## enable forwarded content caching diff --git a/packaging/homebrew-arm64/bee.yaml b/packaging/homebrew-arm64/bee.yaml index f812f395f07..d7b0c27ad39 100644 --- a/packaging/homebrew-arm64/bee.yaml +++ b/packaging/homebrew-arm64/bee.yaml @@ -19,6 +19,8 @@ # bootnode: ["/dnsaddr/mainnet.ethswarm.org"] ## cause the node to always accept incoming connections # bootnode-mode: false +## bzz token contract address (required on chains without a built-in default) +# bzz-token-address: "" ## cache capacity in chunks, multiply by 4096 to get approximate capacity in bytes # cache-capacity: "1000000" ## enable forwarded content caching diff --git a/packaging/scoop/bee.yaml b/packaging/scoop/bee.yaml index f44aaf0e0d0..fe9cda41893 100644 --- a/packaging/scoop/bee.yaml +++ b/packaging/scoop/bee.yaml @@ -19,6 +19,8 @@ # bootnode: ["/dnsaddr/mainnet.ethswarm.org"] ## cause the node to always accept incoming connections # bootnode-mode: false +## bzz token contract address (required on chains without a built-in default) +# bzz-token-address: "" ## cache capacity in chunks, multiply by 4096 to get approximate capacity in bytes # cache-capacity: "1000000" ## enable forwarded content caching diff --git a/pkg/config/chain.go b/pkg/config/chain.go index 1f5b3355961..f1f308271fb 100644 --- a/pkg/config/chain.go +++ b/pkg/config/chain.go @@ -11,8 +11,6 @@ import ( "github.com/ethersphere/go-storage-incentives-abi/abi" ) -// TODO: consider adding BzzAddress (also as a cmd param) to the ChainConfig and remove the postagecontract.LookupERC20Address function. - type ChainConfig struct { // General. ChainID int64 @@ -27,6 +25,7 @@ type ChainConfig struct { RedistributionAddress common.Address SwapPriceOracleAddress common.Address // Swap swear and swindle (S3) Contracts CurrentFactoryAddress common.Address + BzzAddress common.Address // ABIs. StakingABI string @@ -47,6 +46,7 @@ var ( RedistributionAddress: common.HexToAddress(abi.TestnetRedistributionAddress), SwapPriceOracleAddress: common.HexToAddress("0x1814e9b3951Df0CB8e12b2bB99c5594514588936"), CurrentFactoryAddress: common.HexToAddress("0x0fF044F6bB4F684a5A149B46D7eC03ea659F98A1"), + BzzAddress: common.HexToAddress(abi.TestnetBzzTokenAddress), StakingABI: abi.TestnetStakingABI, PostageStampABI: abi.TestnetPostageStampABI, @@ -65,6 +65,7 @@ var ( RedistributionAddress: common.HexToAddress(abi.MainnetRedistributionAddress), SwapPriceOracleAddress: common.HexToAddress("0xA57A50a831B31c904A770edBCb706E03afCdbd94"), CurrentFactoryAddress: common.HexToAddress("0xc2d5a532cf69aa9a1378737d8ccdef884b6e7420"), + BzzAddress: common.HexToAddress(abi.MainnetBzzTokenAddress), StakingABI: abi.MainnetStakingABI, PostageStampABI: abi.MainnetPostageStampABI, diff --git a/pkg/config/chain_test.go b/pkg/config/chain_test.go new file mode 100644 index 00000000000..9d347e498a9 --- /dev/null +++ b/pkg/config/chain_test.go @@ -0,0 +1,76 @@ +// Copyright 2026 The Swarm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package config_test + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethersphere/go-storage-incentives-abi/abi" + + "github.com/ethersphere/bee/v2/pkg/config" +) + +func TestChainConfigBzzAddress(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + cfg config.ChainConfig + want common.Address + }{ + { + name: "mainnet", + cfg: config.Mainnet, + want: common.HexToAddress(abi.MainnetBzzTokenAddress), + }, + { + name: "testnet", + cfg: config.Testnet, + want: common.HexToAddress(abi.TestnetBzzTokenAddress), + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + if (tc.want == common.Address{}) { + t.Fatal("expected a non-zero bzz token address") + } + if tc.cfg.BzzAddress != tc.want { + t.Fatalf("got bzz address %s, want %s", tc.cfg.BzzAddress, tc.want) + } + }) + } +} + +func TestGetByChainIDBzzAddress(t *testing.T) { + t.Parallel() + + t.Run("known chain", func(t *testing.T) { + t.Parallel() + + cfg, found := config.GetByChainID(config.Mainnet.ChainID) + if !found { + t.Fatal("expected mainnet to be a known chain") + } + if cfg.BzzAddress != common.HexToAddress(abi.MainnetBzzTokenAddress) { + t.Fatalf("got bzz address %s, want %s", cfg.BzzAddress, abi.MainnetBzzTokenAddress) + } + }) + + t.Run("unknown chain", func(t *testing.T) { + t.Parallel() + + cfg, found := config.GetByChainID(-1) + if found { + t.Fatal("expected unknown chain to be reported as not found") + } + if (cfg.BzzAddress != common.Address{}) { + t.Fatalf("expected zero bzz address for unknown chain, got %s", cfg.BzzAddress) + } + }) +} diff --git a/pkg/node/node.go b/pkg/node/node.go index 53d96ec5419..6505235aead 100644 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -139,6 +139,7 @@ type Options struct { BlockchainRpcTLSTimeout time.Duration BlockchainRpcIdleTimeout time.Duration BlockchainRpcKeepalive time.Duration + BzzTokenAddress string BlockProfile bool BlockTime time.Duration BlockSyncInterval uint64 @@ -393,6 +394,10 @@ func NewBee( chainEnabled := isChainEnabled(o, o.BlockchainRpcEndpoint, logger) + if o.SwapEnable && !chainEnabled { + return nil, errors.New("swap is enabled but the chain backend is not; provide --blockchain-rpc-endpoint or disable swap") + } + var batchStore postage.Storer = new(postage.NoOpBatchStore) var evictFn func([]byte) error @@ -535,18 +540,25 @@ func NewBee( } } + chainCfg, found := config.GetByChainID(chainID) + + bzzTokenAddress := chainCfg.BzzAddress + if o.BzzTokenAddress != "" { + if !common.IsHexAddress(o.BzzTokenAddress) { + return nil, errors.New("malformed bzz token address") + } + bzzTokenAddress = common.HexToAddress(o.BzzTokenAddress) + } else if chainEnabled && bzzTokenAddress == (common.Address{}) { + return nil, errors.New("no known bzz token address for this network; provide --bzz-token-address") + } + if o.SwapEnable { chequebookFactory, err := InitChequebookFactory(logger, chainBackend, chainID, transactionService, o.SwapFactoryAddress) if err != nil { return nil, fmt.Errorf("init chequebook factory: %w", err) } - erc20Address, err := chequebookFactory.ERC20Address(ctx) - if err != nil { - return nil, fmt.Errorf("factory fail: %w", err) - } - - erc20Service = erc20.New(transactionService, erc20Address) + erc20Service = erc20.New(transactionService, bzzTokenAddress) if o.ChequebookEnable && chainEnabled { chequebookService, err = InitChequebookService( @@ -692,7 +704,6 @@ func NewBee( eventListener postage.Listener ) - chainCfg, found := config.GetByChainID(chainID) postageStampContractAddress, postageSyncStart := chainCfg.PostageStampAddress, chainCfg.PostageStampStartBlock if o.PostageContractAddress != "" { if !common.IsHexAddress(o.PostageContractAddress) { @@ -709,11 +720,6 @@ func NewBee( postageStampContractABI := abiutil.MustParseABI(chainCfg.PostageStampABI) - bzzTokenAddress, err := postagecontract.LookupERC20Address(ctx, transactionService, postageStampContractAddress, postageStampContractABI, chainEnabled) - if err != nil { - return nil, fmt.Errorf("lookup erc20 postage address: %w", err) - } - // Compute gas limit for contract transactions: when TrxDebugMode is enabled, // gas estimation is skipped and DefaultGasLimit is used for all contract calls. var contractGasLimit uint64 diff --git a/pkg/postage/postagecontract/contract.go b/pkg/postage/postagecontract/contract.go index cae599db166..6acd25e0d0d 100644 --- a/pkg/postage/postagecontract/contract.go +++ b/pkg/postage/postagecontract/contract.go @@ -539,29 +539,3 @@ func (m *noOpPostageContract) Paused(context.Context) (bool, error) { func (m *noOpPostageContract) ExpireBatches(context.Context) error { return ErrChainDisabled } - -func LookupERC20Address(ctx context.Context, transactionService transaction.Service, postageStampContractAddress common.Address, postageStampContractABI abi.ABI, chainEnabled bool) (common.Address, error) { - if !chainEnabled { - return common.Address{}, nil - } - - callData, err := postageStampContractABI.Pack("bzzToken") - if err != nil { - return common.Address{}, err - } - - request := &transaction.TxRequest{ - To: &postageStampContractAddress, - Data: callData, - GasPrice: nil, - GasLimit: 0, - Value: big.NewInt(0), - } - - data, err := transactionService.Call(ctx, request) - if err != nil { - return common.Address{}, err - } - - return common.BytesToAddress(data), nil -} diff --git a/pkg/postage/postagecontract/contract_test.go b/pkg/postage/postagecontract/contract_test.go index 92020efbe9a..6b2607d590d 100644 --- a/pkg/postage/postagecontract/contract_test.go +++ b/pkg/postage/postagecontract/contract_test.go @@ -948,30 +948,3 @@ func TestBatchExpirer(t *testing.T) { } }) } - -func TestLookupERC20Address(t *testing.T) { - postageStampContractAddress := common.HexToAddress("ffff") - erc20Address := common.HexToAddress("ffff") - - addr, err := postagecontract.LookupERC20Address( - context.Background(), - transactionMock.New( - transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { - if *request.To != postageStampContractAddress { - return nil, fmt.Errorf("called wrong contract. wanted %v, got %v", postageStampContractAddress, request.To) - } - return common.BytesToHash(erc20Address.Bytes()).Bytes(), nil - }), - ), - postageStampContractAddress, - postageStampContractABI, - true, - ) - if err != nil { - t.Fatal(err) - } - - if addr != postageStampContractAddress { - t.Fatalf("got wrong erc20 address. wanted %v, got %v", erc20Address, addr) - } -} From 6760e926755ea9575b70811a15d0c1d65bbf819a Mon Sep 17 00:00:00 2001 From: Calin Martinconi Date: Wed, 27 May 2026 13:02:38 +0300 Subject: [PATCH 2/8] refactor: shorten --bzz-token-address flag description --- cmd/bee/cmd/cmd.go | 2 +- packaging/bee.yaml | 2 +- packaging/homebrew-amd64/bee.yaml | 2 +- packaging/homebrew-arm64/bee.yaml | 2 +- packaging/scoop/bee.yaml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/bee/cmd/cmd.go b/cmd/bee/cmd/cmd.go index 1d49503db91..6652d4b87c6 100644 --- a/cmd/bee/cmd/cmd.go +++ b/cmd/bee/cmd/cmd.go @@ -300,7 +300,7 @@ func (c *command) setAllFlags(cmd *cobra.Command) { cmd.Flags().Duration(optionNameBlockchainRpcIdleTimeout, 90*time.Second, "blockchain rpc idle connection timeout") cmd.Flags().Duration(optionNameBlockchainRpcKeepalive, 30*time.Second, "blockchain rpc TCP keepalive interval") cmd.Flags().String(optionNameSwapFactoryAddress, "", "swap factory addresses") - cmd.Flags().String(optionNameBzzTokenAddress, "", "bzz token contract address (required on chains without a built-in default)") + cmd.Flags().String(optionNameBzzTokenAddress, "", "bzz token contract address") cmd.Flags().String(optionNameSwapInitialDeposit, "0", "initial deposit if deploying a new chequebook") cmd.Flags().Bool(optionNameSwapEnable, false, "enable swap") cmd.Flags().Bool(optionNameChequebookEnable, true, "enable chequebook") diff --git a/packaging/bee.yaml b/packaging/bee.yaml index 5df4437236d..9772ed6fea8 100644 --- a/packaging/bee.yaml +++ b/packaging/bee.yaml @@ -19,7 +19,7 @@ # bootnode: ["/dnsaddr/mainnet.ethswarm.org"] ## cause the node to always accept incoming connections # bootnode-mode: false -## bzz token contract address (required on chains without a built-in default) +## bzz token contract address # bzz-token-address: "" ## cache capacity in chunks, multiply by 4096 to get approximate capacity in bytes # cache-capacity: "1000000" diff --git a/packaging/homebrew-amd64/bee.yaml b/packaging/homebrew-amd64/bee.yaml index 4a12634b1c4..8357b34f3eb 100644 --- a/packaging/homebrew-amd64/bee.yaml +++ b/packaging/homebrew-amd64/bee.yaml @@ -19,7 +19,7 @@ # bootnode: ["/dnsaddr/mainnet.ethswarm.org"] ## cause the node to always accept incoming connections # bootnode-mode: false -## bzz token contract address (required on chains without a built-in default) +## bzz token contract address # bzz-token-address: "" ## cache capacity in chunks, multiply by 4096 to get approximate capacity in bytes # cache-capacity: "1000000" diff --git a/packaging/homebrew-arm64/bee.yaml b/packaging/homebrew-arm64/bee.yaml index 29f4036182b..3917d11367f 100644 --- a/packaging/homebrew-arm64/bee.yaml +++ b/packaging/homebrew-arm64/bee.yaml @@ -19,7 +19,7 @@ # bootnode: ["/dnsaddr/mainnet.ethswarm.org"] ## cause the node to always accept incoming connections # bootnode-mode: false -## bzz token contract address (required on chains without a built-in default) +## bzz token contract address # bzz-token-address: "" ## cache capacity in chunks, multiply by 4096 to get approximate capacity in bytes # cache-capacity: "1000000" diff --git a/packaging/scoop/bee.yaml b/packaging/scoop/bee.yaml index 1c1bf8e46d8..e03c683c3f2 100644 --- a/packaging/scoop/bee.yaml +++ b/packaging/scoop/bee.yaml @@ -19,7 +19,7 @@ # bootnode: ["/dnsaddr/mainnet.ethswarm.org"] ## cause the node to always accept incoming connections # bootnode-mode: false -## bzz token contract address (required on chains without a built-in default) +## bzz token contract address # bzz-token-address: "" ## cache capacity in chunks, multiply by 4096 to get approximate capacity in bytes # cache-capacity: "1000000" From f6e6847955bd8cdb14eb245d982e0aec26523a76 Mon Sep 17 00:00:00 2001 From: Calin Martinconi Date: Wed, 27 May 2026 14:42:30 +0300 Subject: [PATCH 3/8] build(docker): expose --bzz-token-address as BEE_BZZ_TOKEN_ADDRESS Per @gacevicljubisa's review: surface the new flag through the docker packaging so operators using the docker-compose setup can configure it without dropping to a config file. Adds the env-var declaration in docker-compose.yml and a documented (commented) entry in env, both alphabetically placed between BEE_BOOTNODE_MODE and BEE_CACHE_CAPACITY. --- .github/workflows/beekeeper.yml | 6 +++--- packaging/docker/docker-compose.yml | 1 + packaging/docker/env | 2 ++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/beekeeper.yml b/.github/workflows/beekeeper.yml index 0cb7c41fe2f..cebe1819a10 100644 --- a/.github/workflows/beekeeper.yml +++ b/.github/workflows/beekeeper.yml @@ -7,8 +7,8 @@ on: paths-ignore: - packaging/** - openapi/** - - '**/*.md' - - '.github/ISSUE_TEMPLATE/**' + - "**/*.md" + - ".github/ISSUE_TEMPLATE/**" branches: - "**" @@ -19,7 +19,7 @@ env: SETUP_CONTRACT_IMAGE: "ethersphere/bee-localchain" SETUP_CONTRACT_IMAGE_TAG: "0.9.4" BEELOCAL_BRANCH: "main" - BEEKEEPER_BRANCH: "master" + BEEKEEPER_BRANCH: "feat/bzz-token-address" BEEKEEPER_METRICS_ENABLED: false REACHABILITY_OVERRIDE_PUBLIC: true BATCHFACTOR_OVERRIDE_PUBLIC: 2 diff --git a/packaging/docker/docker-compose.yml b/packaging/docker/docker-compose.yml index 65ad0b526cb..f209971337d 100644 --- a/packaging/docker/docker-compose.yml +++ b/packaging/docker/docker-compose.yml @@ -19,6 +19,7 @@ services: - BEE_BLOCKCHAIN_RPC_TLS_TIMEOUT - BEE_BOOTNODE - BEE_BOOTNODE_MODE + - BEE_BZZ_TOKEN_ADDRESS - BEE_CACHE_CAPACITY - BEE_CACHE_RETRIEVAL - BEE_CHEQUEBOOK_ENABLE diff --git a/packaging/docker/env b/packaging/docker/env index 0a400437b3c..169c19b3bba 100644 --- a/packaging/docker/env +++ b/packaging/docker/env @@ -31,6 +31,8 @@ # BEE_BOOTNODE=[/dnsaddr/mainnet.ethswarm.org] ## cause the node to always accept incoming connections (default false) # BEE_BOOTNODE_MODE=false +## bzz token contract address +# BEE_BZZ_TOKEN_ADDRESS= ## cache capacity in chunks, multiply by 4096 to get approximate capacity in bytes (default 1000000) # BEE_CACHE_CAPACITY=1000000 ## enable forwarded content caching (default true) From 599f33bf8e00d39083258b6b857e5c773bedcacc Mon Sep 17 00:00:00 2001 From: Calin Martinconi Date: Tue, 2 Jun 2026 13:46:12 +0300 Subject: [PATCH 4/8] refactor: validate --bzz-token-address in cmd and pass common.Address --- cmd/bee/cmd/start.go | 11 ++++++++++- pkg/node/node.go | 18 ++++++++---------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/cmd/bee/cmd/start.go b/cmd/bee/cmd/start.go index 98f97eb6399..a423c6bbcaf 100644 --- a/cmd/bee/cmd/start.go +++ b/cmd/bee/cmd/start.go @@ -21,6 +21,7 @@ import ( "syscall" "time" + "github.com/ethereum/go-ethereum/common" "github.com/ethersphere/bee/v2" "github.com/ethersphere/bee/v2/pkg/accesscontrol" "github.com/ethersphere/bee/v2/pkg/bmt" @@ -285,6 +286,14 @@ func buildBeeNode(ctx context.Context, c *command, cmd *cobra.Command, logger lo logger.Info("SIMD hashing enabled", "batch_width", keccak.BatchWidth(), "avx512", keccak.HasAVX512()) } + var bzzTokenAddress common.Address + if a := c.config.GetString(optionNameBzzTokenAddress); a != "" { + if !common.IsHexAddress(a) { + return nil, errors.New("malformed bzz token address") + } + bzzTokenAddress = common.HexToAddress(a) + } + b, err := node.NewBee(ctx, c.config.GetString(optionNameP2PAddr), signerConfig.publicKey, signerConfig.signer, networkID, logger, signerConfig.libp2pPrivateKey, signerConfig.pssPrivateKey, signerConfig.session, &node.Options{ Addr: c.config.GetString(optionNameP2PAddr), AllowPrivateCIDRs: c.config.GetBool(optionNameAllowPrivateCIDRs), @@ -297,7 +306,7 @@ func buildBeeNode(ctx context.Context, c *command, cmd *cobra.Command, logger lo BlockchainRpcTLSTimeout: c.config.GetDuration(configKeyBlockchainRpcTLSTimeout), BlockchainRpcIdleTimeout: c.config.GetDuration(configKeyBlockchainRpcIdleTimeout), BlockchainRpcKeepalive: c.config.GetDuration(configKeyBlockchainRpcKeepalive), - BzzTokenAddress: c.config.GetString(optionNameBzzTokenAddress), + BzzTokenAddress: bzzTokenAddress, BlockProfile: c.config.GetBool(optionNamePProfBlock), BlockTime: networkConfig.blockTime, BlockSyncInterval: c.config.GetUint64(optionNameBlockSyncInterval), diff --git a/pkg/node/node.go b/pkg/node/node.go index 048842e21a3..7e3a86b5260 100644 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -139,7 +139,7 @@ type Options struct { BlockchainRpcTLSTimeout time.Duration BlockchainRpcIdleTimeout time.Duration BlockchainRpcKeepalive time.Duration - BzzTokenAddress string + BzzTokenAddress common.Address BlockProfile bool BlockTime time.Duration BlockSyncInterval uint64 @@ -546,19 +546,17 @@ func NewBee( } } - chainCfg, found := config.GetByChainID(chainID) + chainCfg, knownChain := config.GetByChainID(chainID) bzzTokenAddress := chainCfg.BzzAddress - if o.BzzTokenAddress != "" { - if !common.IsHexAddress(o.BzzTokenAddress) { - return nil, errors.New("malformed bzz token address") - } - bzzTokenAddress = common.HexToAddress(o.BzzTokenAddress) - } else if chainEnabled && bzzTokenAddress == (common.Address{}) { - return nil, errors.New("no known bzz token address for this network; provide --bzz-token-address") + if o.BzzTokenAddress != (common.Address{}) { + bzzTokenAddress = o.BzzTokenAddress } if chainEnabled { + if bzzTokenAddress == (common.Address{}) { + return nil, errors.New("no known bzz token address for this network; provide --bzz-token-address") + } erc20Service = erc20.New(transactionService, bzzTokenAddress) } @@ -752,7 +750,7 @@ func NewBee( return nil, errors.New("postage contract start block option not provided") } postageSyncStart = o.PostageContractStartBlock - } else if !found { + } else if !knownChain { return nil, errors.New("no known postage stamp addresses for this network") } From 6fb543ddf6cf114088880480b1356ca1c7e22770 Mon Sep 17 00:00:00 2001 From: Calin Martinconi Date: Mon, 8 Jun 2026 16:14:07 +0300 Subject: [PATCH 5/8] refactor: rename ChainConfig.BzzAddress to TokenContractAddress --- pkg/config/chain.go | 6 +++--- pkg/config/chain_test.go | 16 ++++++++-------- pkg/node/node.go | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/pkg/config/chain.go b/pkg/config/chain.go index f534c340d2c..0cf07026bf1 100644 --- a/pkg/config/chain.go +++ b/pkg/config/chain.go @@ -26,7 +26,7 @@ type ChainConfig struct { RedistributionAddress common.Address SwapPriceOracleAddress common.Address // Swap swear and swindle (S3) Contracts CurrentFactoryAddress common.Address - BzzAddress common.Address + TokenContractAddress common.Address // ABIs. StakingABI string @@ -64,7 +64,7 @@ var ( RedistributionAddress: common.HexToAddress(abi.TestnetRedistributionAddress), SwapPriceOracleAddress: common.HexToAddress("0x1814e9b3951Df0CB8e12b2bB99c5594514588936"), CurrentFactoryAddress: common.HexToAddress("0x0fF044F6bB4F684a5A149B46D7eC03ea659F98A1"), - BzzAddress: common.HexToAddress(abi.TestnetBzzTokenAddress), + TokenContractAddress: common.HexToAddress(abi.TestnetBzzTokenAddress), StakingABI: abi.TestnetStakingABI, PostageStampABI: abi.TestnetPostageStampABI, @@ -87,7 +87,7 @@ var ( RedistributionAddress: common.HexToAddress(abi.MainnetRedistributionAddress), SwapPriceOracleAddress: common.HexToAddress("0xA57A50a831B31c904A770edBCb706E03afCdbd94"), CurrentFactoryAddress: common.HexToAddress("0xc2d5a532cf69aa9a1378737d8ccdef884b6e7420"), - BzzAddress: common.HexToAddress(abi.MainnetBzzTokenAddress), + TokenContractAddress: common.HexToAddress(abi.MainnetBzzTokenAddress), StakingABI: abi.MainnetStakingABI, PostageStampABI: abi.MainnetPostageStampABI, diff --git a/pkg/config/chain_test.go b/pkg/config/chain_test.go index cfd16d7bb9f..5ecb9262102 100644 --- a/pkg/config/chain_test.go +++ b/pkg/config/chain_test.go @@ -18,7 +18,7 @@ import ( "github.com/ethersphere/bee/v2/pkg/config" ) -func TestChainConfigBzzAddress(t *testing.T) { +func TestChainConfigTokenContractAddress(t *testing.T) { t.Parallel() tests := []struct { @@ -45,14 +45,14 @@ func TestChainConfigBzzAddress(t *testing.T) { if (tc.want == common.Address{}) { t.Fatal("expected a non-zero bzz token address") } - if tc.cfg.BzzAddress != tc.want { - t.Fatalf("got bzz address %s, want %s", tc.cfg.BzzAddress, tc.want) + if tc.cfg.TokenContractAddress != tc.want { + t.Fatalf("got token contract address %s, want %s", tc.cfg.TokenContractAddress, tc.want) } }) } } -func TestGetByChainIDBzzAddress(t *testing.T) { +func TestGetByChainIDTokenContractAddress(t *testing.T) { t.Parallel() t.Run("known chain", func(t *testing.T) { @@ -62,8 +62,8 @@ func TestGetByChainIDBzzAddress(t *testing.T) { if !found { t.Fatal("expected mainnet to be a known chain") } - if cfg.BzzAddress != common.HexToAddress(abi.MainnetBzzTokenAddress) { - t.Fatalf("got bzz address %s, want %s", cfg.BzzAddress, abi.MainnetBzzTokenAddress) + if cfg.TokenContractAddress != common.HexToAddress(abi.MainnetBzzTokenAddress) { + t.Fatalf("got token contract address %s, want %s", cfg.TokenContractAddress, abi.MainnetBzzTokenAddress) } }) @@ -74,8 +74,8 @@ func TestGetByChainIDBzzAddress(t *testing.T) { if found { t.Fatal("expected unknown chain to be reported as not found") } - if (cfg.BzzAddress != common.Address{}) { - t.Fatalf("expected zero bzz address for unknown chain, got %s", cfg.BzzAddress) + if (cfg.TokenContractAddress != common.Address{}) { + t.Fatalf("expected zero token contract address for unknown chain, got %s", cfg.TokenContractAddress) } }) } diff --git a/pkg/node/node.go b/pkg/node/node.go index 7e3a86b5260..4f5d8f492d8 100644 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -548,7 +548,7 @@ func NewBee( chainCfg, knownChain := config.GetByChainID(chainID) - bzzTokenAddress := chainCfg.BzzAddress + bzzTokenAddress := chainCfg.TokenContractAddress if o.BzzTokenAddress != (common.Address{}) { bzzTokenAddress = o.BzzTokenAddress } From f49da5fd66362a0813de15d3c268455e59eb9ffe Mon Sep 17 00:00:00 2001 From: Calin Martinconi Date: Mon, 8 Jun 2026 16:48:47 +0300 Subject: [PATCH 6/8] refactor: drop redundant chainEnabled check in chequebook init --- pkg/node/node.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/node/node.go b/pkg/node/node.go index 4f5d8f492d8..8ded8507902 100644 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -566,7 +566,7 @@ func NewBee( return nil, fmt.Errorf("init chequebook factory: %w", err) } - if o.ChequebookEnable && chainEnabled { + if o.ChequebookEnable { chequebookService, err = InitChequebookService( ctx, logger, From 4bf1b46a58190af508c9b8ba3d3d1e2379ca9bab Mon Sep 17 00:00:00 2001 From: Calin Martinconi Date: Thu, 18 Jun 2026 20:45:02 +0300 Subject: [PATCH 7/8] feat: log the resolved bzz token address at startup --- pkg/node/node.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/node/node.go b/pkg/node/node.go index 8ded8507902..b07a85ccae8 100644 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -557,6 +557,7 @@ func NewBee( if bzzTokenAddress == (common.Address{}) { return nil, errors.New("no known bzz token address for this network; provide --bzz-token-address") } + logger.Info("using bzz token address", "address", bzzTokenAddress) erc20Service = erc20.New(transactionService, bzzTokenAddress) } From 873c982d1eb6184127eec183b2555193c6dd03de Mon Sep 17 00:00:00 2001 From: Calin Martinconi Date: Thu, 18 Jun 2026 22:19:10 +0300 Subject: [PATCH 8/8] chore: restore beekeeper branch to master --- .github/workflows/beekeeper.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/beekeeper.yml b/.github/workflows/beekeeper.yml index cebe1819a10..b907093bad0 100644 --- a/.github/workflows/beekeeper.yml +++ b/.github/workflows/beekeeper.yml @@ -19,7 +19,7 @@ env: SETUP_CONTRACT_IMAGE: "ethersphere/bee-localchain" SETUP_CONTRACT_IMAGE_TAG: "0.9.4" BEELOCAL_BRANCH: "main" - BEEKEEPER_BRANCH: "feat/bzz-token-address" + BEEKEEPER_BRANCH: "master" BEEKEEPER_METRICS_ENABLED: false REACHABILITY_OVERRIDE_PUBLIC: true BATCHFACTOR_OVERRIDE_PUBLIC: 2