Skip to content
On this page

Entrypoints

When you import the base classes as described in Base classes, the FA2 library automatically adds the standard entrypoints that the FA2 standard requires. You can override these entrypoints or add other custom entrypoints.

Off-chain views

In addition to entrypoints, the FA2 library creates off-chain views as described by the FA2 standard. For these views to work, you must upload their code in contract metadata as described in Creating and publishing metadata.

Standard entrypoints

The FA2 library provides the three standard entrypoints transfer, balance_of, and update_operators. These entrypoints work the same way for each type of token. You can modify them with transfer policies or replace them with custom entrypoints as long as the custom entrypoint meets the FA2 standard.

transfer

The transfer entrypoint moves tokens from one account to another. It requires a list of batches as an argument. Each batch is a record that contains the following fields:

  • from_: The account that sends the tokens
  • txs: A list of records, each with these fields:
    • to_: The account that receives the tokens
    • token_id: The token ID
    • amount: The amount of tokens to transfer

By default, the owner of a token and their designated operators can transfer a token. You can change permissions for transferring tokens by setting a transfer policy.

The following example makes three token transfers in a single call to the transfer entrypoint:

smartpy
contract.transfer(
    [
        sp.record(
            from_ = alice.address,
            txs = [
                sp.record(to_=bob.address, amount=10, token_id=0),
                sp.record(to_=bob.address, amount=10, token_id=1)
            ]
        ),
        sp.record(
            from_ = bob.address,
            txs = [
                sp.record(to_=alice.address, amount=11, token_id=0)
            ]
        )
    ],
    _sender=charlie)

The type of the transfer entrypoint's parameter is available in the library as the t.transfer_batch type, which is equivalent to:

python
sp.list[sp.record(from_=sp.address, txs=sp.list[sp.record(to_=sp.address, token_id=sp.nat, amount=sp.nat).layout(("to_", ("token_id", "amount")))]).layout(("from_", "txs"))]

The transfer entrypoint can raise these exceptions: FA2_TOKEN_UNDEFINED, FA2_NOT_OPERATOR, FA2_INSUFFICIENT_BALANCE, and FA2_TX_DENIED.

update_operators

The update_operators entrypoint modifies the list of operators, which are accounts that are authorized to transfer tokens that another account owns. Only the owner of a token can set the operators for their tokens.

This entrypoint takes a list of actions, each of which is either "remove_operator" or "add_operator" associated with an operator permission. Each operator permission is a record of:

  • owner: The account on which the operator can perform the transfer
  • operator: The account given permission to transfer
  • token_id: The token ID for which permission is granted

This example removes the account op1 as the operator for Alice's tokens with the ID 0 and adds the account op2 as an operator for the same tokens:

smartpy
contract.update_operators([
    sp.variant("remove_operator", sp.record(
        owner = alice.address,
        operator = op1.address,
        token_id = 0)),
    sp.variant("add_operator", sp.record(
        owner = alice.address,
        operator = op2.address,
        token_id = 0))
  ],
  _sender=alice
)

The type of the update_operators entrypoint's parameter is available in the library as the t.update_operators_params type, which is equivalent to:

python
sp.list[
    sp.variant(
        add_operator=sp.record(
            owner=sp.address,
            operator=sp.address,
            token_id=sp.nat
        ).layout(("owner", ("operator", "token_id"))),
        remove_operator=sp.record(
            owner=sp.address,
            operator=sp.address,
            token_id=sp.nat
        ).layout(("owner", ("operator", "token_id")))
    )
]

The update_operators can raise these exceptions: FA2_NOT_OWNER and FA2_OPERATORS_UNSUPPORTED.

balance_of

The balance_of entrypoint is used to query the balance of multiple account/token pairs. It sends the balances to a callback address.

It takes two parameters:

  • callback: Information about the contract to send the balance information to, in this format:

    python
    sp.contract[
        sp.list[
            sp.record(
                request=sp.record(
                    owner=sp.address,
                    token_id=sp.nat
                ).layout(("owner", "token_id")),
                balance=sp.nat
            ).layout(("request", "balance"))
        ]
    ]
  • requests: Information about the owners and token IDs to provide information about, in this format:

    python
    sp.list[
        sp.record(
            owner=sp.address,
            token_id=sp.nat
        ).layout(("owner", "token_id"))
    ]

    The layout of this entrypoint is ("requests", "callback").

Together, these parameters are available in the library as the t.balance_of_params type.

This example sends a user's balance of the token ID 0 to the receive_balances entrypoint of another contract:

smartpy
contract.balance_of(
    callback=sp.contract(
        sp.list(fa2.t.balance_of_response),
        contract2.address,
        entry_point="receive_balances",
    ).open_some(),
    requests=[sp.record(owner=alice.address, token_id=0)],
    _sender=alice)

The balance_of transfers 0 mutez to callback with corresponding response. This response is in the type t.balance_of_response, which is equivalent to:

python
sp.record(
    request=sp.record(owner=sp.address, token_id=sp.nat),
    balance: sp.nat
).layout(("request", "balance"))

The balance_of entrypoint can raise these exceptions: FA2_NOT_OWNER and FA2_OPERATORS_UNSUPPORTED.

Custom entrypoints

You can either override the provided entrypoints or add your own, just as you would in any other SmartPy contract.

For example, this contract has an entrypoint named my_entrypoint in addition to the entrypoints provided by the main.Fungible base class:

smartpy
class ExampleFA2(main.Fungible):
    @sp.entrypoint
    def my_entrypoint(self, params):
        # ...

You can override the standard entrypoints in this way, but to maintain compliance with the FA2 standard, they should have the same interface as the standard entrypoints.

Non-standard entrypoints

The FA2 library provides entrypoints and views that are not required by the standard. You can add them to your contracts with the mixins mechanism.

For example, the FA2 standard does not require contracts to have mint and burn entrypoints to create and destroy tokens, but the FA2 library provides them.