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
- Contract Structure - Contract organization
- Interfaces - Interface definitions
- Inheritance - Contract inheritance
- ursus-patterns repository - Multi-contract examples