Sui Move 实现一个简单的无需管理的自动开奖系统 —— Self-service lottery

一:功能简介

  • 任何人都可以发布彩票,自定义售价、奖金、终止日期等基础信息。
  • 任何人都可以购买彩票并获得对应的购买凭证。
  • 当彩票售罄或者超过售卖日期时,任何人都可以调用开奖函数,获奖信息将公示。
  • 获奖者可凭票根兑奖,奖金将全额打入获奖者账户,与此同时,此彩票的收入将一分为二, 1 % \text 1\% 1% 将打入该彩票系统发布者账户,剩下的将打入该彩票发布者账户。
  • 若中奖者长期不兑奖,提供回收奖金功能,奖金将打回该彩票发布者账户,而彩票收入依旧按照上述比例分配。

二:结构设计

2.1 彩票系统

维护发布的所有彩票信息,以及系统发布者的收入。

public struct LotterySystem has key {
    id: UID,
    lotteries: Table<ID, Lottery>,
    ls_income: Balance<SUI>,
}

2.2 彩票

维护彩票信息,包括剩余可售数量、终止日期、单价、总奖金数等。

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,
}

2.3 购买凭证

存储有所购买的彩票的唯一编码,以及对应的兑奖码。

public struct LotteryStub has key {
    id: UID,
    lottery_id: ID,
    code: vector<u8>,
}

2.4 一次性见证与事件

为了让系统管理员提现更安全,使用 O n e \mathit {One} One- T i m e \mathit {Time} Time- W i t n e s s \mathit {Witness} 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,
}

三:功能实现

3.1 初始化

生成唯一的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(),
    });
}

3.2 系统构建者提现

Publisher只用作身份确认,所以用_来表示函数中并不会实际使用。
当且仅当收入不为零时,将所有收入转入个人账户。

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());
}

3.3 创建彩票

根据是否自定义可售期限,提供了两个方法:create_lotterycreate_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);
}

3.4 赎回奖金

当且仅当该套彩票一张未售,或者开奖后超过了兑奖期限时,可以通过此方法赎回奖金。

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是摧毁一套彩票,将里面所包含的 S U I \mathit {SUI} SUI 转入个人账户。
在转账过程中,bonusincome不可能都为零,而且同时支持赎回奖金以及中奖者兑奖后的彩票收入提现。

3.5 开奖公告

当彩票售罄时将自动触发开奖,如果超过了购买日期,所有人也可以手动触发。
随机过程使用了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
}

3.6 购买彩票

未售罄且未超过可售日期时,将根据你是第几个购买者来生成兑奖码并返回凭证,其中要关注传入的货币的处理,此外,如果你购买的是最后一张彩票,那么将自动开奖。

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);
    };
}

3.7 兑奖

凭借彩票购买凭证进行兑奖,系统将进行一系列判断并给出事件信息进行通知,如果兑奖成功,则奖金自动转入获奖者个人账户。

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);
}

四:部署上链及简单测试

4.1 发布

  • 运行命令

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 │ 27816854262.78             │
│ 0x4138ff0b0ff27eeb46fcfb24da66059bb013e0bc05e39f47eea9dd969cff4d67 │ 10000000001.00             │
│ 0x9b6a8d50f03bd3957e6fb5248bbc4e530f327fc4e42c8dfb27eafb2e9f45f093 │ 10000000001.00             │
╰────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────╯

export COIN=0x4138ff0b0ff27eeb46fcfb24da66059bb013e0bc05e39f47eea9dd969cff4d67

4.2 创建彩票

  • 运行命令

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 │ 27785347782.77             │
│ 0x9b6a8d50f03bd3957e6fb5248bbc4e530f327fc4e42c8dfb27eafb2e9f45f093 │ 10000000001.00             │
╰────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────╯

export COIN=0x9b6a8d50f03bd3957e6fb5248bbc4e530f327fc4e42c8dfb27eafb2e9f45f093

4.3 购买彩票

  • 运行命令

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
此时由于彩票买完,自动触发了开奖,可以从 E v e n t \mathit {Event} 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= │                                             │
│  │   └──────────────┴──────────────────────────────────────────────┘                                             │
│  └──                                                                                                             │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

4.4 兑奖

  • 运行命令

sui client call --package $PACKAGE --module self_service_lottery --function redeem_lottery --args $LOTTERYSYSTEM $LOTTERYSTUB1 --gas-budget 100000000

没有触发事件信息,但是通过 O b j e c t   C h a n g e s \mathit {Object\ Changes} Object Changes 可以发现有 S U I \mathit {SUI} SUI 变动,于是键入sui client gas进行验证:

╭────────────────────────────────────────────────────────────────────┬────────────────────┬──────────────────╮
│ gasCoinId                                                          │ mistBalance (MIST) │ suiBalance (SUI) │
├────────────────────────────────────────────────────────────────────┼────────────────────┼──────────────────┤
│ 0x01676de212960b0689245914312ac6be3b4d5cffa0cae91ef527441b894f746a │ 27755064302.77             │
│ 0x9bb06c48c6173af94ba38f41a7ddba227451abfdb4356e68851ba8497cfeca05 │ 10000000001.00             │
│ 0xe9a9be9af022aa5846d4549a6d97200dcebe576561beaa025a51cdbd84e9c361 │ 9900000000.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! │                                   │
│  │   └──────┴────────────────────────────────────────────────────────────────┘                                   │
│  └──                                                                                                             │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

4.5 提现

  • 运行命令

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 │ 27743463822.77             │
│ 0x9bb06c48c6173af94ba38f41a7ddba227451abfdb4356e68851ba8497cfeca05 │ 10000000001.00             │
│ 0xd107cdb05b93da5262fc2b5b9f03f9aa60539555303a1cf2ee935f1087787bee │ 100000000.01             │
│ 0xe9a9be9af022aa5846d4549a6d97200dcebe576561beaa025a51cdbd84e9c361 │ 9900000000.99             │
╰────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────╯

通过简单计算可以发现,满足事先的预期。

五:加入组织,共同进步!

  • 31
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值