Skip to content
Open
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
1 change: 1 addition & 0 deletions Anchor.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ adapter_katana = "ADPTwDKJTizC3V8gZXDxt5uLjJv4pBnh1nTTf9dZJnS2"
adapter_tulip = "ADPT9nhC1asRcEB13FKymLTatqWGCuZHDznGgnakWKxW"
adapter_friktion = "ADPTzbsaBdXA3FqXoPHjaTjPfh9kadxxFKxonZihP1Ji"
adapter_nft_finance = "ADPTyBr92sBCE1hdYBRvXbMpF4hKs17xyDjFPxopcsrh"
adapter_lido = "ADPTPxbHbEBo9A8E53P2PZnmw3ZYJuwc8ArQQkbJtqhx"

[registry]
url = "https://anchor.projectserum.com"
Expand Down
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions programs/adapter-lido/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "adapter-lido"
version = "0.1.0"
description = "Created with Anchor"
edition = "2021"

[lib]
crate-type = ["cdylib", "lib"]
name = "adapter_lido"

[features]
no-entrypoint = []
no-idl = []
no-log-ix-name = []
cpi = ["no-entrypoint"]

[dependencies]
anchor-lang = "0.24.2"
anchor-spl = "0.24.2"
2 changes: 2 additions & 0 deletions programs/adapter-lido/Xargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[target.bpfel-unknown-unknown.dependencies.std]
features = []
208 changes: 208 additions & 0 deletions programs/adapter-lido/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
use anchor_lang::prelude::*;
use anchor_lang::solana_program::{
instruction::{AccountMeta, Instruction},
program::invoke,
pubkey::Pubkey,
stake,
};
use anchor_spl::token::TokenAccount;

declare_id!("4XnyVwkN5dR7Rinnys59qMqLjhxytpv4JbFLJuXe5mKk");

#[program]
pub mod adapter_lido {
use anchor_lang::solana_program::program::invoke_signed;

use super::*;

pub fn deposit<'a, 'b, 'c, 'info>(
ctx: Context<'a, 'b, 'c, 'info, Action<'info>>,
input: Vec<u8>,
) -> Result<()> {
// Get Input
let mut input_bytes = &input[..];
let input_struct = DepositInputWrapper::deserialize(&mut input_bytes)?;

msg!("Input: {:?}", input_struct);

let mut recipient_st_sol_account =
Account::<TokenAccount>::try_from(&ctx.remaining_accounts[2])?;

let token_amount = recipient_st_sol_account.amount;

let deposit_accounts = vec![
AccountMeta::new(ctx.remaining_accounts[0].key(), false),
AccountMeta::new(ctx.remaining_accounts[1].key(), true),
AccountMeta::new(recipient_st_sol_account.key(), false),
AccountMeta::new(ctx.remaining_accounts[3].key(), false),
AccountMeta::new(ctx.remaining_accounts[4].key(), false),
AccountMeta::new_readonly(ctx.remaining_accounts[5].key(), false),
AccountMeta::new_readonly(ctx.remaining_accounts[6].key(), false),
AccountMeta::new_readonly(ctx.remaining_accounts[7].key(), false),
];

// Prepend instruction byte to Solido Input
let mut data = vec![1u8];
data.extend(input);

let ix = Instruction {
program_id: ctx.accounts.base_program_id.key(),
accounts: deposit_accounts,
data,
};

invoke(&ix, ctx.remaining_accounts)?;

recipient_st_sol_account.reload()?;

let share_amount = recipient_st_sol_account
.amount
.checked_sub(token_amount)
.unwrap();

// Wrap Output
let output_struct = DepositOutputWrapper {
share_amount,
..Default::default()
};
let mut output: Vec<u8> = Vec::new();
output_struct.serialize(&mut output).unwrap();

anchor_lang::solana_program::program::set_return_data(&output);

msg!("Output: {:?}", output_struct);

Ok(())
}

pub fn withdraw<'a, 'b, 'c, 'info>(
ctx: Context<'a, 'b, 'c, 'info, Action<'info>>,
input: Vec<u8>,
) -> Result<()> {
// Get Input
let mut input_bytes = &input[..];
let input_struct = WithdrawInputWrapper::deserialize(&mut input_bytes)?;

msg!("Input: {:?}", input_struct);

let user_account = ctx.remaining_accounts[1].clone();
let account_balance = user_account.lamports();

let withdraw_accounts = vec![
AccountMeta::new(ctx.remaining_accounts[0].key(), false),
AccountMeta::new_readonly(user_account.key(), true),
AccountMeta::new(ctx.remaining_accounts[2].key(), false),
AccountMeta::new(ctx.remaining_accounts[3].key(), false),
AccountMeta::new_readonly(ctx.remaining_accounts[4].key(), false),
AccountMeta::new(ctx.remaining_accounts[5].key(), false),
AccountMeta::new(ctx.remaining_accounts[6].key(), true),
AccountMeta::new_readonly(ctx.remaining_accounts[7].key(), false),
AccountMeta::new(ctx.remaining_accounts[8].key(), false),
AccountMeta::new_readonly(ctx.remaining_accounts[9].key(), false),
AccountMeta::new_readonly(ctx.remaining_accounts[10].key(), false),
AccountMeta::new_readonly(ctx.remaining_accounts[11].key(), false),
AccountMeta::new_readonly(ctx.remaining_accounts[12].key(), false),
];

let mut data = vec![23u8];
data.extend(input);

let withdraw_ix = Instruction {
program_id: ctx.accounts.base_program_id.key(),
accounts: withdraw_accounts,
data,
};

invoke(&withdraw_ix, ctx.remaining_accounts)?;

let deactivate_ix = stake::instruction::deactivate_stake(
&user_account.key(),
&ctx.remaining_accounts[6].key(),
);
invoke_signed(&deactivate_ix, &vec![user_account.clone()], &[&[&user_account.key().to_bytes(), &input_struct.gateway_key.to_bytes()]])?;

let lp_amount = user_account
.lamports()
.checked_sub(account_balance)
.unwrap();

// Wrap Output
let output_struct = WithdrawOutputWrapper {
lp_amount,
..Default::default()
};
let mut output: Vec<u8> = Vec::new();
output_struct.serialize(&mut output).unwrap();

anchor_lang::solana_program::program::set_return_data(&output);

Ok(())
}
}

