Let's say I have a simple/contrived ink contract:
#[ink(storage)
pub struct MyContract {
a: u8,
b: u8,
}
Now let's say it's in production and a == 1
and b == 2
.
I've done some work and realised that I no longer need a
and instead need a new variable in storage, c
.
#[ink(storage)
pub struct MyContract {
a: u8,
b: u8,
c: u8,
}
I've compiled the contract and done a set_code_hash()
on my production contract. I've also set the c
variable to 3
.
I now no longer need a
in my contract storage, so I remove it. Here's where the problem lies. The contract storage is currently laid out like so:
[1,2,3]
^ ^ ^
a b c
Removing the a
field like so:
#[ink(storage)
pub struct MyContract {
b: u8,
c: u8,
}
and doing a set_code_hash()
leaves the underlying storage unchanged, but the fields shift like so:
[1,2,3]
^ ^
b c
Which is rather frustrating. How can I remove the a
variable from the storage too? Something to make the storage become:
[2,3]
^ ^
b c
I've contemplated doing some kind of bit shift on the contract storage by the size of the field being removed, but I have no idea where to start accessing the byte[]
for the contract storage!
Further, imagine using complex types where the fields being removed are not at the start. How could that be done? E.g.
#[ink(storage)
pub struct MyContract {
a: u8,
b: u8,
c: u8,
d: Mapping<AccountId, AccountId>, // <-- let's say I want to remove this field
e: Vec<u8>,
f: u128,
g: Mapping<u8, u8>,
}
pub struct MyContract<KEY: StorageKey = ManualKey<0xABCDEF01>>
) but that maintains the storage pointing to the same place all the time, not dealing with any migration of the storage data itself. Thanks for any help in advance :)