Voltar para Documentação

Docs Técnicas

Static Composition

TREA contracts can inherit storage and behaviour from reusable base modules. Composition is resolved entirely at compile time — there is no virtual dispatch or runtime module loading.

O conteúdo abaixo vem das fontes técnicas do repositório e é prerenderizado no site para leitura direta por pessoas, crawlers e agentes.

TREA contracts can inherit storage and behaviour from reusable base modules. Composition is resolved entirely at compile time — there is no virtual dispatch or runtime module loading.

Declaration

python
import std.token.BasicToken
import std.access.Ownable
import std.token.Pausable

contract PausableToken impl BasicToken, Ownable, Pausable:
    storage:
        balances: Map[Address, u128, 4096]

The impl list names the base modules in the order they are merged. Each name must match the short name (or alias) of an import declaration.

What Gets Inherited

Storage — base storage fields are prepended to the child's storage block, in the order the bases are listed. The child's own fields come last.

python
# After flattening PausableToken:
# total: u128 = 0       ← from BasicToken
# owner: Address        ← from Ownable
# paused: bool = False  ← from Pausable
# balances: ...         ← child's own field

Functions — all base functions are available as if they were declared in the child. The child can call them, override them, or leave them as-is.

Helpers — helper functions defined in bases are also inherited.

Overriding a Base Function

python
@tx
override def mint(amount: u128):
    require(self.paused == False, "contract_paused")
    require(ctx.caller == self.owner, "only_owner")
    require(amount > 0, "amount_must_be_positive")
    self.balances[ctx.caller] = self.balances[ctx.caller] + amount
    self.total = self.total + amount

Rules:

  • The override keyword is mandatory.
  • The @tx, @view, or @construct decorator must precede override.
  • The function name must exist in at least one base. The verifier errors if no

base defines that name.

  • A child function that shadows a base function without override is a

compile error.

Delegating to the Base — `super.method()`

python
@tx
override def pause():
    require(ctx.caller == self.owner, "only_owner")
    super.pause()

super.method(args) calls the base implementation from inside an override. The call is rewritten at compile time to a renamed internal function (__super__pause) and carries no runtime overhead beyond a normal function call. super is only valid inside override def.

Conflict Rules

| Situation | Result | |-----------|--------| | Two bases declare the same storage field | Compile error | | Child redeclares a field already in a base | Compile error | | Two bases declare the same function | Conflict — child must override | | Child shadows a base function without override | Compile error | | override names a function not in any base | Compile error |

Storage Namespacing

Base fields live in the same flat namespace as child fields. There is no BaseName.field accessor — self.total is always just self.total, regardless of which base introduced it.

This means the child can read and write inherited fields freely, which is intentional: a token contract that inherits total from BasicToken must be able to update it in its own mint override.

Compile-Time Resolution

The import paths are recorded in the artifact's uses_modules list. The compiler does not embed the base source inside the child artifact — it stores the child source only. At ContractCall time the ledger re-parses the child source and re-flattens it against the base modules fetched from the on-chain registry.

This means a child contract depends on the on-chain presence of its bases. If a base artifact is not published, ContractCall will fail at the resolution step.