Skip to content

Commit 9bc1365

Browse files
authored
Fix native coin forward gas buffer (#3529)
* Fix native coin forward gas buffer to prevent stuck transactions Increase gas fee buffer from 1.00001x to 2x when calculating the send amount for native coin forwards. The previous 0.001% buffer was insufficient to handle gas price fluctuations between the cached fee estimation and actual send, causing value + gas to exceed the wallet balance. This resulted in transactions being dropped from the mempool and an infinite forward/timeout/reset loop. * Use fresh gas cost for native coin forward amount calculation Instead of relying on a cached fee estimate (30s TTL) to calculate the send amount, fetch the current gas cost at dispatch time. This eliminates the race condition where gas price changes between the cached estimation and actual send, causing value + gas > balance and the transaction to be dropped from the mempool. * Reduce gas buffer from 1.5x to 1.05x Fresh gas cost is fetched milliseconds before the actual send, so only a minimal buffer is needed for potential block boundary gas price changes (max 12.5% per block via EIP-1559). * Apply fresh gas cost deduction to both forward and return paths The return path for native coins had no gas deduction at all, which would cause the same value + gas > balance issue when chargebackAmount equals the full deposit amount. * Update handlebars 4.7.8 → 4.7.9 to fix critical vulnerability Resolves 8 security advisories including JS injection, prototype pollution, and DoS via malformed decorator syntax.
1 parent 3ea8fff commit 9bc1365

4 files changed

Lines changed: 14 additions & 8 deletions

File tree

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898
"geoip-lite2": "^2.2.7",
9999
"graphql": "^16.11.0",
100100
"graphql-request": "^6.1.0",
101-
"handlebars": "^4.7.8",
101+
"handlebars": "^4.7.9",
102102
"helmet": "^6.2.0",
103103
"ibantools": "^4.5.1",
104104
"jszip": "^3.10.1",

src/subdomains/supporting/payin/services/base/payin-evm.service.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ export abstract class PayInEvmService {
2323
return this.#client.sendTokenFromAccount(account, addressTo, tokenName, amount);
2424
}
2525

26+
async getGasCostForCoinTransaction(): Promise<number> {
27+
return this.#client.getCurrentGasCostForCoinTransaction();
28+
}
29+
2630
async checkTransactionCompletion(txHash: string, minConfirmations: number): Promise<boolean> {
2731
return this.#client.isTxComplete(txHash, minConfirmations);
2832
}

src/subdomains/supporting/payin/strategies/send/impl/base/evm-coin.strategy.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,14 @@ export abstract class EvmCoinStrategy extends EvmStrategy {
4141
payInGroup.status = PayInStatus.PREPARED;
4242
}
4343

44-
protected dispatchSend(payInGroup: SendGroup, type: SendType, estimatedNativeFee: number): Promise<string> {
44+
protected async dispatchSend(payInGroup: SendGroup, type: SendType, estimatedNativeFee: number): Promise<string> {
4545
const { account, destinationAddress } = payInGroup;
4646

4747
const groupAmount = this.getTotalGroupAmount(payInGroup, type);
48-
// subtract fee for forwarding
49-
const amount = type === SendType.FORWARD ? Util.round(groupAmount - estimatedNativeFee * 1.00001, 12) : groupAmount;
48+
// use fresh gas cost (not cached estimate) to avoid value + gas > balance
49+
const freshGasCost = await this.payInEvmService.getGasCostForCoinTransaction();
50+
const gasCost = Math.max(freshGasCost, estimatedNativeFee);
51+
const amount = Util.round(groupAmount - gasCost * 1.05, 12);
5052

5153
return this.payInEvmService.sendNativeCoin(account, destinationAddress, amount);
5254
}

0 commit comments

Comments
 (0)