Sui Move 实现一个简单的无需管理的自动开奖系统 —— Self-service lottery
维护发布的所有彩票信息,以及系统发布者的收入。
public struct LotterySystem has key {
id: UID,
lotteries: Table<ID, Lottery>,
ls_income: Balance<SUI>,
}
维护彩票信息,包括剩余可售数量、终止日期、单价、总奖金数等。
public struct Lottery has store {
lottery_name: String,
price: u64,
total_amount: u64,
remaining_amount: u64,
end_epoch: u64,
bonus: Balance<SUI>,
announcement: bool,
winner_code: vector<u8>,
income: Balance<SUI>,
creater: address,
}
存储有所购买的彩票的唯一编码,以及对应的兑奖码。
public struct LotteryStub has key {
id: UID,
lottery_id: ID,
code: vector<u8>,
}
为了让系统管理员提现更安全,使用 $\mathit {One}$-$\mathit {Time}$-$\mathit {Witness}$ 来生成唯一的Publisher
并转移给他/她。
public struct SELF_SERVICE_LOTTERY has drop {}
为了让系统运行过程中的一些流程更加公开透明,在关键节点将触发事件信息进行公示。
public struct NewLotteryEvent has copy, drop {
lottery_id: ID,
lottery_name: String,
price: u64,
total_amount: u64,
end_epoch: u64,
bonus_value: u64,
}
public struct WinEvent has copy, drop {
lottery_name: String,
winner_code: vector<u8>,
}
public struct EndEvent has copy, drop {
hint: String,
}
生成唯一的Publisher
,同时构造并共享LotterySystem
。
fun init(otw: SELF_SERVICE_LOTTERY, ctx: &mut TxContext) {
// generate Publisher and transfer it
package::claim_and_keep(otw, ctx);
// generate LotterySystem and share it
transfer::share_object(LotterySystem {
id: object::new(ctx),
lotteries: table::new<ID, Lottery>(ctx),
ls_income: balance::zero(),
});
}
Publisher
只用作身份确认,所以用_
来表示函数中并不会实际使用。<br>当且仅当收入不为零时,将所有收入转入个人账户。
entry fun withdraw(_: &Publisher, lottery_system: &mut LotterySystem, ctx: &mut TxContext) {
// check coin value
let amount = lottery_system.ls_income.value();
assert!(amount > 0, ENotIncome);
// withdraw income
transfer::public_transfer(coin::from_balance(lottery_system.ls_income.split(amount), ctx), ctx.sender());
}
根据是否自定义可售期限,提供了两个方法:create_lottery
和create_lottery_with_epoch
,它们都将接受彩票的基本信息来生成一套可供售卖的彩票,唯一的区别是可售期限是否为默认。一旦创建成功,将触发事件信息公示这一款全新的彩票的基础信息。
entry fun create_lottery(lottery_system: &mut LotterySystem, lottery_name: String, price: u64, total_amount: u64, bonus: Coin<SUI>, ctx: &mut TxContext) {
// default continuous 15 epoch
create_lottery_with_epoch(lottery_system, lottery_name, price, total_amount, 15, bonus, ctx);
}
entry fun create_lottery_with_epoch(lottery_system: &mut LotterySystem, lottery_name: String, price: u64, total_amount: u64, continuous_epoch: u64, bonus: Coin<SUI>, ctx: &mut TxContext) {
// check bonus value
assert!(bonus.value() > 0, ENotBonus);
// generate Lottery ID
let lottery_id = object::id_from_address(ctx.fresh_object_address());
// generate Lottery
let lottery = Lottery {
lottery_name,
price,
total_amount,
remaining_amount: total_amount,
end_epoch: ctx.epoch() + continuous_epoch,
bonus: bonus.into_balance(),
announcement: false,
winner_code: vector<u8>[],
income: balance::zero(),
creater: ctx.sender(),
};
// emit event
event::emit(NewLotteryEvent {
lottery_id,
lottery_name,
price,
total_amount,
end_epoch: ctx.epoch() + continuous_epoch,
bonus_value: lottery.bonus.value(),
});
// store it
lottery_system.lotteries.add(lottery_id, lottery);
}
当且仅当该套彩票一张未售,或者开奖后超过了兑奖期限时,可以通过此方法赎回奖金。
entry fun fedeem_bonus(lottery_system: &mut LotterySystem, lottery_id: ID, ctx: &mut TxContext) {
// check lottery_id
assert!(lottery_system.lotteries.contains(lottery_id), ENotCorrectLotteryID);
// get Lottery
let mut lottery = lottery_system.lotteries.remove(lottery_id);
// check sales status and epoch
assert!(lottery.total_amount == lottery.remaining_amount || ctx.epoch() > lottery.end_epoch + 15, ENotFedeem);
calculate_fee(lottery_system, &mut lottery.income);
destroy_lottery(lottery, ctx);
}
fun calculate_fee(lottery_system: &mut LotterySystem, income: &mut Balance<SUI>) {
// calc fee amount(1%)
let amount = income.value() / 100;
if (amount > 0) {
lottery_system.ls_income.join(income.split(amount));
};
}
fun destroy_lottery(lottery: Lottery, ctx: &mut TxContext) {
let Lottery {
lottery_name: _,
price: _,
total_amount: _,
remaining_amount: _,
end_epoch: _,
bonus,
announcement: _,
mut winner_code,
mut income,
creater,
} = lottery;
// destroy winner_code
while (winner_code.length() > 0) {
winner_code.pop_back();
};
winner_code.destroy_empty();
// destroy bonus
if (bonus.value() > 0) {
income.join(bonus);
} else {
bonus.destroy_zero();
};
// transfer income
transfer::public_transfer(coin::from_balance(income, ctx), creater);
}
其中,calculate_fee
的功能是计算将提供给系统管理者多少分成,destroy_lottery
是摧毁一套彩票,将里面所包含的 $\mathit {SUI}$ 转入个人账户。<br>在转账过程中,bonus
和income
不可能都为零,而且同时支持赎回奖金以及中奖者兑奖后的彩票收入提现。
当彩票售罄时将自动触发开奖,如果超过了购买日期,所有人也可以手动触发。<br>随机过程使用了hmac_sha3_256
来生成一系列数字,并对这一系列数字进行运算得到第几个购买者为中奖者,再用同样的方法生成该顾客手上的兑奖码进行公示。
entry fun announcement(lottery_system: &mut LotterySystem, lottery_id: ID, ctx: &mut TxContext) {
// check lottery_id
assert!(lottery_system.lotteries.contains(lottery_id), ENotCorrectLotteryID);
// get Lottery
let lottery = &mut lottery_system.lotteries[lottery_id];
// check announcement
assert!(!lottery.announcement, EHasBeenEnded);
// check epoch
assert!(ctx.epoch() > lottery.end_epoch || lottery.remaining_amount == 0, ENotEnded);
// sell nothing
if (lottery.total_amount == lottery.remaining_amount) {
fedeem_bonus(lottery_system, lottery_id, ctx);
return
};
// random the winner
lottery.announcement = true;
let index = calculate(lottery.total_amount, lottery.remaining_amount, ctx.fresh_object_address().to_bytes());
lottery.winner_code = hmac_sha3_256(&bcs::to_bytes(&index), &object::id_to_bytes(&lottery_id));
// emit event
event::emit(WinEvent {
lottery_name: lottery.lottery_name,
winner_code: lottery.winner_code,
});
}
fun calculate(total: u64, remaining: u64, mut bytes: vector<u8>): u64 {
let mut bytes1 = hmac_sha3_256(&bcs::to_bytes(&total), &bytes);
bytes = hmac_sha3_256(&bcs::to_bytes(&remaining), &bytes1);
// destroy bytes1
while (bytes1.length() > 0) {
bytes1.pop_back();
};
bytes1.destroy_empty();
// calculate
let mut index = 1;
let d = total - remaining;
while (bytes.length() > 0) {
let byte = bytes.pop_back() as u64;
index = (index * (byte % d + 1)) % d + 1;
};
// destroy bytes
bytes.destroy_empty();
index
}
未售罄且未超过可售日期时,将根据你是第几个购买者来生成兑奖码并返回凭证,其中要关注传入的货币的处理,此外,如果你购买的是最后一张彩票,那么将自动开奖。
entry fun buy_lottery(lottery_system: &mut LotterySystem, lottery_id: ID, mut sui: Coin<SUI>, ctx: &mut TxContext) {
// check lottery_id
assert!(lottery_system.lotteries.contains(lottery_id), ENotCorrectLotteryID);
// get Lottery
let lottery = &mut lottery_system.lotteries[lottery_id];
// check announcement
assert!(!lottery.announcement, EHasBeenEnded);
// check sui value
assert!(sui.value() >= lottery.price, ENotEnoughCoin);
// check epoch
if (ctx.epoch() > lottery.end_epoch || lottery.remaining_amount == 0) {
announcement(lottery_system, lottery_id, ctx);
event::emit(EndEvent {
hint: string::utf8(b"The lottery ticket you purchased has ended!")
});
transfer::public_transfer(sui, ctx.sender());
return
};
// deal with sui
if (sui.value() == lottery.price) {
lottery.income.join(sui.into_balance());
} else {
lottery.income.join(sui.split(lottery.price, ctx).into_balance());
transfer::public_transfer(sui, ctx.sender());
};
// update remaining amount and generate code
lottery.remaining_amount = lottery.remaining_amount - 1;
let index = lottery.total_amount - lottery.remaining_amount;
let code = hmac_sha3_256(&bcs::to_bytes(&index), &object::id_to_bytes(&lottery_id));
// generate and transfer LotteryStub
transfer::transfer(LotteryStub {
id: object::new(ctx),
lottery_id,
code,
}, ctx.sender());
// check sell out
if (lottery.remaining_amount == 0) {
announcement(lottery_system, lottery_id, ctx);
};
}
凭借彩票购买凭证进行兑奖,系统将进行一系列判断并给出事件信息进行通知,如果兑奖成功,则奖金自动转入获奖者个人账户。
entry fun redeem_lottery(lottery_system: &mut LotterySystem, lottery_stub: LotteryStub, ctx: &mut TxContext) {
// get lottery id
let lottery_id = lottery_stub.lottery_id;
if (!lottery_system.lotteries.contains(lottery_id)) {
destroy_lottery_stub(lottery_stub);
event::emit(EndEvent {
hint: string::utf8(b"You have not won a prize or the redemption period has expired!")
});
return
};
// get lottery
let lottery = &mut lottery_system.lotteries[lottery_id];
if (!lottery.announcement && (ctx.epoch() > lottery.end_epoch || lottery.remaining_amount == 0)) {
announcement(lottery_system, lottery_id, ctx);
event::emit(EndEvent {
hint: string::utf8(b"The lottery has just been drawn, please check and redeem again!")
});
transfer::transfer(lottery_stub, ctx.sender());
return
};
// check announcement
assert!(lottery.announcement, ENotOpenLottery);
// check winner code
if (lottery.winner_code == lottery_stub.code) {
// Winner
let amount = lottery.bonus.value();
transfer::public_transfer(coin::from_balance(lottery.bonus.split(amount), ctx), ctx.sender());
// calculate_fee(lottery_system, &mut lottery.income);
// calc fee amount(1%)
let amount = lottery.income.value() / 100;
if (amount > 0) {
lottery_system.ls_income.join(lottery.income.split(amount));
};
destroy_lottery(lottery_system.lotteries.remove(lottery_id), ctx);
} else {
// Loser
event::emit(EndEvent {
hint: string::utf8(b"Unfortunately, the lottery you purchased did not win a prize!")
});
};
destroy_lottery_stub(lottery_stub);
}
sui client publish --gas-budget 100000000
╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Object Changes │
├─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Created Objects: │
│ ┌── │
│ │ ObjectID: 0x469b2b4e2c59821d831e4726a73a74c1e117b80383eeae2041cf9b4ea242c0be │
│ │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 │
│ │ Owner: Account Address ( 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 ) │
│ │ ObjectType: 0x2::package::Publisher │
│ │ Version: 28132105 │
│ │ Digest: H9s7atWdJs4vG7YLTyFvUHqkMnBXQ1rQ2gTBsNKgfjPj │
│ └── │
│ ┌── │
│ │ ObjectID: 0xdb674c063a7c4e3270d6b558adf3feb333da3498c044801d3d4680361ad077f1 │
│ │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 │
│ │ Owner: Account Address ( 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 ) │
│ │ ObjectType: 0x2::package::UpgradeCap │
│ │ Version: 28132105 │
│ │ Digest: 9cjzK99qYszLtcLLYPN4t1GdVuWZ6piips62AkLP7QLq │
│ └── │
│ ┌── │
│ │ ObjectID: 0xf430c82e627840a1c98439565974de87c1078b4be5014843f69d2702c1ae270f │
│ │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 │
│ │ Owner: Shared( 28132105 ) │
│ │ ObjectType: 0xd57f516962ac634529d9a8005812462bce04cc89b457b566232dd818ab2aa9bd::self_service_lottery::LotterySystem │
│ │ Version: 28132105 │
│ │ Digest: AxJJHX3tsPP3QCLbduZkGfZbx9vxtkHRpv8YSbMGYaSz │
│ └── │
│ Mutated Objects: │
│ ┌── │
│ │ ObjectID: 0x01676de212960b0689245914312ac6be3b4d5cffa0cae91ef527441b894f746a │
│ │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 │
│ │ Owner: Account Address ( 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 ) │
│ │ ObjectType: 0x2::coin::Coin<0x2::sui::SUI> │
│ │ Version: 28132105 │
│ │ Digest: 4DLokvD6fC9WndtSz1eqDsp1xd9sBaxi5oLTXB9ZzBpk │
│ └── │
│ Published Objects: │
│ ┌── │
│ │ PackageID: 0xd57f516962ac634529d9a8005812462bce04cc89b457b566232dd818ab2aa9bd │
│ │ Version: 1 │
│ │ Digest: 8MZ5RzHENjhzxKasWX4Ut1aHRFvFvjTHssSGurqfojTv │
│ │ Modules: self_service_lottery │
│ └── │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
export PACKAGE=0xd57f516962ac634529d9a8005812462bce04cc89b457b566232dd818ab2aa9bd
export PUBLISHER=0x469b2b4e2c59821d831e4726a73a74c1e117b80383eeae2041cf9b4ea242c0be
export LOTTERYSYSTEM=0xf430c82e627840a1c98439565974de87c1078b4be5014843f69d2702c1ae270f
sui client gas
# output:
╭────────────────────────────────────────────────────────────────────┬────────────────────┬──────────────────╮
│ gasCoinId │ mistBalance (MIST) │ suiBalance (SUI) │
├────────────────────────────────────────────────────────────────────┼────────────────────┼──────────────────┤
│ 0x01676de212960b0689245914312ac6be3b4d5cffa0cae91ef527441b894f746a │ 2781685426 │ 2.78 │
│ 0x4138ff0b0ff27eeb46fcfb24da66059bb013e0bc05e39f47eea9dd969cff4d67 │ 1000000000 │ 1.00 │
│ 0x9b6a8d50f03bd3957e6fb5248bbc4e530f327fc4e42c8dfb27eafb2e9f45f093 │ 1000000000 │ 1.00 │
╰────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────╯
export COIN=0x4138ff0b0ff27eeb46fcfb24da66059bb013e0bc05e39f47eea9dd969cff4d67
sui client call --package $PACKAGE --module self_service_lottery --function create_lottery --args $LOTTERYSYSTEM "TestLottery" 500000000 2 $COIN --gas-budget 100000000
╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Transaction Block Events │
├─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ ┌── │
│ │ EventID: 7z4J6fGGdhEXj621mezkKwcJs1Qun4smHRaTqc9Uv3cF:0 │
│ │ PackageID: 0xd57f516962ac634529d9a8005812462bce04cc89b457b566232dd818ab2aa9bd │
│ │ Transaction Module: self_service_lottery │
│ │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 │
│ │ EventType: 0xd57f516962ac634529d9a8005812462bce04cc89b457b566232dd818ab2aa9bd::self_service_lottery::NewLotteryEvent │
│ │ ParsedJSON: │
│ │ ┌──────────────┬────────────────────────────────────────────────────────────────────┐ │
│ │ │ bonus_value │ 1000000000 │ │
│ │ ├──────────────┼────────────────────────────────────────────────────────────────────┤ │
│ │ │ end_epoch │ 397 │ │
│ │ ├──────────────┼────────────────────────────────────────────────────────────────────┤ │
│ │ │ lottery_id │ 0x4e18914e22f53858dff84c0d1496c8b7df70ff6015b3d7a4a673b8aa690c43b6 │ │
│ │ ├──────────────┼────────────────────────────────────────────────────────────────────┤ │
│ │ │ lottery_name │ TestLottery │ │
│ │ ├──────────────┼────────────────────────────────────────────────────────────────────┤ │
│ │ │ price │ 500000000 │ │
│ │ ├──────────────┼────────────────────────────────────────────────────────────────────┤ │
│ │ │ total_amount │ 2 │ │
│ │ └──────────────┴────────────────────────────────────────────────────────────────────┘ │
│ └── │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
export LOTTERY=0x4e18914e22f53858dff84c0d1496c8b7df70ff6015b3d7a4a673b8aa690c43b6
sui client gas
# output:
╭────────────────────────────────────────────────────────────────────┬────────────────────┬──────────────────╮
│ gasCoinId │ mistBalance (MIST) │ suiBalance (SUI) │
├────────────────────────────────────────────────────────────────────┼────────────────────┼──────────────────┤
│ 0x01676de212960b0689245914312ac6be3b4d5cffa0cae91ef527441b894f746a │ 2778534778 │ 2.77 │
│ 0x9b6a8d50f03bd3957e6fb5248bbc4e530f327fc4e42c8dfb27eafb2e9f45f093 │ 1000000000 │ 1.00 │
╰────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────╯
export COIN=0x9b6a8d50f03bd3957e6fb5248bbc4e530f327fc4e42c8dfb27eafb2e9f45f093
sui client call --package $PACKAGE --module self_service_lottery --function buy_lottery --args $LOTTERYSYSTEM $LOTTERY $COIN --gas-budget 100000000
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Object Changes │
├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Created Objects: │
│ ┌── │
│ │ ObjectID: 0x5a482ff5935840c89728184c68c478bead87a866f5b6bfdbbbf5da96f65c7dc3 │
│ │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 │
│ │ Owner: Account Address ( 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 ) │
│ │ ObjectType: 0xd57f516962ac634529d9a8005812462bce04cc89b457b566232dd818ab2aa9bd::self_service_lottery::LotteryStub │
│ │ Version: 28132107 │
│ │ Digest: DpT2d3oC4iJzqUFbWg93GZNKm1hVDMekWoh5jCos9cCp │
│ └── │
│ Mutated Objects: │
│ ┌── │
│ │ ObjectID: 0x01676de212960b0689245914312ac6be3b4d5cffa0cae91ef527441b894f746a │
│ │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 │
│ │ Owner: Account Address ( 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 ) │
│ │ ObjectType: 0x2::coin::Coin<0x2::sui::SUI> │
│ │ Version: 28132107 │
│ │ Digest: 2M5DBUCvu9hfyGXZunSqdiE6VrBHK7Q6i6Yeq8SC1rRz │
│ └── │
│ ┌── │
│ │ ObjectID: 0x33ac04798ba0c6fca92804d42f579baad53bae331a097bbde809c4af2a0a33ae │
│ │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 │
│ │ Owner: Object ID: ( 0x2643e8a8fe0b861ee1d8fad4cd5ddeffd40df3792303975ce6847a9108dbbdd8 ) │
│ │ ObjectType: 0x2::dynamic_field::Field<0x2::object::ID, 0xd57f516962ac634529d9a8005812462bce04cc89b457b566232dd818ab2aa9bd::self_service_lottery::Lottery> │
│ │ Version: 28132107 │
│ │ Digest: 8uVWwgUJMG1LxWdhpTUXYxdGGdwTRfpKxPfTvU2Vs5MK │
│ └── │
│ ┌── │
│ │ ObjectID: 0x9b6a8d50f03bd3957e6fb5248bbc4e530f327fc4e42c8dfb27eafb2e9f45f093 │
│ │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 │
│ │ Owner: Account Address ( 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 ) │
│ │ ObjectType: 0x2::coin::Coin<0x2::sui::SUI> │
│ │ Version: 28132107 │
│ │ Digest: 56EMyGyKoGSKEhcyb7EHF4AtMQ1kRGSw3osBNRQwsPh │
│ └── │
│ ┌── │
│ │ ObjectID: 0xf430c82e627840a1c98439565974de87c1078b4be5014843f69d2702c1ae270f │
│ │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 │
│ │ Owner: Shared( 28132105 ) │
│ │ ObjectType: 0xd57f516962ac634529d9a8005812462bce04cc89b457b566232dd818ab2aa9bd::self_service_lottery::LotterySystem │
│ │ Version: 28132107 │
│ │ Digest: BdNzqt5Uimo7dQtp5UDjh371YuUR9WS1JN5AZrZMGymX │
│ └── │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
export LOTTERYSTUB1=0x5a482ff5935840c89728184c68c478bead87a866f5b6bfdbbbf5da96f65c7dc3
类似的,再购买一张,并设置export LOTTERYSTUB2=0xdd5b6a281e34104c3a9b3671ebe8fce770b68d75222a0b8844214972e9435ab5
<br>此时由于彩票买完,自动触发了开奖,可以从 $\mathit {Event}$ 信息当中看见开奖信息:
╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Transaction Block Events │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ ┌── │
│ │ EventID: FC812jAiEHLaNTtS66WRS9DQrxnGqa1bR81y7AHknNLh:0 │
│ │ PackageID: 0xd57f516962ac634529d9a8005812462bce04cc89b457b566232dd818ab2aa9bd │
│ │ Transaction Module: self_service_lottery │
│ │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 │
│ │ EventType: 0xd57f516962ac634529d9a8005812462bce04cc89b457b566232dd818ab2aa9bd::self_service_lottery::WinEvent │
│ │ ParsedJSON: │
│ │ ┌──────────────┬──────────────────────────────────────────────┐ │
│ │ │ lottery_name │ TestLottery │ │
│ │ ├──────────────┼──────────────────────────────────────────────┤ │
│ │ │ winner_code │ rbaG/MO6rqDo0Ad/lK79EACIDTbKMhb6bSL3MkllhRc= │ │
│ │ └──────────────┴──────────────────────────────────────────────┘ │
│ └── │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
sui client call --package $PACKAGE --module self_service_lottery --function redeem_lottery --args $LOTTERYSYSTEM $LOTTERYSTUB1 --gas-budget 100000000
没有触发事件信息,但是通过 $\mathit {Object\ Changes}$ 可以发现有 $\mathit {SUI}$ 变动,于是键入sui client gas
进行验证:
╭────────────────────────────────────────────────────────────────────┬────────────────────┬──────────────────╮
│ gasCoinId │ mistBalance (MIST) │ suiBalance (SUI) │
├────────────────────────────────────────────────────────────────────┼────────────────────┼──────────────────┤
│ 0x01676de212960b0689245914312ac6be3b4d5cffa0cae91ef527441b894f746a │ 2775506430 │ 2.77 │
│ 0x9bb06c48c6173af94ba38f41a7ddba227451abfdb4356e68851ba8497cfeca05 │ 1000000000 │ 1.00 │
│ 0xe9a9be9af022aa5846d4549a6d97200dcebe576561beaa025a51cdbd84e9c361 │ 990000000 │ 0.99 │
╰────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────╯
此时,如果再用第二个彩票凭证兑奖,会触发事件提醒,同时,凭证将被摧毁:
╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Transaction Block Events │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ ┌── │
│ │ EventID: 7eW7EgHkvtuhX6U2JGN3DjsedATNatcVpfttmFNNXD3:0 │
│ │ PackageID: 0xd57f516962ac634529d9a8005812462bce04cc89b457b566232dd818ab2aa9bd │
│ │ Transaction Module: self_service_lottery │
│ │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 │
│ │ EventType: 0xd57f516962ac634529d9a8005812462bce04cc89b457b566232dd818ab2aa9bd::self_service_lottery::EndEvent │
│ │ ParsedJSON: │
│ │ ┌──────┬────────────────────────────────────────────────────────────────┐ │
│ │ │ hint │ You have not won a prize or the redemption period has expired! │ │
│ │ └──────┴────────────────────────────────────────────────────────────────┘ │
│ └── │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
sui client call --package $PACKAGE --module self_service_lottery --function withdraw --args $PUBLISHER $LOTTERYSYSTEM --gas-budget 100000000
sui client gas
# output:
╭────────────────────────────────────────────────────────────────────┬────────────────────┬──────────────────╮
│ gasCoinId │ mistBalance (MIST) │ suiBalance (SUI) │
├────────────────────────────────────────────────────────────────────┼────────────────────┼──────────────────┤
│ 0x01676de212960b0689245914312ac6be3b4d5cffa0cae91ef527441b894f746a │ 2774346382 │ 2.77 │
│ 0x9bb06c48c6173af94ba38f41a7ddba227451abfdb4356e68851ba8497cfeca05 │ 1000000000 │ 1.00 │
│ 0xd107cdb05b93da5262fc2b5b9f03f9aa60539555303a1cf2ee935f1087787bee │ 10000000 │ 0.01 │
│ 0xe9a9be9af022aa5846d4549a6d97200dcebe576561beaa025a51cdbd84e9c361 │ 990000000 │ 0.99 │
╰────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────╯
通过简单计算可以发现,满足事先的预期。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!