When a contract is deployed to StarkNet, if it has a special @constructor function then this function will be run once. It can not be run after deployment.

%lang starknet
%builtins pedersen range_check

from starkware.cairo.common.cairo_builtins import HashBuiltin

@storage_var
func stored_parameter() -> (res : felt):
end

@storage_var
func important_contract_address() -> (res : felt):
end

# Run on deployment only. Must have constructor in name and decorator.
@constructor
func constructor{
        syscall_ptr : felt*,
        pedersen_ptr : HashBuiltin*,
        range_check_ptr
    }(
      special_number : felt,
      important_address : felt
    ):
    stored_parameter.write(special_number)
    important_contract_address.write(important_address)
    return ()
end

# Function to get the numbers stored at deployment.
@view
func read_special_values{
        syscall_ptr : felt*,
        pedersen_ptr : HashBuiltin*,
        range_check_ptr
    }() -> (
        number : felt,
        address : felt
    ):
    let (number) = stored_parameter.read()
    let (address) = important_contract_address.read()
    return (number, address)
end


Save as contracts/constructor.cairo

Compile

Compile

nile compile

Or compile this specific contract

nile compile contracts/constructor.cairo

Test

Make a new file called test_constructor.py and populate it:

In pytest, the deployment arguments are passed as follows:

contract = await starknet.deploy("contracts/constructor.cairo",
    constructor_calldata=[ARG_1, ARG_2])

Full test code:

import pytest
import asyncio
from starkware.starknet.testing.starknet import Starknet

PARAMETER = 23456
IMPORTANT_ADDRESS = 987623451345

# Enables modules.
@pytest.fixture(scope='module')
def event_loop():
    return asyncio.new_event_loop()

# Reusable to save testing time.
@pytest.fixture(scope='module')
async def contract_factory():
    starknet = await Starknet.empty()
    contract = await starknet.deploy("contracts/constructor.cairo",
        constructor_calldata=[PARAMETER, IMPORTANT_ADDRESS])
    return starknet, contract

@pytest.mark.asyncio
async def test_contract(contract_factory):
    starknet, contract = contract_factory

    # Read from contract
    response = await contract.read_special_values().call()
    assert response.result == (PARAMETER, IMPORTANT_ADDRESS)

Run the test

pytest tests/test_constructor.py

Local Deployment

Deploy to the local devnet.

nile deploy constructor 345 876 --alias constructor

Interact

Read

nile call constructor read_special_values

Result: 345 876

Public deployment

Will default to the Goerli/alpha testnet until mainnet is available.

nile deploy constructor --alias constructor --network mainnet

Result:

🚀 Deploying constructor
🌕 artifacts/constructor.json successfully deployed to 0x01d7d821b0316bc0f5f6c5a00a16ae48c33bdbf660e9a6fb3bb592869fd571e1
📦 Registering deployment as constructor in mainnet.deployments.txt

Deployments can be viewed in the voyager explorer https://voyager.online