以后如何升级合约?

How can I upgrade the contract in future?

合约功能可升级,但状态不可升级,例如

#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)]
pub struct Contract {
   owner_id: AccountId
}

如果我想添加另一个字段,比如 saving_id,它会给出错误

#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)]
pub struct Contract {
   owner_id: AccountId,
   saving_id: AccountId
}

如何编写可升级合约?

这是 berrycards 使用的一种方法 https://github.com/evgenykuzyakov/berry-hot/blob/master/contract/src/lib.rs#L58

您应该编写一个类似于 init 函数的迁移函数,但不是从头开始创建状态,而是首先您可以访问旧状态,执行迁移并转储新状态。

要从 Rust 合约执行此操作,您需要使用 #[init(ignore_state)] 注释迁移函数(在 3.0.1 中的 near-sdk-rs 中可用)。这将在不检查合约是否首先初始化的情况下执行该功能。

完整示例取自 near-sdk-rs

#[near_bindgen]
impl Contract {
    #[init(ignore_state)]
    pub fn migrate_state(new_data: String) -> Self {
        // Deserialize the state using the old contract structure.
        let old_contract: OldContract = env::state_read().expect("Old state doesn't exist");
        // Verify that the migration can only be done by the owner.
        // This is not necessary, if the upgrade is done internally.
        assert_eq!(
            &env::predecessor_account_id(),
            &old_contract.owner_id,
            "Can only be called by the owner"
        );

        // Create the new contract using the data from the old contract.
        Self { owner_id: old_contract.owner_id, data: old_contract.data, new_data }
    }
}