深入了解合约
在上一节中,我们给出了一个用Cairo语言编写的智能合约的介绍性示例。在本节中,我们将逐步深入了解智能合约的所有组成部分。
在讨论interfaces时,我们明确了_public函数、external函数和view函数_ 之间的区别,并提到了如何与 storage 交互。
此时,您应该会想到很多问题:
- 如何定义内部/私有函数?
- 如何发出事件?如何索引事件?
- 我应该在哪里定义不需要访问合约状态的函数?
- 有办法减少冗余的模式代码吗?
- 如何存储更复杂的数据类型?
幸运的是,我们将在本章中回答所有这些问题。下面是我们在本章中将使用的合约示例:
use starknet::ContractAddress;
#[starknet::interface]
trait INameRegistry<TContractState> {
fn store_name(
ref self: TContractState, name: felt252, registration_type: NameRegistry::RegistrationType
);
fn get_name(self: @TContractState, address: ContractAddress) -> felt252;
fn get_owner(self: @TContractState) -> NameRegistry::Person;
}
#[starknet::contract]
mod NameRegistry {
use starknet::{ContractAddress, get_caller_address};
#[storage]
struct Storage {
names: LegacyMap::<ContractAddress, felt252>,
registration_type: LegacyMap::<ContractAddress, RegistrationType>,
total_names: u128,
owner: Person
}
#[event]
#[derive(Drop, starknet::Event)]
enum Event {
StoredName: StoredName,
}
#[derive(Drop, starknet::Event)]
struct StoredName {
#[key]
user: ContractAddress,
name: felt252
}
#[derive(Copy, Drop, Serde, starknet::Store)]
struct Person {
name: felt252,
address: ContractAddress
}
#[derive(Drop, Serde, starknet::Store)]
enum RegistrationType {
finite: u64,
infinite
}
#[constructor]
fn constructor(ref self: ContractState, owner: Person) {
self.names.write(owner.address, owner.name);
self.total_names.write(1);
self.owner.write(owner);
}
#[external(v0)]
impl NameRegistry of super::INameRegistry<ContractState> {
fn store_name(ref self: ContractState, name: felt252, registration_type: RegistrationType) {
let caller = get_caller_address();
self._store_name(caller, name, registration_type);
}
fn get_name(self: @ContractState, address: ContractAddress) -> felt252 {
let name = self.names.read(address);
name
}
fn get_owner(self: @ContractState) -> Person {
let owner = self.owner.read();
owner
}
}
#[generate_trait]
impl InternalFunctions of InternalFunctionsTrait {
fn _store_name(
ref self: ContractState,
user: ContractAddress,
name: felt252,
registration_type: RegistrationType
) {
let mut total_names = self.total_names.read();
self.names.write(user, name);
self.registration_type.write(user, registration_type);
self.total_names.write(total_names + 1);
self.emit(StoredName { user: user, name: name });
}
}
fn get_contract_name() -> felt252 {
'Name Registry'
}
fn get_owner_storage_address(self: @ContractState) -> starknet::StorageBaseAddress {
self.owner.address()
}
}