Summary
The wallet RPC send methods can build, sign, and relay a transaction whose fee-payer (Signers[0]) cannot cover the network fee, producing InsufficientFunds (-511) at relay — even though Wallet.MakeTransaction already validated that the selected sender could afford the fee. The network fee is raised after MakeTransaction (i.e. after the signer was selected and the fee validated), with no re-check that the selected sender can still pay. Verified on neo-node v3.9.2 / neo core v3.9.1.
Root cause
Wallet.MakeTransaction selects the fee-payer (Signers[0]) from GAS-holding accounts (L600) and only returns a tx the chosen sender can afford:
tx.NetworkFee = tx.CalculateNetworkFee(...); // Wallet.cs:669
if (value >= tx.SystemFee + tx.NetworkFee) return tx; // Wallet.cs:670 ← signer selected + fee validated here
Then, after that selection, EnsureNetworkFee raises the network fee, with no re-check of the chosen sender:
long calFee = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot) + 100000;
if (tx.NetworkFee < calFee) tx.NetworkFee = calFee; // raises NetworkFee above the validated value
At relay, Transaction.VerifyStateDependent requires GAS.BalanceOf(Signers[0]) >= SystemFee + NetworkFee(raised). When the raised fee exceeds what was validated at Wallet.cs:670, the selected sender no longer covers it and the tx is rejected with -511. Affects sendtoaddress, sendfrom, and sendmany (all call EnsureNetworkFee).
Summary
The wallet RPC send methods can build, sign, and relay a transaction whose fee-payer (
Signers[0]) cannot cover the network fee, producingInsufficientFunds(-511) at relay — even thoughWallet.MakeTransactionalready validated that the selected sender could afford the fee. The network fee is raised afterMakeTransaction(i.e. after the signer was selected and the fee validated), with no re-check that the selected sender can still pay. Verified on neo-node v3.9.2 / neo core v3.9.1.Root cause
Wallet.MakeTransactionselects the fee-payer (Signers[0]) from GAS-holding accounts (L600) and only returns a tx the chosen sender can afford:Then, after that selection,
EnsureNetworkFeeraises the network fee, with no re-check of the chosen sender:At relay,
Transaction.VerifyStateDependentrequiresGAS.BalanceOf(Signers[0]) >= SystemFee + NetworkFee(raised). When the raised fee exceeds what was validated atWallet.cs:670, the selected sender no longer covers it and the tx is rejected with-511. Affectssendtoaddress,sendfrom, andsendmany(all callEnsureNetworkFee).