There is no sense of a native currency in Cairo. Any variable can be used to create a system of ownership of layer-1 ether or tokens.

The contract would need to check that the sender is the owner. Below is a wallet system that does not check if the sender of a transaction has the authority to control a given wallet.

%lang starknet
%builtins pedersen range_check

from starkware.cairo.common.cairo_builtins import HashBuiltin

@storage_var
func wallet_balance(user : felt) -> (res : felt):
end

@external
func register_currency{
        syscall_ptr : felt*,
        pedersen_ptr : HashBuiltin*,
        range_check_ptr
    }(
        user : felt,
        register_amount : felt
    ):
    alloc_locals
    let (local balance) = wallet_balance.read(user)
    wallet_balance.write(user, balance + register_amount)
    return ()
end

@external
func move_currency{
        syscall_ptr : felt*,
        pedersen_ptr : HashBuiltin*,
        range_check_ptr
    }(
        from_user : felt,
        to_user : felt,
        move_amount : felt
    ):
    alloc_locals
    let (local sender_balance) = wallet_balance.read(from_user)
    let (local receiver_balance) = wallet_balance.read(to_user)
    wallet_balance.write(to_user, receiver_balance + move_amount)
    wallet_balance.write(from_user, sender_balance - move_amount)
    return ()
end

@view
func check_wallet{
        syscall_ptr : felt*,
        pedersen_ptr : HashBuiltin*,
        range_check_ptr
    }(
        user : felt
    ) -> (
        balance : felt
    ):
    alloc_locals
    let (local balance) = wallet_balance.read(user)
    return (balance)
end

Save as contracts/currency.cairo

Compile

Compile

nile compile

Or compile this specific contract

nile compile contracts/currency.cairo

Test

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

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

# 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/currency.cairo")
    return starknet, contract

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

    # Register that user 7 owns 100 units currency,
    # which might represent mainnet ether (ETH).
    await contract.register_currency(7, 100).invoke()
    # Move 2 ether from user 7 to user 789.
    await contract.move_currency(7, 789, 2).invoke()

    # Check that the currency was received.
    response = await contract.check_wallet(789).call()
    assert response.result.balance == 2

Run the test

pytest tests/test_currency.py

Local Deployment

Deploy to the local devnet.

nile deploy currency --alias currency

Interact

Write

nile invoke currency register_currency 7 100

Read

nile call currency check_wallet 7

Result: 100

Public deployment

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

nile deploy currency --alias currency --network mainnet

Result:

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

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