跟我一起从0开始学习Solana合约开发,一起实操,一起做项目。这是一个系列文章,系统地记录了我的学习笔记。
本文是对Solana官网文档的翻译。我会根据我的理解对原文修改,并且针对初学者不容易理解的地方做了更多的翻译。
代币是数字资产,代表对多种类型资产的所有权或权利,这些资产包括金融工具、房地产、知识产权、虚拟商品等。代币化实现了资产产权的数字化,是管理同质化代币
和非同质化代币
的重要组成部分。
同质化代币(Fungible Tokens)
代表同类型、同价值且可以互换和分割的资产(例如 USDC)。 类似于以太坊中的 ERC20
标准。
非同质化代币(Non-fungible Tokens,NFT)
代表不可分割资产的所有权(例如艺术品)。 类似于以太坊中的 ERC721
标准。
在 Solana 中,这些代币统称为 SPL(Solana Program Library)
代币。以下是一些基本概念:
代币程序(Token Program)
包含了在网络上与代币交互的所有指令逻辑,涵盖了同质化代币和非同质化代币的管理。
铸币账户(Mint Account)
代表一种特定类型的代币,存储该代币的全局元数据,例如总供应量和铸币权限(即可以创建新代币单位的地址)。
代币账户(Token Account)
用于记录某个地址拥有的特定类型代币(由铸币账户定义)的数量,以便跟踪个人的代币持有情况。
提示
当前有两个版本的代币程序:原始代币程序(Original Token Program)和 扩展代币程序(Token Extensions Program,Token2022)。
扩展代币程序与原始版本的功能相同,但添加了更多特性和改进。对于创建新的代币(铸币账户),建议使用扩展代币程序。
代币
代表对 同质化(可互换) 或 非同质化(独特) 资产的所有权。
代币程序
包含了与网络上同质化代币和非同质化代币交互的所有指令。
扩展代币程序
是代币程序的新版本,增加了额外的功能,同时保持了相同的核心功能。
铸币账户
代表网络上的一种独特代币,并存储全局元数据,如总供应量。
代币账户
跟踪特定铸币账户的代币的个人所有权。
关联代币账户
是通过从所有者和铸币账户地址派生的地址创建的代币账户。
代币程序包含了在网络上与代币(包括同质化代币和非同质化代币)交互的所有指令逻辑。Solana 上的所有代币实际上都是由代币程序拥有的数据账户。
一些常用的指令包括:
InitializeMint
:创建一个新的铸币账户,用于表示一种新的代币类型。
InitializeAccount
:创建一个新的代币账户,用于持有特定类型代币(由铸币账户定义)的单位。
MintTo
:创建特定类型代币的新单位并将其添加到代币账户。这会增加代币的供应量,并且只能由铸币账户的铸币权限地址执行。
Transfer
:将特定类型代币的单位从一个代币账户转移到另一个代币账户。
Solana 上的代币通过由 Token Program
所拥有的 铸币账户(Mint Account)
的地址来唯一标识。
这些铸币账户实际上充当特定代币的全局计数器,并存储以下数据:
总供应量(Total Supply)
:该代币的总供应量,表示发行的代币数量。
铸币权限(Mint Authority)
:有权铸造新单位代币的地址。如果没有设置铸币权限,代币就不能再增加供应量。
冻结权限(Freeze Authority)
:有权冻结代币账户的地址,用于防止某些账户进行代币转账。
代币精度(Decimals)
:定义该代币的最小单位是多少(例如,USDC 使用 6 位小数)。
铸币账户的代码定义如下:
pub struct Mint {
/// Optional authority used to mint new tokens. The mint authority may only
/// be provided during mint creation. If no mint authority is present
/// then the mint has a fixed supply and no further tokens may be
/// minted.
pub mint_authority: COption<Pubkey>,
/// Total supply of tokens.
pub supply: u64,
/// Number of base 10 digits to the right of the decimal place.
pub decimals: u8,
/// Is `true` if this structure has been initialized
pub is_initialized: bool,
/// Optional authority to freeze token accounts.
pub freeze_authority: COption<Pubkey>,
}
供参考,这里是 Solana Explorer 上的USDC Mint Account。
为了跟踪特定代币每个单位的所有权,需要创建由 Token Program 管理的另一种类型的数据账户。这种账户被称为 Token Account(代币账户)
。
代币账户中存储的数据通常包括以下内容:
Mint
:表示该代币账户所持有的代币类型,即关联的铸币账户地址
。
Owner
:授权管理该代币账户的程序账户地址(代币程序)
,只有这个程序账户可以从中转出代币。
Amount
:该代币账户当前持有的代币数量(单位)。
代币账户的代码定义如下:
pub struct Account {
/// The mint associated with this account
pub mint: Pubkey,
/// The owner of this account.
pub owner: Pubkey,
/// The amount of tokens this account holds.
pub amount: u64,
/// If `delegate` is `Some` then `delegated_amount` represents
/// the amount authorized by the delegate
pub delegate: COption<Pubkey>,
/// The account's state
pub state: AccountState,
/// If is_native.is_some, this is a native token, and the value logs the
/// rent-exempt reserve. An Account is required to be rent-exempt, so
/// the value is used by the Processor to ensure that wrapped SOL
/// accounts do not drop below this threshold.
pub is_native: COption<u64>,
/// The amount delegated
pub delegated_amount: u64,
/// Optional authority to close the account.
pub close_authority: COption<Pubkey>,
}
为了让一个钱包拥有某种代币的单位,需要为这种代币(Mint Account
)创建一个 Token Account
,并将钱包指定为该 Token Account 的所有者(即 owner 字段的值时钱包地址)。
一个钱包可以为同一种代币创建多个 Token Account,例如为了进行分类管理。
每个 Token Account 只能由一个钱包拥有,并且只能存储一种类型的代币。
这种设计使得代币的管理和跟踪更加清晰,同时保持 Solana Token Program 的灵活性和效率。
注意:代币账户(AccountInfo)的所有者是代币程序,受程序管理,其中的 data 字段(AccountInfo.data)会解析为上面的 Account 结构,而这个 Account.owner 指向实际持有代币的钱包,表示该账户内的代币所有权归属于谁。
在 Solana 开发中,引入了一个关键概念:程序派生地址(Program Derived Address, PDA)
。通过 PDA,我们能够生成关联代币账户(Associated Token Account)地址。
因为我们还没有学习 PDA 的知识,因此,先跳过这个部分,后面我再专门写文章讲解。
本文到这里就结束了,下一篇文章我们来写一个SPL标准代币的案例。
如果你对 Web3 前沿探索、Go 后端技术,以及产品与哲学的深度思考感兴趣,可以关注我的公众号:认知那些事
。每一篇文章,都是我精心打磨的干货。扫码关注,一起探索技术与思想的广阔世界。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!