Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Payer payee checks #176

Merged
merged 8 commits into from
Jan 2, 2024
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() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this should have been the backstop id in the from parameter

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