NearProtocol中,如何迁移合约状态

Posted

技术标签:

【中文标题】NearProtocol中,如何迁移合约状态【英文标题】:In NearProtocol, how to migrate contract state 【发布时间】:2021-07-06 13:26:05 【问题描述】:

假设有一个用 near-sdk-rs 编写的合约,已部署,状态定义为:

#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize)]
pub struct NFT 
    pub tokens: UnorderedMap<TokenId, Token>,


#[derive(BorshDeserialize, BorshSerialize)]
pub struct Token 
   pub owner: AccountId

现在这个合约有一些用途,结果是一些tokens的记录存储在链上。 然后我想通过在Token 中添加一个字段来更新这个合同:

pub struct Token 
   pub owner: AccountId
   pub name: String // For existing ones, this will be set to ""

如何在保留现有状态的情况下执行此操作(类似于进行数据库迁移)?

【问题讨论】:

【参考方案1】:

您还可以看到我们创建的一些示例如何使用版本控制。

见 BerryClub:

#[derive(BorshDeserialize, BorshSerialize)]
pub struct AccountVersionAvocado 
    pub account_id: AccountId,
    pub account_index: AccountIndex,
    pub balance: u128,
    pub num_pixels: u32,
    pub claim_timestamp: u64,


impl From<AccountVersionAvocado> for Account 
    fn from(account: AccountVersionAvocado) -> Self 
        Self 
            account_id: account.account_id,
            account_index: account.account_index,
            balances: vec![account.balance, 0],
            num_pixels: account.num_pixels,
            claim_timestamp: account.claim_timestamp,
            farming_preference: Berry::Avocado,
        
    

https://github.com/evgenykuzyakov/berryclub/blob/ad2b37045b14fa72181ab92831fb741a7c40234b/contract-rs/pixel-board/src/account.rs#L19-L39

还有其他的,但一旦我找到它们就必须回到这个

【讨论】:

好例子,为了让这个例子更完整,在 berryclub 中还有这个:``` /// 在合约的结构中:pub legacy_accounts: Vector, pub accounts: LookupMap, ``` 这样你就可以在合约中保存两个版本的账户并在代码中处理这两个版本 这也是来自 SputnikDAO v2 github.com/near-daos/sputnik-dao-contract/blob/…【参考方案2】:

到目前为止,我只能建议部署一个临时合约,保留旧的Token 结构,NewToken 实现NewToken::from_token,以及一个更改方法:

impl Token 
    pub fn migrate(&mut self) 
        near_sdk::env::storage_write(
            "STATE",
            NewToken::from_token(self).try_into_vec().unwrap()
        );
    

迁移状态后,您可以使用NewToken 而不是Token 部署合约。

【讨论】:

这更接近迁移的想法。但是,如果 state 变得非常大,调用 migrate 会超过块 gas 限制吗? 对于大状态,一种可能的解决方案是分块运行迁移。

以上是关于NearProtocol中,如何迁移合约状态的主要内容,如果未能解决你的问题,请参考以下文章

从迁移签署交易到智能合约

将 Informix ESQLC 迁移到 Oracle Pro*C

令牌合约不会迁移,因为它是抽象的

如何开发编译部署调用智能合约

经典:浅谈以太坊智能合约的设计模式与升级方法

如何使用迁移laravel为该特定类别产品名称设置唯一功能应该是唯一的?