token register trustless

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>
This commit is contained in:
microwavedcola1 2022-08-03 10:25:09 +02:00 committed by microwavedcola1
parent d3a634c709
commit e31ad9ce34
7 changed files with 519 additions and 32 deletions

View File

@ -37,6 +37,7 @@ pub use token_deposit::*;
pub use token_deregister::*;
pub use token_edit::*;
pub use token_register::*;
pub use token_register_trustless::*;
pub use token_update_index_and_rate::*;
pub use token_withdraw::*;
@ -79,5 +80,6 @@ mod token_deposit;
mod token_deregister;
mod token_edit;
mod token_register;
mod token_register_trustless;
mod token_update_index_and_rate;
mod token_withdraw;

View File

@ -61,7 +61,7 @@ pub struct TokenRegister<'info> {
pub rent: Sysvar<'info, Rent>,
}
#[derive(AnchorSerialize, AnchorDeserialize, Default)]
#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct InterestRateParams {
pub util0: f32,
pub rate0: f32,

View File

@ -0,0 +1,133 @@
use anchor_lang::prelude::*;
use anchor_spl::token::{Mint, Token, TokenAccount};
use fixed::types::I80F48;
use fixed_macro::types::I80F48;
use crate::error::*;
use crate::instructions::{InterestRateParams, INDEX_START};
use crate::state::*;
use crate::util::fill16_from_str;
#[derive(Accounts)]
#[instruction(token_index: TokenIndex, bank_num: u32)]
pub struct TokenRegisterTrustless<'info> {
#[account(
has_one = fast_listing_admin,
)]
pub group: AccountLoader<'info, Group>,
pub fast_listing_admin: Signer<'info>,
pub mint: Account<'info, Mint>,
#[account(
init,
// using the token_index in this seed guards against reusing it
seeds = [group.key().as_ref(), b"Bank".as_ref(), &token_index.to_le_bytes(), &bank_num.to_le_bytes()],
bump,
payer = payer,
space = 8 + std::mem::size_of::<Bank>(),
)]
pub bank: AccountLoader<'info, Bank>,
#[account(
init,
seeds = [group.key().as_ref(), b"Vault".as_ref(), &token_index.to_le_bytes(), &bank_num.to_le_bytes()],
bump,
token::authority = group,
token::mint = mint,
payer = payer
)]
pub vault: Account<'info, TokenAccount>,
#[account(
init,
// using the mint in this seed guards against registering the same mint twice
seeds = [group.key().as_ref(), b"MintInfo".as_ref(), mint.key().as_ref()],
bump,
payer = payer,
space = 8 + std::mem::size_of::<MintInfo>(),
)]
pub mint_info: AccountLoader<'info, MintInfo>,
/// CHECK: The oracle can be one of several different account types
pub oracle: UncheckedAccount<'info>,
#[account(mut)]
pub payer: Signer<'info>,
pub token_program: Program<'info, Token>,
pub system_program: Program<'info, System>,
pub rent: Sysvar<'info, Rent>,
}
#[allow(clippy::too_many_arguments)]
pub fn token_register_trustless(
ctx: Context<TokenRegisterTrustless>,
token_index: TokenIndex,
bank_num: u32,
name: String,
) -> Result<()> {
require_eq!(bank_num, 0);
require_neq!(token_index, 0);
let mut bank = ctx.accounts.bank.load_init()?;
*bank = Bank {
group: ctx.accounts.group.key(),
name: fill16_from_str(name)?,
mint: ctx.accounts.mint.key(),
vault: ctx.accounts.vault.key(),
oracle: ctx.accounts.oracle.key(),
oracle_config: OracleConfig {
conf_filter: I80F48::from_num(0.10),
},
deposit_index: INDEX_START,
borrow_index: INDEX_START,
cached_indexed_total_deposits: I80F48::ZERO,
cached_indexed_total_borrows: I80F48::ZERO,
indexed_deposits: I80F48::ZERO,
indexed_borrows: I80F48::ZERO,
index_last_updated: Clock::get()?.unix_timestamp,
bank_rate_last_updated: Clock::get()?.unix_timestamp,
avg_utilization: I80F48::ZERO,
adjustment_factor: I80F48::from_num(0.001),
util0: I80F48::from_num(0.6),
rate0: I80F48::from_num(0.15),
util1: I80F48::from_num(0.8),
rate1: I80F48::from_num(0.95),
max_rate: I80F48::from_num(3.0),
collected_fees_native: I80F48::ZERO,
loan_origination_fee_rate: I80F48::from_num(0.005),
loan_fee_rate: I80F48::from_num(0.005),
maint_asset_weight: I80F48::from_num(0),
init_asset_weight: I80F48::from_num(0),
maint_liab_weight: I80F48::from_num(1.4),
init_liab_weight: I80F48::from_num(1.5),
liquidation_fee: I80F48::from_num(0.2),
dust: I80F48::ZERO,
flash_loan_vault_initial: u64::MAX,
flash_loan_approved_amount: 0,
token_index,
bump: *ctx.bumps.get("bank").ok_or(MangoError::SomeError)?,
mint_decimals: ctx.accounts.mint.decimals,
bank_num: 0,
reserved: [0; 256],
};
let mut mint_info = ctx.accounts.mint_info.load_init()?;
*mint_info = MintInfo {
group: ctx.accounts.group.key(),
token_index,
padding1: Default::default(),
mint: ctx.accounts.mint.key(),
banks: Default::default(),
vaults: Default::default(),
oracle: ctx.accounts.oracle.key(),
registration_time: Clock::get()?.unix_timestamp,
reserved: [0; 256],
};
mint_info.banks[0] = ctx.accounts.bank.key();
mint_info.vaults[0] = ctx.accounts.vault.key();
Ok(())
}

