Skip to content

Commit

Permalink
Merge pull request #144 from Hydrogen-Labs/feat-logging-events
Browse files Browse the repository at this point in the history
  • Loading branch information
diyahir authored Oct 30, 2024
2 parents fa213eb + 201570a commit 27e1c56
Show file tree
Hide file tree
Showing 23 changed files with 842 additions and 34 deletions.
1 change: 1 addition & 0 deletions contracts/borrow-operations-contract/Forc.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ name = "borrow-operations-contract"
[dependencies]
libraries = { path = "../../libraries" }
standards = { git = "https://github.com/FuelLabs/sway-standards", tag = "v0.6.1" }
sway_libs = { git = "https://github.com/FuelLabs/sway-libs", tag = "v0.23.1" }
26 changes: 26 additions & 0 deletions contracts/borrow-operations-contract/src/events.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
library;

pub struct OpenTroveEvent {
pub user: Identity,
pub asset_id: AssetId,
pub collateral: u64,
pub debt: u64,
}

pub struct AdjustTroveEvent {
pub user: Identity,
pub asset_id: AssetId,
pub collateral_change: u64,
pub debt_change: u64,
pub is_collateral_increase: bool,
pub is_debt_increase: bool,
pub total_collateral: u64,
pub total_debt: u64,
}

pub struct CloseTroveEvent {
pub user: Identity,
pub asset_id: AssetId,
pub collateral: u64,
pub debt: u64,
}
45 changes: 45 additions & 0 deletions contracts/borrow-operations-contract/src/main.sw
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ contract;
// - Enforcing system parameters and stability conditions

mod data_structures;
mod events;

use standards::{src3::SRC3,};
use ::data_structures::{AssetContracts, LocalVariablesAdjustTrove, LocalVariablesOpenTrove};
use ::events::{AdjustTroveEvent, CloseTroveEvent, OpenTroveEvent};
use libraries::trove_manager_interface::data_structures::Status;
use libraries::active_pool_interface::ActivePool;
use libraries::token_interface::Token;
Expand All @@ -24,6 +26,7 @@ use libraries::coll_surplus_pool_interface::CollSurplusPool;
use libraries::oracle_interface::Oracle;
use libraries::borrow_operations_interface::BorrowOperations;
use libraries::fluid_math::*;
use sway_libs::ownership::*;
use std::{
asset::transfer,
auth::msg_sender,
Expand All @@ -34,6 +37,7 @@ use std::{
msg_amount,
},
hash::*,
logging::log,
};

configurable {
Expand Down Expand Up @@ -90,9 +94,28 @@ impl BorrowOperations for Contract {
.usdf_asset_id
.write(AssetId::new(usdf_contract, SubId::zero()));
storage.pauser.write(msg_sender().unwrap());
initialize_ownership(msg_sender().unwrap());
storage.is_initialized.write(true);
}

#[storage(read, write)]
fn set_pauser(pauser: Identity) {
only_owner();
storage.pauser.write(pauser);
}

#[storage(read, write)]
fn transfer_owner(new_owner: Identity) {
only_owner();
transfer_ownership(new_owner);
}

#[storage(read, write)]
fn renounce_owner() {
only_owner();
renounce_ownership();
}

// --- Borrower Trove Operations ---
// Open a new trove by borrowing USDF
// Differences from Liquity:0% frontend fees, no recovery mode, no gas compensation
Expand Down Expand Up @@ -138,6 +161,12 @@ impl BorrowOperations for Contract {
usdf_contract,
asset_contract,
);
log(OpenTroveEvent {
user: sender,
asset_id: asset_contract,
collateral: msg_amount(),
debt: vars.net_debt,
});
}
// Add collateral to an existing trove
#[storage(read, write), payable]
Expand Down Expand Up @@ -265,6 +294,12 @@ impl BorrowOperations for Contract {
transfer(borrower, usdf_asset_id, excess_usdf_returned);
}

