以后如何升级合约?
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 }
}
}
合约功能可升级,但状态不可升级,例如
#[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 }
}
}