> ## Documentation Index
> Fetch the complete documentation index at: https://docs.eco.com/llms.txt
> Use this file to discover all available pages before exploring further.

# contracts: Descriptors, links and registry

> Descriptors, links and registry: 13 exports of the contracts module of @eco-incorp/sauce, including ContractDescriptor, ContractCoverage, ContractKind, DescriptorMethod, ResolvedContract, StateMutability.

The `contracts` namespace describes protocol contracts as descriptors (ABI, methods, per-chain addresses) and exposes them as typed accessors route bodies can call.

```typescript theme={null}
import { contracts } from "@eco-incorp/sauce";
```

This page covers `sdk/dist/descriptors/types.d.ts`, `sdk/dist/descriptors/links.d.ts`, `sdk/dist/descriptors/registry.d.ts`.

<Note>
  Generated from the type declarations shipped in `@eco-incorp/sauce` 0.99.4. Each entry shows the package authors' JSDoc and declaration for this SDK version. For runtime compatibility and deployed addresses, see [architecture and deployments](/programmable-transactions/sauce/architecture-and-deployments).
</Note>

### `contracts.ContractDescriptor`

*Interface* · `sdk/dist/descriptors/types.d.ts`

```typescript theme={null}
export interface ContractDescriptor {
    readonly protocol: string;
    readonly protocolName: string;
    readonly contract: string;
    readonly kind: ContractKind;
    readonly roleKey?: string;
    readonly abiExport?: string;
    readonly abi: Abi;
    readonly methods: readonly DescriptorMethod[];
    readonly perChainAddress: Readonly<Record<number, Address>>;
    readonly chains: readonly ChainSlug[];
    readonly coverage: ContractCoverage;
}
```

### `contracts.ContractCoverage`

*Interface* · `sdk/dist/descriptors/types.d.ts`

```typescript theme={null}
export interface ContractCoverage {
    readonly abiSource: "sdk-registry";
    readonly completeness: "partial" | "unknown";
    readonly typeFidelity: "exact" | "widened";
    readonly methodCount: number;
    readonly caveats: readonly string[];
}
```

### `contracts.ContractKind`

*Type* · `sdk/dist/descriptors/types.d.ts`

What KIND of thing a descriptor represents. Not a boolean: the vendored
registry data genuinely contains three structurally different shapes
sharing one `addresses.ts`/`abis.ts` file pair per protocol.

```typescript theme={null}
export type ContractKind = "singleton" | "address-only" | "interface";
```

### `contracts.DescriptorMethod`

*Interface* · `sdk/dist/descriptors/types.d.ts`

```typescript theme={null}
export interface DescriptorMethod {
    readonly name: string;
    readonly signature: string;
    readonly selector: Hex;
    readonly inputs: readonly AbiParameter[];
    readonly outputs: readonly AbiParameter[];
    readonly stateMutability: StateMutability;
}
```

### `contracts.ResolvedContract`

*Interface* · `sdk/dist/descriptors/types.d.ts`

```typescript theme={null}
export interface ResolvedContract {
    readonly descriptor: ContractDescriptor;
    readonly chain: CanonicalChain;
    readonly address?: Address;
    readonly methods: ReadonlyMap<string, DescriptorMethod>;
}
```

### `contracts.StateMutability`

*Type* · `sdk/dist/descriptors/types.d.ts`

```typescript theme={null}
export type StateMutability = "pure" | "view" | "nonpayable" | "payable";
```

### `contracts.ContractLink`

*Interface* · `sdk/dist/descriptors/links.d.ts`

THE CRUX: role-key \<-> ABI-export \<-> human-contract-name linkage.

`addresses.ts` keys per-chain addresses by a free-form role string
("factory", "swapRouter02", …) and `abis.ts` exports `<Name>ABI` arrays - nothing in the existing registry data connects the two, or names the
resulting contract for a human/accessor tree. That link genuinely isn't
derivable end to end from the data (see the name-normalization measurement
below), so it is hand-authored here, one entry per descriptor, and
cross-checked against the live vendored data by
`test/descriptors-linkage.test.ts` - a role key or ABI export that stops
existing fails that suite immediately rather than silently producing a
stale/hole descriptor.

SCOPE (v1): a STARTER SET of 15 protocols with clean, unambiguous linkage - NOT an attempt to auto-link all \~128 registry protocols. Excluded, with
reasons that are data, not taste:

