Overview
The Env type is the primary interface between your contract code and the Soroban host environment. It provides access to storage, events, cryptographic functions, ledger information, and more.
Getting the Environment
The Env is typically passed as the first parameter to contract functions:
use soroban_sdk :: {contract, contractimpl, Env , Symbol , Vec };
#[contract]
pub struct Contract ;
#[contractimpl]
impl Contract {
pub fn hello ( env : Env , to : Symbol ) -> Vec < Symbol > {
// Use env to access environment functions
vec! [ & env , symbol_short! ( "Hello" ), to ]
}
}
You can use either Env or &Env as the parameter type. Use &Env when you don’t need to clone the environment.
Core Environment Functions
Storage Access
Access contract storage through the storage() method:
pub fn store_value ( env : Env , key : Symbol , value : u32 ) {
env . storage () . persistent () . set ( & key , & value );
}
pub fn get_value ( env : Env , key : Symbol ) -> Option < u32 > {
env . storage () . persistent () . get ( & key )
}
Current Contract Address
Get the address of the currently executing contract:
pub fn get_self ( env : Env ) -> Address {
env . current_contract_address ()
}
Events
Publish events for off-chain consumers:
pub fn transfer ( env : Env , from : Address , to : Address , amount : i128 ) {
// Perform transfer logic...
env . events () . publish (
( symbol_short! ( "transfer" ), from . clone (), to . clone ()),
amount
);
}
Access current ledger state:
pub fn get_timestamp ( env : Env ) -> u64 {
env . ledger () . timestamp ()
}
pub fn get_sequence ( env : Env ) -> u32 {
env . ledger () . sequence ()
}
Cryptographic Functions
Hashing
use soroban_sdk :: Bytes ;
pub fn hash_data ( env : Env , data : Bytes ) -> BytesN < 32 > {
env . crypto () . sha256 ( & data )
}
pub fn keccak_hash ( env : Env , data : Bytes ) -> BytesN < 32 > {
env . crypto () . keccak256 ( & data )
}
Signature Verification
pub fn verify_signature (
env : Env ,
public_key : BytesN < 32 >,
message : Bytes ,
signature : BytesN < 64 >,
) -> bool {
env . crypto () . ed25519_verify (
& public_key ,
& message ,
& signature ,
);
true
}
Contract Invocation
Calling Other Contracts
Invoke functions on other contracts:
pub fn call_other ( env : Env , contract_id : Address ) -> u32 {
let result : u32 = env . invoke_contract (
& contract_id ,
& symbol_short! ( "get_value" ),
vec! [ & env ],
);
result
}
Try Invoke (Error Handling)
Call contracts with error handling:
use soroban_sdk :: { InvokeError , Error };
pub fn safe_call ( env : Env , contract_id : Address ) -> Result < u32 , Error > {
match env . try_invoke_contract :: < u32 , Error >(
& contract_id ,
& symbol_short! ( "get_value" ),
vec! [ & env ],
) {
Ok ( Ok ( value )) => Ok ( value ),
Ok ( Err ( e )) => Err ( e ),
Err ( invoke_error ) => {
// Handle invocation failure
Err ( Error :: from_type_and_code ( 1 , 1 ))
}
}
}
Random Number Generation
The PRNG is not suitable for security-sensitive operations . It’s designed for games and simulations.
pub fn roll_dice ( env : Env ) -> u64 {
env . prng () . u64_in_range ( 1 ..= 6 )
}
pub fn shuffle_seed ( env : Env ) -> BytesN < 32 > {
env . prng () . seed ()
}
Logging and Debugging
Debug Logs
Log debug information (only available with testutils):
pub fn debug_info ( env : Env , value : u32 ) {
env . logs () . log ( "Current value: " , value );
}
Logs are only available in test environments and are stripped from production WASM builds.
Deployer Functions
Deploy new contracts from within a contract:
use soroban_sdk :: { Bytes , BytesN };
pub fn deploy_contract ( env : Env , wasm : Bytes , salt : BytesN < 32 >) -> Address {
env . deployer ()
. with_current_contract ( salt )
. deploy ( wasm )
}
Authorization Context
Authorize sub-contract calls on behalf of the current contract:
use soroban_sdk :: auth :: { InvokerContractAuthEntry , SubContractInvocation , ContractContext };
pub fn authorized_call ( env : Env , target : Address ) {
let auth_entries = vec! [
& env ,
InvokerContractAuthEntry :: Contract ( SubContractInvocation {
context : ContractContext {
contract : target . clone (),
fn_name : symbol_short! ( "protected" ),
args : vec! [ & env ],
},
sub_invocations : vec! [ & env ],
}),
];
env . authorize_as_current_contract ( auth_entries );
// Now call the protected function...
}
Environment in Tests
Creating Test Environments
#[cfg(test)]
mod test {
use super ::* ;
use soroban_sdk :: testutils :: { Address as _, Ledger };
#[test]
fn test_contract () {
let env = Env :: default ();
// Register the contract
let contract_id = env . register ( Contract , ());
let client = ContractClient :: new ( & env , & contract_id );
// Mock authentication
env . mock_all_auths ();
// Set ledger state
env . ledger () . set_timestamp ( 1234567890 );
// Call contract functions
let result = client . hello ( & symbol_short! ( "World" ));
}
}
Test Configuration
use soroban_sdk :: EnvTestConfig ;
#[test]
fn test_with_config () {
let config = EnvTestConfig {
capture_snapshot_at_drop : false ,
};
let env = Env :: new_with_config ( config );
// ... test code
}
Common Environment Methods Reference
Method Description env.storage()Access contract storage (persistent, temporary, instance) env.current_contract_address()Get the current contract’s address env.events()Publish contract events env.ledger()Access ledger information (timestamp, sequence, etc.) env.crypto()Access cryptographic functions env.prng()Access pseudo-random number generator env.deployer()Deploy new contracts env.logs()Debug logging (testutils only) env.invoke_contract()Call another contract env.authorize_as_current_contract()Authorize sub-contract calls
Type Conversions
IntoVal and FromVal
The environment provides conversion utilities:
use soroban_sdk :: { IntoVal , FromVal , Val };
pub fn convert_example ( env : Env ) {
// Convert to Val
let value : Val = 42 u32 . into_val ( & env );
// Convert from Val
let number : u32 = u32 :: from_val ( & env , & value );
}
TryIntoVal and TryFromVal
For fallible conversions:
use soroban_sdk :: TryFromVal ;
pub fn try_convert ( env : Env , val : Val ) -> Option < u32 > {
u32 :: try_from_val ( & env , & val ) . ok ()
}
Best Practices
The Env is relatively cheap to clone, but avoid unnecessary clones. Use &Env when possible.
Error handling in cross-contract calls
Always use try_invoke_contract for cross-contract calls that might fail, and handle errors appropriately.
Ledger information reflects the state at the time of invocation. It won’t change during contract execution.
When debugging, use structured log arguments to make logs more useful and searchable.
Next Steps
Storage Learn about persistent, temporary, and instance storage
Authentication Understand address authentication and authorization