View File

@ -86,6 +86,15 @@ pub mod mango_v4 {
)
}
pub fn token_register_trustless(
ctx: Context<TokenRegisterTrustless>,
token_index: TokenIndex,
bank_num: u32,
name: String,
) -> Result<()> {
instructions::token_register_trustless(ctx, token_index, bank_num, name)
}
#[allow(clippy::too_many_arguments)]
pub fn token_edit(
ctx: Context<TokenEdit>,

View File

@ -88,6 +88,20 @@ export class MangoClient {
.rpc();
}
public async groupEdit(
group: Group,
newAdmin: PublicKey,
newFastListingAdmin: PublicKey,
): Promise<TransactionSignature> {
return await this.program.methods
.groupEdit(newAdmin, newFastListingAdmin)
.accounts({
group: group.publicKey,
admin: (this.program.provider as AnchorProvider).wallet.publicKey,
})
.rpc();
}
public async groupClose(group: Group): Promise<TransactionSignature> {
const adminPk = (this.program.provider as AnchorProvider).wallet.publicKey;
return await this.program.methods
@ -193,6 +207,27 @@ export class MangoClient {
.rpc();
}
public async tokenRegisterTrustless(
group: Group,
mintPk: PublicKey,
oraclePk: PublicKey,
tokenIndex: number,
name: string,
): Promise<TransactionSignature> {
return await this.program.methods
.tokenRegisterTrustless(tokenIndex, 0, name)
.accounts({
group: group.publicKey,
fastListingAdmin: (this.program.provider as AnchorProvider).wallet
.publicKey,
mint: mintPk,
oracle: oraclePk,
payer: (this.program.provider as AnchorProvider).wallet.publicKey,
rent: SYSVAR_RENT_PUBKEY,
})
.rpc();
}
public async tokenEdit(
group: Group,
tokenName: string,

View File

@ -332,6 +332,148 @@ export type MangoV4 = {
}
]
},
{
"name": "tokenRegisterTrustless",
"accounts": [
{
"name": "group",
"isMut": false,
"isSigner": false
},
{
"name": "fastListingAdmin",
"isMut": false,
"isSigner": true
},
{
"name": "mint",
"isMut": false,
"isSigner": false
},
{
"name": "bank",
"isMut": true,
"isSigner": false,
"pda": {
"seeds": [
{
"kind": "account",
"type": "publicKey",
"path": "group"
},
{
"kind": "const",
"type": "string",
"value": "Bank"
},
{
"kind": "arg",
"type": "u16",
"path": "token_index"
},
{
"kind": "arg",
"type": "u32",
"path": "bank_num"
}
]
}
},
{
"name": "vault",
"isMut": true,
"isSigner": false,
"pda": {
"seeds": [
{
"kind": "account",
"type": "publicKey",
"path": "group"
},
{
"kind": "const",
"type": "string",
"value": "Vault"
},
{
"kind": "arg",
"type": "u16",
"path": "token_index"
},
{
"kind": "arg",
"type": "u32",
"path": "bank_num"
}
]
}
},
{
"name": "mintInfo",
"isMut": true,
"isSigner": false,
"pda": {
"seeds": [
{
"kind": "account",
"type": "publicKey",
"path": "group"
},
{
"kind": "const",
"type": "string",
"value": "MintInfo"
},
{
"kind": "account",
"type": "publicKey",
"account": "Mint",
"path": "mint"
}
]
}
},
{
"name": "oracle",
"isMut": false,
"isSigner": false
},
{
"name": "payer",
"isMut": true,
"isSigner": true
},
{
"name": "tokenProgram",
"isMut": false,
"isSigner": false
},
{
"name": "systemProgram",
"isMut": false,
"isSigner": false
},
{
"name": "rent",
"isMut": false,
"isSigner": false
}
],
"args": [
{
"name": "tokenIndex",
"type": "u16"
},
{
"name": "bankNum",
"type": "u32"
},
{
"name": "name",
"type": "string"
}
]
},
{
"name": "tokenEdit",
"accounts": [
@ -5198,6 +5340,148 @@ export const IDL: MangoV4 = {
}
]
},
{
"name": "tokenRegisterTrustless",
"accounts": [
{
"name": "group",
"isMut": false,
"isSigner": false
},
{
"name": "fastListingAdmin",
"isMut": false,
"isSigner": true
},
{
"name": "mint",
"isMut": false,
"isSigner": false
},
{
"name": "bank",
"isMut": true,
"isSigner": false,
"pda": {
"seeds": [
{
"kind": "account",
"type": "publicKey",
"path": "group"
},
{
"kind": "const",
"type": "string",
"value": "Bank"
},
{
"kind": "arg",
"type": "u16",
"path": "token_index"
},
{
"kind": "arg",
"type": "u32",
"path": "bank_num"
}
]
}
},
{
"name": "vault",
"isMut": true,
"isSigner": false,
"pda": {
"seeds": [
{
"kind": "account",
"type": "publicKey",
"path": "group"
},
{
"kind": "const",
"type": "string",
"value": "Vault"
},
{
"kind": "arg",
"type": "u16",
"path": "token_index"
},
{
"kind": "arg",
"type": "u32",
"path": "bank_num"
}
]
}
},
{
"name": "mintInfo",
"isMut": true,
"isSigner": false,
"pda": {
"seeds": [
{
"kind": "account",
"type": "publicKey",
"path": "group"
},
{
"kind": "const",
"type": "string",
"value": "MintInfo"
},
{
"kind": "account",
"type": "publicKey",
"account": "Mint",
"path": "mint"
}
]
}
},
{
"name": "oracle",
"isMut": false,
"isSigner": false
},
{
"name": "payer",
"isMut": true,
"isSigner": true
},
{
"name": "tokenProgram",
"isMut": false,
"isSigner": false
},
{
"name": "systemProgram",
"isMut": false,
"isSigner": false
},
{
"name": "rent",
"isMut": false,
"isSigner": false
}
],
"args": [
{
"name": "tokenIndex",
"type": "u16"
},
{
"name": "bankNum",
"type": "u32"
},
{
"name": "name",
"type": "string"
}
]
},
{
"name": "tokenEdit",
"accounts": [

View File

@ -23,11 +23,13 @@ const DEVNET_MINTS = new Map([
['BTC', '3UNBZ6o52WTWwjac2kPUb4FyodhU1vFkRJheu1Sh2TvU'],
['SOL', 'So11111111111111111111111111111111111111112'],
['ORCA', 'orcarKHSqC5CDDsGbho8GKvwExejWHxTqGzXgcewB9L'],
['MNGO', 'Bb9bsTQa1bGEtQ5KagGkvSHyuLqDWumFUcRqFusFNJWC'],
]);
const DEVNET_ORACLES = new Map([
['BTC', 'HovQMDrbAgAYPCmHVSrezcSmkMtXSSUsLDFANExrZh2J'],
['SOL', 'J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix'],
['ORCA', 'A1WttWF7X3Rg6ZRpB2YQUFHCRh1kiXV8sKKLV3S9neJV'],
['MNGO', '8k7F9Xb36oFJsjpCKpsXvg4cgBRoZtwNTc3EzG5Ttd2o'],
]);
const GROUP_NUM = Number(process.env.GROUP_NUM || 0);
@ -64,37 +66,6 @@ async function main() {
const group = await client.getGroupForAdmin(admin.publicKey, GROUP_NUM);
console.log(`...registered group ${group.publicKey}`);
// register token 1
console.log(`Registering BTC...`);
const btcDevnetMint = new PublicKey(DEVNET_MINTS.get('BTC')!);
const btcDevnetOracle = new PublicKey(DEVNET_ORACLES.get('BTC')!);
try {
await client.tokenRegister(
group,
btcDevnetMint,
btcDevnetOracle,
0.1,
1, // tokenIndex
'BTC',
0.01,
0.4,
0.07,
0.8,
0.9,
0.88,
0.0005,
0.0005,
0.8,
0.6,
1.2,
1.4,
0.02,
);
await group.reloadAll(client);
} catch (error) {
console.log(error);
}
// stub oracle + register token 0
console.log(`Registering USDC...`);
const usdcDevnetMint = new PublicKey(DEVNET_MINTS.get('USDC')!);
@ -132,6 +103,37 @@ async function main() {
await group.reloadAll(client);
} catch (error) {}
// register token 1
console.log(`Registering BTC...`);
const btcDevnetMint = new PublicKey(DEVNET_MINTS.get('BTC')!);
const btcDevnetOracle = new PublicKey(DEVNET_ORACLES.get('BTC')!);
try {
await client.tokenRegister(
group,
btcDevnetMint,
btcDevnetOracle,
0.1,
1, // tokenIndex
'BTC',
0.01,
0.4,
0.07,
0.8,
0.9,
0.88,
0.0005,
0.0005,
0.8,
0.6,
1.2,
1.4,
0.02,
);
await group.reloadAll(client);
} catch (error) {
console.log(error);
}
// register token 2
console.log(`Registering SOL...`);
const solDevnetMint = new PublicKey(DEVNET_MINTS.get('SOL')!);
@ -194,11 +196,33 @@ async function main() {
console.log(error);
}
// register token 4
console.log(
`Editing group, setting existing admin as fastListingAdmin to be able to add MNGO truslessly...`,
);
await client.groupEdit(group, group.admin, group.admin);
console.log(`Registering MNGO...`);
const mngoDevnetMint = new PublicKey(DEVNET_MINTS.get('MNGO')!);
const mngoDevnetOracle = new PublicKey(DEVNET_ORACLES.get('MNGO')!);
try {
await client.tokenRegisterTrustless(
group,
mngoDevnetMint,
mngoDevnetOracle,
4,
'MNGO',
);
await group.reloadAll(client);
} catch (error) {
console.log(error);
}
// log tokens/banks
for (const bank of await group.banksMap.values()) {
console.log(
`...registered Bank ${bank.tokenIndex} ${bank.publicKey}, mint ${bank.mint}, oracle ${bank.oracle}`,
);
console.log(bank.toString());
}
// register serum market