NAC_Blockchain/charter-std/defi/lending.ch

820 lines
24 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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