Run the Example
First go through the Setup process to get your development environment configured, then clone thev23.0.0 tag of soroban-examples repository:
auth directory, and use cargo test.
Code
auth/src/lib.rs
How it Works
The example contract stores a per-Address counter that can only be incremented by the owner of that Address.
Open the auth/src/lib.rs file or see the code above to follow along.
Address
Address is a universal Soroban identifier that may represent a Stellar account, a contract, or a contract account (a contract that defines a custom authentication scheme and authorization policies). Contracts don’t need to distinguish between these internal representations though. Address can be used any time some network identity needs to be represented, like to distinguish between counters for different users in this example.
require_auth
require_auth method can be called for any Address. Semantically user.require_auth() here means ‘require user to have authorized calling increment function of the current IncrementContract instance with the current call arguments, i.e. the current user and value argument values’. In simpler terms, this ensures that the user has allowed incrementing their counter value and nobody else can increment it.
When using require_auth the contract implementation doesn’t need to worry about the signatures, authentication, and replay prevention. All these features are implemented by the Soroban host and happen automatically as long as the Address type is used.
Address has another method called require_auth_for_args. It works in the same fashion as require_auth, but allows customizing the arguments that need to be authorized. Note though, this should be used with care to ensure that there is a deterministic mapping between the contract invocation arguments and the require_auth_for_args arguments.
The following two calls are functionally equivalent to user.require_auth:
Tests
Open theauth/src/test.rs file to follow along.
auth/src/test.rs
Env, which is the Soroban environment that the contract will run in.
require_auth or require_auth_for_args will succeed.
impl block that is annotated with the #[contractimpl] attribute have a corresponding function generated in a generated client type. The client type will be named the same as the contract type with Client appended. For example, in our contract the contract type is IncrementContract, and the client is named IncrementContractClient.
Addresses for two users. Normally the exact value of the Address shouldn’t matter for testing, so they’re simply generated randomly.
increment function for user_1.
require_auth call(s) have indeed happened, use auths function that returns a vector of tuples containing the authorizations from the most recent contract invocation.
increment function several more times for both users. Notice, that the values are tracked separately for each users.
Build the Contract
To build the contract into a.wasm file, use the stellar contract build command.
.wasm file should be found in the target directory after building:
Run the Contract
If you havestellar-cli installed, you can deploy the contract and invoke its functions.
But since we are dealing with authorization and signatures, we need to set up some identities to use for testing and get their public keys:
Deploy
- macOS/Linux
- Windows (PowerShell)
Invoke
Now the contract itself can be invoked. Notice the--source-account must be the identity name matching the address passed to the --user argument. This allows Stellar CLI to automatically sign the necessary payload for the invocation.
- macOS/Linux
- Windows (PowerShell)
- macOS/Linux
- Windows (PowerShell)
stellar contract read.
--auth flag to the invocation:
- macOS/Linux
- Windows (PowerShell)
Further reading
Authorization documentation provides more details on how Soroban auth framework works. Timelock and Single Offer examples demonstrate authorizing token operations on behalf of the user, which can be extended to any nested contract invocations. Atomic Swap example demonstrates multi-party authorization where multiple users sign their parts of the contract invocation. Simple Account example demonstrates a minimal contract account implementation and how__check_auth works end-to-end.