820 lines
24 KiB
Plaintext
820 lines
24 KiB
Plaintext
///! # 借贷协议
|
||
///!
|
||
///! Lending Protocol
|
||
///! 提供抵押借贷、利率计算和清算机制
|
||
///!
|
||
///! **版本**: v1.0
|
||
///! **模块**: charter-std/defi/lending.ch
|
||
|
||
use utils::math::{safe_mul, safe_div, safe_add, safe_sub, percentage};
|
||
use utils::crypto::sha3_384_hash;
|
||
|
||
// ============================================================================
|
||
// 借贷状态枚举
|
||
// ============================================================================
|
||
|
||
/// 贷款状态
|
||
pub enum LoanStatus {
|
||
/// 活跃
|
||
Active,
|
||
|
||
/// 已还清
|
||
Repaid,
|
||
|
||
/// 已清算
|
||
Liquidated,
|
||
|
||
/// 违约
|
||
Defaulted
|
||
}
|
||
|
||
/// 利率模式
|
||
pub enum InterestRateMode {
|
||
/// 固定利率
|
||
Fixed,
|
||
|
||
/// 浮动利率
|
||
Variable
|
||
}
|
||
|
||
// ============================================================================
|
||
// 借贷结构
|
||
// ============================================================================
|
||
|
||
/// 贷款信息
|
||
struct Loan {
|
||
/// 贷款ID
|
||
loan_id: Hash,
|
||
|
||
/// 借款人
|
||
borrower: Address,
|
||
|
||
/// 抵押资产
|
||
collateral_asset: Address,
|
||
|
||
/// 抵押数量
|
||
collateral_amount: u256,
|
||
|
||
/// 借款资产
|
||
borrow_asset: Address,
|
||
|
||
/// 借款数量
|
||
borrow_amount: u256,
|
||
|
||
/// 利率(年化,基点)
|
||
interest_rate: u16,
|
||
|
||
/// 利率模式
|
||
rate_mode: InterestRateMode,
|
||
|
||
/// 创建时间
|
||
created_at: Timestamp,
|
||
|
||
/// 到期时间
|
||
due_date: Timestamp,
|
||
|
||
/// 已还本金
|
||
repaid_principal: u256,
|
||
|
||
/// 已还利息
|
||
repaid_interest: u256,
|
||
|
||
/// 贷款状态
|
||
status: LoanStatus,
|
||
|
||
/// 最后更新时间
|
||
last_updated: Timestamp
|
||
}
|
||
|
||
/// 资产池信息
|
||
struct AssetPool {
|
||
/// 资产地址
|
||
asset: Address,
|
||
|
||
/// 总存款
|
||
total_deposits: u256,
|
||
|
||
/// 总借款
|
||
total_borrows: u256,
|
||
|
||
/// 可用流动性
|
||
available_liquidity: u256,
|
||
|
||
/// 基础利率(年化,基点)
|
||
base_rate: u16,
|
||
|
||
/// 最优利用率(基点)
|
||
optimal_utilization: u16,
|
||
|
||
/// 斜率1(基点)
|
||
slope1: u16,
|
||
|
||
/// 斜率2(基点)
|
||
slope2: u16,
|
||
|
||
/// 抵押率(基点,例如8000表示80%)
|
||
collateral_factor: u16,
|
||
|
||
/// 清算阈值(基点,例如8500表示85%)
|
||
liquidation_threshold: u16,
|
||
|
||
/// 清算奖励(基点,例如500表示5%)
|
||
liquidation_bonus: u16
|
||
}
|
||
|
||
/// 用户账户信息
|
||
struct UserAccount {
|
||
/// 用户地址
|
||
user: Address,
|
||
|
||
/// 存款 (asset => amount)
|
||
deposits: Map<Address, u256>,
|
||
|
||
/// 借款 (asset => amount)
|
||
borrows: Map<Address, u256>,
|
||
|
||
/// 总抵押价值(USD)
|
||
total_collateral_value: u256,
|
||
|
||
/// 总借款价值(USD)
|
||
total_borrow_value: u256,
|
||
|
||
/// 健康因子(基点)
|
||
health_factor: u16
|
||
}
|
||
|
||
// ============================================================================
|
||
// 借贷事件
|
||
// ============================================================================
|
||
|
||
/// 存款事件
|
||
event Deposit {
|
||
user: Address,
|
||
asset: Address,
|
||
amount: u256,
|
||
timestamp: Timestamp
|
||
}
|
||
|
||
/// 提款事件
|
||
event Withdraw {
|
||
user: Address,
|
||
asset: Address,
|
||
amount: u256,
|
||
timestamp: Timestamp
|
||
}
|
||
|
||
/// 借款事件
|
||
event Borrow {
|
||
loan_id: Hash,
|
||
borrower: Address,
|
||
collateral_asset: Address,
|
||
collateral_amount: u256,
|
||
borrow_asset: Address,
|
||
borrow_amount: u256,
|
||
interest_rate: u16,
|
||
timestamp: Timestamp
|
||
}
|
||
|
||
/// 还款事件
|
||
event Repay {
|
||
loan_id: Hash,
|
||
borrower: Address,
|
||
repaid_principal: u256,
|
||
repaid_interest: u256,
|
||
timestamp: Timestamp
|
||
}
|
||
|
||
/// 清算事件
|
||
event Liquidate {
|
||
loan_id: Hash,
|
||
borrower: Address,
|
||
liquidator: Address,
|
||
collateral_liquidated: u256,
|
||
debt_covered: u256,
|
||
timestamp: Timestamp
|
||
}
|
||
|
||
// ============================================================================
|
||
// 借贷协议
|
||
// ============================================================================
|
||
|
||
/// 借贷协议
|
||
certificate LendingProtocol {
|
||
/// 资产池 (asset => pool)
|
||
let _pools: Map<Address, AssetPool>;
|
||
|
||
/// 贷款 (loan_id => loan)
|
||
let _loans: Map<Hash, Loan>;
|
||
|
||
/// 用户账户 (user => account)
|
||
let _accounts: Map<Address, UserAccount>;
|
||
|
||
/// 用户贷款索引 (user => loan_ids)
|
||
let _user_loans: Map<Address, Vec<Hash>>;
|
||
|
||
/// 价格预言机(简化,实际需要外部预言机)
|
||
let _prices: Map<Address, u256>;
|
||
|
||
/// 管理员地址
|
||
let _admin: Address;
|
||
|
||
/// 清算奖励接收地址
|
||
let _treasury: Address;
|
||
|
||
// ========== 构造函数 ==========
|
||
|
||
constructor(treasury: Address) {
|
||
require(!treasury.is_zero(), "Invalid treasury");
|
||
|
||
self._admin = msg.sender;
|
||
self._treasury = treasury;
|
||
}
|
||
|
||
// ========== 资产池管理 ==========
|
||
|
||
/// 创建资产池
|
||
///
|
||
/// # 参数
|
||
/// - `asset`: 资产地址
|
||
/// - `base_rate`: 基础利率(基点)
|
||
/// - `optimal_utilization`: 最优利用率(基点)
|
||
/// - `slope1`: 斜率1(基点)
|
||
/// - `slope2`: 斜率2(基点)
|
||
/// - `collateral_factor`: 抵押率(基点)
|
||
/// - `liquidation_threshold`: 清算阈值(基点)
|
||
/// - `liquidation_bonus`: 清算奖励(基点)
|
||
///
|
||
/// # 返回
|
||
/// - `bool`: 是否成功
|
||
pub fn create_pool(
|
||
asset: Address,
|
||
base_rate: u16,
|
||
optimal_utilization: u16,
|
||
slope1: u16,
|
||
slope2: u16,
|
||
collateral_factor: u16,
|
||
liquidation_threshold: u16,
|
||
liquidation_bonus: u16
|
||
) -> bool {
|
||
require(msg.sender == self._admin, "Only admin");
|
||
require(!asset.is_zero(), "Invalid asset");
|
||
require(!self._pools.contains_key(asset), "Pool already exists");
|
||
require(collateral_factor <= 10000, "Invalid collateral factor");
|
||
require(liquidation_threshold <= 10000, "Invalid liquidation threshold");
|
||
require(collateral_factor < liquidation_threshold, "CF must be < LT");
|
||
|
||
let pool = AssetPool {
|
||
asset: asset,
|
||
total_deposits: 0,
|
||
total_borrows: 0,
|
||
available_liquidity: 0,
|
||
base_rate: base_rate,
|
||
optimal_utilization: optimal_utilization,
|
||
slope1: slope1,
|
||
slope2: slope2,
|
||
collateral_factor: collateral_factor,
|
||
liquidation_threshold: liquidation_threshold,
|
||
liquidation_bonus: liquidation_bonus
|
||
};
|
||
|
||
self._pools[asset] = pool;
|
||
|
||
return true;
|
||
}
|
||
|
||
/// 获取资产池信息
|
||
///
|
||
/// # 参数
|
||
/// - `asset`: 资产地址
|
||
///
|
||
/// # 返回
|
||
/// - `AssetPool`: 资产池信息
|
||
pub fn get_pool(asset: Address) -> AssetPool {
|
||
require(self._pools.contains_key(asset), "Pool not found");
|
||
return self._pools[asset];
|
||
}
|
||
|
||
/// 计算当前借款利率
|
||
///
|
||
/// # 参数
|
||
/// - `asset`: 资产地址
|
||
///
|
||
/// # 返回
|
||
/// - `u16`: 借款利率(基点)
|
||
pub fn get_borrow_rate(asset: Address) -> u16 {
|
||
require(self._pools.contains_key(asset), "Pool not found");
|
||
|
||
let pool = self._pools[asset];
|
||
|
||
if pool.total_deposits == 0 {
|
||
return pool.base_rate;
|
||
}
|
||
|
||
// 计算利用率
|
||
let utilization = safe_mul(pool.total_borrows, 10000) / pool.total_deposits;
|
||
|
||
if utilization <= pool.optimal_utilization as u256 {
|
||
// 利用率 <= 最优利用率
|
||
// rate = base_rate + (utilization / optimal) * slope1
|
||
let rate_increase = safe_mul(utilization, pool.slope1 as u256) / pool.optimal_utilization as u256;
|
||
return pool.base_rate + rate_increase as u16;
|
||
} else {
|
||
// 利用率 > 最优利用率
|
||
// rate = base_rate + slope1 + ((utilization - optimal) / (10000 - optimal)) * slope2
|
||
let excess_utilization = safe_sub(utilization, pool.optimal_utilization as u256);
|
||
let excess_range = safe_sub(10000, pool.optimal_utilization as u256);
|
||
let rate_increase = safe_mul(excess_utilization, pool.slope2 as u256) / excess_range;
|
||
return pool.base_rate + pool.slope1 + rate_increase as u16;
|
||
}
|
||
}
|
||
|
||
/// 计算存款利率
|
||
///
|
||
/// # 参数
|
||
/// - `asset`: 资产地址
|
||
///
|
||
/// # 返回
|
||
/// - `u16`: 存款利率(基点)
|
||
pub fn get_deposit_rate(asset: Address) -> u16 {
|
||
require(self._pools.contains_key(asset), "Pool not found");
|
||
|
||
let pool = self._pools[asset];
|
||
|
||
if pool.total_deposits == 0 {
|
||
return 0;
|
||
}
|
||
|
||
// 存款利率 = 借款利率 * 利用率
|
||
let borrow_rate = self.get_borrow_rate(asset);
|
||
let utilization = safe_mul(pool.total_borrows, 10000) / pool.total_deposits;
|
||
|
||
return safe_mul(borrow_rate as u256, utilization) / 10000 as u16;
|
||
}
|
||
|
||
// ========== 存款和提款 ==========
|
||
|
||
/// 存款
|
||
///
|
||
/// # 参数
|
||
/// - `asset`: 资产地址
|
||
/// - `amount`: 数量
|
||
///
|
||
/// # 返回
|
||
/// - `bool`: 是否成功
|
||
pub fn deposit(asset: Address, amount: u256) -> bool {
|
||
require(self._pools.contains_key(asset), "Pool not found");
|
||
require(amount > 0, "Amount must be positive");
|
||
|
||
// 实际实现需要调用资产合约的transferFrom
|
||
|
||
// 更新资产池
|
||
let mut pool = self._pools[asset];
|
||
pool.total_deposits = safe_add(pool.total_deposits, amount);
|
||
pool.available_liquidity = safe_add(pool.available_liquidity, amount);
|
||
self._pools[asset] = pool;
|
||
|
||
// 更新用户账户
|
||
if !self._accounts.contains_key(msg.sender) {
|
||
self._accounts[msg.sender] = UserAccount {
|
||
user: msg.sender,
|
||
deposits: Map::new(),
|
||
borrows: Map::new(),
|
||
total_collateral_value: 0,
|
||
total_borrow_value: 0,
|
||
health_factor: 10000
|
||
};
|
||
}
|
||
|
||
let mut account = self._accounts[msg.sender];
|
||
let current_deposit = account.deposits.get(asset).unwrap_or(0);
|
||
account.deposits[asset] = safe_add(current_deposit, amount);
|
||
self._accounts[msg.sender] = account;
|
||
|
||
emit Deposit {
|
||
user: msg.sender,
|
||
asset: asset,
|
||
amount: amount,
|
||
timestamp: block.timestamp
|
||
};
|
||
|
||
return true;
|
||
}
|
||
|
||
/// 提款
|
||
///
|
||
/// # 参数
|
||
/// - `asset`: 资产地址
|
||
/// - `amount`: 数量
|
||
///
|
||
/// # 返回
|
||
/// - `bool`: 是否成功
|
||
pub fn withdraw(asset: Address, amount: u256) -> bool {
|
||
require(self._pools.contains_key(asset), "Pool not found");
|
||
require(amount > 0, "Amount must be positive");
|
||
require(self._accounts.contains_key(msg.sender), "No account");
|
||
|
||
let mut account = self._accounts[msg.sender];
|
||
let deposit = account.deposits.get(asset).unwrap_or(0);
|
||
require(deposit >= amount, "Insufficient deposit");
|
||
|
||
// 检查是否有足够的流动性
|
||
let pool = self._pools[asset];
|
||
require(pool.available_liquidity >= amount, "Insufficient liquidity");
|
||
|
||
// 检查健康因子
|
||
// 提款后健康因子不能低于1.0
|
||
let new_health_factor = self._calculate_health_factor_after_withdraw(
|
||
msg.sender,
|
||
asset,
|
||
amount
|
||
);
|
||
require(new_health_factor >= 10000, "Would break health factor");
|
||
|
||
// 更新资产池
|
||
let mut pool = self._pools[asset];
|
||
pool.total_deposits = safe_sub(pool.total_deposits, amount);
|
||
pool.available_liquidity = safe_sub(pool.available_liquidity, amount);
|
||
self._pools[asset] = pool;
|
||
|
||
// 更新用户账户
|
||
account.deposits[asset] = safe_sub(deposit, amount);
|
||
self._accounts[msg.sender] = account;
|
||
|
||
// 实际实现需要调用资产合约的transfer
|
||
|
||
emit Withdraw {
|
||
user: msg.sender,
|
||
asset: asset,
|
||
amount: amount,
|
||
timestamp: block.timestamp
|
||
};
|
||
|
||
return true;
|
||
}
|
||
|
||
// ========== 借款和还款 ==========
|
||
|
||
/// 借款
|
||
///
|
||
/// # 参数
|
||
/// - `collateral_asset`: 抵押资产
|
||
/// - `collateral_amount`: 抵押数量
|
||
/// - `borrow_asset`: 借款资产
|
||
/// - `borrow_amount`: 借款数量
|
||
/// - `duration`: 借款期限(秒)
|
||
///
|
||
/// # 返回
|
||
/// - `Hash`: 贷款ID
|
||
pub fn borrow(
|
||
collateral_asset: Address,
|
||
collateral_amount: u256,
|
||
borrow_asset: Address,
|
||
borrow_amount: u256,
|
||
duration: Duration
|
||
) -> Hash {
|
||
require(self._pools.contains_key(collateral_asset), "Collateral pool not found");
|
||
require(self._pools.contains_key(borrow_asset), "Borrow pool not found");
|
||
require(collateral_amount > 0, "Collateral must be positive");
|
||
require(borrow_amount > 0, "Borrow amount must be positive");
|
||
require(duration > 0, "Duration must be positive");
|
||
|
||
let collateral_pool = self._pools[collateral_asset];
|
||
let borrow_pool = self._pools[borrow_asset];
|
||
|
||
// 检查流动性
|
||
require(
|
||
borrow_pool.available_liquidity >= borrow_amount,
|
||
"Insufficient liquidity"
|
||
);
|
||
|
||
// 计算抵押价值和借款价值
|
||
let collateral_price = self._get_price(collateral_asset);
|
||
let borrow_price = self._get_price(borrow_asset);
|
||
|
||
let collateral_value = safe_mul(collateral_amount, collateral_price) / 1e18;
|
||
let borrow_value = safe_mul(borrow_amount, borrow_price) / 1e18;
|
||
|
||
// 检查抵押率
|
||
let max_borrow_value = safe_mul(
|
||
collateral_value,
|
||
collateral_pool.collateral_factor as u256
|
||
) / 10000;
|
||
|
||
require(borrow_value <= max_borrow_value, "Insufficient collateral");
|
||
|
||
// 计算利率
|
||
let interest_rate = self.get_borrow_rate(borrow_asset);
|
||
|
||
// 生成贷款ID
|
||
let loan_id = self._generate_loan_id(msg.sender, collateral_asset, borrow_asset);
|
||
|
||
let loan = Loan {
|
||
loan_id: loan_id,
|
||
borrower: msg.sender,
|
||
collateral_asset: collateral_asset,
|
||
collateral_amount: collateral_amount,
|
||
borrow_asset: borrow_asset,
|
||
borrow_amount: borrow_amount,
|
||
interest_rate: interest_rate,
|
||
rate_mode: InterestRateMode::Variable,
|
||
created_at: block.timestamp,
|
||
due_date: block.timestamp + duration,
|
||
repaid_principal: 0,
|
||
repaid_interest: 0,
|
||
status: LoanStatus::Active,
|
||
last_updated: block.timestamp
|
||
};
|
||
|
||
self._loans[loan_id] = loan;
|
||
|
||
// 更新用户贷款索引
|
||
if !self._user_loans.contains_key(msg.sender) {
|
||
self._user_loans[msg.sender] = Vec::new();
|
||
}
|
||
self._user_loans[msg.sender].push(loan_id);
|
||
|
||
// 更新资产池
|
||
let mut borrow_pool = self._pools[borrow_asset];
|
||
borrow_pool.total_borrows = safe_add(borrow_pool.total_borrows, borrow_amount);
|
||
borrow_pool.available_liquidity = safe_sub(borrow_pool.available_liquidity, borrow_amount);
|
||
self._pools[borrow_asset] = borrow_pool;
|
||
|
||
// 转移抵押资产(实际需要调用资产合约)
|
||
// 转移借款资产给借款人(实际需要调用资产合约)
|
||
|
||
emit Borrow {
|
||
loan_id: loan_id,
|
||
borrower: msg.sender,
|
||
collateral_asset: collateral_asset,
|
||
collateral_amount: collateral_amount,
|
||
borrow_asset: borrow_asset,
|
||
borrow_amount: borrow_amount,
|
||
interest_rate: interest_rate,
|
||
timestamp: block.timestamp
|
||
};
|
||
|
||
return loan_id;
|
||
}
|
||
|
||
/// 还款
|
||
///
|
||
/// # 参数
|
||
/// - `loan_id`: 贷款ID
|
||
/// - `amount`: 还款数量
|
||
///
|
||
/// # 返回
|
||
/// - `bool`: 是否成功
|
||
pub fn repay(loan_id: Hash, amount: u256) -> bool {
|
||
require(self._loans.contains_key(loan_id), "Loan not found");
|
||
require(amount > 0, "Amount must be positive");
|
||
|
||
let mut loan = self._loans[loan_id];
|
||
require(loan.borrower == msg.sender, "Not the borrower");
|
||
require(loan.status == LoanStatus::Active, "Loan not active");
|
||
|
||
// 计算应还利息
|
||
let interest = self._calculate_interest(loan_id);
|
||
let total_debt = safe_add(
|
||
safe_sub(loan.borrow_amount, loan.repaid_principal),
|
||
safe_sub(interest, loan.repaid_interest)
|
||
);
|
||
|
||
require(amount <= total_debt, "Amount exceeds debt");
|
||
|
||
// 先还利息,再还本金
|
||
let remaining_interest = safe_sub(interest, loan.repaid_interest);
|
||
|
||
let interest_payment = if amount <= remaining_interest {
|
||
amount
|
||
} else {
|
||
remaining_interest
|
||
};
|
||
|
||
let principal_payment = safe_sub(amount, interest_payment);
|
||
|
||
loan.repaid_interest = safe_add(loan.repaid_interest, interest_payment);
|
||
loan.repaid_principal = safe_add(loan.repaid_principal, principal_payment);
|
||
loan.last_updated = block.timestamp;
|
||
|
||
// 检查是否还清
|
||
if loan.repaid_principal == loan.borrow_amount &&
|
||
loan.repaid_interest == interest {
|
||
loan.status = LoanStatus::Repaid;
|
||
|
||
// 返还抵押品(实际需要调用资产合约)
|
||
}
|
||
|
||
self._loans[loan_id] = loan;
|
||
|
||
// 更新资产池
|
||
let mut pool = self._pools[loan.borrow_asset];
|
||
pool.total_borrows = safe_sub(pool.total_borrows, principal_payment);
|
||
pool.available_liquidity = safe_add(pool.available_liquidity, amount);
|
||
self._pools[loan.borrow_asset] = pool;
|
||
|
||
emit Repay {
|
||
loan_id: loan_id,
|
||
borrower: msg.sender,
|
||
repaid_principal: principal_payment,
|
||
repaid_interest: interest_payment,
|
||
timestamp: block.timestamp
|
||
};
|
||
|
||
return true;
|
||
}
|
||
|
||
// ========== 清算 ==========
|
||
|
||
/// 清算
|
||
///
|
||
/// # 参数
|
||
/// - `loan_id`: 贷款ID
|
||
///
|
||
/// # 返回
|
||
/// - `bool`: 是否成功
|
||
pub fn liquidate(loan_id: Hash) -> bool {
|
||
require(self._loans.contains_key(loan_id), "Loan not found");
|
||
|
||
let mut loan = self._loans[loan_id];
|
||
require(loan.status == LoanStatus::Active, "Loan not active");
|
||
|
||
// 检查是否可以清算
|
||
require(self._is_liquidatable(loan_id), "Cannot liquidate");
|
||
|
||
// 计算债务
|
||
let interest = self._calculate_interest(loan_id);
|
||
let total_debt = safe_add(
|
||
safe_sub(loan.borrow_amount, loan.repaid_principal),
|
||
safe_sub(interest, loan.repaid_interest)
|
||
);
|
||
|
||
// 计算清算奖励
|
||
let collateral_pool = self._pools[loan.collateral_asset];
|
||
let liquidation_amount = safe_mul(
|
||
loan.collateral_amount,
|
||
(10000 + collateral_pool.liquidation_bonus) as u256
|
||
) / 10000;
|
||
|
||
loan.status = LoanStatus::Liquidated;
|
||
self._loans[loan_id] = loan;
|
||
|
||
// 转移抵押品给清算人(实际需要调用资产合约)
|
||
// 清算人需要支付债务(实际需要调用资产合约)
|
||
|
||
emit Liquidate {
|
||
loan_id: loan_id,
|
||
borrower: loan.borrower,
|
||
liquidator: msg.sender,
|
||
collateral_liquidated: liquidation_amount,
|
||
debt_covered: total_debt,
|
||
timestamp: block.timestamp
|
||
};
|
||
|
||
return true;
|
||
}
|
||
|
||
/// 检查贷款是否可以清算
|
||
///
|
||
/// # 参数
|
||
/// - `loan_id`: 贷款ID
|
||
///
|
||
/// # 返回
|
||
/// - `bool`: 是否可以清算
|
||
pub fn is_liquidatable(loan_id: Hash) -> bool {
|
||
return self._is_liquidatable(loan_id);
|
||
}
|
||
|
||
// ========== 查询函数 ==========
|
||
|
||
/// 获取贷款信息
|
||
///
|
||
/// # 参数
|
||
/// - `loan_id`: 贷款ID
|
||
///
|
||
/// # 返回
|
||
/// - `Loan`: 贷款信息
|
||
pub fn get_loan(loan_id: Hash) -> Loan {
|
||
require(self._loans.contains_key(loan_id), "Loan not found");
|
||
return self._loans[loan_id];
|
||
}
|
||
|
||
/// 获取用户贷款列表
|
||
///
|
||
/// # 参数
|
||
/// - `user`: 用户地址
|
||
///
|
||
/// # 返回
|
||
/// - `Vec<Hash>`: 贷款ID列表
|
||
pub fn get_user_loans(user: Address) -> Vec<Hash> {
|
||
return self._user_loans.get(user).unwrap_or(Vec::new());
|
||
}
|
||
|
||
/// 计算应还利息
|
||
///
|
||
/// # 参数
|
||
/// - `loan_id`: 贷款ID
|
||
///
|
||
/// # 返回
|
||
/// - `u256`: 应还利息
|
||
pub fn calculate_interest(loan_id: Hash) -> u256 {
|
||
return self._calculate_interest(loan_id);
|
||
}
|
||
|
||
// ========== 内部函数 ==========
|
||
|
||
/// 生成贷款ID
|
||
fn _generate_loan_id(
|
||
borrower: Address,
|
||
collateral_asset: Address,
|
||
borrow_asset: Address
|
||
) -> Hash {
|
||
let mut data = Bytes::new();
|
||
data.extend(borrower.as_bytes());
|
||
data.extend(collateral_asset.as_bytes());
|
||
data.extend(borrow_asset.as_bytes());
|
||
data.extend(block.timestamp.to_bytes());
|
||
data.extend(tx.hash.as_bytes());
|
||
return sha3_384_hash(data);
|
||
}
|
||
|
||
/// 计算利息
|
||
fn _calculate_interest(loan_id: Hash) -> u256 {
|
||
let loan = self._loans[loan_id];
|
||
|
||
let time_elapsed = safe_sub(block.timestamp, loan.last_updated);
|
||
let principal = safe_sub(loan.borrow_amount, loan.repaid_principal);
|
||
|
||
// 年化利率转换为秒利率
|
||
// interest = principal * rate * time / (365 * 24 * 3600 * 10000)
|
||
let interest = safe_mul(
|
||
safe_mul(principal, loan.interest_rate as u256),
|
||
time_elapsed
|
||
) / (365 * 24 * 3600 * 10000);
|
||
|
||
return safe_add(loan.repaid_interest, interest);
|
||
}
|
||
|
||
/// 检查是否可以清算
|
||
fn _is_liquidatable(loan_id: Hash) -> bool {
|
||
let loan = self._loans[loan_id];
|
||
|
||
if loan.status != LoanStatus::Active {
|
||
return false;
|
||
}
|
||
|
||
// 检查是否过期
|
||
if block.timestamp > loan.due_date {
|
||
return true;
|
||
}
|
||
|
||
// 检查健康因子
|
||
let collateral_pool = self._pools[loan.collateral_asset];
|
||
let borrow_pool = self._pools[loan.borrow_asset];
|
||
|
||
let collateral_price = self._get_price(loan.collateral_asset);
|
||
let borrow_price = self._get_price(loan.borrow_asset);
|
||
|
||
let collateral_value = safe_mul(loan.collateral_amount, collateral_price) / 1e18;
|
||
|
||
let interest = self._calculate_interest(loan_id);
|
||
let total_debt = safe_add(
|
||
safe_sub(loan.borrow_amount, loan.repaid_principal),
|
||
safe_sub(interest, loan.repaid_interest)
|
||
);
|
||
let debt_value = safe_mul(total_debt, borrow_price) / 1e18;
|
||
|
||
// 健康因子 = (抵押价值 * 清算阈值) / 债务价值
|
||
let health_factor = safe_mul(
|
||
collateral_value,
|
||
collateral_pool.liquidation_threshold as u256
|
||
) / debt_value;
|
||
|
||
// 健康因子 < 1.0 可以清算
|
||
return health_factor < 10000;
|
||
}
|
||
|
||
/// 计算提款后的健康因子
|
||
fn _calculate_health_factor_after_withdraw(
|
||
user: Address,
|
||
asset: Address,
|
||
amount: u256
|
||
) -> u16 {
|
||
// 简化实现,实际需要重新计算所有抵押和借款
|
||
return 10000;
|
||
}
|
||
|
||
/// 获取价格(简化,实际需要预言机)
|
||
fn _get_price(asset: Address) -> u256 {
|
||
return self._prices.get(asset).unwrap_or(1e18);
|
||
}
|
||
|
||
// ========== 管理函数 ==========
|
||
|
||
/// 设置价格(简化,实际应该使用预言机)
|
||
pub fn set_price(asset: Address, price: u256) -> bool {
|
||
require(msg.sender == self._admin, "Only admin");
|
||
self._prices[asset] = price;
|
||
return true;
|
||
}
|
||
}
|