///! # 借贷协议
///!
///! 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;
}
}