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

> Master intrinsic functions in Sway contracts. Learn how these low-level Fuel VM operations enhance your smart contract development with direct access or safe standard library wrappers.

- Repository: [Fuel Labs/sway](https://github.com/FuelLabs/sway)
- Tags: how-to-guide
- Published: 2026-03-04

---

**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`](https://github.com/FuelLabs/sway/blob/main/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`](https://github.com/FuelLabs/sway/blob/main/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`](https://github.com/FuelLabs/sway/blob/main/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:

```sway
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:

```sway
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`:

```sway
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`](https://github.com/FuelLabs/sway/blob/main/docs/book/src/reference/compiler_intrinsics.md).

### Equality Comparisons

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

```sway
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`](https://github.com/FuelLabs/sway/blob/main/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`](https://github.com/FuelLabs/sway/blob/main/docs/book/src/reference/compiler_intrinsics.md) documents raw intrinsics; [`sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs`](https://github.com/FuelLabs/sway/blob/main/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`.