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 loanedCoin
, 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 whileentry
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 }
}
}