Function ink_env::set_code_hash
source · pub fn set_code_hash<E>(code_hash: &E::Hash) -> Result<()>where
E: Environment,
Expand description
Replace the contract code at the specified address with new code.
§Note
There are a few important considerations which must be taken into account when using this API:
- The storage at the code hash will remain untouched.
Contract developers must ensure that the storage layout of the new code is compatible with that of the old code.
- The contract address (
AccountId
) remains the same, while thecode_hash
changes.
Contract addresses are initially derived from hash(deploying_address ++ code_hash ++ salt)
. This makes it possible to determine a contracts address (AccountId
) using
the code_hash
of the initial code used to instantiate the contract.
However, because set_code_hash
can modify the underlying code_hash
of a contract,
it should not be relied upon that a contracts address can always be derived from its
stored code_hash
.
- Re-entrant calls use new
code_hash
.
If a contract calls into itself after changing its code the new call would use the new
code. However, if the original caller panics after returning from the sub call it
would revert the changes made by set_code_hash
and the next caller would use the old
code.
§Errors
ReturnCode::CodeNotFound
in case the supplied code_hash
cannot be found on-chain.
§Storage Compatibility
When the smart contract code is modified, it is important to observe an additional virtual restriction that is imposed on this procedure: you should not change the order in which the contract state variables are declared, nor their type.
Violating the restriction will not prevent a successful compilation, but will result in the mix-up of values or failure to read the storage correctly. This can result in severe errors in the application utilizing the contract.
If the storage of your contract looks like this:
#[ink(storage)]
pub struct YourContract {
x: u32,
y: bool,
}
The procedures listed below will make it invalid:
Changing the order of variables:
#[ink(storage)]
pub struct YourContract {
y: bool,
x: u32,
}
Removing existing variable:
#[ink(storage)]
pub struct YourContract {
x: u32,
}
Changing type of a variable:
#[ink(storage)]
pub struct YourContract {
x: u64,
y: bool,
}
Introducing a new variable before any of the existing ones:
#[ink(storage)]
pub struct YourContract {
z: Vec<u32>,
x: u32,
y: bool,
}
Please refer to the Open Zeppelin docs for more details and examples.