SUI Move合约学习与实践——极简IDO合约

  • rzexin
  • 更新于 2024-03-15 12:10
  • 阅读 915

SUI Move合约学习与实践——极简IDO合约

SUI Move合约学习与实践——极简IDO合约

1 合约说明

1.1 功能介绍

该合约是SUI Move 首次DEX发行(IDO) 合约。IDO是一种用于新加密货币项目的去中心化筹款机制,参与者可以在这里捐款并获得新铸造的代币作为回报。

该合约提供的功能有:

  • 白名单

    IDO所有者可以维护允许参与IDO的地址的白名单。不在白名单上的参与者将被拒绝。

  • 资金上限

    IDO所有者可以为IDO设定资金上限,超过该上限将不再接受新增资金。

  • 开始和结束时间

    IDO所有者可以为IDO设置开始和结束的时间,在此期间参与者可以捐款。

  • 资金转移

    当参与者向IDO捐款时,资金会转移到IDO所有者的账户,参与者会收到新铸造的代币作为回报。(==当前合约并未实现该功能==)

1.2 合约代码

1.2.1 合约源码地址

https://github.com/karangoraniya/sui-ido

1.2.2 数据结构说明

(1)IDO对象

成员变量说明:

  • start_time、end_time:开始和结束时间,格式:毫秒级别时间戳
  • cap:资金上限,超过该上限将不再接受新增资金
  • ownerIDO所有者
  • whitelisted_addresses:白名单地址列表,即可以申购的用户地址
  • funded_amount:已收到资金数额
  • balance:存放收到的SUI代币
    struct IDO has key, store {
        id: UID,
        start_time: u64,
        end_time: u64,
        cap: u64,
        owner: address,
        whitelisted_addresses: vector<address>,
        funded_amount: u64,
        balance: Balance<SUI>
    }

1.2.3 接口说明

