#[entrypoint]Expand description
Defines the entrypoint, which is where Stylus execution begins.
Without it the contract will fail to pass cargo stylus check.
Most commonly this macro is used to annotate the top level storage struct.
sol_storage! {
#[entrypoint]
pub struct Contract {
}
// only one entrypoint is allowed
pub struct SubStruct {
}
}The above will make the public methods of Contract the first to consider during invocation.
See #[public] for more information on method selection.
§Bytes-in, bytes-out programming
A less common usage of #[entrypoint] is for low-level, bytes-in bytes-out
programming. When applied to a free-standing function, a different way of writing smart
contracts becomes possible, wherein the Stylus SDK’s macros and storage types are entirely
optional.
extern crate alloc;
#[entrypoint]
fn entrypoint(
calldata: Vec<u8>,
_: alloc::boxed::Box<dyn stylus_sdk::stylus_core::Host>,
) -> ArbResult {
// bytes-in, bytes-out programming
}§Reentrancy
If a contract calls another that then calls the first, it is said to be reentrant. Numerous exploits and hacks in Web3 are attributable to developers misusing or not fully understanding reentrant patterns. Always follow the checks-effects-interactions pattern.
§Storage cache flushing
The SDK’s primary reentrancy safety mechanism is automatic storage cache management.
The high-level call functions in stylus_sdk::call (call, delegate_call, and
static_call) flush the storage cache before every external call, ensuring that
pending writes are persisted to storage before control is handed to another contract:
callanddelegate_callflush and clear (persist dirty values, then drop the in-memory cache).static_callflushes without clearing (since static calls cannot modify storage, the cache remains valid).
This happens unconditionally for all contracts. When using RawCall directly, the
cache is not flushed automatically – if you have pending storage writes that
the callee might read, call .flush_storage_cache() to persist dirty values without
dropping the cache, or .clear_storage_cache() to persist and drop the cache
(matching what call and delegate_call do).
§The reentrant feature flag (deprecated)
The reentrant feature flag is deprecated and will be removed in a future
release. Previously, contracts without this flag would automatically revert on
reentrant calls via a msg_reentrant() check at the entrypoint. This guard is
redundant — reentrancy safety is already provided by the cache flushing described
above — and it indiscriminately blocks all reentrant calls, preventing use cases
that require them.
§TopLevelStorage
The #[entrypoint] macro will automatically implement the TopLevelStorage
trait for the annotated struct. The single type implementing TopLevelStorage is special
in that mutable access to it represents mutable access to the entire program’s state.
This has implications for calls via sol_interface.