Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Get ERC20 Token Address from FewToken
sidebar_position: 3
sidebar_position: 4
---

FewTokens wrap original ERC20 tokens. In UI and analytics workflows, you may need to map back to the underlying token.
Expand Down
17 changes: 17 additions & 0 deletions docs/contracts/v2/fewtoken/get-fewtoken-address-via-fewfactory.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ Ring Swap uses wrapped tokens (FewTokens) in pools and swap paths.

When you quote prices or build routes, use FewToken addresses instead of original ERC20 token addresses.

:::warning FewFactory is the only source of truth
Treat an address as a supported FewToken only when it is returned by the official `FewFactory` for the underlying ERC-20. Token `symbol`, `name`, `token()`, and pool existence do not define FewToken identity. See [FewToken Integration → FewToken Address Resolution](./integrating#fewtoken-address-resolution).
:::

## FewFactory Interface

```solidity
Expand Down Expand Up @@ -59,3 +63,16 @@ Then pass:
```text
path = [fwTokenA, fwUSDC, fwTokenB]
```

## Validating an External Wrapper

If a `(underlying, wrapper)` pair reaches your code from an external source (a pool's `token0`/`token1`, a quote, a router, an API), confirm it is canonical before routing, approving, or wrapping:

```solidity
function isCanonicalFewToken(address underlying, address wrapper) external view returns (bool) {
return wrapper != address(0)
&& IFewFactory(fewFactory).getWrappedToken(underlying) == wrapper;
}
```

Use a wrapper only when this check passes. Approval spender addresses should be selected from official Ring deployments or from the canonical FewToken returned by `FewFactory`.
108 changes: 108 additions & 0 deletions docs/contracts/v2/fewtoken/how-to-judge-is-few-token.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
title: How to Identify a FewToken
sidebar_position: 3
---

A supported FewToken is the wrapper address returned by the official `FewFactory` for an underlying ERC-20.

The canonical check is:

```text
FewFactory.getWrappedToken(underlying) == candidateFewToken
```

Token metadata is not an identity source. `symbol` and `name` are not important for determining whether an address is a supported FewToken. A `token()` method or pool can be useful for discovery, but the supported FewToken check must still resolve through `FewFactory`.

## Interfaces

```solidity
interface IFewFactory {
function getWrappedToken(address originalToken) external view returns (address wrappedToken);
}

interface IFewWrappedToken {
function token() external view returns (address originalToken);
}
```

## If You Start from an Original ERC20

Resolve the FewToken directly from the official `FewFactory`:

```solidity
address fewToken = IFewFactory(fewFactory).getWrappedToken(originalToken);
require(fewToken != address(0), "FewToken not found");
```

Use the returned `fewToken` for Ring Swap pairs and paths.

## If You Start from a Candidate FewToken

When a FewToken address comes from an external source, first read its underlying token, then confirm that `FewFactory` maps that underlying token back to the same candidate:

```solidity
function isSupportedFewToken(address candidateFewToken) external view returns (bool) {
// This call reverts if the candidate does not implement the FewToken interface.
address originalToken = IFewWrappedToken(candidateFewToken).token();
address expectedFewToken = IFewFactory(fewFactory).getWrappedToken(originalToken);

return expectedFewToken != address(0) && expectedFewToken == candidateFewToken;
}
```

For integrations that need a reverting check:

```solidity
function _assertSupportedFewToken(address candidateFewToken) internal view returns (address originalToken) {
originalToken = IFewWrappedToken(candidateFewToken).token();

address expectedFewToken = IFewFactory(fewFactory).getWrappedToken(originalToken);
require(expectedFewToken != address(0), "FewToken not found");
require(expectedFewToken == candidateFewToken, "unsupported FewToken");
}
```

## JavaScript Example

```typescript
import { ethers } from 'ethers'

const fewFactoryAbi = ['function getWrappedToken(address originalToken) view returns (address)']
const fewTokenAbi = ['function token() view returns (address)']

async function isSupportedFewToken({
provider,
fewFactoryAddress,
candidateFewToken,
}: {
provider: ethers.providers.Provider
fewFactoryAddress: string
candidateFewToken: string
}): Promise<boolean> {
const fewToken = new ethers.Contract(candidateFewToken, fewTokenAbi, provider)
let originalToken: string

try {
originalToken = await fewToken.token()
} catch {
return false
}

const fewFactory = new ethers.Contract(fewFactoryAddress, fewFactoryAbi, provider)
const expectedFewToken = await fewFactory.getWrappedToken(originalToken)

return (
expectedFewToken !== ethers.constants.AddressZero &&
ethers.utils.getAddress(expectedFewToken) === ethers.utils.getAddress(candidateFewToken)
)
}
```

## Approval Spender Selection

After identifying the FewToken, choose the approval spender from the integration path:

- Official router flow: approve the official Ring Router, Universal Router, or Permit2 address for the chain.
- Manual wrap flow: approve the supported FewToken returned by `FewFactory`.

Display metadata and external route metadata should not be used as the approval spender source.
50 changes: 50 additions & 0 deletions docs/contracts/v2/fewtoken/integrating.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,56 @@ When integrating:
- construct swap paths with FewToken addresses
- resolve wrapped token addresses via FewFactory

## FewToken Address Resolution

:::info FewFactory is the source of truth
Supported FewToken identity must come from the official `FewFactory`.

For Ring integrations, a FewToken is supported only when `FewFactory.getWrappedToken(underlying)` returns that wrapper address. Token `name`, `symbol`, a `token()` method, or the existence of a pool do not define whether an address is a supported FewToken.
:::

### Integration rule

For each chain, read the official `FewFactory` address from the [Deployments](../deployments) page.

When your code starts from an original ERC-20, resolve the FewToken yourself:

```solidity
address wrapper = IFewFactory(fewFactory).getWrappedToken(underlying);
require(wrapper != address(0), "no FewToken for token");
```

When your code receives a wrapper from an external source, validate it before using it in routing, wrapping, or approval logic:

```solidity
function _assertCanonicalFewToken(address underlying, address wrapper) internal view {
address expected = IFewFactory(fewFactory).getWrappedToken(underlying);
require(expected != address(0), "no FewToken for token");
require(expected == wrapper, "non-canonical FewToken");
}
```

Supported FewToken addresses are resolved through `FewFactory`. The following fields are display or discovery data only:

- `symbol()` / `name()`
- a `token()` method
- a `fw` or `Few Wrapped` prefix
- whether a RingSwap-style pool exists
- whether a quote or route looks profitable

### Approval spender selection

ERC-20 approvals grant transfer permission to the spender. Select the spender from the integration path you are using, not from arbitrary route or pool metadata.

Supported patterns:

- If you use the official Ring Router or Universal Router, approve only the official router or Permit2 address for the chain.
- If you manually wrap, approve only the canonical FewToken returned by `FewFactory.getWrappedToken(underlying)`.
- Prefer exact-amount approvals and clear temporary allowances after use when your flow supports it.
- Use a wrapper address from a pool, quote, route, token list, or subgraph only after the `FewFactory` check above.

If you use the official Ring SDK helpers and official deployment addresses, your integration should derive the expected FewToken addresses from Ring configuration. External FewToken-looking addresses should be treated as unsupported unless they pass the `FewFactory` check.

## Important note

Ring Swap (v2) is a native Ring product line. The `v2` label describes the compatible AMM design; it is not
Expand Down
4 changes: 4 additions & 0 deletions docs/sdk/v2/guides/01-quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ console.log(`The chainId of mainnet is ${ChainId.MAINNET}.`)
console.log(`The few token address is ${fewDAI.address}.`)
```

:::warning Use FewFactory-derived addresses
`fw` symbols and `Few Wrapped` names are display metadata. For routing and approvals, derive the FewToken from the original ERC-20 with the SDK, or validate that `FewFactory.getWrappedToken(underlying)` returns the candidate FewToken address.
:::

## CommonJS (require)

```typescript
Expand Down
9 changes: 9 additions & 0 deletions docs/sdk/v2/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,12 @@ as a separate Ring product generation.
recognizing `FewToken` addresses.

Use `@ring-protocol/uniswap-v2-sdk` only when you explicitly want the lower-level v2-compatible primitives rather than the higher-level Ring integration layer.

## FewToken Address Resolution

For Ring Swap integrations, derive FewToken addresses from the original ERC-20 with the official SDK or resolve them from the official `FewFactory`. A FewToken address is supported when `FewFactory.getWrappedToken(underlying)` returns that address; `symbol` and `name` are display metadata.

Approval spender selection depends on the integration path:

- Official router flow: approve only the official Ring Router, Universal Router, or Permit2 address for the chain.
- Manual wrap flow: approve only the canonical FewToken returned by `FewFactory`.
4 changes: 3 additions & 1 deletion docs/sdk/v2/reference/05-other-exports.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,6 @@ Returns a `Token` instance representing the wrapped `FewToken` for an original t
import { isFewToken } from '@ring-protocol/v2-sdk'
```

Returns `true` when the provided token instance already represents a `FewToken`.
Returns `true` when the provided token instance appears to represent a `FewToken` by SDK metadata conventions.

Use this helper only for SDK compatibility or display logic. It does not prove that a token was returned by the official `FewFactory`. For production routing and approvals, derive FewToken addresses from the original ERC-20 or validate an external wrapper with `FewFactory.getWrappedToken(underlying)`.
Loading