How to Use Compile-Time Constants and Configurable Values in Sway

Sway distinguishes between compile-time constants (const) baked permanently into bytecode and configurable values (configurable) that default to compile-time expressions but can be overridden during contract deployment.

When building smart contracts with the FuelLabs/sway repository, efficient management of immutable values is essential for both gas optimization and deployment flexibility. Learning how to use compile-time constants and configurable values in Sway enables developers to hardcode protocol-level invariants while allowing deployment-specific parameters like administrator addresses or token metadata to be customized. This guide explores the internal implementation, from AST parsing in sway-ast to deployment encoding in forc-util.

Understanding the Difference Between Constants and Configurables

Sway resolves both value types before execution, but they differ in mutability during the deployment phase:

Feature Compile-Time Constant Configurable Value
Syntax const NAME: TYPE = EXPR; configurable { const NAME: TYPE = EXPR; }
Evaluation During compilation by the constant evaluator Initial value evaluated at compile time, but overridable at deployment
Storage Inlined into generated bytecode Stored in contract's configurable metadata section
Changeable Never Only during deployment via transaction parameters

The AST representation for constants lives in sway-ast/src/item/item_const.rs, while configurables are parsed into ItemConfigurable nodes defined in sway-ast/src/item/item_configurable.rs.

Declaring Compile-Time Constants

Use the const keyword for values that must remain identical across all deployments, such as mathematical constants or protocol identifiers. The compiler evaluates these expressions using the constant-evaluation engine in sway-core/src/type_system/engine.rs, inlining the literal values directly into the bytecode.

library math_constants;

pub const PI_NUMERATOR: u64 = 314159265;
pub const MAX_DECIMALS: u8 = 18;

// Usage in contract
contract Calculator {
    fn calculate() -> u64 {
        PI_NUMERATOR / MAX_DECIMALS
    }
}

Because the compiler resolves these at build time, referencing a const incurs zero runtime overhead—the value is effectively hardcoded into the instruction stream.

Using Configurable Values for Deployment Flexibility

The configurable block allows you to define defaults that deployers can override. Each declaration inside the block is a standard const statement processed by the same constant evaluator, but the values are serialized into the contract's configurable section rather than inlined.

contract Token {
    configurable {
        const OWNER: Address = #0;
        const NAME: str[32] = "DefaultToken";
        const SYMBOL: str[8] = "DTK";
        const INITIAL_SUPPLY: u64 = 1_000_000;
    }

    storage {
        total_supply: u64 = INITIAL_SUPPLY,
    }

    #[storage(read)]
    fn get_config() -> (str[32], str[8]) {
        (NAME, SYMBOL)
    }
}

The encode_configurable function in sway-lib-std/src/codec.sw handles the serialization of these values for the VM.

Deploying with Custom Configurables

Override configurable values using the forc deploy command with the --configurables flag. The deployment utilities in forc-util/src/tx_utils.rs handle parsing and encoding these overrides into the transaction.

forc build

forc deploy --configurables "OWNER=0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890,INITIAL_SUPPLY=500_000"

If you omit a configurable, the compiler uses the default expression defined in the source code. The VM loads these values once during instantiation and binds them to the contract's symbol table as immutable variables.

Internal Implementation Details

Both const declarations and configurable initial values pass through the constant-evaluation engine in sway-core/src/type_system/engine.rs. This engine requires expressions to be fully resolvable at compile time—attempting to use runtime data results in a compilation error.

For configurables, the compiler generates metadata that the Fuel VM reads during contract instantiation. The encoding process utilizes encode_configurable from the standard library (sway-lib-std/src/codec.sw) to produce the raw slice stored in the configurable section.

Best Practices for Choosing Between Constants and Configurables

  • Use const for universal invariants like mathematical constants, fixed protocol addresses, or magic numbers that should never vary between deployments.

  • Use configurable for deployment-specific parameters such as administrator addresses, token metadata, initial supply caps, or feature flags that must remain immutable after deployment but differ across instances.

The examples/configurable_constants/src/main.sw file in the repository provides a minimal working example demonstrating both patterns.

Summary

  • Compile-time constants (const) are inlined into bytecode and immutable forever, parsed by sway-ast/src/item/item_const.rs.
  • Configurable values (configurable) default to compile-time expressions but can be overridden during deployment using forc deploy --configurables.
  • Both value types are evaluated by the constant-evaluation engine in sway-core/src/type_system/engine.rs before deployment.
  • Configurables are encoded via encode_configurable in sway-lib-std/src/codec.sw and stored in the contract's configurable metadata section.
  • Choose const for universal constants and configurable for deployment-specific settings that must remain immutable after instantiation.

Frequently Asked Questions

Can I change a configurable value after deploying a contract?

No. Configurable values can only be set during the initial deployment transaction. Once the contract is instantiated on-chain, the values become immutable and are loaded into the VM's symbol table as constant variables.

What happens if I deploy without specifying all configurables?

The compiler uses the default values defined in the configurable block's const expressions. These defaults are evaluated at compile time by the constant evaluator, so the contract always has valid values regardless of deployment overrides.

Can I use runtime data to calculate a configurable value?

No. Both const declarations and configurable initial values must be compile-time evaluable. The constant-evaluation engine in sway-core/src/type_system/engine.rs rejects expressions that depend on runtime inputs, storage, or external calls.

How do configurable values differ from storage variables?

Configurable values are set once at deployment and stored in the contract's metadata section, while storage variables are mutable state that can be updated by contract methods during execution. Configurables are more gas-efficient for immutable configuration but cannot be changed after deployment, unlike storage variables.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →