Skip to content

Commit

Permalink
Merge pull request #176 from blend-capital/payer_payee_checks
Browse files Browse the repository at this point in the history
Payer payee checks
  • Loading branch information
mootz12 authored Jan 2, 2024
2 parents 043e98f + 0a866aa commit 78a4864
Show file tree
Hide file tree
Showing 8 changed files with 656 additions and 93 deletions.
51 changes: 49 additions & 2 deletions backstop/src/backstop/deposit.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
use crate::{contract::require_nonnegative, emissions, storage};
use crate::{contract::require_nonnegative, emissions, storage, BackstopError};
use sep_41_token::TokenClient;
use soroban_sdk::{Address, Env};
use soroban_sdk::{panic_with_error, Address, Env};

use super::require_is_from_pool_factory;

/// Perform a deposit into the backstop module
pub fn execute_deposit(e: &Env, from: &Address, pool_address: &Address, amount: i128) -> i128 {
require_nonnegative(e, amount);
if from == pool_address || from == &e.current_contract_address() {
panic_with_error!(e, &BackstopError::BadRequest)
}
let mut pool_balance = storage::get_pool_balance(e, pool_address);
require_is_from_pool_factory(e, pool_address, pool_balance.shares);
let mut user_balance = storage::get_user_balance(e, pool_address, from);
Expand Down Expand Up @@ -141,6 +144,50 @@ mod tests {
});
}

#[test]
#[should_panic(expected = "Error(Contract, #1)")]
fn test_execute_deposit_from_is_to() {
let e = Env::default();
e.mock_all_auths_allowing_non_root_auth();

let backstop_address = create_backstop(&e);
let pool_0_id = Address::generate(&e);
let bombadil = Address::generate(&e);
let samwise = Address::generate(&e);

let (_, backstop_token_client) = create_backstop_token(&e, &backstop_address, &bombadil);
backstop_token_client.mint(&samwise, &100_0000000);

let (_, mock_pool_factory_client) = create_mock_pool_factory(&e, &backstop_address);
mock_pool_factory_client.set_pool(&pool_0_id);

e.as_contract(&backstop_address, || {
execute_deposit(&e, &pool_0_id, &pool_0_id, 100);
});
}

#[test]
#[should_panic(expected = "Error(Contract, #1)")]
fn test_execute_deposit_from_self() {
let e = Env::default();
e.mock_all_auths_allowing_non_root_auth();

let backstop_address = create_backstop(&e);
let pool_0_id = Address::generate(&e);
let bombadil = Address::generate(&e);
let samwise = Address::generate(&e);

let (_, backstop_token_client) = create_backstop_token(&e, &backstop_address, &bombadil);
backstop_token_client.mint(&samwise, &100_0000000);

let (_, mock_pool_factory_client) = create_mock_pool_factory(&e, &backstop_address);
mock_pool_factory_client.set_pool(&pool_0_id);

e.as_contract(&backstop_address, || {
execute_deposit(&e, &backstop_address, &pool_0_id, 100);
});
}