* curve, lido, compound-v2, benqi, moonwell, venus, silo, layerbank:
  role key \<-> ABI export name mismatches that need a human judgment call
  (`lido.stETH` vs `LidoABI`; `curve.threePool` is a StableSwap INSTANCE,
  not a role naming a single ABI-typed contract).
* every bridge (l1-side / l2-side role pairs are a per-chain-SIDE axis this model
  has no slot for yet).
* maker / alchemix / olympus / tokemak / stargate and similar: role keys
  are majority plain ERC20 token addresses, not protocol contracts.

`contract` is the human display name. When omitted it is DERIVED (never
invented) by `deriveContractName` in derive.ts: `abiExport` minus its
trailing "ABI" minus the protocol-name prefix. Only entries that would
otherwise collide, or that have no `abiExport` to derive from, carry an
explicit override - see the comments below.

```typescript theme={null}
export interface ContractLink {
    readonly protocol: string;
    readonly roleKey?: string;
    readonly abiExport?: string;
    readonly contract?: string;
    readonly kind: ContractKind;
    readonly typeFidelity?: "widened";
    readonly caveats?: readonly string[];
}
```

### `contracts.ContractLinkEntry`

*Type* · `sdk/dist/descriptors/links.d.ts`

```typescript theme={null}
export type ContractLinkEntry = (typeof CONTRACT_LINKS)[number];
```

### `contracts.CONTRACT_LINKS`

*Variable* · `sdk/dist/descriptors/links.d.ts`

