sui move实现股票分红的一种实现

1.需求:使用suimove实现购买股票,根据股票分红sui支持把钱转给一个对象地址,提供一种机制,将对象地址拥有的钱,提取到这个对象的owner的钱包。如下图,12:用户A发布合约,拥有分红权限34:用户B花钱购买了股票,合约里面增加了钱5:将股票自由转移

1.需求: 使用sui move 实现购买股票,根据股票分红

sui 支持把钱转给一个对象地址, 提供一种机制,将对象地址拥有的钱,提取到这个对象的owner的钱包。

如下图,

image.png

1 2 : 用户A 发布合约,拥有分红权限

3 4 :用户B 花钱购买了股票 ,合约里面增加了钱

5 : 将股票自由转移给C,不需要通知用户A

6 :用户A 分红,将分红发给股票, 这个例子里面分红20%

----这里可能经过了很多运营,合约里面的钱增值了, 本文不涉及相关逻辑

7 :用户C 拿着股票,到合约来领取分红到钱包

image-20241203190809685

2. 样例代码

#[allow(lint(self_transfer),unused_use)]
module book::stock_market
{
    use sui::coin::{Self,Coin};
    use sui::sui::SUI;
    use sui::balance::{Self,Balance};
    use  sui::table::{Table,Self};
    use sui::transfer::{Receiving};
    //
    public struct Share  has store {
        id : address,
        amount : u64
    }

    public struct Shares has key {
        id : UID,
        count : u32,
        holders : Table<u32, Share > ,
        balances : Balance<SUI>,
        supply   : u64,

    }

    //控制权限,分红需要此权限
    public struct AdminCap has key{
        id : UID,
    }
    public struct Stock has key,store{
        id : UID,
        amount : u64,
    }
    fun init( ctx : &mut TxContext){
        let shares = Shares{
            id : object::new(ctx),
            count : 0,
            holders : table::new<u32,Share>(ctx),
            balances : balance::zero<SUI>(),
            supply : 0
        };
        transfer::share_object(shares);

        let admin = AdminCap{
            id : object::new(ctx)
        };
        transfer::transfer(admin,ctx.sender());
    }

    // 创建股票和份额
    fun create_share(amount :u64 , ctx : &mut TxContext) : (Stock,Share){
        let stock_id = object::new(ctx);
        let stock_addr = stock_id.uid_to_address();
        let stock= Stock{
            id : stock_id,
            amount  : amount
        };
        //记录股票地址,方便给股票地址转账
        let share = Share{
            amount : amount,
            id : stock_addr,
        };
        return (stock,share)
    }

    //记录份额
    fun add_share(shares : &mut Shares,share : Share){

        shares.supply = shares.supply + share.amount;
        table::add(&mut shares.holders,shares.count,share);
        shares.count = shares.count + 1;
    }

    // 花钱购买stock
    entry fun buy_stock(shares: &mut Shares,coin : Coin<SUI>, ctx : &mut TxContext){
        let value = coin::value(&coin);
        balance::join(&mut shares.balances, coin.into_balance());
        let (stock,share) = create_share(value,ctx);
        add_share(shares, share);
        transfer::transfer(stock,ctx.sender());
    }

    //阶段性分红,percent: 百分比乘以10000, 根据份额,把一部分钱发给股票
    public fun allocate(_cap : &AdminCap, 
                        shares :&mut  Shares,
                        percent : u64, 
                        ctx : &mut TxContext){
        let mut index :u32 = 0;
        let supply = shares.supply;
        while(index < shares.count){
            let share = sui::table::borrow(&shares.holders,index);
            let value = share.amount * shares.balances.value() *  percent /(10000) / supply;
            if(value > 0){
                let coin = coin::from_balance( balance::split(&mut shares.balances,value),ctx);
                let coin_id = object::id_to_address(&object::id(&coin));
                //分红发到股票地址
                transfer::public_transfer(coin, share.id);
            };
            index = index + 1;
        }
    }
   // 将股票拥有的钱提取到股票拥有者的钱包.只有拥有股票的人才能使用这个stock参数
    entry fun receive_stock_share(stock: &mut Stock, receiver : Receiving<Coin<SUI>>,ctx :& TxContext){
        let coin = transfer::public_receive<Coin<SUI>>(&mut stock.id ,receiver );
        transfer::public_transfer(coin,ctx.sender());
    }
}

