NAC_Blockchain/charter-std-zh/defi/defi.ch

589 lines
15 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.

///! DeFi模块: 去中心化金融协议
///! NAC的DeFi标准协议专为RWA设计
///!
///! **版本**: v1.0
///! **模块**: charter-std-zh/defi/defi.ch
使用 资产::gnacs::GNACS编码;
使用 主权::规则::主权类型;
使用 acc::acc20::ACC20;
// ============================================================================
// 流动性池接口
// ============================================================================
/// 流动性池接口
///
/// 定义自动做市商(AMM)的标准操作
接口 流动性池 {
// ========== 查询函数 ==========
/// 查询资产A地址
函数 资产A() -> 地址;
/// 查询资产B地址
函数 资产B() -> 地址;
/// 查询资产A储备量
函数 储备量A() -> u256;
/// 查询资产B储备量
函数 储备量B() -> u256;
/// 查询流动性代币总供应量
函数 流动性总量() -> u256;
/// 查询用户流动性
///
/// # 参数
/// - `提供者`: 流动性提供者地址
函数 用户流动性(提供者: 地址) -> u256;
/// 计算兑换输出
///
/// # 参数
/// - `输入量`: 输入资产数量
/// - `输入储备`: 输入资产储备量
/// - `输出储备`: 输出资产储备量
///
/// # 返回
/// - `u256`: 输出资产数量
函数 计算输出量(输入量: u256, 输入储备: u256, 输出储备: u256) -> u256;
// ========== 状态变更函数 ==========
/// 添加流动性
///
/// # 参数
/// - `数量A`: 资产A数量
/// - `数量B`: 资产B数量
/// - `最小数量A`: 最小资产A数量
/// - `最小数量B`: 最小资产B数量
/// - `到`: 接收流动性代币的地址
///
/// # 返回
/// - `u256`: 铸造的流动性代币数量
///
/// # 事件
/// - `添加流动性事件`
函数 添加流动性(
数量A: u256,
数量B: u256,
最小数量A: u256,
最小数量B: u256,
到: 地址
) -> u256;
/// 移除流动性
///
/// # 参数
/// - `流动性`: 流动性代币数量
/// - `最小数量A`: 最小资产A数量
/// - `最小数量B`: 最小资产B数量
/// - `到`: 接收资产的地址
///
/// # 返回
/// - `(u256, u256)`: 返回的资产A和B数量
///
/// # 事件
/// - `移除流动性事件`
函数 移除流动性(
流动性: u256,
最小数量A: u256,
最小数量B: u256,
到: 地址
) -> (u256, u256);
/// 兑换资产
///
/// # 参数
/// - `输入量`: 输入资产数量
/// - `最小输出量`: 最小输出资产数量
/// - `路径`: 兑换路径(资产地址数组)
/// - `到`: 接收资产的地址
///
/// # 返回
/// - `u256`: 实际输出数量
///
/// # 事件
/// - `兑换事件`
函数 兑换(
输入量: u256,
最小输出量: u256,
路径: 数组<地址>,
到: 地址
) -> u256;
}
// ============================================================================
// 借贷协议接口
// ============================================================================
/// 借贷协议接口
///
/// 定义借贷市场的标准操作
接口 借贷协议 {
// ========== 查询函数 ==========
/// 查询资产地址
函数 资产() -> 地址;
/// 查询总存款
函数 总存款() -> u256;
/// 查询总借款
函数 总借款() -> u256;
/// 查询用户存款
///
/// # 参数
/// - `用户`: 用户地址
函数 用户存款(用户: 地址) -> u256;
/// 查询用户借款
///
/// # 参数
/// - `用户`: 用户地址
函数 用户借款(用户: 地址) -> u256;
/// 查询用户抵押品
///
/// # 参数
/// - `用户`: 用户地址
函数 用户抵押品(用户: 地址) -> u256;
/// 查询存款利率
函数 存款利率() -> u256;
/// 查询借款利率
函数 借款利率() -> u256;
/// 查询抵押率
函数 抵押率() -> u256;
/// 查询清算阈值
函数 清算阈值() -> u256;
// ========== 状态变更函数 ==========
/// 存款
///
/// # 参数
/// - `数量`: 存款数量
///
/// # 事件
/// - `存款事件`
函数 存款(数量: u256);
/// 取款
///
/// # 参数
/// - `数量`: 取款数量
///
/// # 事件
/// - `取款事件`
函数 取款(数量: u256);
/// 借款
///
/// # 参数
/// - `数量`: 借款数量
///
/// # 事件
/// - `借款事件`
函数 借款(数量: u256);
/// 还款
///
/// # 参数
/// - `数量`: 还款数量
///
/// # 事件
/// - `还款事件`
函数 还款(数量: u256);
/// 存入抵押品
///
/// # 参数
/// - `数量`: 抵押品数量
///
/// # 事件
/// - `抵押事件`
函数 抵押(数量: u256);
/// 取出抵押品
///
/// # 参数
/// - `数量`: 抵押品数量
///
/// # 事件
/// - `取消抵押事件`
函数 取消抵押(数量: u256);
/// 清算
///
/// # 参数
/// - `借款人`: 被清算的借款人地址
/// - `数量`: 清算数量
///
/// # 事件
/// - `清算事件`
函数 清算(借款人: 地址, 数量: u256);
}
// ============================================================================
// 质押协议接口
// ============================================================================
/// 质押协议接口
///
/// 定义质押挖矿的标准操作
接口 质押协议 {
// ========== 查询函数 ==========
/// 查询质押资产地址
函数 质押资产() -> 地址;
/// 查询奖励资产地址
函数 奖励资产() -> 地址;
/// 查询总质押量
函数 总质押量() -> u256;
/// 查询用户质押量
///
/// # 参数
/// - `用户`: 用户地址
函数 用户质押量(用户: 地址) -> u256;
/// 查询待领取奖励
///
/// # 参数
/// - `用户`: 用户地址
函数 待领取奖励(用户: 地址) -> u256;
/// 查询奖励速率
函数 奖励速率() -> u256;
// ========== 状态变更函数 ==========
/// 质押
///
/// # 参数
/// - `数量`: 质押数量
///
/// # 事件
/// - `质押事件`
函数 质押(数量: u256);
/// 取消质押
///
/// # 参数
/// - `数量`: 取消质押数量
///
/// # 事件
/// - `取消质押事件`
函数 取消质押(数量: u256);
/// 领取奖励
///
/// # 事件
/// - `领取奖励事件`
函数 领取奖励();
}
// ============================================================================
// DeFi事件定义
// ============================================================================
/// 添加流动性事件
事件 添加流动性事件 {
提供者: 地址,
数量A: u256,
数量B: u256,
流动性: u256
}
/// 移除流动性事件
事件 移除流动性事件 {
提供者: 地址,
数量A: u256,
数量B: u256,
流动性: u256
}
/// 兑换事件
事件 兑换事件 {
发送者: 地址,
输入量: u256,
输出量: u256,
到: 地址
}
/// 存款事件
事件 存款事件 {
用户: 地址,
数量: u256
}
/// 取款事件
事件 取款事件 {
用户: 地址,
数量: u256
}
/// 借款事件
事件 借款事件 {
借款人: 地址,
数量: u256
}
/// 还款事件
事件 还款事件 {
借款人: 地址,
数量: u256
}
/// 抵押事件
事件 抵押事件 {
用户: 地址,
数量: u256
}
/// 取消抵押事件
事件 取消抵押事件 {
用户: 地址,
数量: u256
}
/// 清算事件
事件 清算事件 {
清算人: 地址,
借款人: 地址,
数量: u256,
抵押品数量: u256
}
/// 质押事件
事件 质押事件 {
用户: 地址,
数量: u256
}
/// 取消质押事件
事件 取消质押事件 {
用户: 地址,
数量: u256
}
/// 领取奖励事件
事件 领取奖励事件 {
用户: 地址,
数量: u256
}
// ============================================================================
// 流动性池基础实现
// ============================================================================
/// 流动性池基础实现
合约 流动性池基础 实现 流动性池 {
// ========== 状态变量 ==========
私有 _资产A: 地址;
私有 _资产B: 地址;
私有 _储备量A: u256;
私有 _储备量B: u256;
私有 _流动性总量: u256;
私有 _用户流动性: 映射<地址, u256>;
私有 常量 _最小流动性: u256 = 1000;
私有 常量 _手续费率: u256 = 3; // 0.3%
// ========== 构造函数 ==========
构造函数(资产A: 地址, 资产B: 地址) {
要求(资产A != 地址::零地址() && 资产B != 地址::零地址(), "流动性池: 资产地址无效");
要求(资产A != 资产B, "流动性池: 资产相同");
_资产A = 资产A;
_资产B = 资产B;
_储备量A = 0;
_储备量B = 0;
_流动性总量 = 0;
}
// ========== 查询函数实现 ==========
函数 资产A() -> 地址 {
返回 _资产A;
}
函数 资产B() -> 地址 {
返回 _资产B;
}
函数 储备量A() -> u256 {
返回 _储备量A;
}
函数 储备量B() -> u256 {
返回 _储备量B;
}
函数 流动性总量() -> u256 {
返回 _流动性总量;
}
函数 用户流动性(提供者: 地址) -> u256 {
返回 _用户流动性.获取或默认(提供者, 0);
}
函数 计算输出量(输入量: u256, 输入储备: u256, 输出储备: u256) -> u256 {
要求(输入量 > 0, "流动性池: 输入量无效");
要求(输入储备 > 0 && 输出储备 > 0, "流动性池: 储备量无效");
让 扣除手续费输入 = 输入量 * (1000 - _手续费率);
让 分子 = 扣除手续费输入 * 输出储备;
让 分母 = 输入储备 * 1000 + 扣除手续费输入;
返回 分子 / 分母;
}
// ========== 状态变更函数实现 ==========
函数 添加流动性(
数量A: u256,
数量B: u256,
最小数量A: u256,
最小数量B: u256,
到: 地址
) -> u256 {
要求(数量A >= 最小数量A && 数量B >= 最小数量B, "流动性池: 数量不足");
要求(到 != 地址::零地址(), "流动性池: 接收地址无效");
让 流动性: u256;
如果 _流动性总量 == 0 {
// 首次添加流动性
流动性 = (数量A * 数量B).开平方根() - _最小流动性;
_流动性总量 = _最小流动性; // 锁定最小流动性
} 否则 {
// 后续添加流动性
让 流动性A = 数量A * _流动性总量 / _储备量A;
让 流动性B = 数量B * _流动性总量 / _储备量B;
流动性 = 如果 流动性A < 流动性B { 流动性A } 否则 { 流动性B };
}
要求(流动性 > 0, "流动性池: 流动性不足");
// 转入资产
ACC20(_资产A).转移从(消息::发送者(), 本合约::地址(), 数量A);
ACC20(_资产B).转移从(消息::发送者(), 本合约::地址(), 数量B);
// 更新状态
_储备量A = _储备量A + 数量A;
_储备量B = _储备量B + 数量B;
_流动性总量 = _流动性总量 + 流动性;
_用户流动性.插入(到, 用户流动性(到) + 流动性);
触发 添加流动性事件 {
提供者: 到,
数量A: 数量A,
数量B: 数量B,
流动性: 流动性
};
返回 流动性;
}
函数 移除流动性(
流动性: u256,
最小数量A: u256,
最小数量B: u256,
到: 地址
) -> (u256, u256) {
要求(流动性 > 0, "流动性池: 流动性无效");
要求(到 != 地址::零地址(), "流动性池: 接收地址无效");
要求(用户流动性(消息::发送者()) >= 流动性, "流动性池: 流动性不足");
// 计算返还数量
让 数量A = 流动性 * _储备量A / _流动性总量;
让 数量B = 流动性 * _储备量B / _流动性总量;
要求(数量A >= 最小数量A && 数量B >= 最小数量B, "流动性池: 数量不足");
// 更新状态
_用户流动性.插入(消息::发送者(), 用户流动性(消息::发送者()) - 流动性);
_流动性总量 = _流动性总量 - 流动性;
_储备量A = _储备量A - 数量A;
_储备量B = _储备量B - 数量B;
// 转出资产
ACC20(_资产A).转移(到, 数量A);
ACC20(_资产B).转移(到, 数量B);
触发 移除流动性事件 {
提供者: 消息::发送者(),
数量A: 数量A,
数量B: 数量B,
流动性: 流动性
};
返回 (数量A, 数量B);
}
函数 兑换(
输入量: u256,
最小输出量: u256,
路径: 数组<地址>,
到: 地址
) -> u256 {
要求(路径.长度() >= 2, "流动性池: 路径无效");
要求(输入量 > 0, "流动性池: 输入量无效");
要求(到 != 地址::零地址(), "流动性池: 接收地址无效");
// 简化实现:只支持直接兑换
要求(路径.长度() == 2, "流动性池: 只支持直接兑换");
要求((路径[0] == _资产A && 路径[1] == _资产B) ||
(路径[0] == _资产B && 路径[1] == _资产A),
"流动性池: 路径不匹配");
让 输出量: u256;
如果 路径[0] == _资产A {
// A -> B
输出量 = 计算输出量(输入量, _储备量A, _储备量B);
要求(输出量 >= 最小输出量, "流动性池: 输出量不足");
// 转入A转出B
ACC20(_资产A).转移从(消息::发送者(), 本合约::地址(), 输入量);
ACC20(_资产B).转移(到, 输出量);
// 更新储备
_储备量A = _储备量A + 输入量;
_储备量B = _储备量B - 输出量;
} 否则 {
// B -> A
输出量 = 计算输出量(输入量, _储备量B, _储备量A);
要求(输出量 >= 最小输出量, "流动性池: 输出量不足");
// 转入B转出A
ACC20(_资产B).转移从(消息::发送者(), 本合约::地址(), 输入量);
ACC20(_资产A).转移(到, 输出量);
// 更新储备
_储备量B = _储备量B + 输入量;
_储备量A = _储备量A - 输出量;
}
触发 兑换事件 {
发送者: 消息::发送者(),
输入量: 输入量,
输出量: 输出量,
到: 到
};
返回 输出量;
}
}