Skip to content

Commit

Permalink
Merge pull request #51 from solendprotocol/v2.0.2
Browse files Browse the repository at this point in the history
V2.0.2 instruction / state changes
  • Loading branch information
0xodia authored Jul 12, 2023
2 parents b66c863 + fdc44bd commit fa9f445
Show file tree
Hide file tree
Showing 9 changed files with 257 additions and 18 deletions.
40 changes: 40 additions & 0 deletions solend-sdk/src/instructions/forgiveDebt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { PublicKey, TransactionInstruction } from "@solana/web3.js";
import * as BufferLayout from "buffer-layout";
import * as Layout from "../utils/layout";
import { LendingInstruction } from "./instruction";

export const ForgiveDebtInstruction = (
obligation: PublicKey,
reserve: PublicKey,
lendingMarket: PublicKey,
lendingMarketOwner: PublicKey,
liquidityAmount: number,
lendingProgramId: PublicKey
): TransactionInstruction => {
const dataLayout = BufferLayout.struct([
BufferLayout.u8("instruction"),
Layout.uint64("liquidityAmount"),
]);

const data = Buffer.alloc(dataLayout.span);
dataLayout.encode(
{
instruction: LendingInstruction.SetLendingMarketOwnerAndConfig,
liquidityAmount: liquidityAmount,
},
data
);

const keys = [
{ pubkey: obligation, isSigner: false, isWritable: true },
{ pubkey: reserve, isSigner: false, isWritable: true },
{ pubkey: lendingMarket, isSigner: false, isWritable: false },
{ pubkey: lendingMarketOwner, isSigner: true, isWritable: false },
];

return new TransactionInstruction({
keys,
programId: lendingProgramId,
data,
});
};
44 changes: 41 additions & 3 deletions solend-sdk/src/instructions/initReserve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
} from "@solana/web3.js";
import BN from "bn.js";
import * as Layout from "../utils/layout";
import { ReserveConfig, ReserveConfigLayout } from "../state";
import { ReserveConfig } from "../state";
import { LendingInstruction } from "./instruction";