3. 测试

3.1 定义三个用户,A,B,C

export ADDR_A=0xf7ec2215e565b7a18d7b00e70fccda74b30c3ecceffb5857b1b3d2249e28e94f export ADDR_B=0x6560a053cd8d98925b33ab2b951d656736d0133734def0b5d679402fc555576c export ADDR_C=0x540105A7D2F5F54A812C630F2996F1790ED0E60D1F9A870CE397F03E4CEC9B38

3.2 用户A 发布程序包

 sui client switch --address $ADDR_A
 sui  client publish

3.2.1 输出信息:

  ┌──                                                                                                       │
│  │ ObjectID: 0xa041d96de7c3f9a6823c3f73203705ebe69a6ca376d4233c65604c04b2dcc5fe                            │
│  │ Sender: 0xf7ec2215e565b7a18d7b00e70fccda74b30c3ecceffb5857b1b3d2249e28e94f                              │
│  │ Owner: Shared( 51 )                                                                                     │
│  │ ObjectType: 0x6c6b4cad96bf40d9be1ecb2954747924e49c7966208d453557980c26cbf4dccf::stock_market::Shares    │
│  │ Version: 51                                                                                             │
│  │ Digest: 4VMCG7NvCu7UPD45ZcmWa8mkpz84WsJzj3greNTt1V2t                                                    │
│  └──                                                                                                       │
│  ┌──                                                                                                       │
│  │ ObjectID: 0xe40ab477a340442774f77668d4b6708ea366b195c25f9a9cf455eb94222c1b8b                            │
│  │ Sender: 0xf7ec2215e565b7a18d7b00e70fccda74b30c3ecceffb5857b1b3d2249e28e94f                              │
│  │ Owner: Account Address ( 0xf7ec2215e565b7a18d7b00e70fccda74b30c3ecceffb5857b1b3d2249e28e94f )           │
│  │ ObjectType: 0x6c6b4cad96bf40d9be1ecb2954747924e49c7966208d453557980c26cbf4dccf::stock_market::AdminCap  │
│  │ Version: 51                                                                                             │
│  │ Digest: 9A6jXJfMgi87jfnJFJKFZT5PSfH8KRw5NKGKoGuHYi5C    

3.2.2 发布得到如下输出,配置相关包地址, adminCap地址, SHARES对象地址

export SHARES=0xa041d96de7c3f9a6823c3f73203705ebe69a6ca376d4233c65604c04b2dcc5fe
export ADMIN=0xe40ab477a340442774f77668d4b6708ea366b195c25f9a9cf455eb94222c1b8b
export PKG=0x6c6b4cad96bf40d9be1ecb2954747924e49c7966208d453557980c26cbf4dccf

3.3 B用户,购买股票

3.3.1 切换B用户

  sui client switch --address $ADDR_B

3.3.2 获取gas ,devnet会自动发10个sui

  sui client faucet 
  # 查看当前的gas值
  sui client gas

╭────────────────────────────────────────────────────────────────────┬────────────────────┬──────────────────╮
│ gasCoinId                                                          │ mistBalance (MIST) │ suiBalance (SUI) │
├────────────────────────────────────────────────────────────────────┼────────────────────┼──────────────────┤
│ 0x729890d6387c699f2a586fffe1daf803f0cba18a6b3cc481d922df304f40fbe7 │ 10000000000        │ 10.00            │
╰────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────╯

3.4 B用户购买股票buy stocket, STOCK =>B

从现有gas中切出5000000个mist ,用来购买股票

sui client ptb --split-coins gas [5000000] \ --assign new_coin \ --move-call $PKG::stock_market::buy_stock @$SHARES new_coin

