Önceki makalede, Aptos ağında bir Hello World programının nasıl geliştirileceğini kısaca ele aldık. Bundan itibaren, DeFi uygulamalarının geliştirilmesini ve güvenlik kaygılarını biraz daha derinlemesine inceleyeceğiz. Her zamanki gibi, bazı temel ama önemli kavramlarla başlamak istiyoruz. Bu makalede, Aptos coin'e (yani Aptos'taki değiştirilebilir token [1]) odaklanacağız; geliştirme ve yönetimini, ayrıca etkileşim yöntemlerini ele alacağız.
TL;DR
Bu makale size şunları anlatacak:
- Aptos Coin nedir?
- Kendi coin'inizi nasıl oluşturur ve yönetirsiniz?
- Coin'inizle nasıl etkileşime girersiniz?
0x1. Aptos Coin Hakkında
DeFi'nin atomları olan token'lar (ya da coin'ler), blok zinciri ekosistemlerinde yaygın biçimde kullanılmaktadır. Elektronik para birimi, staking payları ve organizasyon yönetimi için oy gücü dahil pek çok şeyi temsil etmek amacıyla kullanılabilirler. Bir ölçüde, DeFi'nin günlük faaliyeti, blok zinciri sistemleri genelinde gerçekleşen devasa hacimli token akışları olarak değerlendirilebilir.
Ethereum, token'lar için bir dizi standart geliştirmiştir. En bilineni, standart bir ERC20 token'ının uyması gereken arayüzleri belirten ERC20 olarak adlandırılır. ERC20 değiştirilebilir bir token standardıyken, ERC721 gibi değiştirilemez token standartları da mevcuttur.
Diğer blok zinciri sistemlerine benzer şekilde, Aptos'un da dijital varlıkların ilgili blok zincirlerinde nasıl oluşturulduğunu ve kullanıldığını tanımlayan kendi token standardı [2] bulunmaktadır. Özellikle Aptos'ta, değiştirilebilir token coin olarak adlandırılırken, değiştirilemez token (yani NFT) token olarak isimlendirilmektedir. Aşağıda, bir Aptos coin'i oluşturma, yönetme ve etkileşime girme yöntemini ele alacağız.
0x2. İlk Coin'inizi Oluşturun ve Yönetin
Aptos, resmi bir standart modül sağlamaktadır (ERC20'ye benzer şekilde): coin.move. Bu modülün API'sini çağırarak herhangi bir kullanıcı kolayca kendi coin'ini oluşturabilir. Bunun yanı sıra, coin.move aynı zamanda karmaşık DeFi uygulamaları geliştirmek için önemli ve kullanışlı olan coin yönetim mekanizması da sunmaktadır. Aşağıda, bu modüle dayanarak bir coin'in nasıl oluşturulacağını göstereceğiz.
Önceki makalede belirtildiği gibi, aşağıdaki komutu yazarak bir proje oluşturabilirsiniz:
aptos move init --name my_coin
Ardından sources klasörü altında yeni bir Move dosyası oluşturmanız gerekir. Şimdi onu aşağıdaki örnek kodla dolduralım; bu kod, BSC adlı standart bir coin oluşturup yönetmek için bsc adında bir modül tanımlamaktadır.
module BlockSec::bsc{
use aptos_framework::coin;
use aptos_framework::event;
use aptos_framework::account;
use aptos_std::type_info;
use std::string::{utf8, String};
use std::signer;
struct BSC{}
struct CapStore has key{
mint_cap: coin::MintCapability<BSC>,
freeze_cap: coin::FreezeCapability<BSC>,
burn_cap: coin::BurnCapability<BSC>
}
struct BSCEventStore has key{
event_handle: event::EventHandle<String>,
}
fun init_module(account: &signer){
let (burn_cap, freeze_cap, mint_cap) = coin::initialize<BSC>(account, utf8(b"BSC"), utf8(b"BSC"), 6, true);
move_to(account, CapStore{mint_cap: mint_cap, freeze_cap: freeze_cap, burn_cap: burn_cap});
}
public entry fun register(account: &signer){
let address_ = signer::address_of(account);
if(!coin::is_account_registered<BSC>(address_)){
coin::register<BSC>(account);
};
if(!exists<BSCEventStore>(address_)){
move_to(account, BSCEventStore{event_handle: account::new_event_handle(account)});
};
}
fun emit_event(account: address, msg: String) acquires BSCEventStore{
event::emit_event<String>(&mut borrow_global_mut<BSCEventStore>(account).event_handle, msg);
}
public entry fun mint_coin(cap_owner: &signer, to_address: address, amount: u64) acquires CapStore, BSCEventStore{
let mint_cap = &borrow_global<CapStore>(signer::address_of(cap_owner)).mint_cap;
let mint_coin = coin::mint<BSC>(amount, mint_cap);
coin::deposit<BSC>(to_address, mint_coin);
emit_event(to_address, utf8(b"minted BSC"));
}
public entry fun burn_coin(account: &signer, amount: u64) acquires CapStore, BSCEventStore{
let owner_address = type_info::account_address(&type_info::type_of<BSC>());
let burn_cap = &borrow_global<CapStore>(owner_address).burn_cap;
let burn_coin = coin::withdraw<BSC>(account, amount);
coin::burn<BSC>(burn_coin, burn_cap);
emit_event(signer::address_of(account), utf8(b"burned BSC"));
}
public entry fun freeze_self(account: &signer) acquires CapStore, BSCEventStore{
let owner_address = type_info::account_address(&type_info::type_of<BSC>());
let freeze_cap = &borrow_global<CapStore>(owner_address).freeze_cap;
let freeze_address = signer::address_of(account);
coin::freeze_coin_store<BSC>(freeze_address, freeze_cap);
emit_event(freeze_address, utf8(b"freezed self"));
}
public entry fun emergency_freeze(cap_owner: &signer, freeze_address: address) acquires CapStore, BSCEventStore{
let owner_address = signer::address_of(cap_owner);
let freeze_cap = &borrow_global<CapStore>(owner_address).freeze_cap;
coin::freeze_coin_store<BSC>(freeze_address, freeze_cap);
emit_event(freeze_address, utf8(b"emergency freezed"));
}
public entry fun unfreeze(cap_owner: &signer, unfreeze_address: address) acquires CapStore, BSCEventStore{
let owner_address = signer::address_of(cap_owner);
let freeze_cap = &borrow_global<CapStore>(owner_address).freeze_cap;
coin::unfreeze_coin_store<BSC>(unfreeze_address, freeze_cap);
emit_event(unfreeze_address, utf8(b"unfreezed"));
}
}
0x2.1 Temel Tasarım
Önce yapı kısmına bakalım. Toplamda üç yapı tanımlanmıştır.
BSCstruct'ı, coin'in benzersiz tanımlayıcısı olarak kullanılır. Bu sayede, bu coinBlockSec::bsc::BSCyoluyla benzersiz biçimde belirlenebilir.CapStorestruct'ı,aptos_framework::coinmodülünden elde edilen bazı yetenekleri depolamak için kullanılır. Bu yetenekler, bazı özel işlemlerin izinlerine karşılık gelmekte olup daha sonra açıklanacaktır.BSCEventStorestruct'ı, kullanıcı olaylarını kaydetmek için kullanılır.
Bu yapıların ardından, modülü başlatmak için kullanılan ve yalnızca modül zincirde yayımlandığında bir kez çağrılacak olan init_module fonksiyonu yer almaktadır. Bu fonksiyonda, modül yeni bir coin için benzersiz tanımlayıcı olarak BlockSec::bsc::BSC'yi kaydetmek üzere coin::initialize<BSC>'yi çağırır.
public fun initialize<CoinType>(
account: &signer,
name: string::String,
symbol: string::String,
decimals: u8,
monitor_supply: bool,
): (BurnCapability<CoinType>, FreezeCapability<CoinType>, MintCapability<CoinType>) {
initialize_internal(account, name, symbol, decimals, monitor_supply, false)
}
/// Capability required to mint coins.
struct MintCapability<phantom CoinType> has copy, store {}
/// Capability required to freeze a coin store.
struct FreezeCapability<phantom CoinType> has copy, store {}
/// Capability required to burn coins.
struct BurnCapability<phantom CoinType> has copy, store {}
Kayıttan sonra, aptos_framework::coin içinde BlockSec::bsc::BSC türünü alan tüm genel fonksiyonlar bu coin üzerinde işlem yapacaktır. Bu kayıt işlemi üç yetenek döndürür: MintCapability, FreezeCapability ve BurnCapability. Bu yetenekler sırasıyla coin basma, kullanıcı hesaplarını dondurma ve coin yakma için gereklidir. Bir ölçüde, böyle bir yetenek struct'ının işlevselliği bir anahtara benzer; belirli bir izni açmak için kullanılır. Anahtara sahip olan kişi ilgili izni elde edebilir. Bu yetenekleri daha sonra kullanmak üzere yöneticiye/modül yayıncısına ait CapStore struct'ında saklıyoruz.
Bu arada, kayıt işlemi sırasında ilgili bilgileri kaydetmek üzere yönetici adresi altında bir CoinInfo struct'ı depolanacaktır:
/// Information about a specific coin type. Stored on the creator of the coin's account.
struct CoinInfo<phantom CoinType> has key {
name: string::String,
/// Symbol of the coin, usually a shorter version of the name.
/// For example, Singapore Dollar is SGD.
symbol: string::String,
/// Number of decimals used to get its user representation.
/// For example, if `decimals` equals `2`, a balance of `505` coins should
/// be displayed to a user as `5.05` (`505 / 10 ** 2`).
decimals: u8,
/// Amount of this coin type in existence.
supply: Option<OptionalAggregator>,
}
init_module fonksiyonu çağrıldıktan sonra, coin'iniz zincire kaydedilmiş olur. Ancak şu an için herhangi bir dolaşım bulunmadığından kimse bu coin'i kullanamaz. Coin'i kullanılabilir kılmak için ihraç, dağıtım ve imha gibi bazı işlemlerin desteklenmesi gerekir. Bu işlemler, coin'i kaydederken elde ettiğimiz yetenekleri gerektirir.
0x2.2 Coin Yönetimi
Bu coin, aşağıdaki kurallara uymak üzere tasarlanmıştır:
- Yalnızca yönetici (admin) coin basabilir.
- Kullanıcılar istedikleri zaman kendi coin'lerini yakabilir.
- Kullanıcılar istedikleri zaman hesaplarını dondurabilir/çözebilir.
Buna göre beş yönetim fonksiyonu tanımlıyoruz: mint_coin, burn_coin, freeze_self, emergency_freeze ve unfreeze. İlk iki fonksiyon sırasıyla coin basma ve coin yakma işlemlerinden sorumluyken, son üçü hesapları dondurma ve çözme için kullanılır.
Coin Basma
Modülümüzde, coin basmak için mint_coin fonksiyonu kullanılır. Yalnızca yöneticiler coin basabildiğinden, bu fonksiyonda ilgili yetkiyi doğrulamamız gerekir.
public entry fun mint_coin(cap_owner: &signer, to_address: address, amount: u64) acquires CapStore, BSCEventStore{
let mint_cap = &borrow_global<CapStore>(signer::address_of(cap_owner)).mint_cap;
let mint_coin = coin::mint<BSC>(amount, mint_cap);
coin::deposit<BSC>(to_address, mint_coin);
emit_event(to_address, utf8(b"minted BSC"));
}
Bu fonksiyon üç parametre gerektirir:
cap_owner,&signertüründedir, yani işlemin başlatıcısıdır.to_address, basılan coin'lerin yatırılacağı adresi belirtir.amount, basılan coin miktarını belirtir.
Üç adımdan oluşur: coin basma yetkisini alma, coin basma ve coin yatırma.
İlk olarak, mint_coin fonksiyonunun başında işlem başlatıcısının hesap adresi signer::address_of(cap_owner) aracılığıyla elde edilebilir. Ardından, borrow_global<CapStore> kullanılarak hesabın modülün yöneticisi olduğunu doğrulamak amacıyla CapStore'a sahip olup olmadığı kontrol edilir. Bu sayede, yalnızca yöneticinin coin basabilmesi güvence altına alınırken diğer kullanıcılar bu adımda başarısız olacaktır.
İkinci olarak, mint_coin fonksiyonu coin basmak için aptos_framework::coin modülünün mint fonksiyonunu çağırır.
public fun mint<CoinType>(
amount: u64,
_cap: &MintCapability<CoinType>,
): Coin<CoinType> acquires CoinInfo {
if (amount == 0) {
return zero<CoinType>()
};
let maybe_supply = &mut borrow_global_mut<CoinInfo<CoinType>>(coin_address<CoinType>()).supply;
if (option::is_some(maybe_supply)) {
let supply = option::borrow_mut(maybe_supply);
optional_aggregator::add(supply, (amount as u128));
};
Coin<CoinType> { value: amount }
}
Burada MintCapability gereklidir. Özellikle, MintCapability'nin referansı olarak _cap adlı bir parametrenin geçirilmesi zorunludur. Ardından, MintCapability yeteneğiyle ilişkili izin de buna göre aktarılır. Açık bir erişim denetimi olmasa da doğrulama Move dili tarafından uygulanır.
Üçüncü olarak, mint_coin fonksiyonu basılan coin'leri belirtilen to_address'e yatırmak için deposit fonksiyonunu çağırır.
İpucu#1: Ayrıcalıklı hesaplara yönelik erişim denetimleri, benzer bir yöntem kullanılarak doğrulanabilir.
Coin Yakma
Coin yakma prosedürü, coin basma prosedüründen farklıdır. Özellikle, yalnızca yöneticinin mint_coin fonksiyonunu çağırmasına izin verilirken, herhangi bir kullanıcı burn_coin fonksiyonunu çağırabilir. Bu amaçla, burn_coin fonksiyonu bu kullanıcılar için geçici olarak ayrıcalık yükseltmesi yapmalı, yani BurnCapability yeteneğini edinmelidir.
public entry fun burn_coin(account: &signer, amount: u64) acquires CapStore, BSCEventStore{
let owner_address = type_info::account_address(&type_info::type_of<BSC>());
let burn_cap = &borrow_global<CapStore>(owner_address).burn_cap;
let burn_coin = coin::withdraw<BSC>(account, amount);
coin::burn<BSC>(burn_coin, burn_cap);
emit_event(signer::address_of(account), utf8(b"burned BSC"));
}
Bu fonksiyon iki parametre gerektirir:
account,&signertüründedir, yani işlemin başlatıcısıdır.amount, yakılacak coin miktarını belirtir.
Aynı zamanda üç adımdan oluşur: coin yakma yetkisini alma, coin çekme ve coin yakma.
Açıkça görüldüğü üzere, aptos_framework::coin modülünün burn fonksiyonu çağrıyı yapandan BurnCapability'ye bir referans iletmesini ister; ancak bu yetenek yöneticinin CapStore'unda saklanmaktadır. Bu nedenle, sıradan kullanıcıların ellerindeki coin'leri yakabilmesi için bu yetkiyi edinmelerine izin vermemiz gerekir.
public fun burn<CoinType>(
coin: Coin<CoinType>,
_cap: &BurnCapability<CoinType>,
) acquires CoinInfo {
let Coin { value: amount } = coin;
assert!(amount > 0, error::invalid_argument(EZERO_COIN_AMOUNT));
let maybe_supply = &mut borrow_global_mut<CoinInfo<CoinType>>(coin_address<CoinType>()).supply;
if (option::is_some(maybe_supply)) {
let supply = option::borrow_mut(maybe_supply);
optional_aggregator::sub(supply, (amount as u128));
}
}
Bu amaca ulaşmak için Move dili tarafından sağlanan borrow_global operatörünü kullanabiliriz. Bu operatör, bir hesabın değiştirilemez genel deposundan belirli bir veri türünü okumak için kullanılır. Bu operatörü kullanarak, bir modül yöneticiye ait yetkiyi diğer kullanıcılara ödünç verebilir. Yani, istediğimiz yetkiyi almak için yönetici adresi gereklidir.
Ancak, burn_coin fonksiyonunun işlem başlatıcısı yönetici değil, kullanıcıdır. Bu nedenle yönetici adresi signer aracılığıyla (mint_coin fonksiyonunda olduğu gibi) elde edilemez. Neyse ki, bu yapının tanımlandığı modülün adresini almak için BSC ile birlikte aptos_std::type_info aracılığıyla elde edilebilir. Modül yönetici adresi altında yayımlandığından, yönetici adresini de bu şekilde elde edebilir ve nihayetinde BurnCapability yeteneğine ulaşabiliriz.
İpucu#2:
_borrow_global_operatörü, bir modülün yeteneklerini geçici olarak edinmek için kullanılabilir.
BurnCapability'yi aldıktan sonra modül, kullanıcıdan belirtilen miktarda coin çekebilir ve bu yetkiyle coin'i yakabilir.
Coin Hesaplarını Dondurma ve Çözme
Yukarıdaki tartışmaya dayanarak, artık coin hesaplarının yönetimini kolayca inceleyebiliriz. Özellikle, kullanıcıların kendi coin hesaplarını dondurabilmesi için freeze_self fonksiyonunu sunuyoruz. Burada aynı zamanda yalnızca yönetici tarafından kullanılabilecek acil dondurma işlevi için emergency_freeze fonksiyonunu da sunuyoruz. Ayrıca, acil dondurma mekanizmasının varlığı nedeniyle kullanıcıların kendilerini çözememesi gerekir. Bu yüzden unfreeze fonksiyonu da kullanıcı hesaplarını çözmek için yönetici gerektirir.
public entry fun freeze_self(account: &signer) acquires CapStore, BSCEventStore{
let owner_address = type_info::account_address(&type_info::type_of<BSC>());
let freeze_cap = &borrow_global<CapStore>(owner_address).freeze_cap;
let freeze_address = signer::address_of(account);
coin::freeze_coin_store<BSC>(freeze_address, freeze_cap);
emit_event(freeze_address, utf8(b"freezed self"));
}
public entry fun emergency_freeze(cap_owner: &signer, freeze_address: address) acquires CapStore, BSCEventStore{
let owner_address = signer::address_of(cap_owner);
let freeze_cap = &borrow_global<CapStore>(owner_address).freeze_cap;
coin::freeze_coin_store<BSC>(freeze_address, freeze_cap);
emit_event(freeze_address, utf8(b"emergency freezed"));
}
public entry fun unfreeze(cap_owner: &signer, unfreeze_address: address) acquires CapStore, BSCEventStore{
let owner_address = signer::address_of(cap_owner);
let freeze_cap = &borrow_global<CapStore>(owner_address).freeze_cap;
coin::unfreeze_coin_store<BSC>(unfreeze_address, freeze_cap);
emit_event(unfreeze_address, utf8(b"unfreezed"));
}
İpucu#3: Yetenekleri fonksiyonlar aracılığıyla döndürürken dikkatli olun! Bu yetenekleri edinen kötü niyetli kullanıcılar, coin sahiplerine zarar vermek için bunları kötüye kullanabilir!
0x3. Coin ile Etkileşim
Burada coin ile etkileşim kurma yöntemine odaklanıyoruz.
0x3.1 Kayıt
Modülde bir register fonksiyonunun bulunduğunu fark etmiş olabilirsiniz:
public entry fun register(account: &signer){
let address_ = signer::address_of(account);
if(!coin::is_account_registered<BSC>(address_)){
coin::register<BSC>(account);
};
if(!exists<BSCEventStore>(address_)){
move_to(account, BSCEventStore{event_handle: account::new_event_handle(account)});
};
}
Bu fonksiyon, kullanıcıların coin kullanım haklarını ve olay kayıt araçlarını kaydetmelerine yardımcı olmak için kullanılır. Belirli bir coin'i kullanabilmek için aptos_framework::coin modülü, kullanıcının önce aptos_framework::coin::register fonksiyonu aracılığıyla coin kullanım hakkını açıkça kaydetmesini zorunlu kılar.
public fun register<CoinType>(account: &signer) {
let account_addr = signer::address_of(account);
assert!(
!is_account_registered<CoinType>(account_addr),
error::already_exists(ECOIN_STORE_ALREADY_PUBLISHED),
);
account::register_coin<CoinType>(account_addr);
let coin_store = CoinStore<CoinType> {
coin: Coin { value: 0 },
frozen: false,
deposit_events: account::new_event_handle<DepositEvent>(account),
withdraw_events: account::new_event_handle<WithdrawEvent>(account),
};
move_to(account, coin_store);
}
Kullanıcılar, bu fonksiyon aracılığıyla bu tür coin'i kaydettikleri takdirde bu coin'i normal şekilde tutabilirler. Başka bir deyişle, belirli bir coin'i tutmak istemiyorsanız, diğerleri sizin onayınız olmadan bu coin'i hesabınıza yatıramaz. Kayıt işlemi aslında hesabınıza (hedef coin türünde) bir CoinStore struct'ı yerleştirir. Bu CoinStore struct'ı, bakiyenizi kaydetmek için bir Coin struct'ı içerir.
İpucu#4: Ethereum token'larından farklı olarak, bir Aptos coin'i kullanıcının açık kaydı olmadan tutulamaz ve üzerinde işlem yapılamaz.
0x3.2 Transfer
Şu an biraz BSC coin'iniz olduğunu varsayarsak, aptos_framework::coin modülünün transfer fonksiyonunu çağırarak bu coin'leri transfer edebilirsiniz.
public entry fun transfer<CoinType>(
from: &signer,
to: address,
amount: u64,
) acquires CoinStore {
let coin = withdraw<CoinType>(from, amount);
deposit(to, coin);
}
Bu, coin modülü tarafından sağlanan bir giriş fonksiyonudur. Mantık, iki genel fonksiyonun çağrılmasından oluşur: withdraw ve deposit. withdraw fonksiyonu, hesabınızdan belirli miktarda varlığı bir coin'e çekmek için kullanılan &signer iznini gerektirir. deposit fonksiyonu, bir coin'i kayıtlı herhangi bir hesaba yatırabilir. Bu fonksiyon ek izin gerektirmez ve belirtilen coin'leri hesap adresine yatırır. Son olarak, transfer edilen coin'ler hedef adresin CoinStore struct'ında saklanan coin'lerle otomatik olarak birleştirilir.
İpucu#5: Çekildikten sonra, coin'deki varlıklar mevcut
_transfer_fonksiyonunun kontrolü altındadır. Bu fonksiyon, ekstra izin almadan bu varlıkları_deposit_fonksiyonuna iletebilir.
0x3.3 Bölme ve Birleştirme
Ethereum token'larından farklı olarak, coin'lerin dolaşımı kullanıcıların bakiyeleri değiştirilerek güncellenemez. Bunun yerine, coin modülündeki Coin struct'ı çekilerek gerçekleştirilebilir. Bunu yaparak, kullanıcılar bu struct'ı diğer modüllere ileterek varlık dolaşımını gerçekleştirir. Bir struct yalnızca onu tanımlayan modül tarafından değiştirilebildiğinden, coin modülü farklı senaryoların ihtiyaçlarını karşılamak üzere Coin struct'ını işlemek için coin'leri daha küçük birimlere bölme ve birden fazla coin'i birleştirme dahil bazı arayüzler sağlar.
1. extract fonksiyonu coin'leri bölmek için kullanılır. Bir Coin struct'ı alır, içindeki varlığın bir kısmını çıkararak yeni bir Coin struct'ı oluşturur ve yeni struct'ı döndürür.
public fun extract<CoinType>(coin: &mut Coin<CoinType>, amount: u64): Coin<CoinType> {
assert!(coin.value >= amount, error::invalid_argument(EINSUFFICIENT_BALANCE));
coin.value = coin.value - amount;
Coin { value: amount }
}
2. extract_all fonksiyonu, orijinal Coin struct'ının tüm değerini çıkararak yeni bir Coin struct'ına aktarmak için kullanılır. Sonuç olarak, orijinal Coin struct'ının değeri sıfır olur (diğer adıyla zero_coin). zero_coin struct'ı, destroy_zero fonksiyonu çağrılarak yok edilebilir.
public fun extract_all<CoinType>(coin: &mut Coin<CoinType>): Coin<CoinType> {
let total_value = coin.value;
coin.value = 0;
Coin { value: total_value }
}
public fun destroy_zero<CoinType>(zero_coin: Coin<CoinType>) {
let Coin { value } = zero_coin;
assert!(value == 0, error::invalid_argument(EDESTRUCTION_OF_NONZERO_TOKEN))
}
3. merge fonksiyonu, coin'leri birleştirmek için kullanılır. İki Coin struct'ının değerlerini, yani source_coin ve dst_coin'i dst_coin struct'ında birleştirebilir ve source_coin struct'ını yok edebilirsiniz.
public fun merge<CoinType>(dst_coin: &mut Coin<CoinType>, source_coin: Coin<CoinType>) {
spec {
assume dst_coin.value + source_coin.value <= MAX_U64;
};
dst_coin.value = dst_coin.value + source_coin.value;
let Coin { value: _ } = source_coin;
}
4. zero fonksiyonu, bir zero_coin struct'ı oluşturmak için kullanılır.
public fun zero<CoinType>(): Coin<CoinType> {
Coin<CoinType> {
value: 0
}
}
0x4. Coin'i Test Etme
Bu coin'i hızlıca test etmek için önce aşağıdaki komutla dağıtabilirsiniz (Move.toml içinde yayıncı hesap adresinizi ayarlamayı unutmayın!)
$ aptos move publish --package-dir ./
Compiling, may take a little while to download git dependencies...
INCLUDING DEPENDENCY AptosFramework
INCLUDING DEPENDENCY AptosStdlib
INCLUDING DEPENDENCY MoveStdlib
BUILDING my_coin
package size 2751 bytes
Do you want to submit a transaction for a range of [868300 - 1302400] Octas at a gas unit price of 100 Octas? [yes/no] >
yes
{
"Result": {
"transaction_hash": "xxx",
...
Bu şekilde, coin zincirde başarıyla yayımlandı; ancak henüz herhangi bir dolaşımı bulunmuyor. Basılan coin'leri almak için hesabınızı kaydetmeniz gerekir.
$ aptos move run --function-id default::bsc::register
Do you want to submit a transaction for a range of [153100 - 229600] Octas at a gas unit price of 100 Octas? [yes/no] >
yes
{
"Result": {
"transaction_hash": "xxx",
...
İkinci komuttaki Your-address'in kendi adresinizle değiştirilmesi gerektiğini unutmayın (.aptos/config.yaml içindeki account'a bakın). Adresinizi tarayıcıya girin ve Resources sekmesine tıklayın; bu hesabın artık 100 BSC coin'e sahip olduğunu görebilirsiniz.


Coin'leri başka bir hesaba transfer etmek istiyorsanız, o hesabın coin'i kullanmak için kayıt olmasını sağlamayı unutmayın. transfer fonksiyonu genel bir fonksiyon olduğundan, genel parametreyi BSC ve to_address olarak belirtmeniz gerekir:
$ aptos move run — function-id 0x1::coin::transfer — type-args BSC-module-address::bsc::BSC — args address:To_address u64:1
Bu komut, 1 BSC coin'i To_address'e transfer etmek için coin modülünün transfer fonksiyonunu çağırır. Burada 0x1::coin::transfer, transfer fonksiyonunun fonksiyon kimliğidir. BlockSec::bsc::BSC'nin coin'inizin tanımlayıcısı olduğunu unutmayın; genel parametre buna göre belirtilmelidir. Ayrıca, BSC-module-address, Move.toml'da BlockSec'e atanan modül yayıncısı hesap adresiyle değiştirilmelidir.
0x5. Sırada Ne Var
Kendi coin'inizi nasıl oluşturacağınızı, yöneteceğinizi ve etkileşime gireceğinizi anladıktan sonra, ilk DeFi temel taşı projesini nasıl inşa edeceğimizi göstereceğiz: Otomatik Piyasa Yapıcısı (AMM). Move geliştirme ve güvenlik uygulamalarıyla ilgili daha ilginç konular ele alınacak. Takipte kalın!
Referans
[1] https://aptos.dev/concepts/coin-and-token/aptos-coin/
[2] https://aptos.dev/concepts/coin-and-token/index
[3] https://aptos.dev/concepts/coin-and-token/aptos-token