```typescript theme={null}
CONTRACT_LINKS: readonly [
    {
        readonly protocol: "uniswap-v2";
        readonly roleKey: "factory";
        readonly abiExport: "UniswapV2FactoryABI";
        readonly contract: "Factory";
        readonly kind: "singleton";
    },
    {
        readonly protocol: "uniswap-v2";
        readonly roleKey: "router";
        readonly abiExport: "UniswapV2RouterABI";
        readonly contract: "Router";
        readonly kind: "singleton";
    },
    {
        readonly protocol: "uniswap-v3";
        readonly roleKey: "factory";
        readonly abiExport: "UniswapV3FactoryABI";
        readonly contract: "Factory";
        readonly kind: "singleton";
        readonly typeFidelity: "widened";
        readonly caveats: readonly [
            "fee is vendored as uint32; the deployed factory uses uint24, so computed selectors do not match the real contract"
        ];
    },
    {
        readonly protocol: "uniswap-v3";
        readonly roleKey: "swapRouter";
        readonly abiExport: "UniswapV3SwapRouterABI";
        readonly contract: "SwapRouter";
        readonly kind: "singleton";
        readonly typeFidelity: "widened";
        readonly caveats: readonly [
            "fee is vendored as uint32; the deployed SwapRouter uses uint24, so computed selectors do not match the real contract"
        ];
    },
    {
        readonly protocol: "uniswap-v3";
        readonly roleKey: "swapRouter02";
        readonly abiExport: "UniswapV3SwapRouterABI";
        readonly contract: "SwapRouter02";
        readonly kind: "singleton";
        readonly typeFidelity: "widened";
        readonly caveats: readonly [
            "fee is vendored as uint32; the deployed SwapRouter02 uses uint24",
            "this ABI is UniswapV3SwapRouterABI's exactInputSingle shape, which still carries a deadline field the deployed SwapRouter02 dropped — selectors do not match the real contract for this reason too"
        ];
    },
    {
        readonly protocol: "uniswap-v3";
        readonly roleKey: "quoterV2";
        readonly abiExport: "UniswapV3QuoterV2ABI";
        readonly contract: "QuoterV2";
        readonly kind: "singleton";
        readonly typeFidelity: "widened";
        readonly caveats: readonly [
            "fee is vendored as uint32; the deployed QuoterV2 uses uint24, so computed selectors do not match the real contract"
        ];
    },
    {
        readonly protocol: "uniswap-v3";
        readonly roleKey: "nonfungiblePositionManager";
        readonly abiExport: "UniswapV3NonfungiblePositionManagerABI";
        readonly contract: "NonfungiblePositionManager";
        readonly kind: "singleton";
    },
    {
        readonly protocol: "uniswap-v4";
        readonly roleKey: "poolManager";
        readonly abiExport: "UniswapV4PoolManagerABI";
        readonly contract: "PoolManager";
        readonly kind: "singleton";
        readonly typeFidelity: "widened";
        readonly caveats: readonly [
            "fee/tickSpacing/tick are vendored as uint32; the deployed PoolManager uses uint24/int24, so computed selectors do not match the real contract"
        ];
    },
    {
        readonly protocol: "uniswap-v4";
        readonly roleKey: "universalRouter";
        readonly abiExport: "UniswapV4UniversalRouterABI";
        readonly contract: "UniversalRouter";
        readonly kind: "singleton";
        readonly caveats: readonly [
            "vendored ABI covers execute(bytes,bytes[],uint256) only; the Universal Router's swap surface is expressed through the commands/inputs byte encoding, not modelled as separate methods here"
        ];
    },
    {
        readonly protocol: "uniswap-v4";
        readonly roleKey: "positionManager";
        readonly abiExport: "UniswapV4PositionManagerABI";
        readonly contract: "PositionManager";
        readonly kind: "singleton";
    },
    {
        readonly protocol: "sushiswap-v2";
        readonly roleKey: "factory";
        readonly abiExport: "SushiSwapV2FactoryABI";
        readonly contract: "Factory";
        readonly kind: "singleton";
    },
    {
        readonly protocol: "sushiswap-v2";
        readonly roleKey: "router";
        readonly abiExport: "SushiSwapV2RouterABI";
        readonly contract: "Router";
        readonly kind: "singleton";
    },
    {
        readonly protocol: "pancakeswap-v2";
        readonly roleKey: "factory";
        readonly abiExport: "PancakeSwapV2FactoryABI";
        readonly contract: "Factory";
        readonly kind: "singleton";
    },
    {
        readonly protocol: "pancakeswap-v2";
        readonly roleKey: "router";
        readonly abiExport: "PancakeSwapV2RouterABI";
        readonly contract: "Router";
        readonly kind: "singleton";
    },
    {
        readonly protocol: "aerodrome";
        readonly roleKey: "router";
        readonly abiExport: "AerodromeRouterABI";
        readonly contract: "Router";
        readonly kind: "singleton";
    },
    {
        readonly protocol: "aerodrome";
        readonly roleKey: "poolFactory";
        readonly abiExport: "AerodromePoolFactoryABI";
        readonly contract: "PoolFactory";
        readonly kind: "singleton";
    },
    {
        readonly protocol: "cctp";
        readonly roleKey: "tokenMessenger";
        readonly abiExport: "TokenMessengerABI";
        readonly contract: "TokenMessenger";
        readonly kind: "singleton";
    },
    {
        readonly protocol: "aave-v3";
        readonly roleKey: "pool";
        readonly abiExport: "PoolABI";
        readonly contract: "Pool";
        readonly kind: "singleton";
    },
    {
        readonly protocol: "aave-v3";
        readonly roleKey: "poolAddressesProvider";
        readonly contract: "PoolAddressesProvider";
        readonly kind: "address-only";
        readonly caveats: readonly [
            "no ABI vendored for this role; address recorded with zero methods"
        ];
    },
    {
        readonly protocol: "aave-v2";
        readonly roleKey: "lendingPool"
/* …truncated… */
```

### `contracts.DESCRIPTORS`

*Variable* · `sdk/dist/descriptors/registry.d.ts`

The whole flat registry, built once at module load. Stable order: as declared in CONTRACT\_LINKS.

```typescript theme={null}
DESCRIPTORS: readonly ContractDescriptor[]
```

### `contracts.byChain`

*Variable* · `sdk/dist/descriptors/registry.d.ts`

REVERSE INDEX: chain slug -> descriptors with an address on that chain (kind:"interface" descriptors are always excluded - see listInterfaces).

```typescript theme={null}
byChain: ReadonlyMap<ChainSlug, readonly ContractDescriptor[]>
```

### `contracts.byProtocol`

*Variable* · `sdk/dist/descriptors/registry.d.ts`

protocol slug (normalized) -> its descriptors, in DESCRIPTORS order.

```typescript theme={null}
byProtocol: ReadonlyMap<string, readonly ContractDescriptor[]>
```

### `contracts.byProtocolAndContract`

*Variable* · `sdk/dist/descriptors/registry.d.ts`

protocol slug (normalized) -> contract name (normalized) -> descriptor.

```typescript theme={null}
byProtocolAndContract: ReadonlyMap<string, ReadonlyMap<string, ContractDescriptor>>
```
