[Astar]コントラクト備忘録20(AccessControlについて)
こちらの知見がたまったので、備忘録として残します。
1 概要
- AccessControlについて
2 内容
こちらのコントラクトを作成しました。
OpenBrushのexampleの中身に「Minter」を確認するための「get_minter」関数を追加しました。
#![cfg_attr(not(feature = "std"), no_std)]
#![feature(min_specialization)]
#[openbrush::contract]
pub mod psp34 {
use ink_storage::traits::SpreadAllocate;
use openbrush::{
contracts::{
access_control::*,
psp34::extensions::{
burnable::*,
mintable::*,
},
},
modifiers,
traits::Storage,
};
#[ink(storage)]
#[derive(Default, SpreadAllocate, Storage)]
pub struct Contract {
#[storage_field]
psp34: psp34::Data,
#[storage_field]
access: access_control::Data,
}
// You can manually set the number for the role.
// But better to use a hash of the variable name.
// It will generate a unique identifier of this role.
// And will reduce the chance to have overlapping roles.
const MINTER: RoleType = ink_lang::selector_id!("MINTER");
impl Contract {
#[ink(constructor)]
pub fn new() -> Self {
ink_lang::codegen::initialize_contract(|instance: &mut Self| {
let caller = instance.env().caller();
instance._init_with_admin(caller);
// We grant minter role to caller in constructor, so he can mint/burn tokens
instance.grant_role(MINTER, caller).expect("Should grant MINTER role");
})
}
#[ink(message)]
pub fn get_minter(&self) -> RoleType {
MINTER
}
}
impl PSP34 for Contract {}
impl AccessControl for Contract {}
impl PSP34Mintable for Contract {
#[ink(message)]
#[modifiers(only_role(MINTER))]
fn mint(&mut self, account: AccountId, id: Id) -> Result<(), PSP34Error> {
self._mint_to(account, id)
}
}
impl PSP34Burnable for Contract {
#[ink(message)]
#[modifiers(only_role(MINTER))]
fn burn(&mut self, account: AccountId, id: Id) -> Result<(), PSP34Error> {
self._burn_from(account, id)
}
}
}
まずは、こちらのように、RoleType型の「MINTER」に対し、「MINTER」をハッシュ化したものを入れています。
「selector_id!」についてはこちらをご確認ください。
https://paritytech.github.io/ink/ink/macro.selector_id.html
また、こちらのように、「RoleType」はただの「u32」型であるということもわかりました。
https://github.dev/Supercolony-net/openbrush-contracts
そして、下のようにして、「grant_role」関数に「MINTER」を渡しています。
では、「grant_role」関数を見てみましょう。
その名の通り、ロール(役割)を与えます。
具体的には「members」というデータに対して、そのロールが付与されているのかを確認し、なければ、ロールを付与しています。
https://github.dev/Supercolony-net/openbrush-contracts
では、その「members」を見てみましょう。
whereの部分で「トレイトバウンド」を利用して、「members::MembersManagerトレイト」を実装していることを要求しています。
では「MembersManagerトレイト」を見てみましょう。
https://github.dev/Supercolony-net/openbrush-contracts
このように、「MembersManager」トレイトを確認すると、3つの関数が実装されていることが確認できます。
これがあるからこそ、「members」は「has_role」や「add」を使うことができたとわかりました。
https://github.dev/Supercolony-net/openbrush-contracts
では、実際のコードに戻りましょう。
「get_minter」関数は簡単に作ったものですが、これで、「MINTER」の値を確認できるようにしました。
では、実際に動かしてみましょう。
下のように、「get_minter」を使って、「MINTER」が「4,254,773,782」であることがわかりました。
そして、デプロイ時に、実行したウォレットに「MINTER」が付与されています。
そのため、「has_role」関数を使い、実行したウォレットに権限がついていることが確認できました。
一方、少し数字を変えて、「4,254,773,783」というロールの権限は付与していないので、下のように、「false」という結果が返ってきました。
その他、「test2」というウォレットには「MINTER」の権限を付与していないので、このように「false」となることが確認できました。
shibuya
bJz21JKwPDaNHtMN9KeQJQJxHWTHxYoaoWb3ux3wr1KnJEf
今回は以上です。
Discussion