Avoid Hardcoded Parameters and Values

Severity: Medium

Description

Hardcoding parameters reduces flexibility, making the code less adaptable to changing environments or configurations. In Substrate runtime development, this rigidity can lead to unnecessary re-deployments and upgrades when requirements change. Configurable parameters enhance versatility, allowing runtime adjustments without altering the source code.

A pallet configuration in Polkadot SDK is a set of associated types and constants defined in the Config trait of a pallet. These configurations allow developers to parameterize aspects of the pallet’s behavior, such as limits, thresholds, or external dependencies, at the runtime level. By implementing the Config trait in the runtime, these values can be adjusted dynamically for different environments without modifying or redeploying the pallet’s source code. This makes it an ideal replacement for hardcoded constants, providing flexibility and adaptability to evolving requirements.

What should be avoided

Hardcoding values, such as limits or thresholds, can make it difficult to adapt the code without modifying the source:

#![allow(unused)]
fn main() {
// Hardcoded limit
const LIMIT: u32 = 100;

impl<T: Config> Pallet<T> {
    fn do_something() {
        // No configurable limit
        for i in 0..T::LIMIT {
            // Logic that uses the configurable limit
        }
    }
}
}

In this example:

  • LIMIT is fixed at compile time, meaning any change requires editing the source code, recompiling, and redeploying the runtime. This process is inefficient and can disrupt the network.

Best practice

Use configurable traits to allow parameter adjustments at the runtime level, enhancing flexibility and adaptability:

#![allow(unused)]
fn main() {
// --- In pallet/lib.rs file ---
pub trait Config: frame_system::Config {
    const LIMIT: u32;
}

impl<T: Config> Pallet<T> {
    fn do_something() {
        // Access configurable limit
        for i in 0..T::LIMIT {
            // Logic that uses the configurable limit
        }
    }
}

// --- In runtime/lib.rs file ---
impl some_pallet::Config for Runtime {
    // ...
    type LIMIT = 100;
}
}

With this approach:

  • LIMIT can be defined in the runtime configuration, allowing you to change it without modifying the source code.
  • This setup makes the code adaptable to different environments and easily configurable to meet evolving needs.