Skip to main content

Entry Functions

The entry modifier allows a function to be called directly from a programmable transaction block, as an "entrypoint" to the module.

When called this way, parameters passed to entry functions must be inputs to the transaction block, not the results of previous transactions in that block, and not modified by previous transactions in that block. Entry functions are also only allowed to return types that have drop.

These restrictions prevent third parties using the scriptable nature of programmable transaction blocks to bypass the fact that entry functions are not otherwise allowed to be called from other modules.

public vs entry functions

The public modifier also allows a function to be called from a programmable transaction block. It additionally allows the function to be called from other modules, and does not impose the same restrictions on where the function's parameters can come from and what it can return, so in many cases public is the right way to expose your function to the outside world. entry is useful if:

  • You want strong guarantees that your function is not being combined with third-party module functions, in programmable transaction blocks. The canonical example of this is a swap protocol that does not want to interact with a flash loan provider: If the swap protocol exposes only entry functions to perform swaps, it will not be possible to pass in a flash loaned Coin, because that coin will be the output of some previous transaction.
  • You do not want the function's signature to appear in your module's ABI. public function signatures must be maintained by upgrades while entry function signatures do not.

It is also possible to create a public entry function, which can be called by other modules and by programmable transaction blocks but is restricted like an entry function in the latter case. This is rarely useful -- you probably only want one of public or entry.

Example

module entry_functions::example {
use sui::object::{Self, UID};
use sui::transfer;
use sui::tx_context::{Self, TxContext};

struct Foo has key {
id: UID,
bar: u64,
}

/// Entry functions can accept a reference to the `TxContext`
/// (mutable or immutable) as their last parameter.
entry fun share(bar: u64, ctx: &mut TxContext) {
transfer::share_object(Foo {
id: object::new(ctx),
bar,
})
}

/// Parameters passed to entry functions called in a programmable
/// transaction block (like `foo`, below) must be inputs to the
/// transaction block, and not results of previous transactions.
entry fun update(foo: &mut Foo, ctx: &TxContext) {
foo.bar = tx_context::epoch(ctx);
}

/// Entry functions can return types that have `drop`.
entry fun bar(foo: &Foo): u64 {
foo.bar
}

/// This function cannot be `entry` because it returns a value
/// that does not have `drop`.
public fun foo(ctx: &mut TxContext): Foo {
Foo { id: object::new(ctx), bar: 0 }
}
}