Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions token-lending/LIQUIDITY_MINING.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,10 @@ A reward vault authority is a PDA that is used to sign CPIs into the token progr
[
b"RewardVaultAuthority",
lending_market_key,
reserve_key,
reward_mint_key,
vault_token_account_key,
]
```

> TBD: Should we use the reward vault token account pubkey instead to create a 1-1 relationship between the authority and the vault?
> What will be easier for the clients to use?

### `add_pool_reward`

Admin only ix that adds a new pool reward to a reserve's reward manager, either a deposit or a borrow one.
Expand Down Expand Up @@ -224,11 +220,13 @@ A lending market will be automatically upgraded on the first mutable ix.

## Outstanding work

- [ ] Review feature parity with Suilend
- [ ] Consider changing the reward vault authority seed
- [x] Review feature parity with Suilend
- Looped rewards are not implemented but that's ok
- [x] Consider changing the reward vault authority seed
- [ ] Consider having another admin account to manage the rewards
- [ ] Consider spending some rent to the obligations from the reclaimed merkle-tree reward distributor
- [ ] Discuss CU limits with the Save client team
- [x] Consider spending some rent to the obligations from the reclaimed merkle-tree reward distributor
- We will fund the obligations to support some of the extra rent
- [x] Discuss CU limits with the Save client team

<!-- List of References -->

Expand Down
63 changes: 30 additions & 33 deletions token-lending/program/src/processor/liquidity_mining.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ struct CheckAndUnpackPoolRewardAccounts<'a, 'info> {
reward_authority_info: &'a AccountInfo<'info>,
lending_market_info: &'a AccountInfo<'info>,
token_program_info: &'a AccountInfo<'info>,
reward_token_vault_info: &'a AccountInfo<'info>,
}

/// Does all the checks of [check_and_unpack_pool_reward_accounts] and additionally:
Expand Down Expand Up @@ -83,7 +84,7 @@ fn check_and_unpack_pool_reward_accounts_for_admin_ixs<'a, 'info>(
/// * ✅ `lending_market_info` unpacks
/// * ✅ `token_program_info` matches `lending_market_info`
/// * ✅ `reward_mint_info` belongs to the token program
/// * ✅ `reward_authority_info` is seed of `lending_market_info`, `reserve_info`, `reward_mint_info`
/// * ✅ `reward_authority_info` is seed of `lending_market_info`, `reward_token_vault_info`
fn check_and_unpack_pool_reward_accounts<'a, 'info>(
program_id: &Pubkey,
bumps: Bumps,
Expand All @@ -93,6 +94,7 @@ fn check_and_unpack_pool_reward_accounts<'a, 'info>(
reward_authority_info,
lending_market_info,
token_program_info,
reward_token_vault_info,
}: CheckAndUnpackPoolRewardAccounts<'a, 'info>,
) -> Result<(LendingMarket, ReserveBorrow<'a, 'info>), ProgramError> {
let reserve = ReserveBorrow::new_mut(program_id, reserve_info)?;
Expand Down Expand Up @@ -121,8 +123,7 @@ fn check_and_unpack_pool_reward_accounts<'a, 'info>(
let expected_reward_vault_authority = create_reward_vault_authority(
program_id,
lending_market_info.key,
reserve_info.key,
reward_mint_info.key,
reward_token_vault_info.key,
bumps.reward_authority,
)?;
if expected_reward_vault_authority != *reward_authority_info.key {
Expand Down Expand Up @@ -244,7 +245,7 @@ mod tests {
.expect_err("Should fail");
}

/// ❌ `reward_authority_info` is seed of `lending_market_info`, `reserve_info`, `reward_mint_info`
/// ❌ `reward_authority_info` is seed of `lending_market_info`, `reward_token_vault_info`
#[test]
fn test_fails_if_reward_authority_info_is_not_seed() {
let (mut account_info_builders, og_bumps) =
Expand All @@ -256,8 +257,7 @@ mod tests {
let (new_reward_authority, new_reward_authority_bump) = find_reward_vault_authority(
&crate::id(),
&Pubkey::new_unique(),
&account_info_builders.reserve.key,
&account_info_builders.mint.key,
&account_info_builders.reward_token_vault.key,
);
account_info_builders.reward_authority.key = new_reward_authority;
account_info_builders
Expand All @@ -270,32 +270,12 @@ mod tests {
)
.expect_err("Should fail");

// wrong reserve
// wrong vault

let (new_reward_authority, new_reward_authority_bump) = find_reward_vault_authority(
&crate::id(),
&account_info_builders.lending_market.key,
&Pubkey::new_unique(),
&account_info_builders.mint.key,
);
account_info_builders.reward_authority.key = new_reward_authority;
account_info_builders
.clone()
.check_and_unpack_pool_reward_accounts(
crate::id(),
Bumps {
reward_authority: new_reward_authority_bump,
},
)
.expect_err("Should fail");

// wrong mint

let (new_reward_authority, new_reward_authority_bump) = find_reward_vault_authority(
&crate::id(),
&account_info_builders.lending_market.key,
&account_info_builders.reserve.key,
&Pubkey::new_unique(),
);
account_info_builders.reward_authority.key = new_reward_authority;
account_info_builders
Expand Down Expand Up @@ -361,6 +341,7 @@ mod tests {
reserve: AccountInfoBuilder,
reward_authority: AccountInfoBuilder,
token_program: AccountInfoBuilder,
reward_token_vault: AccountInfoBuilder,
}

#[derive(Clone)]
Expand Down Expand Up @@ -394,10 +375,10 @@ mod tests {
lending_market: lending_market.key,
..Default::default()
});
let reward_token_vault = AccountInfoBuilder::new_reward_token_vault();
let (reward_authority, bumps) = AccountInfoBuilder::new_reward_authority(
&lending_market.key,
&reserve.key,
&mint.key,
&reward_token_vault.key,
);

(
Expand All @@ -408,6 +389,7 @@ mod tests {
reserve,
reward_authority,
token_program,
reward_token_vault,
},
bumps,
)
Expand All @@ -423,6 +405,7 @@ mod tests {
let reserve_info = self.reserve.as_account_info();
let reward_authority_info = self.reward_authority.as_account_info();
let token_program_info = self.token_program.as_account_info();
let reward_token_vault_info = self.reward_token_vault.as_account_info();

check_and_unpack_pool_reward_accounts(
&program_id,
Expand All @@ -433,6 +416,7 @@ mod tests {
reward_authority_info: &reward_authority_info,
reward_mint_info: &mint_info,
token_program_info: &token_program_info,
reward_token_vault_info: &reward_token_vault_info,
},
)
.map(drop)
Expand All @@ -449,6 +433,7 @@ mod tests {
let reward_authority_info = self.reward_authority.as_account_info();
let token_program_info = self.token_program.as_account_info();
let lending_market_owner_info = self.lending_market_owner.as_account_info();
let reward_token_vault_info = self.reward_token_vault.as_account_info();

check_and_unpack_pool_reward_accounts_for_admin_ixs(
&program_id,
Expand All @@ -459,6 +444,7 @@ mod tests {
reward_authority_info: &reward_authority_info,
reward_mint_info: &mint_info,
token_program_info: &token_program_info,
reward_token_vault_info: &reward_token_vault_info,
},
&lending_market_owner_info,
)
Expand Down Expand Up @@ -549,14 +535,12 @@ mod tests {

fn new_reward_authority(
lending_market_key: &Pubkey,
reserve_key: &Pubkey,
reward_mint_key: &Pubkey,
reward_token_vault_key: &Pubkey,
) -> (Self, Bumps) {
let (key, bump) = find_reward_vault_authority(
&crate::id(),
lending_market_key,
reserve_key,
reward_mint_key,
reward_token_vault_key,
);

let s = Self {
Expand Down Expand Up @@ -590,5 +574,18 @@ mod tests {
is_executable: false,
}
}

fn new_reward_token_vault() -> Self {
Self {
key: Pubkey::new_unique(),
lamports: 0,
data: vec![],
owner: spl_token::id(),
rent_epoch: 0,
is_signer: false,
is_writable: true,
is_executable: false,
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ struct AddPoolRewardAccounts<'a, 'info> {
/// ✅ matches `reward_mint_info`
/// ✅ is writable
reward_token_source_info: &'a AccountInfo<'info>,
/// ✅ seed of `lending_market_info`, `reserve_info`, `reward_mint_info`
/// ✅ seed of `lending_market_info`, `reward_token_vault_info`
reward_authority_info: &'a AccountInfo<'info>,
/// ✅ belongs to the token program
/// ✅ has no data
Expand Down Expand Up @@ -157,6 +157,7 @@ impl<'a, 'info> AddPoolRewardAccounts<'a, 'info> {
reward_authority_info,
lending_market_info,
token_program_info,
reward_token_vault_info,
},
lending_market_owner_info,
)?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ struct ClaimUserReward<'a, 'info> {
/// ✅ is writable
_reserve_info: &'a AccountInfo<'info>,
/// ✅ belongs to the token program
reward_mint_info: &'a AccountInfo<'info>,
/// ✅ seed of `lending_market_info`, `reserve_info`, `reward_mint_info`
_reward_mint_info: &'a AccountInfo<'info>,
/// ✅ seed of `lending_market_info`, `reward_token_vault_info`
reward_authority_info: &'a AccountInfo<'info>,
/// ✅ belongs to the token program
/// ✅ unpacks to a [TokenAccount]
Expand Down Expand Up @@ -123,8 +123,7 @@ pub(crate) fn process(
authority_signer_seeds: &[
reward_vault_authority_seeds(
accounts.lending_market_info.key,
&accounts.reserve.key(),
accounts.reward_mint_info.key,
accounts.reward_token_vault_info.key,
)
.as_slice(),
&[&[reward_authority_bump]],
Expand Down Expand Up @@ -215,6 +214,7 @@ impl<'a, 'info> ClaimUserReward<'a, 'info> {
reward_authority_info,
lending_market_info,
token_program_info,
reward_token_vault_info,
},
)?;

Expand Down Expand Up @@ -286,7 +286,7 @@ impl<'a, 'info> ClaimUserReward<'a, 'info> {
obligation_info,
obligation_owner_token_account_info,
_reserve_info: reserve_info,
reward_mint_info,
_reward_mint_info: reward_mint_info,
reward_authority_info,
reward_token_vault_info,
lending_market_info,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ struct ClosePoolRewardAccounts<'a, 'info> {
/// ✅ unpacks
/// ✅ belongs to `lending_market_info`
/// ✅ is writable
reserve_info: &'a AccountInfo<'info>,
_reserve_info: &'a AccountInfo<'info>,
/// ✅ belongs to the token program
reward_mint_info: &'a AccountInfo<'info>,
_reward_mint_info: &'a AccountInfo<'info>,
/// ✅ belongs to the token program
/// ✅ owned by `lending_market_owner_info`
/// ✅ matches `reward_mint_info`
/// ✅ is writable
reward_token_destination_info: &'a AccountInfo<'info>,
/// ✅ seed of `lending_market_info`, `reserve_info`, `reward_mint_info`
/// ✅ seed of `lending_market_info`, `reward_token_vault_info`
reward_authority_info: &'a AccountInfo<'info>,
/// ❓ we don't know whether it matches vault in the [Reserve]
/// ✅ is writable
Expand Down Expand Up @@ -96,8 +96,7 @@ pub(crate) fn process(
let signer_seeds = [
reward_vault_authority_seeds(
accounts.lending_market_info.key,
accounts.reserve_info.key,
accounts.reward_mint_info.key,
accounts.reward_token_vault_info.key,
)
.as_slice(),
&[&bump_seed],
Expand Down Expand Up @@ -159,6 +158,7 @@ impl<'a, 'info> ClosePoolRewardAccounts<'a, 'info> {
reward_authority_info,
lending_market_info,
token_program_info,
reward_token_vault_info,
},
lending_market_owner_info,
)?;
Expand Down Expand Up @@ -196,8 +196,8 @@ impl<'a, 'info> ClosePoolRewardAccounts<'a, 'info> {
}

Ok(Self {
reserve_info,
reward_mint_info,
_reserve_info: reserve_info,
_reward_mint_info: reward_mint_info,
reward_token_destination_info,
reward_authority_info,
reward_token_vault_info,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ struct EditPoolRewardAccounts<'a, 'info> {
/// ✅ is writable
_reserve_info: &'a AccountInfo<'info>,
/// ✅ belongs to the token program
reward_mint_info: &'a AccountInfo<'info>,
_reward_mint_info: &'a AccountInfo<'info>,
/// ✅ belongs to the token program
/// ✅ matches `reward_mint_info`
/// ✅ is writable
lending_market_reward_token_account_info: &'a AccountInfo<'info>,
/// ✅ seed of `lending_market_info`, `reserve_info`, `reward_mint_info`
/// ✅ seed of `lending_market_info`, `reward_token_vault_info`
reward_authority_info: &'a AccountInfo<'info>,
/// ❓ we don't know whether it matches the reward vault pubkey stored in [Reserve]
/// ✅ is writable
Expand Down Expand Up @@ -124,8 +124,7 @@ pub(crate) fn process(
authority_signer_seeds: &[
reward_vault_authority_seeds(
accounts.lending_market_info.key,
&accounts.reserve.key(),
accounts.reward_mint_info.key,
accounts.reward_token_vault_info.key,
)
.as_slice(),
&[&[reward_authority_bump]],
Expand Down Expand Up @@ -160,6 +159,7 @@ impl<'a, 'info> EditPoolRewardAccounts<'a, 'info> {
reward_authority_info,
lending_market_info,
token_program_info,
reward_token_vault_info,
},
lending_market_owner_info,
)?;
Expand Down Expand Up @@ -192,7 +192,7 @@ impl<'a, 'info> EditPoolRewardAccounts<'a, 'info> {

Ok(Self {
_reserve_info: reserve_info,
reward_mint_info,
_reward_mint_info: reward_mint_info,
lending_market_reward_token_account_info: reward_token_destination_info,
reward_authority_info,
reward_token_vault_info,
Expand Down
Loading
Loading