Addresses
Addresses in SmartPy are of type sp.address. They are written as sp.address("tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU") (implicit account), sp.address("KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo") (smart contract), or sp.address("KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo%entrypoint") (smart contract with entrypoint).
Tezos has different types of addresses based on their prefix: implicit accounts (tz1, tz2, tz3, tz4) and smart contracts (KT1). For details about the different address types and their characteristics, see Address Types below.
- sp.is_implicit_account(address: sp.address) → sp.option[sp.key_hash]
Determines whether an address is an implicit account (tz address and not a KT address) and returns its key hash if it is.
Returns
sp.Some(key_hash)if the address is an implicit account (tz address), wherekey_hashis the public key hash associated with the implicit account. ReturnsNoneif the address is a smart contract (KT address) or smart rollup.This function is useful for distinguishing implicit accounts from smart contracts and smart rollups, as implicit accounts cannot reject incoming transfers nor emit internal operations. The returned key hash can be used with instructions that expect a
sp.key_hashargument, such as delegation operations.Related function
To convert a key hash back to an implicit account contract, use
sp.implicit_account.Example:
python@sp.module def main(): class C(sp.Contract): @sp.entrypoint def test_is_implicit_account(self, address): # Check if an address is an implicit account result = sp.is_implicit_account(address) match result: case Some(key_hash): # Address is an implicit account, key_hash is available sp.send(address, sp.tez(1)) case None: # Address is a smart contract or smart rollup raise "Address is a smart contract or smart rollup" sc = sp.test_scenario("test") c = main.C() sc += c alice = sp.test_account("alice") c.test_is_implicit_account(alice.address, _amount=sp.tez(1))
- sp.index_address(address: sp.address) → sp.nat
Indexes the given address in the global Tezos registry.
If the address is already indexed then the cached index is returned, if it is not present then it is first added to the global cache and then the new index value is returned.
This function is useful for optimising address usage in contracts that use a lot of addresses.
The cache of address indices is global to Tezos itself and cannot be otherwise interacted with from smart contracts.
WARNING
sp.index_addresscannot be used in views because it may have the side-effect of modifying the global cache.As of protocol T a new effect has been added to SmartPy to manage this constraint. Please see the with_index_address documentation.
Related function
A function that can be used in views is
sp.get_address_index.Example:
python@sp.module def main(): class C(sp.Contract): def __init__(self): self.data.index = None @sp.entrypoint def add_address(self, address): self.data.index = sp.Some(sp.index_address(address)) sc = sp.test_scenario("Test") c1 = main.C() sc += c1 alice = sp.test_account("Alice") bob = sp.test_account("Bob") c1.add_address(alice.address) sc.verify(c1.data.index == sp.Some(1)) c1.add_address(bob.address) sc.verify(c1.data.index == sp.Some(2)) c1.add_address(alice.address) sc.verify(c1.data.index == sp.Some(1))
- sp.get_address_index(address: sp.address) → sp.option[sp.nat]
Returns
sp.Some(sp.nat)if the given address present in the global cache.Returns
Noneif the address has not been cached.sp.get_address_indexhas no side-effects and so can be used in both views and entrypoints.Related function
To add an address to the global cache, use
sp.index_address.Example:
python@sp.module def main(): class C(sp.Contract): def __init__(self): self.data.index = None @sp.entrypoint def add_address(self, address): self.data.index = sp.Some(sp.index_address(address)) @sp.onchain_view def get_address(self, address: sp.address) -> sp.option[sp.nat]: return sp.get_address_index(address) sc = sp.test_scenario("Test") c1 = main.C() sc += c1 alice = sp.test_account("Alice") c1.add_address(alice.address) sc.verify(c1.get_address(alice.address) == sp.Some(1))
Null Address
The address tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU is a null address that you can use to burn tokens. You can verify that it is a null address by installing the Octez suite and running the command octez-codec encode alpha.contract from '"tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU"'. The result is 00000000000000000000000000000000000000000000. Conversely, running the command octez-codec decode alpha.contract from 00000000000000000000000000000000000000000000 returns the address tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU.
Address Types
Tezos has different types of addresses based on their prefix and cryptographic scheme:
| Prefix | Cryptographic Scheme | Type | Description |
|---|---|---|---|
tz1 | Ed25519 | Implicit | Implicit accounts using Ed25519 signatures |
tz2 | Secp256k1 | Implicit | Implicit accounts using Secp256k1 signatures |
tz3 | P256 | Implicit | Implicit accounts using P256 signatures |
tz4 | BLS | Implicit | Implicit accounts using BLS signatures |
KT1 | N/A | Originated | Smart contracts (originated accounts) |
Implicit accounts (tz1, tz2, tz3, tz4) are accounts that are directly derived from public keys. They are called "implicit" because they exist implicitly on the blockchain without needing to be explicitly created or originated. Key characteristics of implicit accounts:
- They are controlled by whoever holds the corresponding private key
- They cannot reject incoming transfers (all transfers are automatically accepted)
- They cannot emit internal operations or execute code
- They can delegate their tez to bakers for staking
- Their addresses are deterministically derived from their public keys
- They can receive, hold, and send tez and tickets
- They can create new tickets
- They can call smart contracts by sending optional tez and arguments to their entrypoints
- They can be treated as smart contracts with a "default" entrypoint that does nothing
Smart contracts (KT1) are originated accounts that contain executable code and must be explicitly deployed to the blockchain. Unlike implicit accounts, they can contain complex logic, reject transfers, and emit internal operations.