Skip to content

Commit

Permalink
adding state for Loan Pool Collateral and other changes.
Browse files Browse the repository at this point in the history
  • Loading branch information
arnabmitra committed Aug 4, 2023
1 parent a601f9b commit 7c5c55c
Show file tree
Hide file tree
Showing 9 changed files with 173 additions and 27 deletions.
15 changes: 12 additions & 3 deletions crates/contract/src/core/collateral.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use cosmwasm_std::{Addr, Coin, Uint128};
use provwasm_std::AccessGrant;
use cosmwasm_std::{Addr, Coin, CosmosMsg, Uint128};
use provwasm_std::{AccessGrant, ProvenanceMsg};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

Expand All @@ -16,7 +16,7 @@ impl LoanPoolMarkerCollateral {
marker_address: Addr,
marker_denom: S,
share_count: u128,
removed_permissions: &[AccessGrant],
removed_permissions: Vec<AccessGrant>,
) -> Self {
Self {
marker_address,
Expand All @@ -38,3 +38,12 @@ impl LoanPoolMarkers {
Self { collaterals }
}
}


/// Holds information about a loan pool addition.
pub struct LoanPoolAdditionData {
/// The collateral being added to the loan.
pub collateral: LoanPoolMarkerCollateral,
/// The Provenance messages associated with the loan.
pub messages: Vec<CosmosMsg<ProvenanceMsg>>,
}
3 changes: 3 additions & 0 deletions crates/contract/src/core/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ pub const PAID_IN_CAPITAL_KEY: &str = "paid_in_capital";
pub const SECURITIES_MAP_KEY: &str = "security_types_map";
pub const REMAINING_SECURITIES_KEY: &str = "remaining_securities_map";
pub const AVAILABLE_CAPITAL_KEY: &str = "available_capital";
pub const LOAN_POOL_COLLATERAL: &str = "paid_in_capital";
pub const WHITELIST_CONTRIBUTORS: &str = "whitelist_contributors";

3 changes: 1 addition & 2 deletions crates/contract/src/core/security.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,8 @@ pub struct AcceptedCommitment {

#[cw_serde]
pub struct ContributeLoanPools {
pub original_owner: Addr,
// who owns this set of loan pools, this assumes a homogenous loan pools, i.e one owner owns all loan pools in the markers field
pub markers: Vec<Addr>, // marker address for loan pools being contributed, usually will be only a set of 1
pub markers: Vec<String>, // marker denoms for loan pools being contributed, usually will be only a set of 1
}


Expand Down
2 changes: 1 addition & 1 deletion crates/contract/src/execute/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub fn route(deps: ProvDepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) ->
cancel_commitment::handle(deps, env, info.sender, lp)
}
ExecuteMsg::ContributeLoanPool { loan_pools } => {
add_loanpool::handle(deps, env, info.sender, loan_pools)
add_loanpool::handle(deps, env, info, loan_pools)
}
ExecuteMsg::WhiteListLoanPoolContributors { loan_pool_contributors } => {
whitelist_loanpool_contributors::handle(deps, env, info.sender, loan_pool_contributors.addresses)
Expand Down
88 changes: 70 additions & 18 deletions crates/contract/src/execute/settlement/add_loanpool.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use cosmwasm_std::{Addr, DepsMut, Env, Event, MessageInfo, Response, Storage};
use provwasm_std::{AccessGrant, MarkerAccess, ProvenanceQuerier, ProvenanceQuery};
use cosmwasm_std::{Addr, CosmosMsg, DepsMut, Env, Event, MessageInfo, Response, Storage};
use provwasm_std::{AccessGrant, Marker, MarkerAccess, ProvenanceMsg, ProvenanceQuerier, ProvenanceQuery, revoke_marker_access};

use crate::{
core::{
Expand All @@ -15,17 +15,19 @@ use crate::{
},
util::settlement::timestamp_is_expired,
};
use crate::core::collateral::LoanPoolMarkerCollateral;
use crate::core::collateral::{LoanPoolAdditionData, LoanPoolMarkerCollateral};
use crate::execute::settlement::extensions::ResultExtensions;
use crate::execute::settlement::marker_loan_pool_validation::validate_marker_for_loan_pool_add_remove;
use crate::storage::loan_pool_collateral::set;
use crate::storage::whitelist_contributors_store::get_whitelist_contributors;
use crate::util::provenance_utilities::query_total_supply;
use crate::util::provenance_utilities::{get_single_marker_coin_holding, query_total_supply};

use super::commitment::{Commitment, CommitmentState};

pub fn handle(
deps: ProvDepsMut,
env: Env,
sender: Addr,
info: MessageInfo,
loan_pools: ContributeLoanPools,
) -> ProvTxResponse {
let state = state::get(deps.storage)?;
Expand All @@ -34,17 +36,23 @@ pub fn handle(
let whitelist_contributors = get_whitelist_contributors(deps.storage)?;

// Check if sender is in the whitelist
if !whitelist_contributors.contains(&sender) {
if !whitelist_contributors.contains(&info.sender) {
return Err(ContractError::NotInWhitelist {});
}

let mut response = Response::new()
.add_attribute("action", "accept_commitments")
.add_attribute("gp", state.gp);
.add_attribute("added_by", info.sender.clone());
for pool in loan_pools.markers {
// accept_commitment(deps.storage, commitment.clone())?;
// add the marker, change owner, escrow the account
response = response.add_event(Event::new("loanpool_added").add_attribute("marker_address", pool.to_string()));
let LoanPoolAdditionData {
collateral,
messages
} = create_marker_pool_collateral(&deps, &info, &env, pool.clone()).unwrap();
//inset the collateral
set(deps.storage,&collateral)?;

// Add messages and event in a chained manner
response = response.add_messages(messages)
.add_event(Event::new("loanpool_added").add_attribute("marker_address", pool.to_string()));
}

Ok(response)
Expand All @@ -63,7 +71,9 @@ fn create_marker_pool_collateral(
info: &MessageInfo,
env: &Env,
marker_denom: String,
) -> Result<LoanPoolMarkerCollateral, ContractError> {
) -> Result<LoanPoolAdditionData, ContractError> {

// get marker
let marker =
ProvenanceQuerier::new(&deps.querier).get_marker_by_denom(&marker_denom)?;

Expand All @@ -85,14 +95,56 @@ fn create_marker_pool_collateral(
&[MarkerAccess::Admin, MarkerAccess::Withdraw],
supply,
)?;
// Define some dummy data for removed_permissions
let empty_permissions: Vec<AccessGrant> = Vec::new();

// Create a LoanPoolMarkerCollateral instance with some dummy values
let collateral = LoanPoolMarkerCollateral::new(info.sender.clone(), marker_denom, 10, &empty_permissions);

// Return the instance wrapped in a Result
Ok(collateral)
let messages = get_marker_permission_revoke_messages(&marker, &env.contract.address)?;

LoanPoolAdditionData {
collateral: LoanPoolMarkerCollateral::new(
marker.address.clone(),
&marker.denom,
get_single_marker_coin_holding(&marker)?.amount.u128(),
marker.permissions
.into_iter()
.filter(|perm| perm.address != env.contract.address)
.collect::<Vec<AccessGrant>>(),
),
messages,
}
.to_ok()
}


fn get_marker_permission_revoke_messages(
marker: &Marker,
contract_address: &Addr,
) -> Result<Vec<CosmosMsg<ProvenanceMsg>>, ContractError> {
let mut messages: Vec<CosmosMsg<ProvenanceMsg>> = vec![];
for permission in marker
.permissions
.iter()
.filter(|perm| &perm.address != contract_address)
{
messages.push(revoke_marker_access(
&marker.denom,
permission.address.clone(),
)?);
}
messages.to_ok()
}

#[cfg(test)]
mod tests {
use cosmwasm_std::{Empty, Event, Response};

#[test]
fn test_coin_trade_with_valid_data() {
let mut response: Response<Empty> = Response::new();
response = response.add_event(Event::new("loanpool_added").add_attribute("marker_address", "addr1"));
response = response.add_event(Event::new("loanpool_added").add_attribute("marker_address", "addr2"));

// Now the response object contains two separate events with the name "loanpool_added."
assert_eq!(response.events.len(), 2);
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use cosmwasm_std::{Addr, Env, Response, Storage};
use cosmwasm_std::{Addr, Env, MessageInfo, Response, Storage};

use crate::{
core::{
Expand Down
82 changes: 82 additions & 0 deletions crates/contract/src/storage/loan_pool_collateral.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
use cosmwasm_std::{Addr, Order, Storage};
use cw_storage_plus::Map;
use crate::core::collateral::LoanPoolMarkerCollateral;
use crate::core::constants::LOAN_POOL_COLLATERAL;
use crate::core::error::ContractError;

pub const COLLATERAL: Map<Addr, LoanPoolMarkerCollateral> = Map::new(LOAN_POOL_COLLATERAL);

pub fn get(storage: &dyn Storage, marker_address: Addr) -> Result<LoanPoolMarkerCollateral, ContractError> {
Ok(COLLATERAL.load(storage, marker_address)?)
}

pub fn set(storage: &mut dyn Storage, collateral: &LoanPoolMarkerCollateral) -> Result<(), ContractError> {
Ok(COLLATERAL.save(storage, collateral.marker_address.clone(), collateral)?)
}

pub fn remove(storage: &mut dyn Storage, commitment_lp: Addr) {
COLLATERAL.remove(storage, commitment_lp);
}

pub fn exists(storage: &dyn Storage, lp: Addr) -> bool {
COLLATERAL.has(storage, lp)
}

pub fn get_with_state(storage: &dyn Storage, state: LoanPoolMarkerCollateral) -> Vec<LoanPoolMarkerCollateral> {
let collateral: Vec<LoanPoolMarkerCollateral> = COLLATERAL
.range(storage, None, None, Order::Ascending)
.filter(|item| item.is_ok() && item.as_ref().unwrap().1.marker_denom == state.marker_denom)
.map(|item| item.unwrap().1)
.collect();
collateral
}

#[cfg(test)]
mod tests {
use provwasm_mocks::mock_dependencies;
use super::*;

#[test]
fn test_get_and_set() {
let mut deps = mock_dependencies(&[]);
let marker_address = Addr::unchecked("addr1");
let collateral = LoanPoolMarkerCollateral::new(
marker_address.clone(),
"denom".to_string(),
100,
Vec::new()
);

// Test setting collateral
set(&mut deps.storage, &collateral).unwrap();
let result = get(&deps.storage, marker_address.clone()).unwrap();
assert_eq!(result, collateral);

// Test removing collateral
remove(&mut deps.storage, marker_address.clone());
let result = get(&deps.storage, marker_address.clone());
assert!(result.is_err()); // Expect an error because the collateral has been removed
}

#[test]
fn test_exists() {
let mut deps = mock_dependencies(&[]);
let marker_address = Addr::unchecked("addr1");
let collateral = LoanPoolMarkerCollateral::new(
marker_address.clone(),
"denom".to_string(),
100,
Vec::new()
);

// Test existence after setting
set(&mut deps.storage, &collateral).unwrap();
assert!(exists(&deps.storage, marker_address.clone()));

// Test existence after removing
remove(&mut deps.storage, marker_address.clone());
assert!(!exists(&deps.storage, marker_address.clone()));
}

// Add more tests as needed for other functions and edge cases
}
1 change: 1 addition & 0 deletions crates/contract/src/storage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ pub mod remaining_securities;
pub mod securities;
pub mod state;
pub mod whitelist_contributors_store;
pub mod loan_pool_collateral;
4 changes: 2 additions & 2 deletions crates/contract/src/storage/whitelist_contributors_store.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use cosmwasm_std::{Addr, Storage};
use cw_storage_plus::{Item};
use crate::core::constants::WHITELIST_CONTRIBUTORS;
use crate::core::error::ContractError;
use crate::core::security::LoanPoolContributors;


const KEY: &'static str = "whitelist_contributors";
pub const WHITELIST: Item<Vec<Addr>> = Item::new(KEY);
pub const WHITELIST: Item<Vec<Addr>> = Item::new(WHITELIST_CONTRIBUTORS);

impl LoanPoolContributors {
pub fn human_whitelist(&self) -> Vec<String> {
Expand Down

0 comments on commit 7c5c55c

Please sign in to comment.