From 6e4f7e60200b22552a3cef460e1b873a0f6d4fb0 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 2 Oct 2026 16:20:30 +0000 Subject: [PATCH] fix(chain): canonical RLP for BSC sweeps + official RPC default - EthSigner: encode r/s as minimal big-endian bytes (even-length only) instead of zero-padding to 32 bytes. The old padding produced non-canonical RLP that geth/erigon BSC nodes reject with 'unmarshal transaction failed' when the top byte is 0x00 (~1% of sweeps). Fixes broken BNB/USDT-BEP20 auto-sweep. - coruna.bsc.rpc_url default: switch from third-party bsc.publicnode.com to official BNB Chain Foundation https://bsc-dataseed.bnbchain.org (free, no API key). Co-authored-by: Cursor --- app/Services/Chain/EthSigner.php | 16 ++++++++++++++-- config/coruna.php | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/app/Services/Chain/EthSigner.php b/app/Services/Chain/EthSigner.php index ed8fee6..49c9bea 100644 --- a/app/Services/Chain/EthSigner.php +++ b/app/Services/Chain/EthSigner.php @@ -48,8 +48,20 @@ final class EthSigner $key = $ec->keyFromPrivate($privateKeyHex); $sig = $key->sign($hash, ['canonical' => true]); - $r = str_pad($sig->r->toString(16), 64, '0', STR_PAD_LEFT); - $s = str_pad($sig->s->toString(16), 64, '0', STR_PAD_LEFT); + // Encode r/s as canonical big-endian integers (minimal bytes, no leading + // zero bytes). Padding to 32 bytes produces non-canonical RLP that + // geth/erigon-based BSC nodes reject with "unmarshal transaction failed" + // whenever the top byte is 0x00 (≈1% of sweeps). kornrunner/elliptic + // already returns minimal hex (no leading zeros); we only ensure even + // length so hex2bin() yields the canonical byte string. + $r = $sig->r->toString(16); + $s = $sig->s->toString(16); + if (strlen($r) % 2 !== 0) { + $r = '0'.$r; + } + if (strlen($s) % 2 !== 0) { + $s = '0'.$s; + } $recovery = (int) ($sig->recoveryParam ?? 0); $v = (string) ($recovery + 35 + $chainId * 2); diff --git a/config/coruna.php b/config/coruna.php index 79def69..c840263 100644 --- a/config/coruna.php +++ b/config/coruna.php @@ -143,7 +143,7 @@ return [ 'gas_limit' => env('ETH_GAS_LIMIT', ''), ], 'bsc' => [ - 'rpc_url' => env('BSC_RPC_URL', 'https://bsc.publicnode.com'), + 'rpc_url' => env('BSC_RPC_URL', 'https://bsc-dataseed.bnbchain.org'), 'chain_id' => (int) env('BSC_CHAIN_ID', 56), // Official Tether USDT BEP20 (BSC). 18 decimals. Empty = skip token balance/transfer. 'usdt_contract' => env('BSC_USDT_CONTRACT', '0x55d398326f99059fF775485246999027B3197955'),