Skip to content

erc4626#1431

Merged
pragmaxim merged 4 commits intomasterfrom
erc4626
Mar 27, 2026
Merged

erc4626#1431
pragmaxim merged 4 commits intomasterfrom
erc4626

Conversation

@pragmaxim
Copy link
Copy Markdown
Contributor

@pragmaxim pragmaxim commented Mar 6, 2026

Solves #1428

Solution

Add optional ERC-4626 enrichment into account token payloads for both REST and WebSocket.

  • New request flag:
    • REST: includeErc4626=true
    • WebSocket: includeErc4626: true
  • Scope: EVM fungible tokens (ERC-20 standard in Blockbook token model)
  • Behavior:
    • If token is detected as ERC-4626 vault, include token.erc4626
    • If token is not an ERC-4626 vault, omit token.erc4626
    • If token is a vault but some calls fail, return partial erc4626 fields plus erc4626.error
    • Derived conversion fields are returned only when decimals resolve from decimals() or trusted contract metadata fallback; otherwise the affected fields are omitted and only error is returned
  • Backward compatibility: unchanged by default (includeErc4626 is opt-in)

Request / Response examples

REST request (/api/v2/address/{address})

GET /api/v2/address/0x167478921b907422f8e88b43c4af2b8bea278d3a?details=tokenBalances&tokens=nonzero&includeErc4626=true HTTP/1.1
Host: blockbook.example

WebSocket request (getAccountInfo)

{
  "id": "1",
  "method": "getAccountInfo",
  "params": {
    "descriptor": "0x167478921b907422f8e88b43c4af2b8bea278d3a",
    "details": "tokenBalances",
    "tokens": "nonzero",
    "includeErc4626": true
  }
}

Response excerpt

{
  "address": "0x167478921b907422f8e88b43c4af2b8bea278d3a",
  "tokens": [
    {
      "type": "ERC20",
      "standard": "ERC20",
      "contract": "0xA0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
      "symbol": "USDC",
      "decimals": 6,
      "balance": "1500000"
    },
    {
      "type": "ERC20",
      "standard": "ERC20",
      "contract": "0x83F20F44975D03b1b09e64809B757c47f942BEeA",
      "symbol": "sDAI",
      "decimals": 18,
      "balance": "1230000000000000000",
      "erc4626": {
        "asset": {
          "contract": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
          "name": "Dai Stablecoin",
          "symbol": "DAI",
          "decimals": 18
        },
        "share": {
          "contract": "0x83F20F44975D03b1b09e64809B757c47f942BEeA",
          "name": "Savings Dai",
          "symbol": "sDAI",
          "decimals": 18
        },
        "totalAssets": "1234567890000000000000000",
        "convertToAssets1Share": "1000000000000000000",
        "convertToShares1Asset": "1000000000000000000",
        "previewDeposit1Asset": "1000000000000000000",
        "previewRedeem1Share": "1000000000000000000"
      }
    },
    {
      "type": "ERC20",
      "standard": "ERC20",
      "contract": "0xSomeVaultWithPartialFailure",
      "balance": "500000000000000000",
      "erc4626": {
        "asset": { "contract": "0xUnderlyingAsset", "decimals": 18 },
        "share": { "contract": "0xSomeVaultWithPartialFailure", "decimals": 18 },
        "totalAssets": "999999999",
        "error": "previewDeposit: execution reverted"
      }
    }
  ]
}

Performance and batching

  • No contract filter is required; includeErc4626=true works on full token lists.
  • Detection is batched:
    • probe every fungible token contract with asset() and totalAssets()
    • calls are sent via JSON-RPC batch in chunks of 100 contracts (200 calls per batch roundtrip)
  • This avoids one network roundtrip per token during vault detection, so wallets with many tokens stay practical.
  • After detection, only confirmed vaults are enriched with additional ERC-4626 calls.

Tests (three layers)

  1. Unit tests (fast)

    • api/erc4626_test.go
    • Covers candidate collection, batched detection, chunking, error paths, ABI/math boundaries.
    • Covers decimals-failure behavior:
      • unresolved decimals omit derived ERC-4626 fields and set error
      • trusted metadata fallback still computes derived fields with correct units
  2. API integration tests (fast, REST + WS)

    • Tests:
      • GetAddressIncludeErc4626EVM
      • WsGetAccountInfoIncludeErc4626EVM
    • Files:
      • tests/api/evm_tests.go
      • tests/api/testdata/ethereum.json
    • Validates REST and WebSocket payload shape with includeErc4626.
  3. RPC integration tests (fast)

    • Test: EthCallErc4626
    • Files:
      • tests/rpc/rpc.go
      • tests/rpc/testdata/ethereum.json
    • Validates backend ERC-4626 eth_call support (asset(), totalAssets() etc.).

Test commands

go test ./api -run 'TestErc4626' -count=1
go test -tags=integration ./tests -run 'TestIntegration/ethereum=main/api/GetAddressIncludeErc4626EVM' -count=1 -v
go test -tags=integration ./tests -run 'TestIntegration/ethereum=main/api/WsGetAccountInfoIncludeErc4626EVM' -count=1 -v
go test -tags=integration ./tests -run 'TestIntegration/ethereum=main/rpc/EthCallErc4626' -count=1 -v

@pragmaxim pragmaxim changed the base branch from end-to-end-api-tests to master March 16, 2026 07:09
@pragmaxim pragmaxim merged commit ce206f3 into master Mar 27, 2026
8 of 9 checks passed
@pragmaxim pragmaxim deleted the erc4626 branch April 23, 2026 06:40
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.

2 participants