datahaven-xyz/datahaven · critical · Error

InvalidUpgradeParameters

InvalidUpgradeParameters

Error message

InvalidUpgradeParameters

What it means

The legacy system pallet's `upgrade` extrinsic throws `Error::InvalidUpgradeParameters` under the same rule as system-v2: `impl_address` or `impl_code_hash` must not be zero. This variant uses `ensure_root` instead of a governance origin, but rejects zeroed upgrade targets to prevent bricking the system contract.

Solutions

  1. Deploy the new implementation and pass its actual address and keccak code hash.
  2. Add pre-dispatch validation in the sudo script: fail fast if either value is zero.
  3. Double-check call argument order when encoding the extrinsic.

Example fix

// before
System::upgrade(sudo_origin, H160::zero(), impl_code_hash, None)?;

// after
let addr = H160::from_slice(&deployed_address_bytes);
assert!(!addr.is_zero() && !impl_code_hash.is_zero());
System::upgrade(sudo_origin, addr, impl_code_hash, None)?;
Defensive patterns

Strategy: validation

Validate before calling

if (implAddress === H160::zero() || implCodeHash === H256::zero()) { bail!("zero upgrade target"); }

Type guard

fn is_valid_upgrade_target(addr: H160, hash: H256) -> bool { !addr.is_zero() && !hash.is_zero() }

Try / catch

match System::upgrade(sudo_origin, impl_address, impl_code_hash, initializer) { Err(Error::InvalidUpgradeParameters) => { eprintln!("zeroed impl params"); abort(); }, r => r? }

Prevention

When it happens

Trigger: Calling `upgrade(origin, impl_address, impl_code_hash, initializer)` with sudo/root origin while `impl_address == H160::zero()` or `impl_code_hash == H256::zero()`.

Common situations: Sudo scripts passing default/placeholder H160::zero() or H256::zero() because the implementation contract was never deployed; copy-pasted upgrade calls with zeroed fields; test fixtures forgetting to fill in real deployment artifacts.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of datahaven-xyz/datahaven@edcb13dbbc (2026-09-13). Data as JSON: /api/errors/c740c735f28a1930. Report an issue: GitHub.

Appendix: source

Thrown at operator/pallets/system/src/lib.rs:281

        /// contract
        ///
        /// Fee required: No
        ///
        /// - `origin`: Must be `Root`.
        /// - `impl_address`: The address of the implementation contract.
        /// - `impl_code_hash`: The codehash of the implementation contract.
        /// - `initializer`: Optionally call an initializer on the implementation contract.
        #[pallet::call_index(0)]
        #[pallet::weight((T::WeightInfo::upgrade(), DispatchClass::Operational))]
        pub fn upgrade(
            origin: OriginFor<T>,
            impl_address: H160,
            impl_code_hash: H256,
            initializer: Option<Initializer>,
        ) -> DispatchResult {
            ensure_root(origin)?;

            ensure!(
                !impl_address.eq(&H160::zero()) && !impl_code_hash.eq(&H256::zero()),
                Error::<T>::InvalidUpgradeParameters
            );

            let initializer_params_hash: Option<H256> = initializer
                .as_ref()
                .map(|i| H256::from(blake2_256(i.params.as_ref())));
            let command = Command::Upgrade {
                impl_address,
                impl_code_hash,
                initializer,
            };
            Self::send(PRIMARY_GOVERNANCE_CHANNEL, command, PaysFee::<T>::No)?;

            Self::deposit_event(Event::<T>::Upgrade {
                impl_address,
                impl_code_hash,
                initializer_params_hash,

View on GitHub (pinned to edcb13dbbc)