log(CloseTroveEvent {
user: borrower,
asset_id: asset_contract,
collateral: coll,
debt: debt,
});
storage.lock_close_trove.write(false);
}
// Claim collateral from liquidations
Expand Down Expand Up @@ -435,6 +470,16 @@ fn internal_adjust_trove(
usdf_contract_cache,
);

log(AdjustTroveEvent {
user: borrower,
asset_id: asset,
collateral_change: vars.coll_change,
debt_change: vars.net_debt_change,
is_collateral_increase: vars.is_coll_increase,
is_debt_increase: is_debt_increase,
total_collateral: new_position_res.0,
total_debt: new_position_res.1,
});
storage.lock_internal_adjust_trove.write(false);
}

Expand Down
231 changes: 231 additions & 0 deletions contracts/borrow-operations-contract/tests/events.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
use fuels::{prelude::*, types::Identity};

use test_utils::{
data_structures::PRECISION,
interfaces::{
borrow_operations::{borrow_operations_abi, BorrowOperations},
oracle::oracle_abi,
pyth_oracle::{pyth_oracle_abi, pyth_price_feed, PYTH_TIMESTAMP},
token::token_abi,
},
setup::common::setup_protocol,
utils::with_min_borrow_fee,
};

#[tokio::test]
async fn test_trove_events() {
let (contracts, admin, wallets) = setup_protocol(4, false, false).await;

// Setup initial conditions
token_abi::mint_to_id(
&contracts.asset_contracts[0].asset,
5000 * PRECISION,
Identity::Address(admin.address().into()),
)
.await;

let deposit_amount = 1200 * PRECISION;
let borrow_amount = 600 * PRECISION;
let additional_collateral = 300 * PRECISION;

// Set oracle price
oracle_abi::set_debug_timestamp(&contracts.asset_contracts[0].oracle, PYTH_TIMESTAMP).await;
pyth_oracle_abi::update_price_feeds(
&contracts.asset_contracts[0].mock_pyth_oracle,
pyth_price_feed(1),
)
.await;

// Test OpenTroveEvent
let response = borrow_operations_abi::open_trove(
&contracts.borrow_operations,
&contracts.asset_contracts[0].oracle,
&contracts.asset_contracts[0].mock_pyth_oracle,
&contracts.asset_contracts[0].mock_redstone_oracle,
&contracts.asset_contracts[0].asset,
&contracts.usdf,
&contracts.fpt_staking,
&contracts.sorted_troves,
&contracts.asset_contracts[0].trove_manager,
&contracts.active_pool,
deposit_amount,
borrow_amount,
Identity::Address(Address::zeroed()),
Identity::Address(Address::zeroed()),
)
.await
.unwrap();

let logs = response.decode_logs();
let open_trove_event = logs
.results
.iter()
.find(|log| log.as_ref().unwrap().contains("OpenTroveEvent"))
.expect("OpenTroveEvent not found")
.as_ref()
.unwrap();

assert!(
open_trove_event.contains(&admin.address().hash().to_string()),
"OpenTroveEvent should contain user address"
);
assert!(
open_trove_event.contains(&deposit_amount.to_string()),
"OpenTroveEvent should contain collateral amount"
);
assert!(
open_trove_event.contains(&with_min_borrow_fee(borrow_amount).to_string()),
"OpenTroveEvent should contain debt amount"
);
assert!(
open_trove_event.contains(&contracts.asset_contracts[0].asset_id.to_string()),
"OpenTroveEvent should contain asset id"
);

// Test AdjustTroveEvent
let response = borrow_operations_abi::add_coll(
&contracts.borrow_operations,
&contracts.asset_contracts[0].oracle,
&contracts.asset_contracts[0].mock_pyth_oracle,
&contracts.asset_contracts[0].mock_redstone_oracle,
&contracts.asset_contracts[0].asset,
&contracts.usdf,
&contracts.sorted_troves,
&contracts.asset_contracts[0].trove_manager,
&contracts.active_pool,
additional_collateral,
Identity::Address(Address::zeroed()),
Identity::Address(Address::zeroed()),
)
.await
.unwrap();

let logs = response.decode_logs();
let adjust_event = logs
.results
.iter()
.find(|log| log.as_ref().unwrap().contains("AdjustTroveEvent"))
.expect("AdjustTroveEvent not found")
.as_ref()
.unwrap();
println!("adjust_event: {:?}", adjust_event);
assert!(
adjust_event.contains(&admin.address().hash().to_string()),
"AdjustTroveEvent should contain user address"
);
assert!(
adjust_event.contains(&additional_collateral.to_string()),
"AdjustTroveEvent should contain collateral change amount"
);
assert!(
adjust_event.contains("is_collateral_increase: true"),
"AdjustTroveEvent should indicate collateral increase"
);
assert!(
adjust_event.contains("is_debt_increase: false"),
"AdjustTroveEvent should indicate debt is not increased"
);
// assetid
assert!(
adjust_event.contains(&contracts.asset_contracts[0].asset_id.to_string()),
"AdjustTroveEvent should contain asset id"
);
// total debt
assert!(
adjust_event.contains(&with_min_borrow_fee(borrow_amount).to_string()),
"AdjustTroveEvent should contain total debt"
);
// total coll
assert!(
adjust_event.contains(&(deposit_amount + additional_collateral).to_string()),
"AdjustTroveEvent should contain total collateral"
);

// create one more trove to allow for closing

let second_wallet = wallets[1].clone();

token_abi::mint_to_id(
&contracts.asset_contracts[0].asset,
5000 * PRECISION,
Identity::Address(second_wallet.address().into()),
)
.await;

let borrow_operations_second_wallet = BorrowOperations::new(
contracts.borrow_operations.contract_id().clone(),
second_wallet.clone(),
);

borrow_operations_abi::open_trove(
&borrow_operations_second_wallet,
&contracts.asset_contracts[0].oracle,
&contracts.asset_contracts[0].mock_pyth_oracle,
&contracts.asset_contracts[0].mock_redstone_oracle,
&contracts.asset_contracts[0].asset,
&contracts.usdf,
&contracts.fpt_staking,
&contracts.sorted_troves,
&contracts.asset_contracts[0].trove_manager,
&contracts.active_pool,
deposit_amount,
borrow_amount,
Identity::Address(Address::zeroed()),
Identity::Address(Address::zeroed()),
)
.await
.unwrap();

second_wallet
.transfer(
&admin.address(),
borrow_amount,
contracts.usdf_asset_id,
TxPolicies::default(),
)
.await
.unwrap();

// Test CloseTroveEvent
let response = borrow_operations_abi::close_trove(
&contracts.borrow_operations,
&contracts.asset_contracts[0].oracle,
&contracts.asset_contracts[0].mock_pyth_oracle,
&contracts.asset_contracts[0].mock_redstone_oracle,
&contracts.asset_contracts[0].asset,
&contracts.usdf,
&contracts.fpt_staking,
&contracts.sorted_troves,
&contracts.asset_contracts[0].trove_manager,
&contracts.active_pool,
with_min_borrow_fee(borrow_amount),
)
.await
.unwrap();

let logs = response.decode_logs();
let close_event = logs
.results
.iter()
.find(|log| log.as_ref().unwrap().contains("CloseTroveEvent"))
.expect("CloseTroveEvent not found")
.as_ref()
.unwrap();

assert!(
close_event.contains(&admin.address().hash().to_string()),
"CloseTroveEvent should contain user address"
);
assert!(
close_event.contains(&contracts.asset_contracts[0].asset_id.to_string()),
"CloseTroveEvent should contain asset id"
);
assert!(
close_event.contains(&(deposit_amount + additional_collateral).to_string()),
"CloseTroveEvent should contain collateral amount"
);
assert!(
close_event.contains(&with_min_borrow_fee(borrow_amount).to_string()),
"CloseTroveEvent should contain debt amount"
);
}
Loading

0 comments on commit 27e1c56

Please sign in to comment.