(1)创建IDO(create_ido
    // it will create the IDO 
    public entry fun create_ido(
        start_time: u64,
        end_time: u64,
        // cap: u64,
        whitelisted_addresses: vector<address>,
        ctx: &mut TxContext
    ) {
        let owner = tx_context::sender(ctx);
        let ido = IDO {
            id: object::new(ctx),
            start_time: start_time,
            end_time: end_time,
            cap: MAX_CAP,
            owner: owner,
            whitelisted_addresses: whitelisted_addresses,
            funded_amount: 0,
            balance: balance::zero()
        };

        // 源码这里有BUG,修复之
        // transfer::transfer(ido, owner);
        transfer::share_object(ido);
    }
(2)提供资金(fund_ido
  • 位于白名单中的用户可为IDO提供资金
  • 合约接口会判断是否在有效期内且为达到资金上限
    // Check if an address is whitelisted
    public fun is_whitelisted(ido: &IDO, address: address): bool {
        vector::contains(&ido.whitelisted_addresses, &address)
    }

    //Fund the IDO 
    public entry fun fund_ido(ido: &mut IDO, payment: Coin<SUI>, clock: &Clock, ctx: &mut TxContext) {
        let sender = tx_context::sender(ctx);
        assert!(is_whitelisted(ido, sender), NOT_WHITELIST);

        // For fetching time 
        let current_time = clock::timestamp_ms(clock);

        assert!(current_time >= ido.start_time && current_time <= ido.end_time, NOT_STARTED);

        let amount = coin::value(&payment);
        assert!(ido.funded_amount + amount <= ido.cap, MAX_CAP_REACHED);

        ido.funded_amount = ido.funded_amount + amount;

        coin::put(&mut ido.balance, payment);
    }
(3)转移资金(transfer_ido_funds
  • IDO所有者可以提取所收集的资金
    // It will transfer the funds only owner can transfer
    public entry fun transfer_ido_funds(ido: &mut IDO, recipient: address, ctx: &mut TxContext) {
        let sender = tx_context::sender(ctx); 
        assert!(ido.owner == sender, OWNER_ONLY); 
        let amount = balance::value(&ido.balance);
        let split_amount = balance::split(&mut ido.balance, amount);

        transfer::public_transfer(coin::from_balance(split_amount, ctx), recipient);
    }

2 前置准备

2.1 帐号准备及角色分配

别名 地址 角色
Jason 0x5c5882d73a6e5b6ea1743fb028eff5e0d7cc8b7ae123d27856c5fe666d91569a IDO创建者
Alice 0x2d178b9704706393d2630fe6cf9415c2c50b181e9e3c7a977237bb2929f82d19 投资人1
Bob 0xf2e6ffef7d0543e258d4c47a53d6fa9872de4630cc186950accbd83415b009f0 投资人2
  • 将地址添加到环境变量
export JASON=0x5c5882d73a6e5b6ea1743fb028eff5e0d7cc8b7ae123d27856c5fe666d91569a
export ALICE=0x2d178b9704706393d2630fe6cf9415c2c50b181e9e3c7a977237bb2929f82d19
export BOB=0xf2e6ffef7d0543e258d4c47a53d6fa9872de4630cc186950accbd83415b009f0

3 合约部署

切换到Jason账号

sui client publish --gas-budget 100000000
  • 记录PACKAGE_ID
export PACKAGE_ID=0xe7b63ff49f3337ca9563366a00741bbe14fc1cc537f526e75ae16b18247bb141

4 合约交互

4.1 创建IDO(create_ido

export START_TIME=$(( $(date +"%s") + 60 ))000  # 合约创建后1分钟后开始
export END_TIME=$(( $(date +"%s") + 20*60 ))999  # 合约创建后20分钟后结束
echo $START_TIME $END_TIME
export WHITELIST="[$ALICE,$BOB]"
sui client call --function create_ido --package $PACKAGE_ID --module IDO --args $START_TIME $END_TIME $WHITELIST --gas-budget 10000000
  • 得到IDO共享对象
export IDO=0x3261ce9bf723631122cffafcff1b5c3d524dec2113ecd305cb0031c134c0fcb3
  • 查看IDO共享对象
sui client object $IDO

image.png

4.2 提供资金(fund_ido

4.2.1 Alice存入

切换到Alice,存入20000000

如未到开始时间进行存入将报错:

Error executing transaction: Failure {
    error: "MoveAbort(MoveLocation { module: ModuleId { address: e7b63ff49f3337ca9563366a00741bbe14fc1cc537f526e75ae16b18247bb141, name: Identifier(\"IDO\") }, function: 2, instruction: 42, function_name: Some(\"fund_ido\") }, 2) in command 0",
}
sui client switch --address alice
sui client gas --json | jq '.[] | select(.gasBalance > 20000000) | .gasCoinId' -r > output.txt
GAS=$(sed -n '1p' output.txt)
SPLIT_COIN=$(sed -n '2p' output.txt)

export COIN=`sui client split-coin --coin-id $SPLIT_COIN --amounts 20000000 --gas $GAS --gas-budget 10000000 --json | jq -r '.objectChanges[] | select(.objectType=="0x2::coin::Coin<0x2::sui::SUI>" and .type=="created") | .objectId'`
echo $COIN

sui client call --function fund_ido --package $PACKAGE_ID --module IDO --args $IDO $COIN 0x6 --gas-budget 10000000

image.png

4.2.2 Bob存入

切换到Bob,Bob最多只能存入1000000

若Bob存入操作上限,将会报错:

Error executing transaction: Failure {
    error: "MoveAbort(MoveLocation { module: ModuleId { address: e7b63ff49f3337ca9563366a00741bbe14fc1cc537f526e75ae16b18247bb141, name: Identifier(\"IDO\") }, function: 2, instruction: 60, function_name: Some(\"fund_ido\") }, 3) in command 0",
}
sui client switch --address bob
sui client gas --json | jq '.[] | select(.gasBalance > 1000000) | .gasCoinId' -r > output.txt
GAS=$(sed -n '1p' output.txt)
SPLIT_COIN=$(sed -n '2p' output.txt)

export COIN=`sui client split-coin --coin-id $SPLIT_COIN --amounts 1000000 --gas $GAS --gas-budget 10000000 --json | jq -r '.objectChanges[] | select(.objectType=="0x2::coin::Coin<0x2::sui::SUI>" and .type=="created") | .objectId'`
echo $COIN

sui client call --function fund_ido --package $PACKAGE_ID --module IDO --args $IDO $COIN 0x6 --gas-budget 10000000

image.png

4.2.3 非白名单用户存入

若是任意非白名单用户存入,将会直接报错

sui client call --function fund_ido --package $PACKAGE_ID --module IDO --args $IDO 0x177f7dc252d43fca6e8af4a046efeac2d4b11fd662a7f7d3b3a89402ae8a5820 0x6 --gas-budget 10000000

Error executing transaction: Failure {
    error: "MoveAbort(MoveLocation { module: ModuleId { address: e7b63ff49f3337ca9563366a00741bbe14fc1cc537f526e75ae16b18247bb141, name: Identifier(\"IDO\") }, function: 2, instruction: 17, function_name: Some(\"fund_ido\") }, 1) in command 0",
}

4.3 转移资金(transfer_ido_funds

切换到Jason,创建者可以将所有存入资金转移到指定地址

export RECIPIENT=0x69872fc4781f115e08f72dd37de1216c431afea4faa4b794e5327da59abce681
sui client call --function transfer_ido_funds --package $PACKAGE_ID --module IDO --args $IDO $RECIPIENT --gas-budget 10000000

5 前端交互

image.png

5.1 修改配置

将文件:utils/constants.ts中的PACKAGE_ID改成自己的:

export const PACKAGE_OBJECT_ID =
  '0xe7b63ff49f3337ca9563366a00741bbe14fc1cc537f526e75ae16b18247bb141';

5.2 创建IDO(create_ido

image.png

5.3 修改IDO对象配置

将文件pages/fund.tsx硬编码的IDO对象,修改为上面创建的:

      const ido =
        '0xdf4a5306f3eca5e71ad7d659cd7141ea2681d9c2493387952b4dc39604b87689';

5.4 提供资金(fund_ido

image.png

切换到白名单用户,点击按钮,会进行一笔固定金额的捐赠。

代码存在BUG,进行修复:

  • 修复前
      const [coin] = tx.splitCoins(tx.gas, [tx.pure(1000000000)]);

      tx.moveCall({
        target: `${PACKAGE_OBJECT_ID}::IDO::fund_ido`,

        arguments: [tx.object(ido), tx.object(clock), coin],
        typeArguments: ['0x2::sui::SUI'],
      });
  • 修复后
      const [coin] = tx.splitCoins(tx.gas, [tx.pure(1000000)]);

      tx.moveCall({
        target: `${PACKAGE_OBJECT_ID}::IDO::fund_ido`,
        arguments: [tx.object(ido), coin, tx.object(clock)],
      });
      tx.setGasBudget(3000000);

https://suiexplorer.com/object/0xdf4a5306f3eca5e71ad7d659cd7141ea2681d9c2493387952b4dc39604b87689?deviceId=a83be6f6-21d2-4c6d-9b14-3fc3e0ec270e&network=testnet

image.png

5.3 转移资金(transfer_ido_funds

image.png

代码同样存在问题,基本没有实现这块逻辑,进行修复。

  • 修复前
      const recipient =
        '0x32d8abc746056dcfafbf45850a8286531d7231c736af117f5185f16ec72e4037';
      const [coin] = tx.splitCoins(tx.gas, [tx.pure(1000000000)]);

      tx.moveCall({
        target: `${PACKAGE_OBJECT_ID}::IDO::fund_ido`,

        arguments: [
          // tx.object(ido),
          tx.transferObjects([coin], tx.pure(recipient)),
        ],

        // typeArguments: ['0x2::sui::SUI'],
      });
  • 修复后
      const ido =
        '0xdf4a5306f3eca5e71ad7d659cd7141ea2681d9c2493387952b4dc39604b87689';

      tx.moveCall({
        target: `${PACKAGE_OBJECT_ID}::IDO::transfer_ido_funds`,
        arguments: [
          tx.object(ido),
          tx.pure(address),
        ],
      });

查看钱包,确认资金到账:

image.png

6 更多

欢迎关注微信公众号:Move中文,以及参与星航计划🚀,开启你的 Sui Move 之旅!

image.png

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

0 条评论

请先 登录 后评论
rzexin
rzexin
0x6Fa5...8165
江湖只有他的大名,没有他的介绍。