///! # 借贷协议 ///! ///! 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, /// 借款 (asset => amount) borrows: Map, /// 总抵押价值(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; /// 贷款 (loan_id => loan) let _loans: Map; /// 用户账户 (user => account) let _accounts: Map; /// 用户贷款索引 (user => loan_ids) let _user_loans: Map>; /// 价格预言机(简化,实际需要外部预言机) let _prices: Map; /// 管理员地址 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`: 贷款ID列表 pub fn get_user_loans(user: Address) -> Vec { 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; } }