sui 存钱罐涉及的管理权限adminCap 和upgradeCap ,其中upgradeCap 可能绕过adminCap限制
风险
module upgrade_demo::upgrade_demo ;
use sui::object::{Self, UID};
use sui::transfer;
use sui::balance::{Self, Balance};
use sui::coin::{Self, Coin};
use sui::sui::SUI;
use sui::tx_context::{Self, TxContext};
// 错误码
const ENotAdmin: u64 = 0;
const EInsufficientBalance: u64 = 1;
// 管理员权限凭证
public struct AdminCap has key, store {
id: UID
}
// 金库结构
public struct Treasury has key {
id: UID,
balance: Balance<SUI>
}
// 初始化函数 - 创建管理员凭证和金库
fun init(ctx: &mut TxContext) {
let admin_cap = AdminCap {
id: object::new(ctx)
};
let treasury = Treasury {
id: object::new(ctx),
balance: balance::zero(),
};
// 将AdminCap转移给部署合约的地址
transfer::transfer(admin_cap, tx_context::sender(ctx));
// 共享金库对象
transfer::share_object(treasury);
}
// 存入SUI代币
public fun deposit(treasury: &mut Treasury, payment: Coin<SUI>) {
sui::balance::join(&mut treasury.balance, payment.into_balance());
}
// 管理员提取SUI代币
public fun withdraw(
treasury: &mut Treasury,
amount: u64,
_admin_cap: &AdminCap,
ctx: &mut TxContext
): Coin<SUI> {
// 检查余额是否充足
assert!(balance::value(&treasury.balance) >= amount, EInsufficientBalance);
// 从金库中提取代币
coin::from_balance(balance::split(&mut treasury.balance, amount), ctx)
}
// 查询金库余额
public fun balanceOf(treasury: &Treasury): u64 {
balance::value(&treasury.balance)
}
sui move --skip-fetch-latest-git-deps publish
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Object Changes │
├────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Created Objects: │
│ ┌── │
│ │ ObjectID: 0x10ca605ce0437c10274bcc260901ef5b34bab91c747f2dc498b722ae151a5baf │
│ │ Sender: 0x6560a053cd8d98925b33ab2b951d656736d0133734def0b5d679402fc555576c │
│ │ Owner: Account Address ( 0x6560a053cd8d98925b33ab2b951d656736d0133734def0b5d679402fc555576c ) │
│ │ ObjectType: 0x38417a57a4f061487895b2c97b3e188e847c25de37762c5e0146bd6a32cd5a89::upgrade_demo::AdminCap │
│ │ Version: 245323791 │
│ │ Digest: BLp2DjwNMD1fZ4Y4HxNMRz1AQq28afgMQ57pNFt4BZoa │
│ └──
│ ┌── │
│ │ ObjectID: 0x67a5815e053ab8be8248c894ec288baf79bc6f323321812074cac70e63915bb0 │
│ │ Sender: 0x6560a053cd8d98925b33ab2b951d656736d0133734def0b5d679402fc555576c │
│ │ Owner: Account Address ( 0x6560a053cd8d98925b33ab2b951d656736d0133734def0b5d679402fc555576c ) │
│ │ ObjectType: 0x2::package::UpgradeCap │
│ │ Version: 245323791 │
│ │ Di
┌── │
│ │ ObjectID: 0x830243c107ff3ad19e4506d9a61d04af4a0c35771445e468c3a7befbc6d9293c │
│ │ Sender: 0x6560a053cd8d98925b33ab2b951d656736d0133734def0b5d679402fc555576c │
│ │ Owner: Shared( 245323791 ) │
│ │ ObjectType: 0x38417a57a4f061487895b2c97b3e188e847c25de37762c5e0146bd6a32cd5a89::upgrade_demo::Treasury │
│ │ Version: 245323791 │
│ │ Digest: Enq9zenKrY4r3fXYEWr9XJCcA8FixSTZhKbVqXqDueNM
对象名 | 取值 | 说明 |
---|---|---|
package address | 0x38417a57a4f061487895b2c97b3e188e847c25de37762c5e0146bd6a32cd5a89 | 合约包的地址 |
upgradeCap | 0x67a5815e053ab8be8248c894ec288baf79bc6f323321812074cac70e63915bb0 | 控制升级的权限 |
adminCap | 0x10ca605ce0437c10274bcc260901ef5b34bab91c747f2dc498b722ae151a5baf | 控制提取Treasury余额 |
owner | 0x6560a053cd8d98925b33ab2b951d656736d0133734def0b5d679402fc555576c | 目前合约发布者拥有adminCap,upgradeCap |
treasury | 0x830243c107ff3ad19e4506d9a61d04af4a0c35771445e468c3a7befbc6d9293c | 存钱罐 |
查看当前用户的coin
sui client gas
╭────────────────────────────────────────────────────────────────────┬────────────────────┬──────────────────╮
│ gasCoinId │ mistBalance (MIST) │ suiBalance (SUI) │
├────────────────────────────────────────────────────────────────────┼────────────────────┼──────────────────┤
│ 0x09119914c43f80a486b30cc5d4f1382d0b57929eabd70f116ae4e918d9c89bf0 │ 470927364 │ 0.47 │
│ 0xae3da3cb598610db16ea040ad6b09cfd324e146a2a7e5b18ccfa76b34b8d3b22 │ 497664604 │ 0.49 │
│ 0xeda78a0ba9b2ef153a209f51380d8e77af0f35c60eb8ea26d4239c639844680d │ 995399888 │ 0.99 │
╰────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────╯
export PKG=0x38417a57a4f061487895b2c97b3e188e847c25de37762c5e0146bd6a32cd5a89
export ADMIN_CAP=0x10ca605ce0437c10274bcc260901ef5b34bab91c747f2dc498b722ae151a5baf
export UPGRADE_CAP=0x67a5815e053ab8be8248c894ec288baf79bc6f323321812074cac70e63915bb0
export TREASURY=0x830243c107ff3ad19e4506d9a61d04af4a0c35771445e468c3a7befbc6d9293c
export ADDR_A=0x6560a053cd8d98925b33ab2b951d656736d0133734def0b5d679402fc555576c
export ADDR_B=0x7cbe5e6596e23266dd5763dd89b4ab1195516908ecde8febfe96685c7cbe6432
# 查看当前用户有哪些coin
sui client switch --address $ADDR_A
sui client gas
╭────────────────────────────────────────────────────────────────────┬────────────────────┬──────────────────╮
│ gasCoinId │ mistBalance (MIST) │ suiBalance (SUI) │
├────────────────────────────────────────────────────────────────────┼────────────────────┼──────────────────┤
│ 0x09119914c43f80a486b30cc5d4f1382d0b57929eabd70f116ae4e918d9c89bf0 │ 470927364 │ 0.47 │
│ 0xae3da3cb598610db16ea040ad6b09cfd324e146a2a7e5b18ccfa76b34b8d3b22 │ 497664604 │ 0.49 │
│ 0xeda78a0ba9b2ef153a209f51380d8e77af0f35c60eb8ea26d4239c639844680d │ 995399888 │ 0.99 │
╰────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────╯
# 根据前面的输出,设置需要存入的coin
export COIN_A=0xae3da3cb598610db16ea040ad6b09cfd324e146a2a7e5b18ccfa76b34b8d3b22
# 存入货币
sui client ptb --move-call $PKG::upgrade_demo::deposit "@$TREASURY,@$COIN_A"
$ sui client ptb --move-call $PKG::upgrade_demo::deposit "@$TREASURY @0xae3da3cb598610db16ea040ad6b09cfd324e146a2a7e5b18ccfa76b34b8d3b22"
取回5000单位
sui client ptb --move-call $PKG::upgrade_demo::withdraw "@$TREASURY 50000 @$ADMIN_CAP"
sui client ptb --move-call $PKG::upgrade_demo::withdraw "@$TREASURY 50000 @$ADMIN_CAP" --assign coin1 --transfer-objects [coin1] @$ADDR_A
查看当前A用户拥有的coin
sui client gas $ADDR_A
╭────────────────────────────────────────────────────────────────────┬────────────────────┬──────────────────╮
│ gasCoinId │ mistBalance (MIST) │ suiBalance (SUI) │
├────────────────────────────────────────────────────────────────────┼────────────────────┼──────────────────┤
│ 0x09119914c43f80a486b30cc5d4f1382d0b57929eabd70f116ae4e918d9c89bf0 │ 466808880 │ 0.46 │
│ 0xd91123cfc325ba1eff95e839837a1bf443046cc00a72da5192a005ffea1a7117 │ 50000 │ 0.00 │
│ 0xeda78a0ba9b2ef153a209f51380d8e77af0f35c60eb8ea26d4239c639844680d │ 995399888 │ 0.99 │
╰────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────╯
sui client ptb --transfer-objects [@$ADMIN_CAP] @$ADDR_B
# 显示ADMIN_CAP 对象的owner是0x7cbe5e6596e23266dd5763dd89b4ab1195516908ecde8febfe96685c7cbe6432
│ ┌── │
│ │ ObjectID: 0x10ca605ce0437c10274bcc260901ef5b34bab91c747f2dc498b722ae151a5baf │
│ │ Sender: 0x6560a053cd8d98925b33ab2b951d656736d0133734def0b5d679402fc555576c │
│ │ Owner: Account Address ( 0x7cbe5e6596e23266dd5763dd89b4ab1195516908ecde8febfe96685c7cbe6432 ) │
│ │ ObjectType: 0x38417a57a4f061487895b2c97b3e188e847c25de37762c5e0146bd6a32cd5a89::upgrade_demo::AdminCap │
│ │ Version: 245323796 │
│ │ Digest: 6QpfZqgrTFjTcaySHPrfS5cDE1K1L5xvuWDQRxh1vumS │
│ └──
sui client ptb --move-call $PKG::upgrade_demo::withdraw "@$TREASURY 50000 @$ADMIN_CAP" --assign coin1 --transfer-objects [coin1] @$ADDR_A --gas-budget 30000000
RPC call failed: ErrorObject { code: ServerError(-32002), message: "Transaction validator signing failed due to issues with transaction inputs, please review the errors and try again:\n- Transaction was not signed by the correct sender: Object 0x10ca605ce0437c10274bcc260901ef5b34bab91c747f2dc498b722ae151a5baf is owned by account address 0x7cbe5e6596e23266dd5763dd89b4ab1195516908ecde8febfe96685c7cbe6432, but given owner/signer address is 0x6560a053cd8d98925b33ab2b951d656736d0133734def0b5d679402fc555576c\n- Could not find the referenced object 0x38417a57a4f061487895b2c97b3e188e847c25de37762c5e0146bd6a32cd5a89 at version None", data: None }
# 切换到ADDR_B
$ sui client switch --address $ADDR_B
Active address switched to 0x7cbe5e6596e23266dd5763dd89b4ab1195516908ecde8febfe96685c7cbe6432
# 调用withdraw取款
$ sui client ptb --move-call $PKG::upgrade_demo::withdraw "@$TREASURY 50000 @$ADMIN_CAP" --assign coin1 --transfer-objects [coin1] @$ADDR_B
# 查看获得50000 mist的coin
$ sui client gas
╭────────────────────────────────────────────────────────────────────┬────────────────────┬──────────────────╮
│ gasCoinId │ mistBalance (MIST) │ suiBalance (SUI) │
├────────────────────────────────────────────────────────────────────┼────────────────────┼──────────────────┤
│ 0x015a3cb7a04cdcd7631e4056f56e8a55b77a1a7d05dc7da6f30e9ac705d19b7c │ 50000 │ 0.00 │
│ 0x418760c10d6fe9ecaa2594803848412c834f58983f1be03b26962a22dd84f9e5 │ 995949216 │ 0.99 │
╰────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────╯
public fun mintCap(ctx: &mut TxContext): AdminCap {
AdminCap{id: object::new(ctx)}
}
# 切换为A
sui client switch --address $ADDR_A
Active address switched to 0x6560a053cd8d98925b33ab2b951d656736d0133734def0b5d679402fc555576c
# A 升级合约
sui client upgrade --upgrade-capability $UPGRADE_CAP --gas-budget 100000000 --skip-fetch-latest-git-deps
# 升级对象变更,package版本增长 ,版本id 变成了 0xc163e33f376cae7a90b0c56b49af9a0aa387c210792d6c76aba0a12a22de8869
老的版本id是0x38417a57a4f061487895b2c97b3e188e847c25de37762c5e0146bd6a32cd5a89
│ ┌── │
│ │ ObjectID: 0x67a5815e053ab8be8248c894ec288baf79bc6f323321812074cac70e63915bb0 │
│ │ Sender: 0x6560a053cd8d98925b33ab2b951d656736d0133734def0b5d679402fc555576c │
│ │ Owner: Account Address ( 0x6560a053cd8d98925b33ab2b951d656736d0133734def0b5d679402fc555576c ) │
│ │ ObjectType: 0x2::package::UpgradeCap │
│ │ Version: 245323797 │
│ │ Digest: 64rX9ChLmX5mupim2UqRGUoKnHD3wTiiYg4uXxzjvppc │
│ └── │
│ Published Objects: │
│ ┌── │
│ │ PackageID: 0xc163e33f376cae7a90b0c56b49af9a0aa387c210792d6c76aba0a12a22de8869 │
│ │ Version: 2 │
│ │ Digest: 8aWACYMu9nLjAG3MHQGteXMsNiBUY5xCt6KhKmMEmrTX │
│ │ Modules: upgrade_demo │
│ └──
新发布的的包 id发生改变
0x67a5815e053ab8be8248c894ec288baf79bc6f323321812074cac70e63915bb0
用户用新创建的adminCap2 来取钱
初始的package
升级后的packageid发生变更
但是从代码看,package地址 还是最初发布的地址,version=2, 代码module后面的地址不变。 但是objectid发生变更(图1)
$ export PKG2=0xc163e33f376cae7a90b0c56b49af9a0aa387c210792d6c76aba0a12a22de8869
$ sui client ptb --move-call $PKG2::upgrade_demo::mintCap --assign new_cap --transfer-objects ["new_cap" ] @$ADDR_A
Created Objects: │
│ ┌── │
│ │ ObjectID: 0xb71d4b11e35d769bcdefa42f9706af118b76b2ab2896fe2a294639e19f52d816 │
│ │ Sender: 0x6560a053cd8d98925b33ab2b951d656736d0133734def0b5d679402fc555576c │
│ │ Owner: Account Address ( 0x6560a053cd8d98925b33ab2b951d656736d0133734def0b5d679402fc555576c ) │
│ │ ObjectType: 0x38417a57a4f061487895b2c97b3e188e847c25de37762c5e0146bd6a32cd5a89::upgrade_demo::AdminCap │
│ │ Version: 245323798 │
│ │ Digest: 8xio19V93oLgmF8jLxWKoCfgCpSitFJqYLLLTbN9Wc77 │
│ └──
$ export ADMIN_CAP2=0xb71d4b11e35d769bcdefa42f9706af118b76b2ab2896fe2a294639e19f52d816
$ sui client ptb --move-call $PKG2::upgrade_demo::withdraw "@$TREASURY 6000 @$ADMIN_CAP2" \
--assign coin2 --transfer-objects [coin2] @$ADDR_A
# 偷取成功,获得一个6000mist的coin
$ sui client gas $ADDR_A
╭────────────────────────────────────────────────────────────────────┬────────────────────┬──────────────────╮
│ gasCoinId │ mistBalance (MIST) │ suiBalance (SUI) │
├────────────────────────────────────────────────────────────────────┼────────────────────┼──────────────────┤
│ 0x09119914c43f80a486b30cc5d4f1382d0b57929eabd70f116ae4e918d9c89bf0 │ 450920664 │ 0.45 │
│ 0x33233ad9e71a8ef079b7c1c58ac9c99a263d04620f585d37e1ae94b4bd64d538 │ 6000 │ 0.00 │
│ 0x64502383e84a24dda2e531ec0cac4d8123c9c4d7820451a1b42a02eae1888bea │ 50000 │ 0.00 │
│ 0xd91123cfc325ba1eff95e839837a1bf443046cc00a72da5192a005ffea1a7117 │ 50000 │ 0.00 │
│ 0xeda78a0ba9b2ef153a209f51380d8e77af0f35c60eb8ea26d4239c639844680d │ 995399888 │ 0.99 │
╰────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────╯
export PKG=0x38417a57a4f061487895b2c97b3e188e847c25de37762c5e0146bd6a32cd5a89
export UPGRADE_CAP=0x67a5815e053ab8be8248c894ec288baf79bc6f323321812074cac70e63915嗯嗯
$ sui client upgrade --upgrade-capability $UPGRADE_CAP --package-id $PKG --gas-budget 100000000
在 Treasury 中添加adminCap的id。
在取款的时候做校验
// 金库结构
public struct Treasury has key {
id: UID,
balance: Balance<SUI>,
+ admin_id : ID,
}
// 初始化函数 - 创建管理员凭证和金库
fun init(ctx: &mut TxContext) {
let admin_cap = AdminCap {
id: object::new(ctx)
};
let treasury = Treasury {
id: object::new(ctx),
balance: balance::zero(),
+ admin_id: *admin_cap.id.as_inner(),
}
...
// 管理员提取SUI代币
public fun withdraw(
treasury: &mut Treasury,
amount: u64,
admin_cap: &AdminCap,
ctx: &mut TxContext
): Coin<SUI> {
+ assert!(admin_cap.id.as_inner() == treasury.admin_id, ENotAdmin);
...
<!--StartFragment-->
最近在参加HOH 共学活动,
📹 课程B站账号
💻 Github仓库 <https://github.com/move-cn/letsmove>
<!--EndFragment-->
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!