const BufferLayout = require("buffer-layout");
Expand Down Expand Up @@ -34,15 +34,53 @@ export const initReserveInstruction = (
const dataLayout = BufferLayout.struct([
BufferLayout.u8("instruction"),
Layout.uint64("liquidityAmount"),
ReserveConfigLayout,
BufferLayout.u8("optimalUtilizationRate"),
BufferLayout.u8("maxUtilizationRate"),
BufferLayout.u8("loanToValueRatio"),
BufferLayout.u8("liquidationBonus"),
BufferLayout.u8("liquidationThreshold"),
BufferLayout.u8("minBorrowRate"),
BufferLayout.u8("optimalBorrowRate"),
BufferLayout.u8("maxBorrowRate"),
Layout.uint64("borrowFeeWad"),
Layout.uint64("flashLoanFeeWad"),
BufferLayout.u8("hostFeePercentage"),
Layout.uint64("depositLimit"),
Layout.uint64("borrowLimit"),
Layout.publicKey("feeReceiver"),
BufferLayout.u8("protocolLiquidationFee"),
BufferLayout.u8("protocolTakeRate"),
Layout.uint64("addedBorrowWeightBPS"),
BufferLayout.u8("reserveType"),
BufferLayout.u8("maxLiquidationBonus"),
BufferLayout.u8("maxLiquidationThreshold"),
]);

const data = Buffer.alloc(dataLayout.span);
dataLayout.encode(
{
instruction: LendingInstruction.InitReserve,
liquidityAmount: new BN(liquidityAmount),
config,
optimalUtilizationRate: config.optimalUtilizationRate,
maxUtilizationRate: config.maxUtilizationRate,
loanToValueRatio: config.loanToValueRatio,
liquidationBonus: config.liquidationBonus,
liquidationThreshold: config.liquidationThreshold,
minBorrowRate: config.minBorrowRate,
optimalBorrowRate: config.optimalBorrowRate,
maxBorrowRate: config.maxBorrowRate,
borrowFeeWad: config.fees.borrowFeeWad,
flashLoanFeeWad: config.fees.flashLoanFeeWad,
hostFeePercentage: config.fees.hostFeePercentage,
depositLimit: config.depositLimit,
borrowLimit: config.borrowLimit,
feeReceiver: config.feeReceiver,
protocolLiquidationFee: config.protocolLiquidationFee,
protocolTakeRate: config.protocolTakeRate,
addedBorrowWeightBPS: config.addedBorrowWeightBPS,
reserveType: config.reserveType,
maxLiquidationBonus: config.maxLiquidationBonus,
maxLiquidationThreshold: config.maxLiquidationThreshold,
},
data
);
Expand Down
4 changes: 3 additions & 1 deletion solend-sdk/src/instructions/instruction.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export enum LendingInstruction {
InitLendingMarket = 0,
SetLendingMarketOwner = 1,
SetLendingMarketOwnerAndConfig = 1,
InitReserve = 2,
RefreshReserve = 3,
DepositReserveLiquidity = 4,
Expand All @@ -18,6 +18,8 @@ export enum LendingInstruction {
UpdateReserveConfig = 16,
FlashBorrowReserveLiquidity = 19,
FlashRepayReserveLiquidity = 20,
ForgiveDebt = 21,
UpdateMetadata = 22,
}

/** Instructions defined by the program */
Expand Down
58 changes: 58 additions & 0 deletions solend-sdk/src/instructions/setLendingMarketOwnerAndConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { PublicKey, TransactionInstruction } from "@solana/web3.js";
import * as BufferLayout from "buffer-layout";
import { RateLimiterConfig } from "../state/rateLimiter";
import * as Layout from "../utils/layout";
import { LendingInstruction } from "./instruction";

/// Sets the new owner of a lending market.
///
/// Accounts expected by this instruction:
///
/// 0. `[writable]` Lending market account.
/// 1. `[signer]` Current owner.
export const SetLendingMarketOwnerAndConfigInstruction = (
lendingMarket: PublicKey,
currentMarketOwner: PublicKey,
newMarketOwner: PublicKey,
newRateLimiterConfig: RateLimiterConfig,
whitelistedLiquidator: PublicKey | null,
riskAuthority: PublicKey,
lendingProgramId: PublicKey
): TransactionInstruction => {
if (whitelistedLiquidator != null) {
throw new Error("Whitelisted liquidator not supported yet");
}

const dataLayout = BufferLayout.struct([
BufferLayout.u8("instruction"),
Layout.publicKey("newOwner"),
Layout.uint64("windowDuration"),
Layout.uint64("maxOutflow"),
BufferLayout.u8("whitelistedLiquidator"),
Layout.publicKey("riskAuthority"),
]);

const data = Buffer.alloc(dataLayout.span);
dataLayout.encode(
{
instruction: LendingInstruction.SetLendingMarketOwnerAndConfig,
newOwner: newMarketOwner,
windowDuration: newRateLimiterConfig.windowDuration,
maxOutflow: newRateLimiterConfig.maxOutflow,
whitelistedLiquidator: 0,
riskAuthority: riskAuthority,
},
data
);

const keys = [
{ pubkey: lendingMarket, isSigner: false, isWritable: true },
{ pubkey: currentMarketOwner, isSigner: true, isWritable: false },
];

return new TransactionInstruction({
keys,
programId: lendingProgramId,
data,
});
};
59 changes: 59 additions & 0 deletions solend-sdk/src/instructions/updateMetadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import * as anchor from "@coral-xyz/anchor";
import { PublicKey, SystemProgram, TransactionInstruction } from "@solana/web3.js";
import { findProgramAddressSync } from "@project-serum/anchor/dist/cjs/utils/pubkey";
import { LendingInstruction } from "./instruction";

const BufferLayout = require("buffer-layout");

export const updateMetadataInstruction = (
lendingMarket: PublicKey,
lendingMarketOwner: PublicKey,
lendingProgramId: PublicKey,
marketName: string,
marketDescription: string,
marketImageUrl: string
): TransactionInstruction => {
const dataLayout = BufferLayout.struct([
BufferLayout.u8("instruction"),
BufferLayout.blob(50, "marketName"),
BufferLayout.blob(250, "marketDescription"),
BufferLayout.blob(250, "marketImageUrl"),
BufferLayout.blob(200, "padding"),
BufferLayout.u8("bumpSeed"),
]);

const [lendingMarketMetadata, _] = findProgramAddressSync(
[
lendingMarket.toBytes(),
Buffer.from(anchor.utils.bytes.utf8.encode("MetaData")),
],

lendingProgramId
);

const data = Buffer.alloc(dataLayout.span);
dataLayout.encode(
{
instruction: LendingInstruction.UpdateMetadata,
marketName,
marketDescription,
marketImageUrl,
padding: Buffer.alloc(200),
},
data
);

const keys = [
{ pubkey: lendingMarket, isSigner: false, isWritable: false },
{ pubkey: lendingMarketOwner, isSigner: true, isWritable: false },
{ pubkey: lendingMarketMetadata, isSigner: false, isWritable: true },
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
];


return new TransactionInstruction({
keys,
programId: lendingProgramId,
data,
});
};
16 changes: 16 additions & 0 deletions solend-sdk/src/instructions/updateReserveConfig.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { PublicKey, TransactionInstruction } from "@solana/web3.js";
import { RateLimiterConfig } from "../state/rateLimiter";
import { ReserveConfig } from "../state/reserve";
import * as Layout from "../utils/layout";
import { LendingInstruction } from "./instruction";
Expand All @@ -25,11 +26,13 @@ export const updateReserveConfig = (
pythPrice: PublicKey,
switchboardOracle: PublicKey,
reserveConfig: ReserveConfig,
rateLimiterConfig: RateLimiterConfig,
solendProgramAddress: PublicKey
): TransactionInstruction => {
const dataLayout = BufferLayout.struct([
BufferLayout.u8("instruction"),
BufferLayout.u8("optimalUtilizationRate"),
BufferLayout.u8("maxUtilizationRate"),
BufferLayout.u8("loanToValueRatio"),
BufferLayout.u8("liquidationBonus"),
BufferLayout.u8("liquidationThreshold"),
Expand All @@ -44,13 +47,20 @@ export const updateReserveConfig = (
Layout.publicKey("feeReceiver"),
BufferLayout.u8("protocolLiquidationFee"),
BufferLayout.u8("protocolTakeRate"),
Layout.uint64("addedBorrowWeightBPS"),
BufferLayout.u8("reserveType"),
BufferLayout.u8("maxLiquidationBonus"),
BufferLayout.u8("maxLiquidationThreshold"),
Layout.uint64("windowDuration"),
Layout.uint64("maxOutflow"),
]);

const data = Buffer.alloc(dataLayout.span);
dataLayout.encode(
{
instruction: LendingInstruction.UpdateReserveConfig,
optimalUtilizationRate: reserveConfig.optimalUtilizationRate,
maxUtilizationRate: reserveConfig.maxUtilizationRate,
loanToValueRatio: reserveConfig.loanToValueRatio,
liquidationBonus: reserveConfig.liquidationBonus,
liquidationThreshold: reserveConfig.liquidationThreshold,
Expand All @@ -65,6 +75,12 @@ export const updateReserveConfig = (
feeReceiver: reserveConfig.feeReceiver,
protocolLiquidationFee: reserveConfig.protocolLiquidationFee,
protocolTakeRate: reserveConfig.protocolTakeRate,
addedBorrowWeightBPS: reserveConfig.addedBorrowWeightBPS,
reserveType: reserveConfig.reserveType,
maxLiquidationBonus: reserveConfig.maxLiquidationBonus,
maxLiquidationThreshold: reserveConfig.maxLiquidationThreshold,
windowDuration: rateLimiterConfig.windowDuration,
maxOutflow: rateLimiterConfig.maxOutflow,
},
data
);
Expand Down
12 changes: 6 additions & 6 deletions solend-sdk/src/state/lendingMarket.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import { AccountInfo, PublicKey } from "@solana/web3.js";
import * as fzstd from "fzstd";
import * as Layout from "../utils/layout";
import {
RateLimiter,
RateLimiterLayout,
RATE_LIMITER_LEN,
} from "./rateLimiter";
import { RateLimiter, RateLimiterLayout } from "./rateLimiter";

const BufferLayout = require("buffer-layout");

Expand All @@ -18,6 +14,8 @@ export interface LendingMarket {
oracleProgramId: PublicKey;
switchboardOracleProgramId: PublicKey;
rateLimiter: RateLimiter;
whitelistedLiquidator: PublicKey | null;
riskAuthority: PublicKey;
}

export const LendingMarketLayout: typeof BufferLayout.Structure =
Expand All @@ -30,7 +28,9 @@ export const LendingMarketLayout: typeof BufferLayout.Structure =
Layout.publicKey("oracleProgramId"),
Layout.publicKey("switchboardOracleProgramId"),
RateLimiterLayout,
BufferLayout.blob(128 - RATE_LIMITER_LEN, "padding"),
Layout.publicKey("whitelistedLiquidator"),
Layout.publicKey("riskAuthority"),
BufferLayout.blob(8, "padding"),
]);

export const LENDING_MARKET_SIZE = LendingMarketLayout.span;
Expand Down
8 changes: 6 additions & 2 deletions solend-sdk/src/state/obligation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ export interface Obligation {
borrows: ObligationLiquidity[];
depositedValue: BN; // decimals
borrowedValue: BN; // decimals
borrowedValueUpperBound: BN; // decimals
allowedBorrowValue: BN; // decimals
unhealthyBorrowValue: BN; // decimals
borrowedValueUpperBound: BN; // decimals
superUnhealthyBorrowValue: BN; // decimals
borrowingIsolatedAsset: boolean;
}

// BN defines toJSON property, which messes up serialization
Expand Down Expand Up @@ -73,7 +75,9 @@ export const ObligationLayout: typeof BufferLayout.Structure =
Layout.uint128("allowedBorrowValue"),
Layout.uint128("unhealthyBorrowValue"),
Layout.uint128("borrowedValueUpperBound"),
BufferLayout.blob(48, "_padding"),
BufferLayout.u8("borrowingIsolatedAsset"),
Layout.uint128("superUnhealthyBorrowValue"),
BufferLayout.blob(31, "_padding"),

BufferLayout.u8("depositsLen"),
BufferLayout.u8("borrowsLen"),
Expand Down
Loading

0 comments on commit fa9f445

Please sign in to comment.