Intelligent Contracts
Transaction Context

Transaction Context

Every contract execution has access to information about the transaction that triggered it — caller addresses, value, chain ID, and the transaction timestamp (datetime). This page covers how to read the current time, get a Unix timestamp, access caller and tx metadata, and what is not exposed (block number, gas, wall-clock).

gl.message — typed accessors

The most common fields are exposed as a typed NamedTuple:

FieldTypeDescription
sender_addressAddressImmediate caller — EOA, EVM contract, or IC depending on how the call was initiated
origin_addressAddressOriginal transaction submitter — preserved through internal message chains
contract_addressAddressThe current contract's own address
valueu256GEN sent with the call (only in @gl.public.write.payable methods)
chain_idu256Current chain ID
@gl.public.write
def deposit(self):
    self.balances[gl.message.sender_address] += gl.message.value

For the difference between sender_address and origin_address across internal message chains, see Messages.

gl.message_raw — full message dict

gl.message_raw is a TypedDict with everything the bootloader receives. It includes all gl.message fields plus:

FieldTypeDescription
datetimestrTransaction datetime as an ISO 8601 string
is_initboolTrue iff this execution is a deployment
stacklist[Address]Stack of view-method callers, excluding the current contract
entry_kindint0 = MAIN, 1 = SANDBOX, 2 = CONSENSUS_STAGE
entry_databytesRaw entry payload
entry_stage_dataConsensus-stage-specific data
# Detect whether the current execution is a deploy
if gl.message_raw['is_init']:
    self.deployer = gl.message.sender_address

Prefer gl.message for the common fields — it gives you autocompletion and type checking. Reach for gl.message_raw only when you need one of the extra fields.

Time and Timestamps

Time inside the GenVM is deterministic and pinned to the transaction's timestamp. Every validator re-executing the transaction sees the same value, so you can use it for storage, comparisons, and prompt context without breaking equivalence.

The Python standard library's clock is wired to the transaction datetime — datetime.now(), datetime.now(tz), and time.time() all return the same value across validators.

Transaction Timestamp

The transaction timestamp is exposed three ways. Use whichever fits:

FormHowUse for
Unix secondsint(datetime.now(timezone.utc).timestamp())Arithmetic, expiries, deltas
Unix seconds (alt)int(time.time())Same — shorter
datetime objectdatetime.now(timezone.utc)Comparisons, formatting
ISO 8601 stringdatetime.now(timezone.utc).isoformat() or gl.message_raw['datetime']Storage, audit trails, prompts

Common patterns

Unix timestamp for arithmetic:

from datetime import datetime, timezone
 
@gl.public.write
def mint(self):
    now = int(datetime.now(timezone.utc).timestamp())
    self.tokens[gl.message.sender_address] = Token(
        expiry=u256(now + 86400),  # 24h from now
    )

Expiry check:

@gl.public.view
def is_expired(self, token_id: u256) -> bool:
    now = int(datetime.now(timezone.utc).timestamp())
    return now > int(self.tokens[token_id].expiry)

ISO string for audit trails or events:

@gl.public.write
def submit(self, payload: str):
    self.submissions.append(Submission(
        sender=gl.message.sender_address,
        payload=payload,
        timestamp=datetime.now(timezone.utc).isoformat(),
    ))

Raw ISO string from the message (skip the clock):

ts: str = gl.message_raw['datetime']
⚠️

The clock returns the transaction datetime, not host wall-clock time. Do not call datetime.now() expecting current real-world time — by the time validators re-execute, the transaction may be minutes or hours old. Use it for relative arithmetic ("expires 24h after the tx") and timestamping, not for "is it past 5pm right now".

What is not in the context

  • No block number, no block hash. The transaction context does not carry block-level metadata. If your contract needs block height, fetch it via Web Access against an RPC inside a non-deterministic block.
  • No gas price, no nonce. Transaction metadata beyond what is listed above is not exposed to the contract.
  • No host wall-clock time. As above — the clock is the transaction datetime, not the validator's current time.