Skip to content

Commit

Permalink
Morpho Vault integration (p3) (#68)
Browse files Browse the repository at this point in the history
- Morpho Vault integration (earn/withdraw flow)
  • Loading branch information
cwang25 authored Sep 13, 2024
1 parent 9e6cf93 commit 528477d
Show file tree
Hide file tree
Showing 14 changed files with 1,984 additions and 75 deletions.
21 changes: 21 additions & 0 deletions src/builder/Accounts.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ library Accounts {
AssetPositions[] assetPositionsList;
CometPositions[] cometPositions;
MorphoPositions[] morphoPositions;
MorphoVaultPositions[] morphoVaultPositions;
}

// We map this to the Portfolio data structure that the client will already have.
Expand Down Expand Up @@ -77,6 +78,13 @@ library Accounts {
uint256[] balances;
}

struct MorphoVaultPositions {
address asset;
address[] accounts;
uint256[] balances;
address vault;
}

function findChainAccounts(uint256 chainId, ChainAccounts[] memory chainAccountsList)
internal
pure
Expand Down Expand Up @@ -119,6 +127,19 @@ library Accounts {
}
}

function findMorphoVaultPositions(uint256 chainId, address asset, ChainAccounts[] memory chainAccountsList)
internal
pure
returns (MorphoVaultPositions memory found)
{
ChainAccounts memory chainAccounts = findChainAccounts(chainId, chainAccountsList);
for (uint256 i = 0; i < chainAccounts.morphoVaultPositions.length; ++i) {
if (chainAccounts.morphoVaultPositions[i].asset == asset) {
return found = chainAccounts.morphoVaultPositions[i];
}
}
}

