Environment & Invocation
Access runtime information about the current call and execution environment.
Invocation
Get information about the current endpoint call:
| Method | Returns | Description |
|---|---|---|
Invocation.ID() | Identifier | Unique ID of this invocation |
Invocation.Caller() | Identifier | Immediate caller (differs from Sender in cross-logic calls) |
Sender vs Caller
Sender— The actor who initiated the interaction (stays the same through cross-logic calls)Invocation.Caller()— The immediate caller (changes in cross-logic calls)
endpoint CheckCaller() -> (sender Identifier, caller Identifier):
sender = Sender // Original actor
caller = Invocation.Caller() // Immediate caller (could be another logic)
Environment
Access runtime environment data:
| Method | Returns | PISA target | Description |
|---|---|---|---|
Environment.Timestamp() | U64 | all | Current interaction timestamp |
Environment.EffortCapacity() | U64 | 0.4.0 and later | Total fuel available |
Environment.EffortAvailable() | U64 | 0.4.0 and later | Remaining fuel |
Environment.VolumeCapacity() | U64 | 0.4.0 – 0.7.1 | Total storage space |
Environment.VolumeAvailable() | U64 | 0.4.0 – 0.7.1 | Remaining storage space |
Environment.StorageResult(account, payer) | (U64, U64) | 0.8.0 only | Storage bytes added and removed in this interaction |
endpoint GetEnvInfo() -> (
timestamp U64,
fuel_remaining U64,
invocation_id Identifier
):
timestamp = Environment.Timestamp()
fuel_remaining = Environment.EffortAvailable()
invocation_id = Invocation.ID()
Storage metering changed in PISA v0.8.0
VolumeCapacity() and VolumeAvailable() are not supported on 0.8.0 targets — v0.8.0 meters
storage per account and payer instead of globally, and StorageResult() replaces them.
StorageResult() in turn is not available on earlier targets.
StorageResult()
Returns two values: how many storage bytes the current interaction has added and removed so far, for one storage account charged to one payer.
added, removed = Environment.StorageResult(account, payer)
| Argument | Type | Meaning |
|---|---|---|
account | Identifier | Whose storage is being measured |
payer | Identifier | Who is being charged — matches the payer clause on the write |
coco Token
state logic:
name String
endpoint deploy Init(name String) -> (added, removed U64):
mutate name -> Token.Logic.name payer Logic
added, removed = Environment.StorageResult(Identifier(Token), Identifier(Token))
// "noname" polorizes to 7 bytes -> added = 7, removed = 0
endpoint dynamic Clear() -> (added, removed U64):
mutate "" -> Token.Logic.name // payer Sender is the default
added, removed = Environment.StorageResult(Identifier(Token), Sender)
// added = 1, removed = 7
Because both values are returned together, assign them to two outputs in a single statement.
Example: Time-based Logic
coco TimeLock
state actor:
locked_until U64
endpoint dynamic Lock(duration U64):
memory unlock_time = Environment.Timestamp() + duration
mutate unlock_time -> TimeLock.Sender.locked_until
endpoint dynamic Withdraw():
observe locked <- TimeLock.Sender.locked_until:
if Environment.Timestamp() < locked:
throw "Still locked"
// proceed with withdrawal