3. 实现保证金账户系统
任务目标
实现一个用户保证金账户系统,支持存入、提取、查询余额以及计算保证金率。系统需维护每个用户的抵押品余额与仓位占用保证金,并确保提取操作不会导致保证金率低于安全阈值。
核心实现
// margin_account.rs
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub struct MarginAccount {
pub collateral: u64, // 抵押品余额(最小单位)
pub position_margin: u64, // 当前仓位占用的保证金
}
impl MarginAccount {
pub fn new() -> Self {
Self { collateral: 0, position_margin: 0 }
}
/// 存入抵押品
pub fn deposit(&mut self, amount: u64) -> Result<(), String> {
if amount == 0 {
return Err("存款金额必须大于0".to_string());
}
self.collateral = self.collateral.checked_add(amount)
.ok_or("余额溢出")?;
Ok(())
}
/// 提取抵押品(需保证提取后保证金率 >= 维持保证金率)
pub fn withdraw(&mut self, amount: u64, maintenance_margin_rate: u64) -> Result<(), String> {
if amount == 0 {
return Err("提取金额必须大于0".to_string());
}
if amount > self.collateral {
return Err("余额不足".to_string());
}
let remaining = self.collateral - amount;
let margin_ratio = self.calc_margin_ratio(remaining);
if margin_ratio < maintenance_margin_rate {
return Err("提取后保证金率低于维持保证金率".to_string());
}
self.collateral = remaining;
Ok(())
}
/// 查询余额
pub fn get_balance(&self) -> u64 {
self.collateral
}
/// 计算保证金率(百分比,保留整数)
pub fn calc_margin_ratio(&self, collateral: u64) -> u64 {
if self.position_margin == 0 {
return u64::MAX; // 无仓位时视为无穷大
}
collateral * 100 / self.position_margin
}
/// 更新仓位占用保证金(开仓/平仓时调用)
pub fn update_position_margin(&mut self, new_margin: u64) {
self.position_margin = new_margin;
}
}
/// 用户账户管理器
pub struct MarginAccountManager {
accounts: HashMap<String, MarginAccount>,
}
impl MarginAccountManager {
pub fn new() -> Self {
Self { accounts: HashMap::new() }
}
pub fn get_or_create(&mut self, user: &str) -> &mut MarginAccount {
self.accounts.entry(user.to_string()).or_insert_with(MarginAccount::new)
}
pub fn get(&self, user: &str) -> Option<&MarginAccount> {
self.accounts.get(user)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_deposit_withdraw_and_ratio() {
let mut manager = MarginAccountManager::new();
let user = "alice";
// 存入 1000 USDC
manager.get_or_create(user).deposit(1000).unwrap();
// 开仓占用 400 USDC 保证金
manager.get_or_create(user).update_position_margin(400);
// 查询余额
assert_eq!(manager.get(user).unwrap().get_balance(), 1000);
// 保证金率 = 1000 * 100 / 400 = 250%
assert_eq!(manager.get(user).unwrap().calc_margin_ratio(1000), 250);
// 尝试提取 700,剩余 300,保证金率 = 300*100/400 = 75%
// 若维持保证金率为 80%,则提取被拒绝
let result = manager.get_or_create(user).withdraw(700, 80);
assert!(result.is_err());
// 提取 600,剩余 400,保证金率 = 100%,通过
manager.get_or_create(user).withdraw(600, 80).unwrap();
assert_eq!(manager.get(user).unwrap().get_balance(), 400);
}
}
运行与验证
- 将上述代码保存为
margin_account.rs。 - 运行测试:
rustc --test margin_account.rs && ./margin_account或使用cargo test(若在Cargo项目中)。 - 通过条件:所有测试通过,且控制台无错误输出。测试覆盖了存入、提取成功/拒绝、余额查询和保证金率计算。
关键说明
- 保证金率 = 抵押品余额 / 仓位保证金 × 100%。当无仓位时返回
u64::MAX表示无穷大。 - 提取操作内置安全校验:提取后保证金率不得低于传入的维持保证金率参数(示例中为80%)。
- 实际链上环境中,
deposit/withdraw应接入代币转账逻辑,此处聚焦账户状态管理。