Skip to content

Commit 71f627b

Browse files
jlin27claude
andcommitted
fix: use checksummed native token address; add mainnet e2e verification
- Use EIP-55 checksummed form of the native token sentinel (0xEeee...) so the 0x API passes address validation - Note in README that selling native ETH is unsupported via AllowanceHolder (wrap to WETH first); buying native ETH uses the checksummed sentinel - Improve e2e error output to print full API response body on failure - Add mainnet verification section to README with confirmed Base tx Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 1b7b322 commit 71f627b

3 files changed

Lines changed: 18 additions & 5 deletions

File tree

‎README.md‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ Call `getSupportedChains()` to retrieve the full list at runtime.
135135

136136
The 0x Swap API accepts **any liquid ERC-20 token by contract address**. There is no supported token list — `getSupportedTokens()` throws `NotImplementedError`. Pass token addresses directly to `quoteSwidge` and `swidge`.
137137

138-
For native ETH (or any chain's native token), use `0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee` or the alias `'native'`.
138+
For native ETH (or any chain's native token) as a **buy token**, use `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeeeE` or the alias `'native'`. Selling native ETH is not supported by the AllowanceHolder flow — wrap to WETH first.
139139

140140
---
141141

@@ -206,6 +206,16 @@ ZERO_EX_API_KEY=... MNEMONIC="word word ..." npm run e2e
206206

207207
---
208208

209+
## Verified on mainnet
210+
211+
End-to-end tested against the live 0x API on Base mainnet (chain 8453):
212+
213+
| Swap | Chain | Tx |
214+
|---|---|---|
215+
| 1 USDC → WETH | Base | [`0x87afe3…704ec`](https://basescan.org/tx/0x87afe381a625f1af33f7e4faec1f43fbbcb2dde569c2cf1471f37bb825b704ec) |
216+
217+
---
218+
209219
## Unsupported options
210220

211221
The following fields from `SwidgeCommonOptions` are accepted by the interface but not supported by this module:

‎src/0x-protocol.js‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,18 @@ import { ZeroExFeeLimitExceededError, ZeroExInsufficientLiquidityError, ZeroExRe
4646
* @property {number | bigint} [maxProtocolFeeBps] - Maximum acceptable protocol fee in basis points of the input amount.
4747
*/
4848

49-
// 0x uses this sentinel for native ETH / chain native token
50-
const NATIVE_TOKEN_ADDRESS = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'
49+
// 0x uses this checksummed sentinel for native ETH / chain native token.
50+
// Must use the EIP-55 checksummed form — the 0x API rejects the all-lowercase variant.
51+
const NATIVE_TOKEN_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeeeE'
52+
const NATIVE_TOKEN_ADDRESS_LOWER = NATIVE_TOKEN_ADDRESS.toLowerCase()
5153

5254
// Identifiers callers may pass to mean "native token"
5355
const NATIVE_TOKEN_ALIASES = new Set([
5456
'',
5557
'native',
5658
'eth',
5759
'0x0000000000000000000000000000000000000000',
58-
'0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'
60+
NATIVE_TOKEN_ADDRESS_LOWER
5961
])
6062

6163
/** @type {SwidgeSupportedChain[]} */
@@ -512,7 +514,7 @@ export default class ZeroExProtocol extends SwidgeProtocol {
512514

513515
// Network fee: only comparable when selling the native token
514516
if (maxNetworkFeeBps != null && quote.totalNetworkFee) {
515-
if (sellToken.toLowerCase() === NATIVE_TOKEN_ADDRESS) {
517+
if (sellToken.toLowerCase() === NATIVE_TOKEN_ADDRESS_LOWER) {
516518
const bps = (Number(quote.totalNetworkFee) / sellAmount) * 10000
517519
if (bps > Number(maxNetworkFeeBps)) {
518520
throw new ZeroExFeeLimitExceededError('network', bps, Number(maxNetworkFeeBps))

‎tests/e2e/swap-base.js‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,5 +119,6 @@ async function main () {
119119

120120
main().catch(err => {
121121
console.error('\nE2E failed:', err.message)
122+
if (err.body != null) console.error('API response body:', JSON.stringify(err.body, null, 2))
122123
process.exitCode = 1
123124
})

0 commit comments

Comments
 (0)