Skip to content

Conversation

@ryanRfox
Copy link

Summary

This PR fixes a critical bug where ERC-20 token transfers fail with ERC20: transfer from the zero address during gas estimation. The fix adds proper sender address handling to the estimateGas() method.

Fixes #9

Changes

  • Added optional from?: Address parameter to estimateGas() method
  • Modified prepareTx() to pass the signer's address to estimateGas() when available
  • Added JSDoc documentation explaining when from is required
  • Added comprehensive tests for the fix

Problem

When calling eth_estimateGas without a from address, Ethereum nodes default to address(0). This causes any contract that validates msg.sender to fail during gas estimation.

Before (Broken)

async estimateGas(tx: Transaction): Promise<bigint> {
  const estimate = await this.ethClient.estimateGas({
    to: tx.to?.ethAddress(),
    data: tx.data ? eth.hexlify(tx.data) : undefined,
    value: tx.value,
    // Missing: from address
  });
}

After (Fixed)

async estimateGas(tx: Transaction, from?: Address): Promise<bigint> {
  const estimate = await this.ethClient.estimateGas({
    from: from?.ethAddress(),  // Now includes sender address
    to: tx.to?.ethAddress(),
    data: tx.data ? eth.hexlify(tx.data) : undefined,
    value: tx.value,
  });
}

How Other SDKs Handle This

SDK Implementation
ethers.js v6 Automatically populates from when transaction is connected to a Signer
viem Requires explicit account parameter for estimateGas

Our fix aligns with ethers.js behavior - automatically including the sender when available while maintaining backward compatibility.

Testing

New Tests Added (6 tests in test/gas-estimation.test.ts)

  1. ERC-20 token transfer succeeds with the fix
  2. estimateGas with explicit from parameter returns valid estimate
  3. estimateGas with from parameter works for contract calls
  4. Backward compatibility: estimateGas without from works for native transfers
  5. Backward compatibility: estimateGas without from works for contract deployments
  6. Contract.execute correctly estimates gas for ERC-20 transfers

Test Results

✓ test/gas-estimation.test.ts (6 tests) 3313ms
✓ test/integration.test.ts (2 tests) 3037ms

Test Files  2 passed
Tests       8 passed

Manual Verification

Successfully transferred SBC/ISB tokens on Radius testnet after applying the fix.

Breaking Changes

None - This fix is fully backward compatible:

  • estimateGas(tx) continues to work (from defaults to undefined)
  • All existing code paths remain functional
  • New from parameter is optional

Checklist

  • Code follows project style guidelines
  • JSDoc documentation added for new parameter
  • All new tests pass
  • All existing tests pass
  • Manual testing on testnet completed
  • No breaking changes introduced

The estimateGas() method was not including the 'from' address when
calling eth_estimateGas RPC. This caused ERC-20 token transfers to
fail with "ERC20: transfer from the zero address" because Ethereum
nodes default to address(0) when from is not provided.

Changes:
- Add optional 'from' parameter to estimateGas() method
- Pass signer's address from prepareTx() when available
- Add tests for ERC-20 transfers and gas estimation

This fix aligns with how other EVM SDKs handle gas estimation:
- ethers.js v6: automatically includes from when using a Signer
- viem: requires account parameter explicitly for estimateGas

The fix is backward compatible - existing code without 'from' continues
to work for operations that don't depend on msg.sender.
@ryanRfox ryanRfox force-pushed the fix/gas-estimation-from-address branch from c8af555 to 80c74bb Compare December 30, 2025 13:46
@ryanRfox ryanRfox requested a review from sscovil December 30, 2025 13:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: ERC-20 Token Transfers Fail - estimateGas() missing 'from' address

1 participant