900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > Facebook Libra币开发指南---Move语言开发代币智能合约

Facebook Libra币开发指南---Move语言开发代币智能合约

时间:2024-05-11 18:03:05

相关推荐

Facebook Libra币开发指南---Move语言开发代币智能合约

由于Libra Core基本还处于试验阶段,还没有API和SDK,因此除了命令行之外,没有其他接口。虽然文档中有Move语言介绍,但是在目前的testnet上,还不支持部署基于Move语言的智能合约,因此使我们这种特别喜欢动手尝试的人,非常抓狂。不过还是有牛人,发现可以使用Libra的功能测试框架,来编写和运行Move语言编写的智能合约,所以我们也可以基于这种方法来尝试一把。

代币智能合约

我们可以使用Move语言来开发一个代币的智能合约,代码如下所示:

modules:module Capability {// Capability is responsible for declaring an account's permissions.// We define the notion of an owner, minter and blacklisted.// Only the owner can assign blacklisted and minter capabilities.// The owner is defined by hardcoding its account before publishing the module.// -----------------------------------------------------------------// Declare owner as a resource. It's only meant to be published onceresource Owner { }// Declare a resource that declares an address's capabilities.// Every address using EToken will need to publish a resource themselves.// However, only the owner can change its content.resource T {minter: bool,blacklisted: bool,}// Every account should execute this once before using Capability and EToken module.// If the sender is the hardcoded owner, then owner capability is published.// Reverts if already publishedpublic publish() {let sender: address;sender = get_txn_sender();// Publish owner capability if sender is the privileged account// Uncomment the following line in production and use a real owner account: if (move(sender) == 0x0) {if (true) {// Always branch to here when testing, otherwise the test can't complete as the sender address is randomly chosen.Self.grant_owner_capability();}// Publish a new capability with no permissions.move_to_sender<T>(T{ minter: false, blacklisted: false });return; }// Internal function that grants owner capabilitygrant_owner_capability() {move_to_sender<Owner>(Owner {});return;}// Grants minter capability to receiver, but can only succeed if sender owns the owner capability.public grant_minter_capability(receiver: address, owner_capability: &R#Self.Owner) {let capability_ref: &mut R#Self.T;release(move(owner_capability));// Pull a mutable reference to the receiver's capability, and change its permission.capability_ref = borrow_global<T>(move(receiver));*(&mut move(capability_ref).minter) = true;return;}// Grants blacklist capability to receiver, but can only succeed if sender owns the owner capability.public grant_blacklisted_capability(receiver: address, owner_capability: &R#Self.Owner) {let capability_ref: &mut R#Self.T;release(move(owner_capability));// Pull a mutable reference to the receiver's capability, and change its permission.capability_ref = borrow_global<T>(move(receiver));*(&mut move(capability_ref).blacklisted) = true;return;}// This returns an immutable reference to the owner capability if it exists.// Is used by the owner to show ownership to privileged functions.// Reverts if owner capability does not exist.public borrow_owner_capability(): &R#Self.Owner {let sender: address;let owner_capability_ref: &mut R#Self.Owner;let owner_capability_immut_ref: &R#Self.Owner;sender = get_txn_sender();owner_capability_ref = borrow_global<Owner>(move(sender));owner_capability_immut_ref = freeze(move(owner_capability_ref));return move(owner_capability_immut_ref);}// This returns an immutable reference to the general capability if it exists.// Should be used by every account to prove capabilities.// Reverts if capability does not exist.public borrow_capability(): &R#Self.T {let sender: address;let capability_ref: &mut R#Self.T;let capability_immut_ref: &R#Self.T;sender = get_txn_sender();capability_ref = borrow_global<T>(move(sender));capability_immut_ref = freeze(move(capability_ref));return move(capability_immut_ref);}// Return whether the capability allows minting.public is_minter(capability: &R#Self.T): bool {let is_minter: bool;is_minter = *(&move(capability).minter);return move(is_minter);}// Return true the capability is not blacklisted.public is_not_blacklisted(capability: &R#Self.T): bool {let is_blacklisted: bool;is_blacklisted = *(&move(capability).blacklisted);return !move(is_blacklisted);}// Reverts if capability does not allow mintingpublic require_minter(capability: &R#Self.T) {let is_minter: bool;is_minter = Self.is_minter(move(capability));assert(move(is_minter), 0);return;}// Reverts if capability is blacklistedpublic require_not_blacklisted(capability: &R#Self.T) {let is_not_blacklisted: bool;is_not_blacklisted = Self.is_not_blacklisted(move(capability));assert(move(is_not_blacklisted), 0);return;}}module EToken {// This module is responsible for an actual eToken.// For it to be useful a capability has to be published by using the Capability module above.// -----------------------------------------------------------------import Transaction.Capability;// Declare the eToken resource, storing an account's total balance.resource T {value: u64,}// Publishes an initial zero eToken to the sender.// Should be called once before using this module.public publish() {move_to_sender<T>(T{ value: 0 });return;}// Mint new eTokens.// Reverts if capability does not allow it.public mint(value: u64, capability: &R#Capability.T): R#Self.T {Capability.require_minter(move(capability));return T{value: move(value)};}// Returns an account's eToken balance.// Reverts if an initial eToken hasn't been published.public balance(): u64 {let sender: address;let token_ref: &mut R#Self.T;let token_value: u64;sender = get_txn_sender();token_ref = borrow_global<T>(move(sender));token_value = *(&move(token_ref).value);return move(token_value);}// Deposit owned tokens to an payee's address, and destroy the tokens to deposit,// Reverts if user is blacklisted.public deposit(payee: address, to_deposit: R#Self.T, capability: &R#Capability.T) {let payee_token_ref: &mut R#Self.T;let payee_token_value: u64;let to_deposit_value: u64;Capability.require_not_blacklisted(move(capability));payee_token_ref = borrow_global<T>(move(payee));payee_token_value = *(&copy(payee_token_ref).value);// Unpack and destroy to_deposit tokensT{ value: to_deposit_value } = move(to_deposit);// Increase the payees balance with the destroyed token amount*(&mut move(payee_token_ref).value) = move(payee_token_value) + move(to_deposit_value);return;}// Withdraw an amount of tokens of the sender and return it.// This works by splitting the token published and returning the specified amount as tokens. public withdraw(amount: u64, capability: &R#Capability.T): R#Self.T {let sender: address;let sender_token_ref: &mut R#Self.T;let value: u64;Capability.require_not_blacklisted(move(capability));sender = get_txn_sender();sender_token_ref = borrow_global<T>(move(sender));value = *(&copy(sender_token_ref).value);// Make sure that sender has enough tokensassert(copy(value) >= copy(amount), 1);// Split the senders token and return the amount specified*(&mut move(sender_token_ref).value) = move(value) - copy(amount);return T{ value: move(amount) };}}script:// Performs simple testing to crudely verify the published modules above.import Transaction.Capability;import Transaction.EToken;main() {let sender: address;let owner_capability: &R#Capability.Owner;let capability: &R#Capability.T;let minted_tokens: R#EToken.T;let balance: u64;sender = get_txn_sender();// Publish initial capabilityCapability.publish();// Borrow owner_capability for minter delegationowner_capability = Capability.borrow_owner_capability();// Delegate itself as a minterCapability.grant_minter_capability(copy(sender), move(owner_capability));// Borrow general capability for proof of minting capabilitycapability = Capability.borrow_capability();// Publish an eToken accountEToken.publish();// Mint 100 eTokens and prove minter capabilityminted_tokens = EToken.mint(100, copy(capability));// Deposit the freshly minted tokens to itselfEToken.deposit(move(sender), move(minted_tokens), move(capability));// Test that the balance corresponds with the intended behaviourbalance = EToken.balance();assert(move(balance) == 100, 3);return;}

将该文件保存到language/functional_tests/tests/testsuite/modules/目录下,然后运行如下命令:

cargo test -p functional_tests eToken

运行结果如下所示:

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。