#[derive(Accounts)]
pub struct Action<'info> {
pub gateway_authority: Signer<'info>,
/// CHECK: Safe
pub base_program_id: AccountInfo<'info>,
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone, Debug, Default)]
pub struct DepositInputWrapper {
/// Amount to deposit.
pub amount: u64,
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone, Debug, Default)]
pub struct WithdrawInputWrapper {
/// Amount to withdraw.
pub amount: u64,
/// Index of the Heaviest Validator.
pub validator_index: u32,
pub gateway_key: Pubkey,
}

// OutputWrapper needs to take up all the space of 32 bytes
#[derive(AnchorSerialize, AnchorDeserialize, Clone, Debug, Default)]
pub struct DepositOutputWrapper {
pub share_amount: u64,
pub dummy_2: u64,
pub dummy_3: u64,
pub dummy_4: u64,
}

// OutputWrapper needs to take up all the space of 32 bytes
#[derive(AnchorSerialize, AnchorDeserialize, Clone, Debug, Default)]
pub struct WithdrawOutputWrapper {
pub lp_amount: u64,
pub dummy_2: u64,
pub dummy_3: u64,
pub dummy_4: u64,
}

pub type DepositOutputTuple = (u64, u64, u64, u64);
pub type WithdrawOutputTuple = (u64, u64, u64, u64);

impl From<DepositOutputWrapper> for DepositOutputTuple {
fn from(result: DepositOutputWrapper) -> DepositOutputTuple {
let DepositOutputWrapper {
share_amount,
dummy_2,
dummy_3,
dummy_4,
} = result;
(share_amount, dummy_2, dummy_3, dummy_4)
}
}

impl From<WithdrawOutputWrapper> for WithdrawOutputTuple {
fn from(result: WithdrawOutputWrapper) -> WithdrawOutputTuple {
let WithdrawOutputWrapper {
lp_amount,
dummy_2,
dummy_3,
dummy_4,
} = result;
(lp_amount, dummy_2, dummy_3, dummy_4)
}
}
99 changes: 99 additions & 0 deletions target/idl/adapter_lido.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
{
"version": "0.1.0",
"name": "adapter_lido",
"instructions": [
{
"name": "deposit",
"accounts": [
{
"name": "gatewayAuthority",
"isMut": false,
"isSigner": true
},
{
"name": "gatewayStateInfo",
"isMut": false,
"isSigner": false
},
{
"name": "baseProgramId",
"isMut": false,
"isSigner": false
}
],
"args": [
{
"name": "input",
"type": "bytes"
}
]
},
{
"name": "withdraw",
"accounts": [
{
"name": "gatewayAuthority",
"isMut": false,
"isSigner": true
},
{
"name": "gatewayStateInfo",
"isMut": false,
"isSigner": false
},
{
"name": "baseProgramId",
"isMut": false,
"isSigner": false
}
],
"args": [
{
"name": "input",
"type": "bytes"
}
]
}
],
"types": [
{
"name": "DepositInputWrapper",
"type": {
"kind": "struct",
"fields": [
{
"name": "instruction",
"type": "u8"
},
{
"name": "amount",
"type": "u64"
}
]
}
},
{
"name": "WithdrawInputWrapper",
"type": {
"kind": "struct",
"fields": [
{
"name": "instruction",
"type": "u8"
},
{
"name": "amount",
"type": "u64"
},
{
"name": "validatorIndex",
"type": "u32"
}
]
}
}
],
"metadata": {
"address": "4XnyVwkN5dR7Rinnys59qMqLjhxytpv4JbFLJuXe5mKk"
}
}
Loading