From 8230d5b4dea66777af83c9cc5d0a0247abfff74a Mon Sep 17 00:00:00 2001 From: mUniKeS Date: Thu, 6 Aug 2026 02:28:02 +0200 Subject: [PATCH 01/10] fix: remove dead Multichain BNB from Polygon bluechip tokens The BNB address (0xA649325...CE23F) was mislabeled as 'WETH' in BLUECHIP_POLY, and is bridged via the Multichain bridge which has been defunct since its 2023 exploit. It has $0 price/liquidity on PolygonScan and never resolves a price via CoinGecko. No live, liquid BNB representation currently exists on Polygon PoS worth including as a fee token, so this removes the entry entirely rather than relabeling it. --- src/server/config/config-token-addresses.ts | 3 ++- src/server/config/config-token-sets.ts | 3 --- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/server/config/config-token-addresses.ts b/src/server/config/config-token-addresses.ts index 9c6a89ee..86c6b8d9 100644 --- a/src/server/config/config-token-addresses.ts +++ b/src/server/config/config-token-addresses.ts @@ -28,7 +28,8 @@ export enum TokenAddressBSC { export enum TokenAddressPolygonPOS { WMATIC = '0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270', DAI = '0x8f3cf7ad23cd3cadbd9735aff958023239c6a063', - BNB = '0xA649325Aa7C5093d12D6F98EB4378deAe68CE23F', + // Unused: bridged BNB via Multichain, bridge defunct since 2023 hack. $0 liquidity/price on-chain. + // BNB = '0xA649325Aa7C5093d12D6F98EB4378deAe68CE23F', WETH = '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619', USDC = '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', USDT = '0xc2132D05D31c914a87C6611C10748AEb04B58e8F', diff --git a/src/server/config/config-token-sets.ts b/src/server/config/config-token-sets.ts index c61dd7e4..41ce05f7 100644 --- a/src/server/config/config-token-sets.ts +++ b/src/server/config/config-token-sets.ts @@ -58,9 +58,6 @@ export const BLUECHIP_POLY: AddressToTokenMap = { [TokenAddressPolygonPOS.WETH]: { symbol: 'WETH', }, - [TokenAddressPolygonPOS.BNB]: { - symbol: 'WETH', - }, [TokenAddressPolygonPOS.WMATIC]: { symbol: 'WMATIC', }, From b1a75846b3dc0ca808f6e81078db1ae46ffb34a7 Mon Sep 17 00:00:00 2001 From: mUniKeS Date: Thu, 6 Aug 2026 02:54:16 +0200 Subject: [PATCH 02/10] fix: correct WBNB symbol label on BSC (was mislabeled as WETH) TokenAddressBSC.WBNB (0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c) was labeled with symbol 'WETH' in BLUECHIP_BSC. The token itself is a legitimate, liquid asset and prices resolve fine regardless (price lookups are by address, not symbol), but the label is misleading in logs and any UI that surfaces the symbol. --- src/server/config/config-token-sets.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/config/config-token-sets.ts b/src/server/config/config-token-sets.ts index c61dd7e4..b7d84757 100644 --- a/src/server/config/config-token-sets.ts +++ b/src/server/config/config-token-sets.ts @@ -47,7 +47,7 @@ export const REN_TOKENS_ETH: AddressToTokenMap = { export const BLUECHIP_BSC: AddressToTokenMap = { [TokenAddressBSC.WBNB]: { - symbol: 'WETH', + symbol: 'WBNB', }, [TokenAddressBSC.CAKE]: { From 8179003a51b3e92bfce0bdad8c030fc000bc6d1b Mon Sep 17 00:00:00 2001 From: mUniKeS Date: Thu, 6 Aug 2026 02:59:12 +0200 Subject: [PATCH 03/10] fix: batch CoinGecko token price requests instead of one-per-token MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit coingeckoPriceLookup was making one HTTP request per token address in a loop with a 250ms delay, despite CoinGecko's simple/token_price endpoint natively supporting comma-separated contract_addresses in a single call. For a broadcaster running 3 networks with ~6-8 tokens each, this meant ~20 requests per refresh cycle (every ~60s) instead of 3 — burning through the free Demo tier's 10,000 requests/month quota in about 10 hours of uptime. Also lowered batchSize from 50 to 30 to match CoinGecko's documented Demo tier limit of 30 addresses per request (50 would only be safe on paid tiers). --- src/server/api/coingecko/coingecko-price.ts | 36 ++++++++------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/src/server/api/coingecko/coingecko-price.ts b/src/server/api/coingecko/coingecko-price.ts index 0b609f94..8cd45e78 100644 --- a/src/server/api/coingecko/coingecko-price.ts +++ b/src/server/api/coingecko/coingecko-price.ts @@ -41,28 +41,20 @@ const coingeckoPriceLookup = async ( ): Promise => { const currency = 'usd'; - const paramArr = tokenAddresses.map((address) => { - return { - contract_addresses: address, - vs_currencies: currency, - include_last_updated_at: true, - }; - }); let coingeckoPriceMap: CoingeckoPriceMap = {}; - for (const params of paramArr) { - try { - // eslint-disable-next-line no-await-in-loop - const geckoPriceMap: CoingeckoPriceMap = await getCoingeckoData( - CoingeckoApiEndpoint.PriceLookup, - coingeckoNetworkId, - params, - ); - coingeckoPriceMap = { ...coingeckoPriceMap, ...geckoPriceMap }; - // eslint-disable-next-line no-await-in-loop - await delay(250); - } catch (error) { - console.error(error); - } + try { + const geckoPriceMap: CoingeckoPriceMap = await getCoingeckoData( + CoingeckoApiEndpoint.PriceLookup, + coingeckoNetworkId, + { + contract_addresses: tokenAddresses.join(','), + vs_currencies: currency, + include_last_updated_at: true, + }, + ); + coingeckoPriceMap = { ...coingeckoPriceMap, ...geckoPriceMap }; + } catch (error) { + console.error(error); } const tokenPrices = tokenPriceArrayFromCoingeckoPriceMap( @@ -77,7 +69,7 @@ export const coingeckoUpdatePricesByAddresses = async ( tokenAddresses: string[], updater: TokenPriceUpdater, ): Promise => { - const batchSize = 50; + const batchSize = 30; // CoinGecko Demo API tier limit is 30 addresses per request for (let i = 0; i < tokenAddresses.length; i += batchSize) { const batch = tokenAddresses.slice(i, i + batchSize); // eslint-disable-next-line no-await-in-loop From 3f1f41801d2cc00ed186359082aff57791f527ea Mon Sep 17 00:00:00 2001 From: mUniKeS Date: Thu, 6 Aug 2026 15:01:18 +0200 Subject: [PATCH 04/10] fix: remove FEI and RENBTC from Ethereum default tokens FEI: Fei Protocol officially dissolved in August 2022 (Tribe DAO voted to redeem FEI->DAI and wind down operations). Observed in production: CoinGecko price for this token gets stuck/fails to refresh for 25+ minutes at a stretch while every other configured token refreshes normally each cycle. RENBTC: the backing bridge (RenVM) shut down in late 2022 following the Alameda/FTX collapse, with no active development since. On-chain volume is negligible (~$3/24h as observed), making it unsuitable as a fee token even though it still resolves a price. Neither token is a good candidate for fee collection: FEI is a defunct stablecoin and RENBTC is functionally illiquid. --- src/server/config/config-token-addresses.ts | 11 +++++++++-- src/server/config/config-token-sets.ts | 9 --------- src/server/config/config-tokens.ts | 1 - 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/server/config/config-token-addresses.ts b/src/server/config/config-token-addresses.ts index 9c6a89ee..cb1a9ac4 100644 --- a/src/server/config/config-token-addresses.ts +++ b/src/server/config/config-token-addresses.ts @@ -6,9 +6,16 @@ export enum TokenAddressEthereum { USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', RAIL = '0xe76C6c83af64e4C60245D8C7dE953DF673a7A33D', FRAX = '0x853d955acef822db058eb8505911ed77f175b99e', - FEI = '0x956F47F50A910163D8BF957Cf5846D573E7f87CA', RAI = '0x03ab458634910aad20ef5f1c8ee96f1d6ac54919', - RENBTC = '0xeb4c2781e4eba804ce9a9803c67d0893436bb27d', + // Unused: Fei Protocol dissolved Aug 2022 (Tribe DAO voted to redeem + // FEI->DAI and wind down). CoinGecko price consistently fails to + // refresh in production (observed stuck >25min while other tokens + // refreshed normally every cycle). + // FEI = '0x956F47F50A910163D8BF957Cf5846D573E7f87CA', + // Unused: backing bridge (RenVM) shut down in late 2022 after the + // Alameda/FTX collapse. No active development since; ~$3/24h volume + // on-chain as of 2026. Not viable as a fee token. + // RENBTC = '0xeb4c2781e4eba804ce9a9803c67d0893436bb27d', } export enum TokenAddressGoerli { WETH = '0xb4fbf271143f4fbf7b91a5ded31805e42b2208d6', diff --git a/src/server/config/config-token-sets.ts b/src/server/config/config-token-sets.ts index c61dd7e4..e6ee3430 100644 --- a/src/server/config/config-token-sets.ts +++ b/src/server/config/config-token-sets.ts @@ -19,9 +19,6 @@ export const STABLES_ETH: AddressToTokenMap = { [TokenAddressEthereum.FRAX]: { symbol: 'FRAX', }, - [TokenAddressEthereum.FEI]: { - symbol: 'FEI', - }, [TokenAddressEthereum.RAI]: { symbol: 'RAI', }, @@ -39,12 +36,6 @@ export const BLUECHIP_ETH: AddressToTokenMap = { }, }; -export const REN_TOKENS_ETH: AddressToTokenMap = { - [TokenAddressEthereum.RENBTC]: { - symbol: 'RENBTC', - }, -}; - export const BLUECHIP_BSC: AddressToTokenMap = { [TokenAddressBSC.WBNB]: { symbol: 'WETH', diff --git a/src/server/config/config-tokens.ts b/src/server/config/config-tokens.ts index b9646ae4..9018d26a 100644 --- a/src/server/config/config-tokens.ts +++ b/src/server/config/config-tokens.ts @@ -36,7 +36,6 @@ const tokensConfig: NetworkTokensConfig = { [NetworkChainID.Ethereum]: { ...STABLES_ETH, ...BLUECHIP_ETH, - ...REN_TOKENS_ETH, }, [NetworkChainID.EthereumGoerli]: { [TokenAddressGoerli.WETH]: { From b90e6b31dc1a26c402e7bf80a640bce32f8443d5 Mon Sep 17 00:00:00 2001 From: mUniKeS Date: Thu, 6 Aug 2026 16:14:27 +0200 Subject: [PATCH 05/10] fix: remove leftover REN_TOKENS_ETH import (broke build) --- src/server/config/config-tokens.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/server/config/config-tokens.ts b/src/server/config/config-tokens.ts index 9018d26a..6a9322b3 100644 --- a/src/server/config/config-tokens.ts +++ b/src/server/config/config-tokens.ts @@ -11,7 +11,6 @@ import { STABLES_BSC, STABLES_POLY, BLUECHIP_ETH, - REN_TOKENS_ETH, BLUECHIP_BSC, BLUECHIP_POLY, BLUECHIP_ARBITRUM, From b3dac5c733dd17a6a852a6011ae50fd93ef81c2c Mon Sep 17 00:00:00 2001 From: mUniKeS Date: Thu, 20 Aug 2026 20:49:49 +0200 Subject: [PATCH 06/10] fix: publish/getMessages ignore config.waku.pubSubTopic, hardcoded to dead cluster 0 topic --- src/server/networking/waku-rest-api-client.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/server/networking/waku-rest-api-client.ts b/src/server/networking/waku-rest-api-client.ts index 404da8c6..e781cc3d 100644 --- a/src/server/networking/waku-rest-api-client.ts +++ b/src/server/networking/waku-rest-api-client.ts @@ -18,11 +18,12 @@ export type WakuApiClientOptions = { export enum WakuRequestMethods { DebugInfo = '/debug/v1/info', // GET PublishSubscription = '/relay/v1/subscriptions', // POST - PublishMessage = '/relay/v1/messages/%2Fwaku%2F2%2Frs%2F0%2F1', // POST - requires pubsub topic UTF8 URL encoded /waku/2/rs/0/1 - GetMessages = '/relay/v1/messages/%2Fwaku%2F2%2Frs%2F0%2F1', // GET - requires pubsub topic UTF8 URL encoded /waku/2/rs/0/1 DeleteSubscriptions = '/relay/v1/subscriptions', // DELETE } +const relayMessagesPath = (topic: string): string => + `/relay/v1/messages/${encodeURIComponent(topic)}`; + const MAX_RETRIES = 4; const checkResponseStatus = (response: any, dbg: any) => { @@ -76,12 +77,10 @@ export class WakuRestApiClient { static determineRequestType(method: string) { switch (method) { - case WakuRequestMethods.DebugInfo: - case WakuRequestMethods.GetMessages: { + case WakuRequestMethods.DebugInfo: { return 'GET'; } - case WakuRequestMethods.PublishSubscription: - case WakuRequestMethods.PublishMessage: { + case WakuRequestMethods.PublishSubscription: { return 'POST'; } case WakuRequestMethods.DeleteSubscriptions: { @@ -175,10 +174,11 @@ export class WakuRestApiClient { const { timestamp } = message; const payload = Buffer.from(message.payload).toString('base64'); const { contentTopic } = message; + const publishPath = relayMessagesPath(topic); if (contentTopic?.includes('fees') === true) { // we have fee message.. dont try to resend. const data = await this.request( - WakuRequestMethods.PublishMessage, + publishPath, 'POST', { payload, timestamp, version: 0, contentTopic }, MAX_RETRIES, @@ -186,7 +186,7 @@ export class WakuRestApiClient { return data; } - const data = await this.request(WakuRequestMethods.PublishMessage, 'POST', { + const data = await this.request(publishPath, 'POST', { payload, timestamp, version: 0, @@ -212,10 +212,10 @@ export class WakuRestApiClient { * however, specifying contentTopics locally filters out uninteresting messages before return */ async getMessages( - topic: string, // unused + topic: string, contentTopics: string[] = [], ): Promise { - const data = await this.request(WakuRequestMethods.GetMessages, 'GET', []); + const data = await this.request(relayMessagesPath(topic), 'GET', []); if (isDefined(data.error)) { throw data.error; From dcce43095ed54ab1128eaab92d618375bf538d9a Mon Sep 17 00:00:00 2001 From: mUniKeS Date: Thu, 20 Aug 2026 20:50:28 +0200 Subject: [PATCH 07/10] fix: nwaku default config points at dead cluster 0, with stale bootstrap nodes --- docker/nwaku/config.toml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/docker/nwaku/config.toml b/docker/nwaku/config.toml index 7b1edb99..976d289b 100644 --- a/docker/nwaku/config.toml +++ b/docker/nwaku/config.toml @@ -16,6 +16,12 @@ keep-alive=false staticnode=[ # dev-node "/dns4/core.rootedinprivacy.com/tcp/60000/p2p/16Uiu2HAm4Ai1GzKv4EykU26ST1BPT4AHtABsYCLKrDG74GWX7D6H", + "/dns4/relay-a.rootedinprivacy.com/tcp/8000/wss/p2p/16Uiu2HAmMkCL9Y4R6V8eyTfHRfPA9JUBSnsJXwiUvgUJHU7N9AsR", + "/dns4/relay-a.rootedinprivacy.com/tcp/30304/p2p/16Uiu2HAmMkCL9Y4R6V8eyTfHRfPA9JUBSnsJXwiUvgUJHU7N9AsR", + "/dns4/relay-b.rootedinprivacy.com/tcp/8000/wss/p2p/16Uiu2HAm1XAZUTsZcbvLBWe9MR2QxEJ1oowv5VgZavwiwTEx4uPC", + "/dns4/relay-b.rootedinprivacy.com/tcp/30304/p2p/16Uiu2HAm1XAZUTsZcbvLBWe9MR2QxEJ1oowv5VgZavwiwTEx4uPC", + "/dns4/client-edge.rootedinprivacy.com/tcp/8000/wss/p2p/16Uiu2HAmS8YbNhE1rJGBQ3VaubZjM1iAR7zVvtLf6CrEB3Hc9Krr", + "/dns4/client-edge.rootedinprivacy.com/tcp/30304/p2p/16Uiu2HAmS8YbNhE1rJGBQ3VaubZjM1iAR7zVvtLf6CrEB3Hc9Krr", ] dns-discovery=false discv5-discovery=false @@ -23,14 +29,14 @@ discv5-bootstrap-node=[ # dev-node "enr:-Ou4QF5uFxGUG9WVUuysEWm8nketT_Pe6hG0P6NRxu9dTOwHWHWQgGFhm-vqmYwUvU0LtrW2LhSEO7iEHKD4l8JEd14BgmlkgnY0gmlwhIxSIGiKbXVsdGlhZGRyc7hAAB02GGNvcmUucm9vdGVkaW5wcml2YWN5LmNvbQbqYAAfNhhjb3JlLnJvb3RlZGlucHJpdmFjeS5jb20GH0DeA4Jyc48AAAYAAAABAAIAAwAEAAWJc2VjcDI1NmsxoQKB48KxVciQEh-6cSmBBGdTm-ehZ_6_oht-pjmrU52YEoN0Y3CC6mCFd2FrdTIN", ] -shard=[0, 1, 2, 3, 4, 5] +shard=[0, 1, 2, 3, 4, 5, 6, 7] max-msg-size="512KiB" -cluster-id=0 # needed when switch to 0.33 nwaku, pubsub-topic is deprecated +cluster-id=5 # needed when switch to 0.33 nwaku, pubsub-topic is deprecated filter-subscription-timeout=3000 filter-max-peers-to-serve=10000 reliability=false -num-shards-in-network=6 +num-shards-in-network=8 peer-store-capacity=500 max-connections=500 From b1bb55d09ca5bc7c1ad49bbc4b79abc2c6b88e0a Mon Sep 17 00:00:00 2001 From: mUniKeS Date: Thu, 20 Aug 2026 21:02:25 +0200 Subject: [PATCH 08/10] docs: warn that priceTTLInMS must stay >= CoinGecko refreshDelayInMS --- src/server/config/config-networks.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/server/config/config-networks.ts b/src/server/config/config-networks.ts index 72841902..d61ec978 100644 --- a/src/server/config/config-networks.ts +++ b/src/server/config/config-networks.ts @@ -45,6 +45,15 @@ const MINIMUM_BALANCE_FOR_AVAILABILITY_L2 = 0.01; // 10 minute timeout on ticket prices retrieved from API. // Shorter is safer, but Coingecko free tier can lag by 15-30 minutes. +// +// IMPORTANT: this MUST stay >= the price refresher's refreshDelayInMS +// (configTokenPriceRefresher.tokenPriceRefreshers[...].refreshDelayInMS, +// overridable in MY-CONFIG.ts). If you raise the refresh interval (e.g. to +// save CoinGecko free-tier quota) without raising this TTL by at least as +// much, every cycle gets a guaranteed window - equal to the gap between the +// two values - where cached prices are considered "expired" and the +// broadcaster silently stops publishing fees for every token (NO TOKEN +// PRICE warnings), with no underlying error: the API call itself succeeds. const defaultTokenPriceTTL = 10 * 60 * 1000; const networksConfig: NetworksConfig = { From 6e9b432de91b540e2393d66b10fc83732b87790b Mon Sep 17 00:00:00 2001 From: mUniKeS Date: Fri, 21 Aug 2026 23:02:25 +0200 Subject: [PATCH 09/10] docs: warn that profitMargin overrides don't retroactively update built fee configs --- src/server/config/config-fees.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/server/config/config-fees.ts b/src/server/config/config-fees.ts index ef7bf6a6..d85c8c15 100644 --- a/src/server/config/config-fees.ts +++ b/src/server/config/config-fees.ts @@ -11,6 +11,16 @@ const feeConfig = ( profit, }); +// IMPORTANT: `profit` defaults to configDefaults.transactionFees.profitMargin, +// but a default parameter is resolved the moment this function is CALLED, +// not read live afterwards. Default network fee configs are built once, at +// module load time in config-networks.ts, using whatever profitMargin holds +// at that point (the built-in default). If you override profitMargin later +// in MY-CONFIG.ts, the fee config already built for a network is NOT +// retroactively updated - setting profitMargin alone silently does nothing +// to fees computed before the override ran. To actually apply a new margin, +// call setFeesForNetworkEVM(chain, feeConfigL1(ratio)) (or feeConfigL2) +// again, AFTER setting profitMargin, so it re-reads the current value. export const feeConfigL1 = ( gasEstimateLimitToActualRatio: number, gasEstimateVarianceBuffer = 0.1, From 7be221ef2915f181057ab2a73e855df8c1ba1583 Mon Sep 17 00:00:00 2001 From: mUniKeS Date: Tue, 25 Aug 2026 20:01:42 +0200 Subject: [PATCH 10/10] feat: upgrade @railgun-community/wallet to 10.9.0, handle new EIP-7702 transaction type --- package.json | 4 +- .../block-native/gas-by-speed-block-native.ts | 6 ++ src/server/fees/gas-by-speed.ts | 6 ++ src/server/fees/gas-estimate.ts | 5 ++ .../transactions/process-transaction.ts | 6 ++ .../methods/transact-method.ts | 12 ++++ yarn.lock | 62 ++++++++++++++----- 7 files changed, 83 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index fb0e1b98..f07ba535 100644 --- a/package.json +++ b/package.json @@ -31,8 +31,8 @@ "dependencies": { "@0x/contract-addresses": "^8.0.0", "@noble/ed25519": "^1.7.1", - "@railgun-community/shared-models": "^8.0.0", - "@railgun-community/wallet": "^10.8.1", + "@railgun-community/shared-models": "^8.0.1", + "@railgun-community/wallet": "^10.9.0", "@walletconnect/jsonrpc-types": "^1.0.2", "@walletconnect/jsonrpc-utils": "^1.0.4", "axios": "1.7.2", diff --git a/src/server/api/block-native/gas-by-speed-block-native.ts b/src/server/api/block-native/gas-by-speed-block-native.ts index d7c7238b..1ac7f538 100644 --- a/src/server/api/block-native/gas-by-speed-block-native.ts +++ b/src/server/api/block-native/gas-by-speed-block-native.ts @@ -207,6 +207,12 @@ export const getGasDetailsBySpeedBlockNative = async ( }, }; } + case EVMGasType.Type4: { + // EIP-7702 not yet supported by this broadcaster. + throw new Error( + 'EVMGasType 4 (EIP-7702) not yet supported for gas-by-speed lookups.', + ); + } } } catch (err) { dbg(err); diff --git a/src/server/fees/gas-by-speed.ts b/src/server/fees/gas-by-speed.ts index 83bf4327..c544e632 100644 --- a/src/server/fees/gas-by-speed.ts +++ b/src/server/fees/gas-by-speed.ts @@ -164,6 +164,12 @@ export const getGasDetailsForSpeed = async ( ); return gasDetailsBySpeed[percentile]; } + case EVMGasType.Type4: { + // EIP-7702 not yet supported by this broadcaster. + throw new Error( + 'EVMGasType 4 (EIP-7702) not yet supported for gas-by-speed lookups.', + ); + } } }; diff --git a/src/server/fees/gas-estimate.ts b/src/server/fees/gas-estimate.ts index 39c10b08..28f50738 100644 --- a/src/server/fees/gas-estimate.ts +++ b/src/server/fees/gas-estimate.ts @@ -124,6 +124,11 @@ export const getEstimateGasDetailsRelayed = async ( // minGasPrice not allowed on EVMGasType 2 throw new Error('EVMGasType 2 not allowed for Broadcaster transactions.'); } + if (evmGasType === EVMGasType.Type4) { + // EIP-7702 (Type4) transactions use maxFeePerGas/maxPriorityFeePerGas, + // not gasPrice - not yet supported on this relayed estimation path. + throw new Error('EVMGasType 4 (EIP-7702) not yet supported for Broadcaster transactions.'); + } const gasPrice = minGasPrice; const transactionWithOptionalMinGas: ContractTransaction = { ...transaction, diff --git a/src/server/transactions/process-transaction.ts b/src/server/transactions/process-transaction.ts index 874e6597..31761361 100644 --- a/src/server/transactions/process-transaction.ts +++ b/src/server/transactions/process-transaction.ts @@ -58,6 +58,12 @@ export const processTransaction = async ( if (evmGasType === EVMGasType.Type2) { throw new Error('Invalid gas type for Broadcaster transaction.'); } + if (evmGasType === EVMGasType.Type4) { + // EIP-7702 requests are rejected earlier, in transact-method.ts, before + // reaching this point - this is a defensive guard, not expected in + // practice today. + throw new Error('EVMGasType 4 (EIP-7702) not yet supported for Broadcaster transactions.'); + } const transactionRequestForGasEstimate: ContractTransaction = { ...transaction, diff --git a/src/server/waku-broadcaster/methods/transact-method.ts b/src/server/waku-broadcaster/methods/transact-method.ts index 06ea61d3..6c9d135b 100644 --- a/src/server/waku-broadcaster/methods/transact-method.ts +++ b/src/server/waku-broadcaster/methods/transact-method.ts @@ -27,6 +27,7 @@ import configNetworks from '../../config/config-networks'; import { BroadcasterEncryptedMethodParams, BroadcasterRawParamsTransact, + BroadcasterTransactRequestType, TXIDVersion, isDefined, versionCompare, @@ -98,6 +99,17 @@ export const transactMethod = async ( return undefined; } + // EIP-7702 (TX7702) requests are not yet supported by this broadcaster. + // Reject explicitly instead of assuming the old COMMON-only shape - the + // fields below (to/data/minGasPrice/useRelayAdapt/etc.) only exist on the + // COMMON variant. + if (decrypted.transactType !== BroadcasterTransactRequestType.COMMON) { + dbg('Cannot process tx - TX7702 (EIP-7702) requests not yet supported'); + // Do nothing. No error response. + await incrementReliability(incomingChain, ReliabilityMetric.BAD_DATA); + return undefined; + } + const { chainType, chainID, diff --git a/yarn.lock b/yarn.lock index 2802a9c9..2b767d32 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1353,10 +1353,10 @@ resolved "https://registry.yarnpkg.com/@railgun-community/curve25519-scalarmult-wasm/-/curve25519-scalarmult-wasm-0.1.5.tgz#edb5e40a8f1fdb7f7e0de1d04e8badabe41cb2a8" integrity sha512-Cur8uM/IdNW3WzUwdPloDG1CF0rpSBDWq2yGXJMZ7IMeBGdc4Jj0h9tnNMFRZ35ZuCVVbZ3yClmqSa4PsbpdGQ== -"@railgun-community/engine@9.5.1": - version "9.5.1" - resolved "https://registry.yarnpkg.com/@railgun-community/engine/-/engine-9.5.1.tgz#ed761969c133ef85edc15900de7fdad96dbeeb37" - integrity sha512-tLX0WSHABzRC1VB7vhdwSBDFUYCFqRYHD2ek5/GT9+AZaKZJ6fU+UrAJYKxyEaGJ066l3M70fChc0Q6qM21scQ== +"@railgun-community/engine@^9.6.0": + version "9.6.0" + resolved "https://registry.yarnpkg.com/@railgun-community/engine/-/engine-9.6.0.tgz#c2d2f07bd37dce7c95f65ab827131e4c1fdc0683" + integrity sha512-dFMhO8i+hxFIr/u0gtaVKV0C3SRaM6bHccfIzzJ/nAWQOK5gPI/h6cgkw0ICjycDUy8ZSkism19jWsIuIBJVwg== dependencies: "@noble/ciphers" "^0.4.0" "@noble/ed25519" "^1.7.1" @@ -1371,7 +1371,7 @@ chai-as-promised "^7.1.1" encoding-down "^7.1.0" ethereum-cryptography "^2.0.0" - ethers "6.13.1" + ethers "6.14.3" fast-text-encoding "^1.0.6" levelup "^5.1.1" msgpack-lite "^0.1.26" @@ -1388,15 +1388,15 @@ resolved "https://registry.yarnpkg.com/@railgun-community/poseidon-hash-wasm/-/poseidon-hash-wasm-1.0.1.tgz#bfd3b3f915391a59486d8c9d632069f029e152d6" integrity sha512-zDAbMu095ZjMqsKIoyOnuKR4Zofnqqx4eTCtnA6qYglnexX5cadxItvJa3ozhDDTmFkDGAidDssQ7Pzl3wwLDA== -"@railgun-community/shared-models@8.0.0", "@railgun-community/shared-models@^8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@railgun-community/shared-models/-/shared-models-8.0.0.tgz#689d4f6a3a80060e018abeb1b351cc711f97e77c" - integrity sha512-JY2HOobRlZpX9CsfiOfbjA2zmG3qLYA/QUupfz0V3ERUErQIm1ZQBSdMfVDZWhflW/4As+rbsY7vc3rXLGbpvA== +"@railgun-community/shared-models@^8.0.1": + version "8.0.1" + resolved "https://registry.yarnpkg.com/@railgun-community/shared-models/-/shared-models-8.0.1.tgz#185a74f9fa60b7da74de7afde583926efc52b180" + integrity sha512-g5Gt3j2O8XAMoJ+SzxvzyuB/KioFXXOs+2T0wxFQS5ebXB52e+HFBZ5UFVlORCbHteaAwLiURRcR2W8hOBUuoA== -"@railgun-community/wallet@^10.8.1": - version "10.8.1" - resolved "https://registry.yarnpkg.com/@railgun-community/wallet/-/wallet-10.8.1.tgz#361c6a11e41b194dcc4878ef8a66848d0d8dfd24" - integrity sha512-UEVydOi6k2nWEXh54gsgTpX5/ncbiV/uqnkV0DQzinXSeGcCLKNEopcogSYT/1mcIjTwHEs+rR6iNc5IwlZdcA== +"@railgun-community/wallet@^10.9.0": + version "10.9.0" + resolved "https://registry.yarnpkg.com/@railgun-community/wallet/-/wallet-10.9.0.tgz#60061855c37cf74a045ba8a718312520ee36475d" + integrity sha512-y2ncKCWkG3rWSYysBzXzPsTQvKMGE2lCFVwCgKjS3JnkZAHiKRYWjWrcMw1mSrFYmNjTO1/loYO4qALGz09cbg== dependencies: "@graphql-mesh/cache-localforage" "^0.7.20" "@graphql-mesh/cross-helpers" "^0.3.4" @@ -1409,8 +1409,8 @@ "@graphql-mesh/types" "^0.91.14" "@graphql-mesh/utils" "^0.43.22" "@noble/ed25519" "^1.7.1" - "@railgun-community/engine" "9.5.1" - "@railgun-community/shared-models" "8.0.0" + "@railgun-community/engine" "^9.6.0" + "@railgun-community/shared-models" "^8.0.1" "@whatwg-node/fetch" "^0.8.4" assert "2.0.0" axios "1.7.2" @@ -1418,7 +1418,7 @@ buffer "^6.0.3" crypto-browserify "3.12.0" ethereum-cryptography "^2.0.0" - ethers "6.13.1" + ethers "6.14.3" events "3.3.0" graphql "^16.6.0" stream-browserify "3.0.0" @@ -1662,6 +1662,13 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469" integrity sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q== +"@types/node@22.7.5": + version "22.7.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.5.tgz#cfde981727a7ab3611a481510b473ae54442b92b" + integrity sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ== + dependencies: + undici-types "~6.19.2" + "@types/node@^12.12.6": version "12.20.55" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" @@ -3748,6 +3755,19 @@ ethers@6.13.1: tslib "2.4.0" ws "8.17.1" +ethers@6.14.3: + version "6.14.3" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.14.3.tgz#7c4443c165ee59b2964e691600fd4586004b2000" + integrity sha512-qq7ft/oCJohoTcsNPFaXSQUm457MA5iWqkf1Mb11ujONdg7jBI6sAOrHaTi3j0CBqIGFSCeR/RMc+qwRRub7IA== + dependencies: + "@adraffy/ens-normalize" "1.10.1" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@types/node" "22.7.5" + aes-js "4.0.0-beta.5" + tslib "2.7.0" + ws "8.17.1" + ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" @@ -7593,6 +7613,11 @@ tslib@2.4.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== +tslib@2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" + integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== + tslib@^2.0.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.5.0, tslib@^2.6.1: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" @@ -7732,6 +7757,11 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + unique-filename@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-3.0.0.tgz#48ba7a5a16849f5080d26c760c86cf5cf05770ea"