Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Multi-Contract Systems

Ursus supports multi-contract systems where contracts can interact with each other through message passing. This is essential for building complex decentralized applications.

Contract Interfaces

Declaring Interfaces

Contracts declare which interfaces they can send messages to using the Sends To clause:

Syntax:

Contract MyContract ;
Sends To Interface1 Interface2 Interface3 ;
Inherits ;

Example:

Contract ContractSolidity ;
Sends To IContractTVM ;
Inherits ;

Empty Sends To

If a contract doesn't send messages to other contracts:

Contract SimpleContract ;
Sends To ;
Inherits ;

Defining Interfaces

Interface Structure

Interfaces define the message protocol between contracts:

Contract IMyInterface ;
Sends To ;
Inherits ;

#[no_body]
Ursus Definition myFunction (arg: uint256): UExpression uint256 false.

#[no_body]
Ursus Definition anotherFunction (addr: address): UExpression boolean false.

Real Example: IContractTVM

From ursus-patterns:

Contract IContractTVM ;
Sends To ;
Inherits ;

#[no_body]
Ursus Definition someMethod (value: uint256): UExpression PhantomType false.

Sending Messages

Message Syntax

To send a message to another contract:

::// targetContract.method(args) |.

Example

Ursus Definition callOtherContract (addr: address) (amount: uint256):
  UExpression PhantomType false.
{
    ::// IContractTVM(addr).transfer(amount) |.
}
return.
Defined.

Multi-Contract Patterns

Pattern 1: Factory Pattern

Factory Contract:

Contract TokenFactory ;
Sends To IToken ;
Inherits ;

Record Contract := {
    tokens: mapping uint256 address
}.

Ursus Definition createToken (id: uint256): UExpression address false.
{
    ::// var 'newToken : address := deployContract(TokenCode) .
    ::// tokens[[id]] := newToken .
    ::// _result := newToken |.
}
return.
Defined.

Pattern 2: Proxy Pattern

Proxy Contract:

Contract Proxy ;
Sends To IImplementation ;
Inherits ;

Record Contract := {
    implementation: address
}.

Ursus Definition upgrade (newImpl: address): UExpression unit false.
{
    ::// implementation := newImpl |.
}
return.
Defined.

Ursus Definition delegateCall (data: bytes): UExpression bytes false.
{
    ::// _result := IImplementation(implementation).execute(data) |.
}
return.
Defined.

Pattern 3: Registry Pattern

Registry Contract:

Contract Registry ;
Sends To IService ;
Inherits ;

Record Contract := {
    services: mapping string address
}.

Ursus Definition register (name: string) (addr: address): UExpression unit false.
{
    ::// services[[name]] := addr |.
}
return.
Defined.

Ursus Definition lookup (name: string): UExpression address false.
{
    ::// _result := services[[name]] |.
}
return.
Defined.

Message Types

Synchronous Calls

Direct function calls (if supported by platform):

::// result := otherContract.getValue() |.

Asynchronous Messages

Send message without waiting for response:

::// otherContract.notify(data) |.

Value Transfer

Send tokens with message:

::// otherContract.deposit{value: amount}() |.

Interface Composition

Multiple Interfaces

A contract can implement multiple interfaces:

Contract MultiService ;
Sends To ITokenReceiver INotifiable IUpgradeable ;
Inherits ;

Interface Inheritance

Interfaces can inherit from other interfaces:

Contract IExtendedToken ;
Sends To ;
Inherits IToken ;

#[no_body]
Ursus Definition mint (to: address) (amount: uint256): UExpression boolean false.

See Also