The Morpho Ability enables Vincent Apps to interact with Morpho lending vaults on behalf of Vincent Users. This allows Vincent Apps to provide yield-generating DeFi functionality through Morpho's lending markets, including depositing assets to earn yield, withdrawing funds, and managing vault positions.
The Morpho Ability is built using the Vincent Ability SDK and operates in two phases:
Precheck Phase: Validates all prerequisites for the Morpho operation
convertToShares
Execution Phase: Executes the Morpho vault operation
Depending on your role in the Vincent Ecosystem, you'll be interacting with this Ability in different ways. Click on the link below that matches your role to see how to get started:
If you want to enable your App Delegatees to perform Morpho vault operations on behalf of your Vincent App Users, you can add this Ability to your App.
Adding Abilities to your Vincent App is done using the Vincent App Dashboard. Visit the Create Vincent App guide to learn more about how to add Abilities to your App during creation, or check out the Upgrading Your App guide to learn how to add Abilities to an existing App.
Note
To learn more about executing Vincent Abilities, see the Executing Abilities guide.
Before executing Morpho vault operations, the following conditions must be met. You can use the Ability's precheck
function to check if these conditions are met, or you can check them manually.
The Vincent App User's Vincent Wallet must have enough native tokens (ETH, MATIC, etc.) to cover the transaction gas fees for the Morpho operation.
For deposit operations, the Vincent App User's Vincent Wallet must have approved the Morpho vault contract to spend the underlying tokens.
If your Vincent App has enabled the ERC20 Approval Ability, you can use it to handle submitting the approval transaction using the App User's Vincent Wallet.
Each Morpho operation has specific validation requirements that are checked during the precheck
phase:
Deposit Operation:
Withdraw Operation:
Redeem Operation:
precheck
FunctionThis Ability's precheck
function validates all prerequisites for executing a Morpho vault operation and provides detailed account information.
Before executing the precheck
function, you'll need to provide the following parameters for the Morpho operation:
{
/**
* The Morpho operation to perform (deposit, withdraw, redeem)
*/
operation: 'deposit' | 'withdraw' | 'redeem';
/**
* The Morpho vault contract address
*/
vaultAddress: string;
/**
* The amount to operate with, as a decimal string
* For deposit/withdraw: amount of underlying asset (e.g., "100.5" for 100.5 USDC)
* For redeem: amount of vault shares
*/
amount: string;
/**
* The blockchain network to perform the operation on
*/
chain: string;
/**
* Custom RPC URL (optional, for precheck only)
*/
rpcUrl?: string;
/**
* Enable Alchemy gas sponsorship (optional)
*/
alchemyGasSponsor?: boolean;
/**
* Alchemy API key (required if gas sponsorship enabled)
*/
alchemyGasSponsorApiKey?: string;
/**
* Alchemy policy ID (required if gas sponsorship enabled)
*/
alchemyGasSponsorPolicyId?: string;
}
To execute precheck
, you'll need to:
VincentAbilityClient
using the getVincentAbilityClient
function (imported from @lit-protocol/vincent-app-sdk/abilityClient
)
bundledVincentAbility
object (imported from @lit-protocol/vincent-ability-morpho
)ethersSigner
you'll be using to sign the request to Lit with your Delegatee private keyprecheck
functionVincentAbilityClient
instance to call the precheck
functionimport { getVincentAbilityClient } from '@lit-protocol/vincent-app-sdk/abilityClient';
import { bundledVincentAbility } from '@lit-protocol/vincent-ability-morpho';
// Create ability client
const abilityClient = getVincentAbilityClient({
bundledVincentAbility: bundledVincentAbility,
ethersSigner: yourEthersSigner,
});
// Example: Deposit 100 USDC into a Morpho vault on Base
const morphoParams = {
operation: 'deposit' as const,
vaultAddress: '0x...', // Morpho USDC vault address on Base
amount: '100.0', // 100 USDC
chain: 'base',
rpcUrl: 'https://mainnet.base.org', // Optional for precheck
};
const precheckResult = await abilityClient.precheck(morphoParams, {
delegatorPkpEthAddress: '0x...', // The Vincent App User's Vincent Wallet address
});
if (precheckResult.success) {
const result = precheckResult.result;
console.log('Operation valid:', result.operationValid);
console.log('User balance:', result.userBalance);
console.log('Current allowance:', result.allowance);
console.log('Vault shares:', result.vaultShares);
console.log('Estimated gas:', result.estimatedGas);
} else {
// Handle different types of failures
if (precheckResult.runtimeError) {
console.error('Runtime error:', precheckResult.runtimeError);
}
if (precheckResult.schemaValidationError) {
console.error('Schema validation error:', precheckResult.schemaValidationError);
}
if (precheckResult.result) {
console.error('Morpho precheck failed:', precheckResult.result.error);
}
}
A successful precheck
response will contain detailed validation information:
{
/**
* Whether the requested operation is valid
*/
operationValid: boolean;
/**
* Whether the specified vault address is valid
*/
vaultValid: boolean;
/**
* Whether the specified amount is valid
*/
amountValid: boolean;
/**
* The user's current balance of the vault's underlying asset (for deposits)
*/
userBalance?: string;
/**
* The current allowance approved for the vault contract (for deposits)
*/
allowance?: string;
/**
* The user's current vault share balance (for withdrawals/redeems)
*/
vaultShares?: string;
/**
* Estimated gas cost for the operation
*/
estimatedGas?: number;
}
A failure precheck
response will contain:
{
/**
* A string containing the error message if the precheck failed
*/
error: string;
}
execute
FunctionThis Ability's execute
function performs the actual Morpho vault operation.
The execute
function expects the same parameters as the precheck
function (except rpcUrl
which is not allowed), and can be executed using the same VincentAbilityClient
instance:
// Remove rpcUrl for execute - chain parameter is used instead
const executeParams = {
operation: 'deposit' as const,
vaultAddress: '0x...', // Morpho USDC vault address on Base
amount: '100.0', // 100 USDC
chain: 'base',
// Optional: Enable gas sponsorship
alchemyGasSponsor: true,
alchemyGasSponsorApiKey: 'YOUR_API_KEY',
alchemyGasSponsorPolicyId: 'YOUR_POLICY_ID',
};
const executeResult = await abilityClient.execute(executeParams, {
delegatorPkpEthAddress: '0x...', // The Vincent App User's Vincent Wallet address
});
if (executeResult.success) {
const result = executeResult.result;
console.log('Transaction hash:', result.txHash);
console.log('Operation:', result.operation);
console.log('Vault address:', result.vaultAddress);
console.log('Amount:', result.amount);
console.log('Timestamp:', result.timestamp);
} else {
// Handle different types of failures
if (executeResult.runtimeError) {
console.error('Runtime error:', executeResult.runtimeError);
}
if (executeResult.schemaValidationError) {
console.error('Schema validation error:', executeResult.schemaValidationError);
}
if (executeResult.result) {
console.error('Morpho execution failed:', executeResult.result.error);
}
}
A successful execute
response will contain:
{
/**
* The transaction hash of the executed operation
*/
txHash: string;
/**
* The type of Morpho operation that was executed
*/
operation: 'deposit' | 'withdraw' | 'redeem';
/**
* The vault address involved in the operation
*/
vaultAddress: string;
/**
* The amount of tokens/shares involved in the operation
*/
amount: string;
/**
* The Unix timestamp when the operation was executed
*/
timestamp: number;
}
A failure execute
response will contain:
{
/**
* A string containing the error message if the execution failed
*/
error: string;
}
The Morpho Ability supports operations on the following networks where Morpho vaults are deployed:
ethereum
(chainId: 1
)base
(chainId: 8453
)arbitrum
(chainId: 42161
)optimism
(chainId: 10
)polygon
(chainId: 137
)sepolia
(chainId: 11155111
)The amount
parameter should be specified in human-readable format (e.g., "100.5" for 100.5 tokens), not in wei or smallest units.
deposit
and withdraw
: Amount represents underlying assets (e.g., USDC)redeem
: Amount represents vault sharesWhen using Alchemy gas sponsorship:
precheck
: You can provide either chain
or rpcUrl
execute
: Only chain
is allowed, rpcUrl
will cause an errorCommon failure scenarios include: