Morpho Vaults V1 Adapter – Absinthe Docs
Skip to content

Morpho Vaults V1 Adapter

Vault positions (MetaMorpho)

What It Tracks

  • Vault share holdings
  • Factory events (optional)

Design Reasoning

Why two trackables?
  1. createMetaMorphoFactory: Tracks when new vaults are created (action, no pricing)
  2. vaults: Tracks user positions in vaults (position, with pricing)
Why track vault shares?

Similar to ERC4626 vaults:

  • Users deposit assets, receive shares
  • Share value appreciates with yield
  • The pricer converts shares → assets → USD

Manifest

export const manifest: Manifest = {
  name: 'morpho-vaultsv1',
  version: '0.0.1',
  chainArch: 'evm',
  trackables: {
    vaults: {
      kind: 'position',
      quantityType: 'token_based',
      params: {
        vaultAddress: evmAddress('The vault contract address'),
      },
      requiredPricer: morphov1vaultsFeed,
    },
    createMetaMorphoFactory: {
      kind: 'action',
      quantityType: 'none',  // Just recording the event
      params: {
        factoryAddress: evmAddress('The factory contract address'),
      },
    },
  },
};

Event Handling

// Track vault share transfers (same pattern as ERC20)
export async function handleVault(log, emitFns, instance, vaultAddress, redis, sqdRpcCtx) {
  const { from, to, value } = moprhov1Vaults.events.Transfer.decode(log);
 
  // Decrease sender's balance (skip mints from zero address)
  if (from !== ZERO_ADDRESS) {
    await emitFns.position.balanceDelta({
      user: from.toLowerCase(),
      asset: { type: 'custom', prefix: 'morpho', key: vaultAddress },
      amount: -BigInt(value),
      activity: 'hold',
      trackableInstance: instance,
    });
  }
 
  // Increase receiver's balance (skip burns to zero address)
  if (to !== ZERO_ADDRESS) {
    await emitFns.position.balanceDelta({
      user: to.toLowerCase(),
      asset: { type: 'custom', prefix: 'morpho', key: vaultAddress },
      amount: BigInt(value),
      activity: 'hold',
      trackableInstance: instance,
    });
  }
 
  // Trigger repricing
  await emitFns.position.reprice({ trackableInstance: instance });
}

Example Config

{
  "adapterConfig": {
    "adapterId": "morpho-vaultsv1",
    "config": {
      "createMetaMorphoFactory": [
        {
          "params": {
            "factoryAddress": "0x1897A8997241C1cD4bD0698647e4EB7213535c24"
          }
        }
      ],
      "vaults": [
        {
          "params": {
            "vaultAddress": "0xdcd35020c5bb97016358578131f012baa9f53cf3"
          },
          "pricing": {
            "kind": "morphov1vaults",
            "underlyingAsset": {
              "kind": "coingecko",
              "id": "usd-coin"
            }
          }
        }
      ]
    }
  }
}

Config Fields

TrackableFieldDescription
createMetaMorphoFactoryparams.factoryAddressThe vault factory contract
vaultsparams.vaultAddressThe specific vault to track
vaultspricing.underlyingAssetHow to price the underlying asset

Key Patterns

  1. Same as ERC20 Transfer tracking: Vault shares are ERC20-like tokens
  2. Skip zero address: Mints and burns involve zero address
  3. Call reprice after changes: Ensures share value is recalculated
  4. Custom asset type: Uses custom:morpho:{vaultAddress} format