Build with GenLayer
Advanced Features
Contract-to-Contract Interaction

Contract-to-Contract Interaction

Contract-to-Contract Interaction in GenLayer allows developers to create more complex and modular Intelligent Contracts by enabling communication between different contracts. This feature is crucial for building scalable and composable decentralized applications, allowing contracts to read from and write to other contracts.

Please note that this feature is experimental and will be subject to changes in the near future.

Key Features of Contract-to-Contract Interaction

The Contract-to-Contract Interaction provides several powerful capabilities:

1. Cross-Contract Reads

Contracts can read data from other contracts, allowing for the sharing of state and information across different parts of your application.

2. Cross-Contract Writes

Contracts can initiate state changes in other contracts, enabling complex multi-step operations that span multiple contracts.

3. Modular Design

By separating concerns into different contracts, developers can create more maintainable and upgradable systems.

4. Composability

Contracts can be designed to work together, creating more powerful and flexible applications by combining different functionalities.

How to Use Contract-to-Contract Interaction in Your Contracts

To use Contract-to-Contract Interaction in your Intelligent Contracts, you'll use the Contract class to interact with other contracts. Below are the details of how to use this feature.

Creating a Contract with Cross-Contract Interaction

Here's an example of a contract that interacts with an ERC20 token contract:

token_interaction
# { "Depends": "py-genlayer:test" }
 
from genlayer import *
 
 
@gl.contract
class TokenInteraction:
    token_contract_address: Address
 
    def __init__(self, token_contract_address: str):
        self.token_contract_address = Address(token_contract_address)
 
    @gl.public.view
    def get_balance(self, account_address: str) -> int:
        return gl.ContractAt(self.token_contract_address).view().get_balance_of(account_address)
 
    @gl.public.write 
    def transfer_tokens(self, to_address: str, amount: int) -> bool:
        return gl.ContractAt(self.token_contract_address).emit(gas=100000).transfer(to_address, amount)

Key Methods for Contract-to-Contract Interaction

1. Reading from Another Contract

To read data from another contract, create an instance of the Contract class and call its methods:

token_interaction
token_contract = gl.ContractAt(self.token_contract_address)
balance = token_contract.view().get_balance_of(account_address)

2. Writing to Another Contract

To initiate a state change in another contract, call a method that modifies its state:

token_interaction
token_contract = gl.ContractAt(self.token_contract_address)
success = token_contract.emit(gas=100000).transfer(to_address, amount)

3. Handling Multiple Contract Interactions

For more complex scenarios involving multiple contracts:

multi_contract_interaction
@gl.contract
class MultiContractInteraction:
    token_contract: Address
    storage_contract: Address
 
    def __init__(self, token_contract: str, storage_contract: str):
        self.token_contract = Address(token_contract)
        self.storage_contract = Address(storage_contract)
 
    @gl.public.write
    def complex_operation(self, account: str, amount: int, data: str) -> bool:
        token = gl.ContractAt(self.token_contract)
        storage = gl.ContractAt(self.storage_contract)
 
        # Read from token contract
        balance = token.view().get_balance_of(account)
 
        if balance >= amount:
            # Write to token contract
            token.emit(gas=100000).transfer(self.address, amount)
            # Write to storage contract
            storage.emit(gas=100000).store_data(account, data)
            return True
        return False

Best Practices for Contract-to-Contract Interaction

  1. Security: Always validate inputs and check permissions before allowing cross-contract interactions.
  2. Error Handling: Implement proper error handling for cases where called contracts might revert or throw exceptions.
  3. Upgradability: Consider using upgradable patterns if you need to change contract interactions in the future.
  4. Testing: Thoroughly test all contract interactions, including edge cases and potential vulnerabilities.

By leveraging Contract-to-Contract Interaction, you can create more sophisticated, modular, and powerful Intelligent Contracts in GenLayer. This approach enables better separation of concerns and can lead to more maintainable and scalable decentralized applications.