#[test]
#[should_panic(expected = "Error(Contract, #10)")]
fn text_execute_deposit_not_pool() {
Expand Down
115 changes: 114 additions & 1 deletion backstop/src/backstop/fund_management.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use crate::{
constants::SCALAR_7, contract::require_nonnegative, dependencies::CometClient, storage,
BackstopError,
};
use sep_41_token::TokenClient;
use soroban_fixed_point_math::FixedPoint;
use soroban_sdk::{unwrap::UnwrapOptimized, Address, Env};
use soroban_sdk::{panic_with_error, unwrap::UnwrapOptimized, Address, Env};

use super::require_is_from_pool_factory;

Expand All @@ -23,6 +24,9 @@ pub fn execute_draw(e: &Env, pool_address: &Address, amount: i128, to: &Address)
/// Perform a donation to a pool's backstop
pub fn execute_donate(e: &Env, from: &Address, pool_address: &Address, amount: i128) {
require_nonnegative(e, amount);
if from == pool_address || from == &e.current_contract_address() {
panic_with_error!(e, &BackstopError::BadRequest)
}

let mut pool_balance = storage::get_pool_balance(e, pool_address);
require_is_from_pool_factory(e, pool_address, pool_balance.shares);
Expand All @@ -37,6 +41,9 @@ pub fn execute_donate(e: &Env, from: &Address, pool_address: &Address, amount: i
/// Perform a donation of USDC to a pool's backstop
pub fn execute_donate_usdc(e: &Env, from: &Address, pool_address: &Address, amount: i128) {
require_nonnegative(e, amount);
if from == pool_address || from == &e.current_contract_address() {
panic_with_error!(e, &BackstopError::BadRequest)
}

let mut pool_usdc = storage::get_pool_usdc(e, pool_address);
require_is_from_pool_factory(e, pool_address, pool_usdc);
Expand Down Expand Up @@ -172,6 +179,66 @@ mod tests {
});
}

#[test]
#[should_panic(expected = "Error(Contract, #1)")]
fn test_execute_donate_from_is_to() {
let e = Env::default();
e.mock_all_auths_allowing_non_root_auth();
e.budget().reset_unlimited();

let backstop_id = create_backstop(&e);
let pool_0_id = Address::generate(&e);
let bombadil = Address::generate(&e);
let samwise = Address::generate(&e);
let frodo = Address::generate(&e);

let (_, backstop_token_client) = create_backstop_token(&e, &backstop_id, &bombadil);
backstop_token_client.mint(&samwise, &100_0000000);
backstop_token_client.mint(&frodo, &100_0000000);

let (_, mock_pool_factory_client) = create_mock_pool_factory(&e, &backstop_id);
mock_pool_factory_client.set_pool(&pool_0_id);

// initialize pool 0 with funds
e.as_contract(&backstop_id, || {
execute_deposit(&e, &frodo, &pool_0_id, 25_0000000);
});

e.as_contract(&backstop_id, || {
execute_donate(&e, &pool_0_id, &pool_0_id, 10_0000000);
});
}

#[test]
#[should_panic(expected = "Error(Contract, #1)")]
fn test_execute_donate_from_is_self() {
let e = Env::default();
e.mock_all_auths_allowing_non_root_auth();
e.budget().reset_unlimited();

let backstop_id = create_backstop(&e);
let pool_0_id = Address::generate(&e);
let bombadil = Address::generate(&e);
let samwise = Address::generate(&e);
let frodo = Address::generate(&e);

let (_, backstop_token_client) = create_backstop_token(&e, &backstop_id, &bombadil);
backstop_token_client.mint(&samwise, &100_0000000);
backstop_token_client.mint(&frodo, &100_0000000);

let (_, mock_pool_factory_client) = create_mock_pool_factory(&e, &backstop_id);
mock_pool_factory_client.set_pool(&pool_0_id);

// initialize pool 0 with funds
e.as_contract(&backstop_id, || {
execute_deposit(&e, &frodo, &pool_0_id, 25_0000000);
});

e.as_contract(&backstop_id, || {
execute_donate(&e, &backstop_id, &pool_0_id, 10_0000000);
});
}

#[test]
#[should_panic(expected = "Error(Contract, #10)")]
fn test_execute_donate_not_pool() {
Expand Down Expand Up @@ -348,6 +415,52 @@ mod tests {
});
}

#[test]
#[should_panic(expected = "Error(Contract, #1)")]
fn test_execute_donate_usdc_from_is_to() {
let e = Env::default();
e.mock_all_auths_allowing_non_root_auth();
e.budget().reset_unlimited();

let backstop_id = create_backstop(&e);
let pool_0_id = Address::generate(&e);
let bombadil = Address::generate(&e);
let samwise = Address::generate(&e);

let (_, usdc_token_client) = create_usdc_token(&e, &backstop_id, &bombadil);
usdc_token_client.mint(&samwise, &100_0000000);

let (_, mock_pool_factory_client) = create_mock_pool_factory(&e, &backstop_id);
mock_pool_factory_client.set_pool(&pool_0_id);

e.as_contract(&backstop_id, || {
execute_donate_usdc(&e, &pool_0_id, &pool_0_id, 10_0000000);
});
}

#[test]
#[should_panic(expected = "Error(Contract, #1)")]
fn test_execute_donate_usdc_from_is_self() {
let e = Env::default();
e.mock_all_auths_allowing_non_root_auth();
e.budget().reset_unlimited();

let backstop_id = create_backstop(&e);
let pool_0_id = Address::generate(&e);
let bombadil = Address::generate(&e);
let samwise = Address::generate(&e);

let (_, usdc_token_client) = create_usdc_token(&e, &backstop_id, &bombadil);
usdc_token_client.mint(&samwise, &100_0000000);

let (_, mock_pool_factory_client) = create_mock_pool_factory(&e, &backstop_id);
mock_pool_factory_client.set_pool(&pool_0_id);

e.as_contract(&backstop_id, || {
execute_donate_usdc(&e, &backstop_id, &pool_0_id, 10_0000000);
});
}

#[test]
#[should_panic(expected = "Error(Contract, #10)")]
fn test_execute_donate_usdc_not_pool() {
Expand Down
67 changes: 63 additions & 4 deletions pool/src/auctions/auction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,6 @@ pub fn fill(
percent_filled: u64,
) {
let auction_data = storage::get_auction(e, &auction_type, user);
if percent_filled > 100 || percent_filled == 0 {
panic_with_error!(e, PoolError::BadRequest);
}

let (to_fill_auction, remaining_auction) = scale_auction(e, &auction_data, percent_filled);
match AuctionType::from_u32(auction_type) {
AuctionType::UserLiquidation => {
Expand Down Expand Up @@ -164,12 +160,19 @@ pub fn fill(
/// Returns the (Scaled Auction, Remaining Auction) such that:
/// - Scaled Auction is the auction data scaled
/// - Remaining Auction is the leftover auction data that will be stored in the ledger, or deleted if None
///
/// ### Panics
/// If the percent filled is greater than 100 or less than 0
#[allow(clippy::zero_prefixed_literal)]
fn scale_auction(
e: &Env,
auction_data: &AuctionData,
percent_filled: u64,
) -> (AuctionData, Option<AuctionData>) {
if percent_filled > 100 || percent_filled == 0 {
panic_with_error!(e, PoolError::BadRequest);
}

let mut to_fill_auction = AuctionData {
bid: map![e],
lot: map![e],
Expand Down Expand Up @@ -1577,4 +1580,60 @@ mod tests {
12_5000003
);
}

#[test]
#[should_panic(expected = "Error(Contract, #2)")]
fn test_scale_auction_fill_percentage_zero() {
let e = Env::default();
let underlying_0 = Address::generate(&e);
let underlying_1 = Address::generate(&e);

let base_auction_data = AuctionData {
bid: map![&e, (underlying_0.clone(), 25_0000005)],
lot: map![&e, (underlying_1.clone(), 25_0000005)],
block: 1000,
};

// 0 blocks
e.ledger().set(LedgerInfo {
timestamp: 12345,
protocol_version: 20,
sequence_number: 1000,
network_id: Default::default(),
base_reserve: 10,
min_temp_entry_ttl: 172800,
min_persistent_entry_ttl: 172800,
max_entry_ttl: 9999999,
});

let (_, _) = scale_auction(&e, &base_auction_data, 0);
}

#[test]
#[should_panic(expected = "Error(Contract, #2)")]
fn test_scale_auction_fill_percentage_over_100() {
let e = Env::default();
let underlying_0 = Address::generate(&e);
let underlying_1 = Address::generate(&e);

let base_auction_data = AuctionData {
bid: map![&e, (underlying_0.clone(), 25_0000005)],
lot: map![&e, (underlying_1.clone(), 25_0000005)],
block: 1000,
};

// 0 blocks
e.ledger().set(LedgerInfo {
timestamp: 12345,
protocol_version: 20,
sequence_number: 1000,
network_id: Default::default(),
base_reserve: 10,
min_temp_entry_ttl: 172800,
min_persistent_entry_ttl: 172800,
max_entry_ttl: 9999999,
});

let (_, _) = scale_auction(&e, &base_auction_data, 101);
}
}
Loading

0 comments on commit 78a4864

Please sign in to comment.