function findAssetPositions(string memory assetSymbol, AssetPositions[] memory assetPositionsList)
internal
pure
Expand Down
154 changes: 154 additions & 0 deletions src/builder/Actions.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@ library Actions {
string constant ACTION_TYPE_REPAY = "REPAY";
string constant ACTION_TYPE_MORPHO_REPAY = "MORPHO_REPAY";
string constant ACTION_TYPE_SUPPLY = "SUPPLY";
string constant ACTION_TYPE_MORPHO_VAULT_SUPPLY = "MORPHO_VAULT_SUPPLY";
string constant ACTION_TYPE_SWAP = "SWAP";
string constant ACTION_TYPE_TRANSFER = "TRANSFER";
string constant ACTION_TYPE_WITHDRAW = "WITHDRAW";
string constant ACTION_TYPE_MORPHO_VAULT_WITHDRAW = "MORPHO_VAULT_WITHDRAW";
string constant ACTION_TYPE_WITHDRAW_AND_BORROW = "WITHDRAW_AND_BORROW";
string constant ACTION_TYPE_WRAP = "WRAP";
string constant ACTION_TYPE_UNWRAP = "UNWRAP";
Expand Down Expand Up @@ -199,6 +201,24 @@ library Actions {
address repayer;
}

struct MorphoVaultSupply {
Accounts.ChainAccounts[] chainAccountsList;
string assetSymbol;
uint256 amount;
uint256 blockTimestamp;
uint256 chainId;
address sender;
}

struct MorphoVaultWithdraw {
Accounts.ChainAccounts[] chainAccountsList;
string assetSymbol;
uint256 amount;
uint256 blockTimestamp;
uint256 chainId;
address withdrawer;
}

// Note: Mainly to avoid stack too deep errors
struct BridgeOperationInfo {
string assetSymbol;
Expand Down Expand Up @@ -285,6 +305,15 @@ library Actions {
address token;
}

struct MorphoVaultSupplyActionContext {
uint256 amount;
string assetSymbol;
uint256 chainId;
address morphoVault;
uint256 price;
address token;
}

struct SwapActionContext {
uint256 chainId;
uint256 feeAmount;
Expand Down Expand Up @@ -335,6 +364,15 @@ library Actions {
address token;
}

struct MorphoVaultWithdrawActionContext {
uint256 amount;
string assetSymbol;
uint256 chainId;
address morphoVault;
uint256 price;
address token;
}

struct WithdrawAndBorrowActionContext {
uint256 borrowAmount;
uint256 chainId;
Expand Down Expand Up @@ -1055,6 +1093,122 @@ library Actions {
return (quarkOperation, action);
}

function morphoVaultSupply(
MorphoVaultSupply memory vaultSupply,
PaymentInfo.Payment memory payment,
bool useQuotecall
) internal pure returns (IQuarkWallet.QuarkOperation memory, Action memory) {
bytes[] memory scriptSources = new bytes[](1);
scriptSources[0] = type(MorphoVaultActions).creationCode;

Accounts.ChainAccounts memory accounts =
Accounts.findChainAccounts(vaultSupply.chainId, vaultSupply.chainAccountsList);

Accounts.AssetPositions memory assetPositions =
Accounts.findAssetPositions(vaultSupply.assetSymbol, accounts.assetPositionsList);

Accounts.QuarkState memory accountState = Accounts.findQuarkState(vaultSupply.sender, accounts.quarkStates);

bytes memory scriptCalldata = abi.encodeWithSelector(
MorphoVaultActions.deposit.selector,
MorphoInfo.getMorphoVaultAddress(vaultSupply.chainId, vaultSupply.assetSymbol),
assetPositions.asset,
vaultSupply.amount
);

// Construct QuarkOperation
IQuarkWallet.QuarkOperation memory quarkOperation = IQuarkWallet.QuarkOperation({
nonce: accountState.quarkNextNonce,
scriptAddress: CodeJarHelper.getCodeAddress(type(MorphoVaultActions).creationCode),
scriptCalldata: scriptCalldata,
scriptSources: scriptSources,
expiry: vaultSupply.blockTimestamp + STANDARD_EXPIRY_BUFFER
});

// Construct Action
MorphoVaultSupplyActionContext memory vaultSupplyActionContext = MorphoVaultSupplyActionContext({
amount: vaultSupply.amount,
assetSymbol: assetPositions.symbol,
chainId: vaultSupply.chainId,
morphoVault: MorphoInfo.getMorphoVaultAddress(vaultSupply.chainId, vaultSupply.assetSymbol),
price: assetPositions.usdPrice,
token: assetPositions.asset
});

Action memory action = Actions.Action({
chainId: vaultSupply.chainId,
quarkAccount: vaultSupply.sender,
actionType: ACTION_TYPE_MORPHO_VAULT_SUPPLY,
actionContext: abi.encode(vaultSupplyActionContext),
paymentMethod: PaymentInfo.paymentMethodForPayment(payment, useQuotecall),
// Null address for OFFCHAIN payment.
paymentToken: payment.isToken ? PaymentInfo.knownToken(payment.currency, vaultSupply.chainId).token : address(0),
paymentTokenSymbol: payment.currency,
paymentMaxCost: payment.isToken ? PaymentInfo.findMaxCost(payment, vaultSupply.chainId) : 0
});

return (quarkOperation, action);
}

function morphoVaultWithdraw(MorphoVaultWithdraw memory vaultWithdraw, PaymentInfo.Payment memory payment)
internal
pure
returns (IQuarkWallet.QuarkOperation memory, Action memory)
{
bytes[] memory scriptSources = new bytes[](1);
scriptSources[0] = type(MorphoVaultActions).creationCode;

Accounts.ChainAccounts memory accounts =
Accounts.findChainAccounts(vaultWithdraw.chainId, vaultWithdraw.chainAccountsList);

Accounts.AssetPositions memory assetPositions =
Accounts.findAssetPositions(vaultWithdraw.assetSymbol, accounts.assetPositionsList);

Accounts.QuarkState memory accountState =
Accounts.findQuarkState(vaultWithdraw.withdrawer, accounts.quarkStates);

bytes memory scriptCalldata = abi.encodeWithSelector(
MorphoVaultActions.withdraw.selector,
MorphoInfo.getMorphoVaultAddress(vaultWithdraw.chainId, vaultWithdraw.assetSymbol),
vaultWithdraw.amount
);

// Construct QuarkOperation
IQuarkWallet.QuarkOperation memory quarkOperation = IQuarkWallet.QuarkOperation({
nonce: accountState.quarkNextNonce,
scriptAddress: CodeJarHelper.getCodeAddress(type(MorphoVaultActions).creationCode),
scriptCalldata: scriptCalldata,
scriptSources: scriptSources,
expiry: vaultWithdraw.blockTimestamp + STANDARD_EXPIRY_BUFFER
});

// Construct Action
MorphoVaultWithdrawActionContext memory vaultWithdrawActionContext = MorphoVaultWithdrawActionContext({
amount: vaultWithdraw.amount,
assetSymbol: assetPositions.symbol,
chainId: vaultWithdraw.chainId,
morphoVault: MorphoInfo.getMorphoVaultAddress(vaultWithdraw.chainId, vaultWithdraw.assetSymbol),
price: assetPositions.usdPrice,
token: assetPositions.asset
});

Action memory action = Actions.Action({
chainId: vaultWithdraw.chainId,
quarkAccount: vaultWithdraw.withdrawer,
actionType: ACTION_TYPE_MORPHO_VAULT_WITHDRAW,
actionContext: abi.encode(vaultWithdrawActionContext),
paymentMethod: PaymentInfo.paymentMethodForPayment(payment, false),
// Null address for OFFCHAIN payment.
paymentToken: payment.isToken
? PaymentInfo.knownToken(payment.currency, vaultWithdraw.chainId).token
: address(0),
paymentTokenSymbol: payment.currency,
paymentMaxCost: payment.isToken ? PaymentInfo.findMaxCost(payment, vaultWithdraw.chainId) : 0
});

return (quarkOperation, action);
}

function wrapOrUnwrapAsset(
WrapOrUnwrapAsset memory wrapOrUnwrap,
PaymentInfo.Payment memory payment,
Expand Down
Loading

0 comments on commit 528477d

Please sign in to comment.