///! 工具模块: 常用工具库 ///! NAC的通用工具函数集合 ///! ///! **版本**: v1.0 ///! **模块**: charter-std-zh/utils/utils.ch 使用 资产::gnacs::GNACS编码; // ============================================================================ // 数学工具库 // ============================================================================ /// 数学工具库 库 数学 { /// 最小值 /// /// # 参数 /// - `a`: 第一个数 /// - `b`: 第二个数 /// /// # 返回 /// - `u256`: 较小的数 函数 最小值(a: u256, b: u256) -> u256 { 如果 a < b { 返回 a; } 否则 { 返回 b; } } /// 最大值 /// /// # 参数 /// - `a`: 第一个数 /// - `b`: 第二个数 /// /// # 返回 /// - `u256`: 较大的数 函数 最大值(a: u256, b: u256) -> u256 { 如果 a > b { 返回 a; } 否则 { 返回 b; } } /// 平方根(牛顿迭代法) /// /// # 参数 /// - `x`: 输入值 /// /// # 返回 /// - `u256`: 平方根(向下取整) 函数 平方根(x: u256) -> u256 { 如果 x == 0 { 返回 0; } 让 可变 z = (x + 1) / 2; 让 可变 y = x; 循环 y > z { y = z; z = (x / z + z) / 2; } 返回 y; } /// 安全加法 /// /// # 参数 /// - `a`: 第一个数 /// - `b`: 第二个数 /// /// # 返回 /// - `u256`: 和 函数 安全加(a: u256, b: u256) -> u256 { 让 c = a + b; 要求(c >= a, "数学: 加法溢出"); 返回 c; } /// 安全减法 /// /// # 参数 /// - `a`: 被减数 /// - `b`: 减数 /// /// # 返回 /// - `u256`: 差 函数 安全减(a: u256, b: u256) -> u256 { 要求(b <= a, "数学: 减法下溢"); 返回 a - b; } /// 安全乘法 /// /// # 参数 /// - `a`: 第一个数 /// - `b`: 第二个数 /// /// # 返回 /// - `u256`: 积 函数 安全乘(a: u256, b: u256) -> u256 { 如果 a == 0 { 返回 0; } 让 c = a * b; 要求(c / a == b, "数学: 乘法溢出"); 返回 c; } /// 安全除法 /// /// # 参数 /// - `a`: 被除数 /// - `b`: 除数 /// /// # 返回 /// - `u256`: 商 函数 安全除(a: u256, b: u256) -> u256 { 要求(b > 0, "数学: 除数为零"); 返回 a / b; } /// 百分比计算 /// /// # 参数 /// - `数值`: 基数 /// - `百分比`: 百分比(基点,10000=100%) /// /// # 返回 /// - `u256`: 计算结果 函数 百分比(数值: u256, 百分比: u256) -> u256 { 返回 数值 * 百分比 / 10000; } } // ============================================================================ // 地址工具库 // ============================================================================ /// 地址工具库 库 地址工具 { /// 判断是否为合约地址 /// /// # 参数 /// - `地址`: 待检查的地址 /// /// # 返回 /// - `布尔`: 是否为合约地址 函数 是否为合约(地址: 地址) -> 布尔 { 让 代码大小 = 地址.代码大小(); 返回 代码大小 > 0; } /// 判断是否为零地址 /// /// # 参数 /// - `地址`: 待检查的地址 /// /// # 返回 /// - `布尔`: 是否为零地址 函数 是否为零地址(地址: 地址) -> 布尔 { 返回 地址 == 地址::零地址(); } /// 发送NAC币 /// /// # 参数 /// - `接收者`: 接收者地址 /// - `数量`: 发送数量 /// /// # 返回 /// - `布尔`: 是否发送成功 函数 发送(接收者: 地址, 数量: u256) -> 布尔 { 让 (成功, _) = 接收者.调用带值(数量, 字节数组::新建()); 返回 成功; } } // ============================================================================ // 字符串工具库 // ============================================================================ /// 字符串工具库 库 字符串工具 { /// 字符串长度 /// /// # 参数 /// - `字符串`: 输入字符串 /// /// # 返回 /// - `u256`: 字符串长度 函数 长度(字符串: 字符串) -> u256 { 返回 字符串.长度(); } /// 字符串拼接 /// /// # 参数 /// - `a`: 第一个字符串 /// - `b`: 第二个字符串 /// /// # 返回 /// - `字符串`: 拼接后的字符串 函数 拼接(a: 字符串, b: 字符串) -> 字符串 { 返回 a + b; } /// 字符串比较 /// /// # 参数 /// - `a`: 第一个字符串 /// - `b`: 第二个字符串 /// /// # 返回 /// - `布尔`: 是否相等 函数 相等(a: 字符串, b: 字符串) -> 布尔 { 返回 a == b; } /// 数字转字符串 /// /// # 参数 /// - `数字`: 输入数字 /// /// # 返回 /// - `字符串`: 字符串表示 函数 数字转字符串(数字: u256) -> 字符串 { 如果 数字 == 0 { 返回 "0"; } 让 可变 临时 = 数字; 让 可变 位数 = 0; 循环 临时 != 0 { 位数 = 位数 + 1; 临时 = 临时 / 10; } 让 可变 字节 = 字节数组::新建带容量(位数); 临时 = 数字; 对于 i 在 0..位数 { 字节[位数 - 1 - i] = (临时 % 10 + 48) 作为 u8; 临时 = 临时 / 10; } 返回 字符串::从字节(字节); } } // ============================================================================ // 数组工具库 // ============================================================================ /// 数组工具库 库 数组工具 { /// 数组求和 /// /// # 参数 /// - `数组`: 输入数组 /// /// # 返回 /// - `u256`: 数组元素之和 函数 求和(数组: 数组) -> u256 { 让 可变 总和 = 0; 对于 i 在 0..数组.长度() { 总和 = 总和 + 数组[i]; } 返回 总和; } /// 数组平均值 /// /// # 参数 /// - `数组`: 输入数组 /// /// # 返回 /// - `u256`: 数组元素平均值 函数 平均值(数组: 数组) -> u256 { 要求(数组.长度() > 0, "数组工具: 数组为空"); 返回 求和(数组) / 数组.长度(); } /// 数组最大值 /// /// # 参数 /// - `数组`: 输入数组 /// /// # 返回 /// - `u256`: 数组最大值 函数 最大值(数组: 数组) -> u256 { 要求(数组.长度() > 0, "数组工具: 数组为空"); 让 可变 最大 = 数组[0]; 对于 i 在 1..数组.长度() { 如果 数组[i] > 最大 { 最大 = 数组[i]; } } 返回 最大; } /// 数组最小值 /// /// # 参数 /// - `数组`: 输入数组 /// /// # 返回 /// - `u256`: 数组最小值 函数 最小值(数组: 数组) -> u256 { 要求(数组.长度() > 0, "数组工具: 数组为空"); 让 可变 最小 = 数组[0]; 对于 i 在 1..数组.长度() { 如果 数组[i] < 最小 { 最小 = 数组[i]; } } 返回 最小; } /// 数组包含元素 /// /// # 参数 /// - `数组`: 输入数组 /// - `元素`: 待查找元素 /// /// # 返回 /// - `布尔`: 是否包含 函数 包含(数组: 数组, 元素: u256) -> 布尔 { 对于 i 在 0..数组.长度() { 如果 数组[i] == 元素 { 返回 真; } } 返回 假; } } // ============================================================================ // 哈希工具库 // ============================================================================ /// 哈希工具库 库 哈希工具 { /// 计算SHA3-384哈希 /// /// # 参数 /// - `数据`: 输入数据 /// /// # 返回 /// - `哈希`: 48字节哈希值 函数 哈希384(数据: 字节数组) -> 哈希 { 返回 哈希::从字节(密码学::sha3_384(数据)); } /// 计算消息哈希 /// /// # 参数 /// - `消息`: 消息内容 /// /// # 返回 /// - `哈希`: 消息哈希 函数 消息哈希(消息: 字符串) -> 哈希 { 返回 哈希384(消息.作为字节()); } /// 计算地址哈希 /// /// # 参数 /// - `地址`: 地址 /// /// # 返回 /// - `哈希`: 地址哈希 函数 地址哈希(地址: 地址) -> 哈希 { 返回 哈希384(地址.作为字节()); } } // ============================================================================ // 时间工具库 // ============================================================================ /// 时间工具库 库 时间工具 { /// 获取当前时间戳 /// /// # 返回 /// - `u256`: 当前时间戳(秒) 函数 当前时间() -> u256 { 返回 区块::时间戳(); } /// 获取当前区块号 /// /// # 返回 /// - `u256`: 当前区块号 函数 当前区块() -> u256 { 返回 区块::号(); } /// 计算天数 /// /// # 参数 /// - `秒数`: 秒数 /// /// # 返回 /// - `u256`: 天数 函数 秒转天(秒数: u256) -> u256 { 返回 秒数 / 86400; } /// 计算小时数 /// /// # 参数 /// - `秒数`: 秒数 /// /// # 返回 /// - `u256`: 小时数 函数 秒转小时(秒数: u256) -> u256 { 返回 秒数 / 3600; } /// 计算分钟数 /// /// # 参数 /// - `秒数`: 秒数 /// /// # 返回 /// - `u256`: 分钟数 函数 秒转分钟(秒数: u256) -> u256 { 返回 秒数 / 60; } } // ============================================================================ // 权限控制工具 // ============================================================================ /// 可拥有合约 /// /// 提供基础的所有权管理功能 合约 可拥有 { 私有 _所有者: 地址; 事件 所有权转移 { 前所有者: 地址, 新所有者: 地址 } 构造函数() { _所有者 = 消息::发送者(); } 修饰符 仅所有者() { 要求(消息::发送者() == _所有者, "可拥有: 非所有者"); _; } 函数 所有者() -> 地址 { 返回 _所有者; } 函数 转移所有权(新所有者: 地址) 仅所有者 { 要求(新所有者 != 地址::零地址(), "可拥有: 新所有者地址无效"); 让 旧所有者 = _所有者; _所有者 = 新所有者; 触发 所有权转移 { 前所有者: 旧所有者, 新所有者: 新所有者 }; } 函数 放弃所有权() 仅所有者 { 让 旧所有者 = _所有者; _所有者 = 地址::零地址(); 触发 所有权转移 { 前所有者: 旧所有者, 新所有者: 地址::零地址() }; } } /// 可暂停合约 /// /// 提供暂停和恢复功能 合约 可暂停 实现 可拥有 { 私有 _已暂停: 布尔; 事件 暂停 {} 事件 恢复 {} 构造函数() { _已暂停 = 假; } 修饰符 未暂停() { 要求(!_已暂停, "可暂停: 已暂停"); _; } 修饰符 已暂停() { 要求(_已暂停, "可暂停: 未暂停"); _; } 函数 是否已暂停() -> 布尔 { 返回 _已暂停; } 函数 暂停() 仅所有者 未暂停 { _已暂停 = 真; 触发 暂停 {}; } 函数 恢复() 仅所有者 已暂停 { _已暂停 = 假; 触发 恢复 {}; } } // ============================================================================ // 重入保护 // ============================================================================ /// 重入保护合约 /// /// 防止重入攻击 合约 重入保护 { 私有 _状态: u256; 常量 未进入: u256 = 1; 常量 已进入: u256 = 2; 构造函数() { _状态 = 未进入; } 修饰符 防重入() { 要求(_状态 != 已进入, "重入保护: 重入调用"); _状态 = 已进入; _; _状态 = 未进入; } }