{"content":{"title":"deny_list在coin中的应用","body":"## 引言\r\n上篇文章介绍了deny_list,它是由系统事务创建的一个share_obj，用于进行对sui核心类型的地址访问控制。coin中有部分代码使用了deny_list，用来创建可以阻止某些地址在交易中使用相应的coin，也就是之前没有讲到的部分。  \r\n\r\n## Regulated Coin  \r\ncoin中提供了create_regulated_currency方法用来创建一个受管制的coin。  \r\n```rust\r\n    public fun create_regulated_currency<T: drop>(\r\n        witness: T,\r\n        decimals: u8,\r\n        symbol: vector<u8>,\r\n        name: vector<u8>,\r\n        description: vector<u8>,\r\n        icon_url: Option<Url>,\r\n        ctx: &mut TxContext\r\n    ): (TreasuryCap<T>, DenyCap<T>, CoinMetadata<T>) {\r\n        let (treasury_cap, metadata) = create_currency(\r\n            witness,\r\n            decimals,\r\n            symbol,\r\n            name,\r\n            description,\r\n            icon_url,\r\n            ctx\r\n        );\r\n        let deny_cap = DenyCap {\r\n            id: object::new(ctx),\r\n        };\r\n        transfer::freeze_object(RegulatedCoinMetadata<T> {\r\n            id: object::new(ctx),\r\n            coin_metadata_object: object::id(&metadata),\r\n            deny_cap_object: object::id(&deny_cap),\r\n        });\r\n        (treasury_cap, deny_cap, metadata)\r\n    }\r\n```\r\n与create_currency不相同的是，此方法多返回了一个权限凭证DenyCap，持有DenyCap的人可以将一些地址列入deny_list，从而让这个地址不能在交易中使用coin<T<T>>作为交易的输入，也可以将它移除，从而恢复权限  \r\n\r\n### 增加/移除/检查是否存在\r\n```rust\r\n    public fun deny_list_add<T>(\r\n       deny_list: &mut DenyList,\r\n       _deny_cap: &mut DenyCap<T>,\r\n       addr: address,\r\n       _ctx: &mut TxContext\r\n    ) {\r\n        let type =\r\n            ascii::into_bytes(type_name::into_string(type_name::get_with_original_ids<T>()));\r\n        deny_list::add(\r\n            deny_list,\r\n            DENY_LIST_COIN_INDEX,\r\n            type,\r\n            addr,\r\n        )\r\n    }\r\n\r\n    public fun deny_list_remove<T>(\r\n       deny_list: &mut DenyList,\r\n       _deny_cap: &mut DenyCap<T>,\r\n       addr: address,\r\n       _ctx: &mut TxContext\r\n    ) {\r\n        let type =\r\n            ascii::into_bytes(type_name::into_string(type_name::get_with_original_ids<T>()));\r\n        deny_list::remove(\r\n            deny_list,\r\n            DENY_LIST_COIN_INDEX,\r\n            type,\r\n            addr,\r\n        )\r\n    }\r\n\r\n    public fun deny_list_contains<T>(\r\n       freezer: &DenyList,\r\n       addr: address,\r\n    ): bool {\r\n        let name = type_name::get_with_original_ids<T>();\r\n        if (type_name::is_primitive(&name)) return false;\r\n\r\n        let type = ascii::into_bytes(type_name::into_string(name));\r\n        deny_list::contains(\r\n            freezer,\r\n            DENY_LIST_COIN_INDEX,\r\n            type,\r\n            addr,\r\n        )\r\n    }\r\n\r\n```\r\n### 交互示例\r\n使用地址  \r\n\r\n│ address1 │ 0x2fcdfe7c92fe670d267474fbd7aa89baef55c5f93b1953a9e82614c9abb7abc6 │\r\n│ address2  │ 0x48c5fdc3d18989593d68435f4f4310f67391298c1b2e1325fae7a4a9fb8fd6e7 |\r\n\r\n合约代码  \r\n```rust\r\nmodule rcoin::rcoin {\r\n    use std::option;\r\n    use sui::coin::{Self,TreasuryCap,DenyCap};\r\n    use sui::transfer;\r\n    use sui::tx_context::{Self, TxContext};\r\n    use sui::deny_list::{Self, DenyList};\r\n\r\n    struct RCOIN has drop {}\r\n\r\n    fun init(witness: RCOIN, ctx: &mut TxContext) {\r\n        let (treasury, deny_cap, metadata) = coin::create_regulated_currency(witness, 6, b\"RCOIN\", b\"shaflow\", b\"shaflow`s rcoin\", option::none(), ctx);\r\n\r\n        transfer::public_freeze_object(metadata);\r\n        transfer::public_transfer(treasury, tx_context::sender(ctx));\r\n        transfer::public_transfer(deny_cap, tx_context::sender(ctx));\r\n    }\r\n\r\n    public fun add_addr_from_deny_list(denylist: &mut DenyList, denycap: &mut DenyCap<RCOIN>, denyaddy: address, ctx: &mut TxContext){\r\n        coin::deny_list_add(denylist, denycap, denyaddy, ctx );\r\n    }\r\n\r\n    public fun remove_addr_from_deny_list(denylist: &mut DenyList, denycap: &mut DenyCap<RCOIN>, denyaddy: address, ctx: &mut TxContext){\r\n        coin::deny_list_remove(denylist, denycap, denyaddy, ctx );\r\n    }\r\n\r\n    public fun airdrop(cap: &mut TreasuryCap<RCOIN>, receiver:address ,ctx: &mut TxContext){\r\n        let new_coin = coin::mint<RCOIN>(cap, 100,ctx);\r\n        transfer::public_transfer(new_coin, receiver);\r\n    }\r\n}\r\n```\r\n1. 用address1部署合约  \r\n```rust\r\nsui client publish --gas-budget=100000000 --skip-fetch-latest-git-deps --skip-dependency-verification\r\n```\r\n获得：\r\n|TreasuryCap|0xe8e782b425fe85a768bfa63fda885ad21cf1c8939f6b216c26ec5b437f2a6a59|\r\n|DenyCap|0xc8da5610388f40617eb88a81588e321be7c9f64678d8b1407adbcf81d4dbd990|\r\n|package|0x4f76f0634d1dff123c19150ba96ce0ed7f56eb4dbda28ab66b627fdb1ecff523|\r\n2. address1 调用airdrop 给address2铸币  \r\n```rust\r\nsui client call --function airdrop --args 0xe8e782b425fe85a768bfa63fda885ad21cf1c8939f6b216c26ec5b437f2a6a59 0x48c5fdc3d18989593d68435f4f4310f67391298c1b2e1325fae7a4a9fb8fd6e7 --package 0x4f76f0634d1dff123c19150ba96ce0ed7f56eb4dbda28ab66b627fdb1ecff523 --module rcoin --gas-budget 100000000 \r\n```\r\n获得：  \r\ncoin：0x9a45669e6e8702e6e7928559b2ee0241500401ecef14ca29b6481a97c2eee201  \r\n3. address1 将address2加入deny_list  \r\n```rust\r\nsui client call --function add_addr_from_deny_list --args 0x0000000000000000000000000000000000000000000000000000000000000403 0xc8da5610388f40617eb88a81588e321be7c9f64678d8b1407adbcf81d4dbd990 0x48c5fdc3d18989593d68435f4f4310f67391298c1b2e1325fae7a4a9fb8fd6e7 --package 0x4f76f0634d1dff123c19150ba96ce0ed7f56eb4dbda28ab66b627fdb1ecff523 --module rcoin --gas-budget 100000000 \r\n```\r\n成功交易：4t8MFsnzBi9Z4KWMyCzS32JCGdt6T2LZBrM2i6Cx6QDk  \r\n\r\n4. address2尝试将coin转移给address1  \r\n在钱包中进行  \r\n报错：  \r\n```rust\r\nSend transaction failed: Error: Transaction execution failed due to issues with transaction inputs, please review the errors and try again: Address 0x48c5fdc3d18989593d68435f4f4310f67391298c1b2e1325fae7a4a9fb8fd6e7 is denied for coin 4f76f0634d1dff123c19150ba96ce0ed7f56eb4dbda28ab66b627fdb1ecff523::rcoin::RCOIN. \r\n```\r\n\r\n5. address1将address2从deny_list中移除  \r\n```rust\r\nsui client call --function remove_addr_from_deny_list  --args 0x0000000000000000000000000000000000000000000000000000000000000403 0xc8da5610388f40617eb88a81588e321be7c9f64678d8b1407adbcf81d4dbd990 0x48c5fdc3d18989593d68435f4f4310f67391298c1b2e1325fae7a4a9fb8fd6e7 --package 0x4f76f0634d1dff123c19150ba96ce0ed7f56eb4dbda28ab66b627fdb1ecff523 --module rcoin --gas-budget 100000000 \r\n```\r\n成功交易：5UGRtRbxKDx7hafV9orwKRZaZEzBx3kfDp5bzcnY68Zr  \r\n\r\n6.address2再次尝试将coin转移给address1  \r\n成功交易：8LBc5Sok5NFVHXgHpq2TbxGCbtqu8KXvo6QoBg9WN9aM  \r\n## 总结  \r\n\r\n本文介绍了deny_list在coin中的应用。首先，我们了解了如何创建受管制的coin，并获取相应的权限凭证DenyCap。然后，通过示例展示了如何使用DenyCap来管理deny_list，包括添加和移除地址，并验证了交易中deny_list的限制。这个简短的示例展示了deny_list在coin中的实际应用。希望有所帮助。\r\n    \r\n<!--StartFragment-->\r\n\r\nMove语言学习交流QQ群: 79489587\\\r\nSui官方中文开发者电报群: https\\://t.me/sui_dev_cn\r\n\r\n<!--EndFragment-->"},"author":{"user":"https://learnblockchain.cn/people/18488","address":null},"history":null,"timestamp":1709798499,"version":1}