Skip to content

Commit

Permalink
Merge branch 'sdk-fixes' of github.com:Synthetify/synthetify-protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
NorbertBodziony committed Apr 20, 2021
2 parents 1019900 + 07002f5 commit 9062619
Show file tree
Hide file tree
Showing 14 changed files with 500 additions and 220 deletions.
146 changes: 76 additions & 70 deletions migrations/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,24 @@ const initialTokens = [
{ price: new BN(25 * 1e4), ticker: Buffer.from('xLINK'), decimals: 6, limit: new BN(1e12) },
{ price: new BN(300 * 1e4), ticker: Buffer.from('xBNB'), decimals: 6, limit: new BN(1e12) }
]
// const provider = Provider.local('https://devnet.solana.com', {
// // preflightCommitment: 'max',
// skipPreflight: true
// })
const provider = Provider.local('http://127.0.0.1:8899', {
const provider = Provider.local('https://testnet.solana.com', {
// preflightCommitment: 'max',
skipPreflight: true
})
// const provider = Provider.local('http://127.0.0.1:8899', {
// // preflightCommitment: 'max',
// skipPreflight: true
// })
const exchangeProgramId: web3.PublicKey = new web3.PublicKey(
'4pzefKJgV5aSAhvzgv3Su7THyrxTkcUCU58fmXNHxh9Z'
'9buhRrePiSBr6no7mR8is5UAx19YXjLTJuPcuvg2LSSd'
)
const oracleProgramId: web3.PublicKey = new web3.PublicKey(
'7aYbRN3RN7vvPvyr3igRtcRtgns6LDMUKf3MPxKFe4MG'
'8B1scSRf6xnYsQHdrwusF8kpSdEUZDcnFcNjRciSG96W'
)
const managerProgramId: web3.PublicKey = new web3.PublicKey(
'8tz9z3uGwmC62E3Uarp9zUJkR8tjzbnk9gyAhys7hzoz'
'2joXgqZtcTsSnBotkxmyYiZo3xPEzeGq7r4UZFXX2Kqu'
)
const authority = 'AddxzY6F4KEEEwgjfbwdpRuucxWcEzmEm1A1Yikc2SLW'
// const exchangeProgramId: web3.PublicKey = new web3.PublicKey(
// 'H6AgoP6cPWtTxTJpuMYMvTjnkSRevUVX2GJSLJGTxLUQ'
// )
Expand All @@ -58,34 +59,34 @@ const main = async () => {
)
console.log('Create Collateral Token')
console.log(exchangeAuthority.toString())
const collateralTokenFeed = await createPriceFeed({
admin: wallet.publicKey,
oracleProgram,
initPrice: new BN(2 * 1e4)
})
// const collateralTokenFeed = await createPriceFeed({
// admin: wallet.publicKey,
// oracleProgram,
// initPrice: new BN(2 * 1e4)
// })

const collateralToken = await createToken({
connection,
payer: wallet,
mintAuthority: admin.publicKey
})
console.log('Create Account')
await sleep(15000)
const collateralAccount = await collateralToken.createAccount(exchangeAuthority)
const liquidationAccount = await collateralToken.createAccount(exchangeAuthority)
console.log('Create Asset List')
// const collateralToken = await createToken({
// connection,
// payer: wallet,
// mintAuthority: admin.publicKey
// })
// console.log('Create Account')
// await sleep(15000)
// const collateralAccount = await collateralToken.createAccount(exchangeAuthority)
// const liquidationAccount = await collateralToken.createAccount(exchangeAuthority)
// console.log('Create Asset List')

const data = await createAssetsList({
exchangeAuthority,
assetsAdmin: wallet,
collateralToken,
collateralTokenFeed,
connection,
manager,
wallet
})
const assetsList = data.assetsList
const usdToken = data.usdToken
// const data = await createAssetsList({
// exchangeAuthority,
// assetsAdmin: wallet,
// collateralToken,
// collateralTokenFeed,
// connection,
// manager,
// wallet
// })
// const assetsList = data.assetsList
// const usdToken = data.usdToken

//@ts-ignore
let exchange: Exchange = new Exchange(
Expand All @@ -96,47 +97,52 @@ const main = async () => {
exchangeAuthority,
exchangeProgramId
)
console.log('Initialize Exchange')
await sleep(10000)
await exchange.init({
admin: wallet.publicKey,
assetsList,
collateralAccount,
liquidationAccount,
collateralToken: collateralToken.publicKey,
nonce
})
console.log('Initialize Tokens')
// console.log('Initialize Exchange')
// await sleep(10000)
// await exchange.init({
// admin: wallet.publicKey,
// assetsList,
// collateralAccount,
// liquidationAccount,
// collateralToken: collateralToken.publicKey,
// nonce
// })
// console.log('Initialize Tokens')

for (const asset of initialTokens) {
console.log(`Adding ${asset.ticker.toString()}`)
// for (const asset of initialTokens) {
// console.log(`Adding ${asset.ticker.toString()}`)

const newToken = await createToken({
connection,
payer: wallet,
mintAuthority: exchangeAuthority,
decimals: asset.decimals
})
const newFeed = await createPriceFeed({
admin: wallet.publicKey,
oracleProgram,
initPrice: asset.price
})
console.log(`Adding ${newToken.publicKey.toString()}`)
await sleep(10000)
// const newToken = await createToken({
// connection,
// payer: wallet,
// mintAuthority: exchangeAuthority,
// decimals: asset.decimals
// })
// const newFeed = await createPriceFeed({
// admin: wallet.publicKey,
// oracleProgram,
// initPrice: asset.price
// })
// console.log(`Adding ${newToken.publicKey.toString()}`)
// await sleep(10000)

await manager.addNewAsset({
assetsAdmin: wallet,
assetsList,
maxSupply: asset.limit,
tokenAddress: newToken.publicKey,
tokenDecimals: asset.decimals,
tokenFeed: newFeed
})
}
// await manager.addNewAsset({
// assetsAdmin: wallet,
// assetsList,
// maxSupply: asset.limit,
// tokenAddress: newToken.publicKey,
// tokenDecimals: asset.decimals,
// tokenFeed: newFeed
// })
// }
const state = await exchange.getState()
await manager.updatePrices(state.assetsList)
const assets = await manager.getAssetsList(state.assetsList)

console.log(await exchange.getState())
for (const asset of assets.assets) {
console.log(asset.assetAddress.toString())
console.log(asset.price.toString())
}
// console.log(await exchange.getState())
}
main()
112 changes: 104 additions & 8 deletions programs/exchange/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub mod exchange {
pub liquidation_account: Pubkey,
pub liquidation_penalty: u8, // in % range 0-25%
pub liquidation_threshold: u8, // in % should range from 130-200%
pub liquidation_buffer: u32, // time given user to fix collateralization ratio
}
impl InternalState {
pub fn new(ctx: Context<New>, nonce: u8) -> Result<Self> {
Expand All @@ -45,6 +46,7 @@ pub mod exchange {
fee: 300,
liquidation_penalty: 15,
liquidation_threshold: 200,
liquidation_buffer: 172800, // about 24 Hours
})
}
pub fn deposit(&mut self, ctx: Context<Deposit>, amount: u64) -> Result<()> {
Expand All @@ -65,7 +67,7 @@ pub mod exchange {
let seeds = &[SYNTHETIFY_EXCHANGE_SEED.as_bytes(), &[self.nonce]];
let signer = &[&seeds[..]];
let cpi_ctx = CpiContext::from(&*ctx.accounts).with_signer(signer);
let result = token::transfer(cpi_ctx, amount);
token::transfer(cpi_ctx, amount);
let new_shares = get_collateral_shares(
&exchange_collateral_balance,
&amount,
Expand Down Expand Up @@ -417,8 +419,8 @@ pub mod exchange {
return Err(ErrorCode::InvalidSigner.into());
}
let slot = ctx.accounts.clock.slot;
let assets = &assets_list.assets;

let assets = &assets_list.assets;
let collateral_account = &ctx.accounts.collateral_account;
if !collateral_account
.to_account_info()
Expand All @@ -433,16 +435,22 @@ pub mod exchange {
return Err(ErrorCode::ExchangeLiquidationAccount.into());
}

let collateral_amount_in_token = calculate_user_collateral_in_token(
exchange_account.collateral_shares,
self.collateral_shares,
collateral_account.amount,
);
let usd_token = &assets[0];
if !ctx.accounts.usd_token.key.eq(&usd_token.asset_address) {
msg!("Error: NotSyntheticUsd");
return Err(ErrorCode::NotSyntheticUsd.into());
}

if exchange_account.liquidation_deadline > slot {
msg!("Error: LiquidationDeadline");
return Err(ErrorCode::LiquidationDeadline.into());
}

let collateral_amount_in_token = calculate_user_collateral_in_token(
exchange_account.collateral_shares,
self.collateral_shares,
collateral_account.amount,
);
let collateral_asset = &assets[1];

let collateral_amount_in_usd =
Expand Down Expand Up @@ -488,7 +496,7 @@ pub mod exchange {
.collateral_shares
.checked_sub(burned_collateral_shares)
.unwrap();

exchange_account.liquidation_deadline = u64::MAX;
let seeds = &[SYNTHETIFY_EXCHANGE_SEED.as_bytes(), &[self.nonce]];
let signer_seeds = &[&seeds[..]];
{
Expand Down Expand Up @@ -543,6 +551,75 @@ pub mod exchange {

Ok(())
}
pub fn check_account_collateralization(
&mut self,
ctx: Context<CheckCollateralization>,
) -> Result<()> {
msg!("Syntetify: CHECK ACCOUNT COLLATERALIZATION");
let assets_list = &ctx.accounts.assets_list;
let collateral_account = &ctx.accounts.collateral_account;
let exchange_account = &mut ctx.accounts.exchange_account;
if !collateral_account
.to_account_info()
.key
.eq(&self.collateral_account)
{
msg!("Error: CollateralAccountError");
return Err(ErrorCode::CollateralAccountError.into());
}
if !assets_list.to_account_info().key.eq(&self.assets_list) {
msg!("Error: InvalidAssetsList");
return Err(ErrorCode::InvalidAssetsList.into());
}
let assets = &assets_list.assets;
let slot = ctx.accounts.clock.slot;
let collateral_asset = &assets[1];

let collateral_amount_in_token = calculate_user_collateral_in_token(
exchange_account.collateral_shares,
self.collateral_shares,
collateral_account.amount,
);
let collateral_amount_in_usd =
calculate_amount_mint_in_usd(&collateral_asset, collateral_amount_in_token);

let debt = calculate_debt(&assets, slot, self.max_delay).unwrap();
let user_debt = calculate_user_debt_in_usd(exchange_account, debt, self.debt_shares);

let result = check_liquidation(
collateral_amount_in_usd,
user_debt,
self.liquidation_threshold,
);
match result {
Ok(_) => {
if exchange_account.liquidation_deadline == u64::MAX {
exchange_account.liquidation_deadline =
slot.checked_add(self.liquidation_buffer.into()).unwrap();
}
}
Err(_) => {
exchange_account.liquidation_deadline = u64::MAX;
}
}

Ok(())
}
// admin methods
pub fn set_liquidation_buffer(
&mut self,
ctx: Context<AdminAction>,
liquidation_buffer: u32,
) -> Result<()> {
msg!("Syntetify:Admin: SET LIQUIDATION BUFFER");

if !ctx.accounts.admin.key.eq(&self.admin) {
msg!("Error: Unauthorized");
return Err(ErrorCode::Unauthorized.into());
}
self.liquidation_buffer = liquidation_buffer;
Ok(())
}
}
pub fn create_exchange_account(
ctx: Context<CreateExchangeAccount>,
Expand All @@ -552,6 +629,7 @@ pub mod exchange {
exchange_account.owner = owner;
exchange_account.debt_shares = 0;
exchange_account.collateral_shares = 0;
exchange_account.liquidation_deadline = u64::MAX;
Ok(())
}
}
Expand Down Expand Up @@ -579,6 +657,7 @@ pub struct ExchangeAccount {
pub owner: Pubkey,
pub debt_shares: u64,
pub collateral_shares: u64,
pub liquidation_deadline: u64,
}
#[derive(Accounts)]
pub struct Withdraw<'info> {
Expand Down Expand Up @@ -754,6 +833,21 @@ impl<'a, 'b, 'c, 'info> From<&Swap<'info>> for CpiContext<'a, 'b, 'c, 'info, Min
}
}

#[derive(Accounts)]
pub struct CheckCollateralization<'info> {
#[account(mut)]
pub exchange_account: ProgramAccount<'info, ExchangeAccount>,
pub assets_list: CpiAccount<'info, AssetsList>,
pub clock: Sysvar<'info, Clock>,
pub collateral_account: CpiAccount<'info, TokenAccount>,
}

#[derive(Accounts)]
pub struct AdminAction<'info> {
#[account(signer)]
pub admin: AccountInfo<'info>,
}

#[error]
pub enum ErrorCode {
#[msg("Your error message")]
Expand Down Expand Up @@ -782,4 +876,6 @@ pub enum ErrorCode {
WashTrade,
#[msg("Invalid exchange liquidation account")]
ExchangeLiquidationAccount,
#[msg("Liquidation deadline not passed")]
LiquidationDeadline,
}
Loading

0 comments on commit 9062619

Please sign in to comment.