根据输出信息,可以获得STOCK Created Objects: │ │ ┌── │ │ │ ObjectID: 0x16b4b76e57c92325dc44a47cf5734b4241f11ba25eb9360d77bdf8a0e2b8cbd8 │ │ │ Sender: 0x6560a053cd8d98925b33ab2b951d656736d0133734def0b5d679402fc555576c │ │ │ Owner: Account Address ( 0x6560a053cd8d98925b33ab2b951d656736d0133734def0b5d679402fc555576c ) │ │ │ ObjectType: 0x6c6b4cad96bf40d9be1ecb2954747924e49c7966208d453557980c26cbf4dccf::stock_market::Stock │ │ │ Version: 54 │ │ │ Digest: BfuEtZjb2TL6wrrsajwH7ZamgsnV71LB6W2mVHwkmjma │ │ └──

export STOCK=0x16b4b76e57c92325dc44a47cf5734b4241f11ba25eb9360d77bdf8a0e2b8cbd8

3.5 股票自由转移,这里B将股票转移给C B->C : stock

sui client ptb --transfer-objects [@$STOCK]  @$ADDR_C

3.6 用户A 发起分红,分红20% ,将分红转移到股票地址

sui client switch --address $ADDR_A
sui client ptb --move-call $PKG::stock_market::allocate @$ADMIN @$SHARES 2000

3.7 用户C 提取股票分红到钱包

3.7.1 查看股票拥有的对象列表,可以发现股票已经拥有了coin:

sui client objects $STOCK

得到

╭───────────────────────────────────────────────────────────────────────────────────────╮
│ ╭────────────┬──────────────────────────────────────────────────────────────────────╮ │
│ │ objectId   │  0xc06d80746fd966134e89e527d24484afa647f60f919db31d373dcb9a292b046c  │ │
│ │ version    │  55                                                                  │ │
│ │ digest     │  ntJJXEPdJz0gE+8IqFXtHt7pOgf36Tapb0YV16cp+Gg=                        │ │
│ │ objectType │  0x0000..0002::coin::Coin                                            │ │
│ ╰────────────┴──────────────────────────────────────────────────────────────────────╯ │

根据输出的objectId,配置需要提取的COIN_ID

export COIN_ID=0xc06d80746fd966134e89e527d24484afa647f60f919db31d373dcb9a292b046c

3.7.2 切换到用户C, 用户c 才拥有stock

 sui client switch --address $ADDR_C

3.7.3 查看交易前的 C 的余额

 sui client gas
╭────────────────────────────────────────────────────────────────────┬────────────────────┬──────────────────╮
│ gasCoinId                                                          │ mistBalance (MIST) │ suiBalance (SUI) │
├────────────────────────────────────────────────────────────────────┼────────────────────┼──────────────────┤
│ 0x15789f7840c3d7758a024545376a8f6ee61e8162b3593ac8f3ae9a7f7b499200 │ 9996916552         │ 9.99             │
╰────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────╯

3.7.4 执行交易,获取股票分红, 股票的拥有者C , coin.owner = stock => coin.owner == ADDR_C

sui client ptb --move-call $PKG::stock_market::receive_stock_share @$STOCK @$COIN_ID

3.7.5 查看交易后的余额

sui client gas
╭────────────────────────────────────────────────────────────────────┬────────────────────┬──────────────────╮
│ gasCoinId                                                          │ mistBalance (MIST) │ suiBalance (SUI) │
├────────────────────────────────────────────────────────────────────┼────────────────────┼──────────────────┤
│ 0x15789f7840c3d7758a024545376a8f6ee61e8162b3593ac8f3ae9a7f7b499200 │ 9995882960         │ 9.99             │
│ 0xc06d80746fd966134e89e527d24484afa647f60f919db31d373dcb9a292b046c │ 1000000            │ 0.00             │
╰────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────╯

附录

点赞 1
收藏 1
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
科学减肥
科学减肥
0xf54D...aDcd
http://github.com/nextuser