自定义错误
在上一课“abort和assert”中,我们学习了如何在需要的特定情况下故意“抛出”错误。当错误被抛出后,应用程序需要解析错误信息,并以设计的方式表现,例如弹出错误模态窗口。
应用程序如何识别特定错误呢?中止代码是关键,在一个模块中,你需要管理所有中止情况,并用中止代码标识它们,将它们声明为常量:
// battle.move
/// 战斗双方之一或双方都处于战斗冷却中
const EBattleCooldown: u64 = 0;
中止代码或错误代码的命名约定是驼峰命名法,以大写字母E开头。
在特定情况下使用常量中止:
// battle.move
entry fun battle(...) {
...
// 3. 检查战斗冷却
let current_timestamp = clock::timestamp_ms(clock);
assert!(core::get_castle_battle_cooldown(&attacker) < current_timestamp, EBattleCooldown);
assert!(core::get_castle_battle_cooldown(&defender) < current_timestamp, EBattleCooldown);
...
}
core.move
中的其他中止情况:
/// 士兵数量超过限制
const ESoldierCountLimit: u64 = 0;
/// 招募士兵的资金不足
const EInsufficientTreasury: u64 = 1;
/// 战斗城堡数量不足
const ENotEnoughCastles: u64 = 2;
情况:
public(package) fun recruit_soldiers(...) {
...
// 2. 检查数量限制
let final_soldiers = castle_data.millitary.soldiers + count;
assert!(final_soldiers <= get_castle_soldier_limit(castle_data.size), ESoldierCountLimit);
// 3. 检查资金充足性
let total_soldier_price = SOLDIER_PRICE * count;
assert!(castle_data.economy.treasury >= total_soldier_price, EInsufficientTreasury);
...
}
public fun random_battle_target(...) {
let total_length = vector::length<ID>(&game_store.castle_ids);
assert!(total_length > 1, ENotEnoughCastles);
...
}
在 Castle.move
中,我们漏掉了一个情况,当建造城堡时,每个城堡大小都有数量限制,我们需要在build_castle
函数的开头进行数量检查。
在 core.move
中添加一个函数来检查每种大小城堡的数量:
public(package) fun allow_new_castle(size: u64, game_store: &GameStore): bool {
let allow;
if (size == CASTLE_SIZE_SMALL) {
allow = game_store.small_castle_count < CASTLE_AMOUNT_LIMIT_SMALL;
} else if (size == CASTLE_SIZE_MIDDLE) {
allow = game_store.middle_castle_count < CASTLE_AMOUNT_LIMIT_MIDDLE;
} else if (size == CASTLE_SIZE_BIG) {
allow = game_store.big_castle_count < CASTLE_AMOUNT_LIMIT_BIG;
} else {
abort 0
};
allow
}
/// 城堡数量限制 - 小
const CASTLE_AMOUNT_LIMIT_SMALL : u64 = 500;
/// 城堡数量限制 - 中
const CASTLE_AMOUNT_LIMIT_MIDDLE : u64 = 300;
/// 城堡数量限制 - 大
const CASTLE_AMOUNT_LIMIT_BIG : u64 = 200;
在 castle.move
中的 build_castle
函数中添加断言:
entry fun build_castle(...) {
// 城堡数量检查
assert!(core::allow_new_castle(size, game_store), ECastleAmountLimit);
...
}
const ECastleAmountLimit: u64 = 0;