How to Use Intrinsic Functions in Sway Contracts: A Complete Guide

Intrinsic functions in Sway contracts provide low-level, compiler-provided operations that map directly to Fuel VM instructions, accessible either through safe standard library wrappers or directly via double-underscore prefixes for advanced use cases.

The FuelLabs/sway repository exposes these compiler intrinsics through a two-layer architecture that balances safety with zero-overhead performance. Understanding how to leverage intrinsic functions in Sway contracts allows developers to query type information, perform raw memory operations, and access VM-specific features that are unavailable through standard language constructs.

What Are Intrinsic Functions in Sway?

Sway provides two distinct layers for low-level, compiler-provided operations called intrinsics:

Layer Purpose Location
Compiler intrinsics Direct, unchecked access to VM-level features via special functions the compiler replaces with bytecode instructions Compiler internals (prefixed with __)
Std-lib wrappers Safe, publicly exported functions that forward to compiler intrinsics with type safety sway-lib-std/src/intrinsics.sw

Compiler Intrinsics: The __ Prefix

Compiler intrinsics are special functions prefixed with double underscores (__) that the Sway compiler replaces directly with Fuel VM instructions. These include operations like __size_of, __addr_of, __gtf, __eq, __slice, and __dbg. Because they bypass standard safety checks, direct intrinsics are not part of the public API and may change without semantic versioning guarantees.

Standard Library Wrappers

The standard library provides safe wrappers in std::intrinsics that expose intrinsic functionality with proper type constraints. These wrappers live in sway-lib-std/src/intrinsics.sw and include functions like size_of::<T>(), is_reference_type::<T>(), and eq(). Contract authors should use these wrappers for production code to ensure future compatibility and type safety.

Architecture and Implementation

The Sway compiler processes intrinsic functions through a well-defined pipeline from parsing to code generation.

Parsing and AST Definitions

Intrinsic signatures are defined at the parser level in sway-ast/src/intrinsics.rs. This module establishes the recognized intrinsic names and their expected argument patterns, allowing the parser to identify calls like __size_of::<T>() during the initial syntax analysis phase.

Semantic Analysis

Type checking and validation occur in sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs. This module enforces type constraints—for example, ensuring __eq<T> only accepts primitive numeric or boolean types—and resolves generic parameters before code generation.

Code Generation

During the compilation phase, the compiler emits Fuel VM instructions directly for intrinsic calls. The type representation layer in sway-core/src/language/ty/expression/intrinsic_function.rs maintains the low-level mapping between high-level intrinsic calls and their corresponding VM bytecode, ensuring zero-overhead execution.

Practical Examples of Intrinsic Functions

Getting Type Sizes with size_of

The size_of wrapper returns the size of any type in bytes, useful for memory allocation and buffer calculations:

use std::intrinsics::size_of;

pub struct Point {
    x: u64,
    y: u64,
}

fn main() {
    // Primitive types
    assert(size_of::<u64>() == 8);
    
    // User-defined structs
    assert(size_of::<Point>() == 16);
}

Implementation reference: size_of wrapper in sway-lib-std/src/intrinsics.sw (lines 24-53).

Detecting Reference Types

Use is_reference_type to determine if a type is passed by reference at runtime:

use std::intrinsics::is_reference_type;

fn main() {
    // Primitive values return false
    assert(!is_reference_type::<u64>());
    
    // References return true
    assert(is_reference_type::<&u64>());
}

Implementation reference: is_reference_type wrapper in sway-lib-std/src/intrinsics.sw (lines 4-22).

Direct Memory Access with __addr_of

For advanced scenarios requiring raw pointers, use the direct compiler intrinsic __addr_of:

fn main() {
    let x = 42;
    
    // Returns a raw pointer to the value
    let ptr = __addr_of::<u64>(x);
    
    // Pointer can be used with arithmetic intrinsics like __ptr_add
}

Documentation reference: __addr_of specification in docs/book/src/reference/compiler_intrinsics.md.

Equality Comparisons

The eq wrapper provides type-safe equality checks backed by the __eq intrinsic:

use std::intrinsics::eq;

fn main() {
    let a: u64 = 10;
    let b: u64 = 10;
    
    assert(eq(a, b)); // Calls __eq under the hood
}

Implementation note: The eq wrapper forwards to __eq, defined in the compiler at sway-core/src/language/ty/expression/intrinsic_function.rs.

When to Use Direct Intrinsics vs Wrappers

Use standard library wrappers for all production contract development. The std::intrinsics module provides type safety, semantic versioning guarantees, and cleaner error messages.

Use direct compiler intrinsics only when:

  • Building advanced libraries that require zero-overhead calls and accept the unsafe nature of double-underscore names
  • Debugging compiler behavior with intrinsics like __dbg
  • Accessing intrinsics not yet exposed in the standard library

Direct intrinsics are not part of the public API and may change without a semver bump. The compiler enforces type constraints at compile time—for example, __eq<T> only works with primitive numeric or boolean types, while __addr_of<T> works for any value.

Summary

  • Intrinsic functions provide direct access to Fuel VM instructions through compiler-built-in operations.
  • Two-layer architecture: Compiler intrinsics (__ prefix) offer raw VM access, while std::intrinsics wrappers provide safe, versioned APIs.
  • Key files: sway-lib-std/src/intrinsics.sw contains wrappers; docs/book/src/reference/compiler_intrinsics.md documents raw intrinsics; sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs handles type checking.
  • Common use cases: Type size inspection (size_of), reference type detection (is_reference_type), raw memory access (__addr_of), and equality comparisons (eq).
  • Safety recommendation: Use std::intrinsics wrappers for production code; reserve direct __ intrinsics for advanced library development or debugging.

Frequently Asked Questions

What is the difference between __size_of and size_of in Sway?

__size_of is a compiler intrinsic that maps directly to a Fuel VM instruction, while size_of is a safe wrapper function defined in sway-lib-std/src/intrinsics.sw that calls __size_of internally. You should use size_of in production code because it is part of the stable public API, whereas __size_of is an implementation detail that may change without notice.

Are intrinsic functions in Sway safe to use?

Standard library intrinsic wrappers like size_of, eq, and is_reference_type are completely safe and type-checked by the compiler. However, direct compiler intrinsics prefixed with __ bypass certain safety guarantees—for example, __slice and __elem_at do not perform bounds checks, and __addr_of exposes raw pointers. Use direct intrinsics only when building low-level libraries or debugging.

How do I import intrinsic functions in a Sway contract?

Import the safe wrappers from the standard library using use std::intrinsics::* for all available functions, or specify individual imports like use std::intrinsics::{size_of, is_reference_type}. These wrappers are defined in sway-lib-std/src/intrinsics.sw and provide type-safe access to compiler intrinsics without requiring the __ prefix.

Can I create custom intrinsic functions in Sway?

No, intrinsic functions are built into the Sway compiler and cannot be defined by users. They represent special operations that the compiler maps directly to Fuel VM bytecode instructions. However, you can create wrapper functions around existing intrinsics to provide domain-specific APIs, similar to how the standard library wraps __size_of with size_of.

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 →