hyperlane-xyz / fuel-contracts

5 stars 2 forks source link

Better configuration of initial storage variables, like owners #54

Closed tkporter closed 1 year ago

tkporter commented 1 year ago

Sway has no constructors. Instead, they let you initialize storage slots at deploy time. But the tooling for this is super immature. The way storage works is a bit opaque -- the storage keys of variables don't just start from 0 and work up, each storage variable is found at a slot something like sha("storage-0"). And the way certain types are encoded in storage is also a bit unclear.

Unfortunately, it doesn't seem like there's nice tooling yet to let you override the storage. The best we can get is by manually specifying the raw storage keys and values like this (from https://rust.fuel.network/v0.38.1/getting-started/contracts.html?highlight=storage#the-deploy-functions):

        // Optional: Configure storage
        let key = Bytes32::from([1u8; 32]);
        let value = Bytes32::from([2u8; 32]);
        let storage_slot = StorageSlot::new(key, value);
        let storage_configuration =
            StorageConfiguration::default().set_manual_storage(vec![storage_slot]);

But figuring out the right storage keys to use and the correct encoding is pretty unreasonable for us to do ourselves. For example, for this storage block:

const INITIAL_OWNER: Option<Identity> = Option::Some(Identity::Address(Address::from(0x6b63804cfbf9856e68e5b6e7aef238dc8311ec55bec04df774003a2c96e0418e)));

storage {
    owner: Option<Identity> = INITIAL_OWNER,
    remote_gas_data: StorageMap<u32, RemoteGasData> = StorageMap {},
}

This is the initial storage that's generated:

[
  {
    "key": "c4f29cca5a7266ecbc35c82c55dd2b0059a3db4c83a3410653ec33aded8e9840",
    "value": "00000000000000006b63804cfbf9856e68e5b6e7aef238dc8311ec55bec04df7"
  },
  {
    "key": "c4f29cca5a7266ecbc35c82c55dd2b0059a3db4c83a3410653ec33aded8e9841",
    "value": "74003a2c96e0418e000000000000000000000000000000000000000000000000"
  },
  {
    "key": "d625ff6d8e88efd7bb3476e748e5d5935618d78bfc7eedf584fe909ce0809fc3",
    "value": "0000000000000001000000000000000000000000000000000000000000000000"
  }
]

It'd be great to not need to put our deployer address as a const within the actual contract and to set the storage slots ourselves, but atm this isn't really reasonable

The desired output here would be to be able to set the owner key for all relevant contracts at deploy time. This could look something like:

  1. Finding or building primitive tooling to help us generate storage slots
  2. Just accepting that the easiest path here is to hardcode our address
  3. Considering finding and replacing the hardcoded owner in these storage slots before deploying
  4. Considering an initialize-style function (knowing that this could probably be frontran...)

helpful context: Configurable constants exist but they cannot be used for initial storage https://fuellabs.github.io/sway/master/book/basics/variables.html?highlight=configuration#configurable-constants

tkporter commented 1 year ago

This should really be addressed by moving to the sway-libs Ownership library, so closing in favor of #67