Skip to content

Commit

Permalink
Support nearx in rated stable pool (#89)
Browse files Browse the repository at this point in the history
* support nearx in rated stable pool

* fix bug on shares
  • Loading branch information
MagicGordon authored Jul 20, 2022
1 parent 1aae875 commit 173cbce
Show file tree
Hide file tree
Showing 15 changed files with 533 additions and 6 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion ref-exchange/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ref-exchange"
version = "1.5.2"
version = "1.5.3"
authors = ["Illia Polosukhin <illia.polosukhin@gmail.com>"]
edition = "2018"
publish = false
Expand Down
5 changes: 5 additions & 0 deletions ref-exchange/release_notes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Release Notes

### Version 1.5.3
1. Support nearx in rated stable pool;
2. Add check when initializing simple pool liquidity
3. Add ERR36_SHARES_TOTAL_SUPPLY_OVERFLOW

### Version 1.5.2
1. Lower MIN_RESERVE to 1*10**15;

Expand Down
1 change: 1 addition & 0 deletions ref-exchange/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub const ERR32_ZERO_SHARES: &str = "E32: minting zero shares";
pub const ERR33_TRANSFER_TO_SELF: &str = "E33: transfer to self";
pub const ERR34_INSUFFICIENT_LP_SHARES: &str = "E34: insufficient lp shares";
pub const ERR35_AT_LEAST_ONE_YOCTO: &str = "E35: requires attached deposit of at least 1 yoctoNEAR";
pub const ERR36_SHARES_TOTAL_SUPPLY_OVERFLOW: &str = "E36: shares_total_supply overflow";

// Action result.

Expand Down
56 changes: 56 additions & 0 deletions ref-exchange/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,62 @@ mod tests {
assert_eq!(amounts[1].0 + deposit2, to_yocto("100"));
}

#[test]
#[should_panic(expected = "E31: adding zero amount")]
fn test_init_zero_liquidity() {
let (mut context, mut contract) = setup_contract();
deposit_tokens(
&mut context,
&mut contract,
accounts(3),
vec![
(accounts(1), to_yocto("1000000")),
(accounts(2), to_yocto("1000000")),
],
);
testing_env!(context
.predecessor_account_id(accounts(3))
.attached_deposit(to_yocto("1"))
.build());
let id0 = contract.add_simple_pool(vec![accounts(1), accounts(2)], 1);
testing_env!(context.attached_deposit(to_yocto("0.0007")).build());
contract.add_liquidity(id0, vec![U128(0), U128(0)], None);
}

#[test]
#[should_panic(expected = "E36: shares_total_supply overflow")]
fn test_shares_total_supply_overflow() {
let (mut context, mut contract) = setup_contract();
deposit_tokens(
&mut context,
&mut contract,
accounts(3),
vec![
(accounts(1), to_yocto("1000000")),
(accounts(2), to_yocto("1000000")),
],
);
testing_env!(context
.predecessor_account_id(accounts(3))
.attached_deposit(to_yocto("1"))
.build());
let id0 = contract.add_simple_pool(vec![accounts(1), accounts(2)], 1);
testing_env!(context.attached_deposit(to_yocto("0.0007")).build());
contract.add_liquidity(id0, vec![U128(4801823983302), U128(14399)], None);
testing_env!(context.attached_deposit(to_yocto("0.0007")).build());
contract.add_liquidity(id0, vec![U128(340282366920167 * 4801823983302), U128(340282366920167 * 14399)], None);
contract.swap(
vec![SwapAction {
pool_id: 0,
token_in: accounts(1).into(),
amount_in: Some(U128(12446461932933863316530306u128)),
token_out: accounts(2).into(),
min_amount_out: U128(0),
}],
None,
);
}

/// Should deny creating a pool with duplicate tokens.
#[test]
#[should_panic(expected = "E92: token duplicated")]
Expand Down
1 change: 1 addition & 0 deletions ref-exchange/src/rated_swap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ mod math;
pub mod rate;
mod stnear_rate;
mod linear_rate;
mod nearx_rate;

pub const TARGET_DECIMAL: u8 = 24;
pub const MIN_DECIMAL: u8 = 1;
Expand Down
61 changes: 61 additions & 0 deletions ref-exchange/src/rated_swap/nearx_rate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use super::{rate::RateTrait, PRECISION};
use crate::errors::ERR126_FAILED_TO_PARSE_RESULT;
use crate::utils::{GAS_FOR_BASIC_OP, NO_DEPOSIT};
use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::{
env, ext_contract, json_types::U128, serde_json::from_slice, AccountId, Balance, Promise,
};

// default expire time is 24 hours
const EXPIRE_TS: u64 = 24 * 3600 * 10u64.pow(9);

#[derive(BorshSerialize, BorshDeserialize, Clone)]
pub struct NearxRate {
/// *
pub stored_rates: Balance,
/// *
pub rates_updated_at: u64,
/// *
pub contract_id: AccountId,
}

#[ext_contract(ext_nearx)]
pub trait ExtNearx {
//https://github.com/stader-labs/near-liquid-token/blob/1420b7ceb2cd28577f9e89481a98280d8d13739c/contracts/near-x/src/contract/public.rs#L427
fn get_nearx_price(&self) -> U128;
}

impl RateTrait for NearxRate {
fn are_actual(&self) -> bool {
env::block_timestamp() <= self.rates_updated_at + EXPIRE_TS
}
fn get(&self) -> Balance {
self.stored_rates
}
fn last_update_ts(&self) -> u64 {
self.rates_updated_at
}
fn async_update(&self) -> Promise {
ext_nearx::get_nearx_price(&self.contract_id, NO_DEPOSIT, GAS_FOR_BASIC_OP)
}
fn set(&mut self, cross_call_result: &Vec<u8>) -> u128 {
if let Ok(U128(price)) = from_slice::<U128>(cross_call_result) {
self.stored_rates = price;
self.rates_updated_at = env::block_timestamp();
price
} else {
env::panic(ERR126_FAILED_TO_PARSE_RESULT.as_bytes());
}
}
}

impl NearxRate {
pub fn new(contract_id: AccountId) -> Self {
Self {
stored_rates: PRECISION,
rates_updated_at: 0,
contract_id,
}
}
}

10 changes: 10 additions & 0 deletions ref-exchange/src/rated_swap/rate.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::stnear_rate::StnearRate;
use super::linear_rate::LinearRate;
use super::nearx_rate::NearxRate;
use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::{env, AccountId, Balance, Promise};
use crate::ERR127_INVALID_RATE_TYPE;
Expand All @@ -18,6 +19,7 @@ pub static RATES: Lazy<Mutex<HashMap<AccountId, Rate>>> = Lazy::new(|| Mutex::ne
pub enum Rate {
Stnear(StnearRate),
Linear(LinearRate),
Nearx(NearxRate),
}

pub trait RateTrait {
Expand All @@ -33,30 +35,35 @@ impl RateTrait for Rate {
match self {
Rate::Stnear(rates) => rates.are_actual(),
Rate::Linear(rates) => rates.are_actual(),
Rate::Nearx(rates) => rates.are_actual(),
}
}
fn get(&self) -> Balance {
match self {
Rate::Stnear(rates) => rates.get(),
Rate::Linear(rates) => rates.get(),
Rate::Nearx(rates) => rates.get(),
}
}
fn last_update_ts(&self) -> u64 {
match self {
Rate::Stnear(rates) => rates.last_update_ts(),
Rate::Linear(rates) => rates.last_update_ts(),
Rate::Nearx(rates) => rates.last_update_ts(),
}
}
fn async_update(&self) -> Promise {
match self {
Rate::Stnear(rates) => rates.async_update(),
Rate::Linear(rates) => rates.async_update(),
Rate::Nearx(rates) => rates.async_update(),
}
}
fn set(&mut self, cross_call_result: &Vec<u8>) -> u128 {
match self {
Rate::Stnear(rates) => rates.set(cross_call_result),
Rate::Linear(rates) => rates.set(cross_call_result),
Rate::Nearx(rates) => rates.set(cross_call_result),
}
}
}
Expand All @@ -66,6 +73,7 @@ impl Rate {
match rates_type.as_str() {
"STNEAR" => Rate::Stnear(StnearRate::new(contract_id)),
"LINEAR" => Rate::Linear(LinearRate::new(contract_id)),
"NEARX" => Rate::Nearx(NearxRate::new(contract_id)),
_ => unimplemented!(),
}
}
Expand All @@ -74,13 +82,15 @@ impl Rate {
match self {
Rate::Stnear(_) => "STNEAR".to_string(),
Rate::Linear(_) => "LINEAR".to_string(),
Rate::Nearx(_) => "NEARX".to_string(),
}
}

pub fn is_valid_rate_type(rates_type: &str) -> bool {
match rates_type {
"STNEAR" => true,
"LINEAR" => true,
"NEARX" => true,
_ => false,
}
}
Expand Down
3 changes: 2 additions & 1 deletion ref-exchange/src/simple_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ impl SimplePool {
fair_supply.as_u128()
} else {
for i in 0..self.token_account_ids.len() {
assert!(amounts[i] > 0, "{}", ERR31_ZERO_AMOUNT);
self.amounts[i] += amounts[i];
}
INIT_SHARES_SUPPLY
Expand All @@ -159,7 +160,7 @@ impl SimplePool {
if shares == 0 {
return;
}
self.shares_total_supply += shares;
self.shares_total_supply = self.shares_total_supply.checked_add(shares).expect(ERR36_SHARES_TOTAL_SUPPLY_OVERFLOW);
add_to_collection(&mut self.shares, &account_id, shares);
}

Expand Down
4 changes: 4 additions & 0 deletions ref-exchange/tests/common/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,10 @@ pub fn linear() -> AccountId {
"linear".to_string()
}

pub fn nearx() -> AccountId {
"nearx".to_string()
}

pub fn to_va(a: AccountId) -> ValidAccountId {
ValidAccountId::try_from(a).unwrap()
}
Expand Down
2 changes: 1 addition & 1 deletion ref-exchange/tests/test_migrate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ fn test_upgrade() {
.assert_success();
let metadata = get_metadata(&pool);
// println!("{:#?}", metadata);
assert_eq!(metadata.version, "1.5.2".to_string());
assert_eq!(metadata.version, "1.5.3".to_string());
assert_eq!(metadata.exchange_fee, 4);
assert_eq!(metadata.referral_fee, 1);
assert_eq!(metadata.state, RunningState::Running);
Expand Down
Loading

0 comments on commit 173cbce

Please sign in to comment.