From 1967a9396538f08bfb1ef2d625e460bd57f245e3 Mon Sep 17 00:00:00 2001 From: Support Bot Date: Thu, 25 Jun 2026 17:10:06 +0000 Subject: [PATCH] fix(statics): add EIP1559 to ETH_FEATURES_WITH_FRANKFURT for v4 forwarder flush MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ETH mainnet has required EIP1559 (type-2) transactions since the London hard fork (Aug 2021). Tokens on Ethereum using ETH_FEATURES_WITH_FRANKFURT (e.g. SUSHI, LINK, DAI) lacked the EIP1559 coin feature flag, which caused the BitGo platform to fall back to legacy transaction format when building flush transactions for v4 forwarders. V4 forwarders require the flush transaction to be sent directly to the forwarder address using the flushTokens(address) method — and this path requires EIP1559 on mainnet. Add CoinFeature.EIP1559 to ETH_FEATURES_WITH_FRANKFURT so all tokens using this feature set (including SUSHI) correctly declare EIP1559 support and receive properly-typed flush transactions from v4 hot wallet forwarders. Also add a regression test that builds a SUSHI v4 forwarder flush with EIP1559 fees, confirming the correct method ID and calldata encoding. Ticket: COINS-558 Session-Id: 11a8d890-1ca4-4c30-acd7-158927258cfd Task-Id: d32e686b-2479-4535-a80d-0b0ee0871065 --- .../unit/transactionBuilder/flushTokens.ts | 35 +++++++++++++++++++ modules/statics/src/coinFeatures.ts | 6 +++- modules/statics/test/unit/coins.ts | 1 + 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/modules/sdk-coin-eth/test/unit/transactionBuilder/flushTokens.ts b/modules/sdk-coin-eth/test/unit/transactionBuilder/flushTokens.ts index 097127f13f..f21475551c 100644 --- a/modules/sdk-coin-eth/test/unit/transactionBuilder/flushTokens.ts +++ b/modules/sdk-coin-eth/test/unit/transactionBuilder/flushTokens.ts @@ -162,6 +162,41 @@ describe('Eth Transaction builder flush tokens (ETH-specific)', function () { txJson.data.should.startWith(flushForwarderTokensMethodIdV4); }); + it('a SUSHI token flush from v4 forwarder with EIP-1559 fees', async () => { + // SUSHI mainnet contract: 0x6b3595068778dd592e39a122f4f5a5cf09c90fe2 + // For v4 forwarder, contractAddress must equal forwarderAddress + const sushiContractAddress = '0x6b3595068778dd592e39a122f4f5a5cf09c90fe2'; + const v4ForwarderAddress = '0x53b8e91bb3b8f618b5f01004ef108f134f219573'; + + const tx = await buildTransaction({ + fee: { + fee: '30', + eip1559: { + maxPriorityFeePerGas: '2000000000', + maxFeePerGas: '30000000000', + }, + gasLimit: '100000', + }, + counter: 1, + forwarderAddress: v4ForwarderAddress, + tokenAddress: sushiContractAddress, + contractAddress: v4ForwarderAddress, + forwarderVersion: 4, + }); + + tx.type.should.equal(TransactionType.FlushTokens); + const txJson = tx.toJson(); + txJson.gasLimit.should.equal('100000'); + txJson._type.should.equals(ETHTransactionType.EIP1559); + txJson.maxFeePerGas!.should.equal('30000000000'); + txJson.maxPriorityFeePerGas!.should.equal('2000000000'); + txJson.to!.should.equal(v4ForwarderAddress); + should.equal(txJson.nonce, 1); + txJson.data.should.startWith(flushForwarderTokensMethodIdV4); + // Verify SUSHI contract address is encoded in calldata + txJson.data.should.containEql(sushiContractAddress.slice(2).toLowerCase()); + }); + it('decode wallet flush forwarder transaction with forwarder Version 4', async () => { const tx = await buildTransaction({ fee: { diff --git a/modules/statics/src/coinFeatures.ts b/modules/statics/src/coinFeatures.ts index 238d66dc6d..d96ef9ad71 100644 --- a/modules/statics/src/coinFeatures.ts +++ b/modules/statics/src/coinFeatures.ts @@ -702,7 +702,11 @@ export const POLYX_TOKEN_FEATURES = [ CoinFeature.TOKEN_STANDARD_USES_ALTERNATIVE_ADDRESS_IDENTIFIER, ]; -export const ETH_FEATURES_WITH_FRANKFURT = [...ETH_FEATURES, CoinFeature.CUSTODY_BITGO_FRANKFURT]; +export const ETH_FEATURES_WITH_FRANKFURT = [ + ...ETH_FEATURES, + CoinFeature.CUSTODY_BITGO_FRANKFURT, + CoinFeature.EIP1559, +]; export const ETH_FEATURES_WITH_GERMANY = [...ETH_FEATURES, CoinFeature.CUSTODY_BITGO_GERMANY]; export const ETH_FEATURES_WITH_FRANKFURT_GERMANY = [...ETH_FEATURES_WITH_FRANKFURT, CoinFeature.CUSTODY_BITGO_GERMANY]; export const SOL_TOKEN_FEATURES_WITH_FRANKFURT = [ diff --git a/modules/statics/test/unit/coins.ts b/modules/statics/test/unit/coins.ts index 644323c0a0..d54bd51bbf 100644 --- a/modules/statics/test/unit/coins.ts +++ b/modules/statics/test/unit/coins.ts @@ -1288,6 +1288,7 @@ describe('Eip1559 coins', () => { 'toas', 'coredao', 'tcoredao', + 'sushi', ]; it('should have EIP1559 feature', () => { eip1559Coins.forEach((coinName) => {