Bug: Base App rejects valid Seaport EIP-712 criteria-order signatures with misleading insufficient-funds error
- Dominant language
- TypeScript
- Stars
- 172
- Forks
- 207
- Avg merge
- 49m
- Merged PRs (30d)
- 1
Description
### Describe the bug
Base App on iOS fails to sign valid OpenSea Seaport 1.6 trait-offer typed data using eth_signTypedData_v4. The Base App displays: Error Generating message Please make sure you have enough funds to complete this signature request.
### Steps
Base App on iOS fails to sign valid OpenSea Seaport 1.6 trait-offer typed data using `eth_signTypedData_v4`.
The Base App displays:
> Error Generating message
> Please make sure you have enough funds to complete this signature request.
The provider then rejects with:
```text
Provider.UserRejectedRequestError
code: 4001
message: The user rejected the request.
```
The user did not reject the request.
The same Trait Offer implementation works successfully through:
- Farcaster wallet
- Trust Wallet
- MetaMask/browser wallet
Base App can also sign a nearly identical OpenSea Collection Offer. The significant difference is that the Trait Offer contains a nonzero Seaport `identifierOrCriteria` Merkle root.
### Steps to reproduce
1. Connect a Base Account inside Base App.
2. Ensure the account has sufficient WETH, native ETH, and WETH allowance.
3. Prepare an OpenSea Seaport trait offer whose NFT consideration item is:
```json
{
"itemType": 4,
"token": "0x780446dd12e080ae0db762fcd4daf313f3e359de",
"identifierOrCriteria": "31543439137372029629788762898279123583003892896341457774606321223654009495127",
"startAmount": "1",
"endAmount": "1",
"recipient": ""
}
```
4. Request the signature:
```js
await provider.request({
method: "eth_signTypedData_v4",
params: [account, JSON.stringify(typedData)]
});
```
We also tested passing the typed-data object directly as the second parameter.
### Expected behavior
### Expected result
Base App should display the Seaport order and return a valid EIP-712 signature, as it does for a collection offer where `identifierOrCriteria` is `0`.
If the payload is unsupported, it should return an actionable format or unsupported-operation error.
### Actual result
Base App fails while generating the confirmation UI, displays an insufficient-funds message, and ultimately returns error `4001`, even though the user did not reject the request.
No request is submitted to OpenSea because the failure occurs during signing.
### Latest reproduction: single Trait Offer
Timestamp: `2026-08-16T11:44:37.884Z`
- Trait: Volume Level `10X`
- Offer amount: `0.0001 WETH`
- Total required including fees: `0.000111 WETH`
- Available WETH: `0.00591463 WETH`
- WETH allowance: `0.00111 WETH`
- Native ETH: approximately `0.00630691 ETH`
- Chain ID: `8453`
- Criteria source: OpenSea
- Nonzero criteria root:
`31543439137372029629788762898279123583003892896341457774606321223654009495127`
Signature request:
```json
{
"method": "eth_signTypedData_v4",
"payload": "structured",
"primaryType": "OrderComponents",
"domain": {
"name": "Seaport",
"version": "1.6",
"chainId": 8453,
"verifyingContract": "0x0000000000000068f116a894984e2db1123eb395"
}
}
```
Failure approximately 18.6 seconds later:
```json
{
"name": "Provider.UserRejectedRequestError",
"message": "The user rejected the request.",
"code": 4001
}
```
### Additional reproduction: 10 Trait Offers
All ten orders prepared successfully. Base App also successfully completed the required WETH approval transaction:
```text
0x286d9826593054af17fcc758b5475d5805c69f00254d9137e940f21a0eea760d
```
It then failed on the first Seaport signature with the same `4001` response.
This confirms that Base App could submit and confirm an onchain transaction from the same account immediately before rejecting the offchain typed-data signature.
### Control case
A Collection Offer succeeds using:
- The same Base Account
- The same network
- The same Seaport contract and domain
- The same WETH token and conduit
- The same `eth_signTypedData_v4` method
- The same general `OrderComponents` structure
The principal criteria difference is:
```text
Collection Offer: identifierOrCriteria = 0
Trait Offer: identifierOrCriteria = nonzero uint256 Merkle root
```
The trait criteria orders also sign successfully in Farcaster, Trust Wallet, and MetaMask.
### Formats and alternatives already tested
- Documented serialized `eth_signTypedData_v4` payload
- Structured typed-data payload
- Decimal-string `uint256` values
- Equivalent hexadecimal `uint256` values
- Base `wallet_sign`/EIP-7871 variants, which returned `-32603 Internal error`
- Single-trait and multi-trait offers
- Verified WETH balance, ETH balance, allowance, chain, account, domain and protocol address
### Version
2.5.8
### Additional info
### Request
Could the Base App team investigate whether its signature-rendering or simulation path rejects Seaport `OrderComponents` containing:
- `itemType: 4`
- A nonzero 256-bit `identifierOrCriteria`
- Nested `OfferItem[]` and `ConsiderationItem[]` arrays
Could you also confirm whether Base App intentionally imposes restrictions on Seaport criteria-order signatures, and why a wallet-generation failure is surfaced as `4001 UserRejectedRequest`?
### Desktop
N/A
### Smartphone
- Platform: Base App on iOS
- Base App version: `30.7.78`
- iOS version/device: `26.6`
- Base Account SDK: `@base-org/account@2.5.8`
- Network: Base Mainnet, chain ID `8453`
- Signing method: `eth_signTypedData_v4`
- Seaport version: `1.6`
- Seaport contract: `0x0000000000000068f116a894984e2db1123eb395`
- Application URL: `an internal testing app - sorry can't share publically`
Contributor guide
Research direction
No source files or tests are named. Start at the eth_signTypedData_v4 handling and compare the successful Collection Offer path with the failing Seaport trait-order path, including the nonzero identifierOrCriteria and nested arrays. Done means valid criteria orders produce a confirmation and EIP-712 signature, or an actionable unsupported-operation error instead of 4001.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- ios, typescript
- Domain
- blockchain, mobile
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100