SUI Move合约学习与实践——极简IDO合约
该合约是SUI Move
首次DEX发行(IDO) 合约。IDO
是一种用于新加密货币项目的去中心化筹款机制,参与者可以在这里捐款并获得新铸造的代币作为回报。
该合约提供的功能有:
白名单
IDO
所有者可以维护允许参与IDO
的地址的白名单。不在白名单上的参与者将被拒绝。
资金上限
IDO
所有者可以为IDO
设定资金上限,超过该上限将不再接受新增资金。
开始和结束时间
IDO
所有者可以为IDO
设置开始和结束的时间,在此期间参与者可以捐款。
资金转移
当参与者向IDO
捐款时,资金会转移到IDO
所有者的账户,参与者会收到新铸造的代币作为回报。(==当前合约并未实现该功能==)
https://github.com/karangoraniya/sui-ido
成员变量说明:
start_time、end_time
:开始和结束时间,格式:毫秒级别时间戳cap
:资金上限,超过该上限将不再接受新增资金owner
:IDO
所有者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>
}
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);
}
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);
}
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);
}
别名 | 地址 | 角色 |
---|---|---|
Jason | 0x5c5882d73a6e5b6ea1743fb028eff5e0d7cc8b7ae123d27856c5fe666d91569a |
IDO 创建者 |
Alice | 0x2d178b9704706393d2630fe6cf9415c2c50b181e9e3c7a977237bb2929f82d19 |
投资人1 |
Bob | 0xf2e6ffef7d0543e258d4c47a53d6fa9872de4630cc186950accbd83415b009f0 |
投资人2 |
export JASON=0x5c5882d73a6e5b6ea1743fb028eff5e0d7cc8b7ae123d27856c5fe666d91569a
export ALICE=0x2d178b9704706393d2630fe6cf9415c2c50b181e9e3c7a977237bb2929f82d19
export BOB=0xf2e6ffef7d0543e258d4c47a53d6fa9872de4630cc186950accbd83415b009f0
切换到Jason账号
sui client publish --gas-budget 100000000
export PACKAGE_ID=0xe7b63ff49f3337ca9563366a00741bbe14fc1cc537f526e75ae16b18247bb141
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
export IDO=0x3261ce9bf723631122cffafcff1b5c3d524dec2113ecd305cb0031c134c0fcb3
sui client object $IDO
fund_ido
)切换到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
切换到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
若是任意非白名单用户存入,将会直接报错
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",
}
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
将文件:utils/constants.ts
中的PACKAGE_ID
改成自己的:
export const PACKAGE_OBJECT_ID =
'0xe7b63ff49f3337ca9563366a00741bbe14fc1cc537f526e75ae16b18247bb141';
create_ido
)将文件pages/fund.tsx
硬编码的IDO对象,修改为上面创建的:
const ido =
'0xdf4a5306f3eca5e71ad7d659cd7141ea2681d9c2493387952b4dc39604b87689';
fund_ido
)切换到白名单用户,点击按钮,会进行一笔固定金额的捐赠。
代码存在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);
transfer_ido_funds
)代码同样存在问题,基本没有实现这块逻辑,进行修复。
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),
],
});
查看钱包,确认资金到账:
欢迎关注微信公众号:Move中文,以及参与星航计划🚀,开启你的 Sui Move 之旅!
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!