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:
# { "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_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_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:
@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
- Security: Always validate inputs and check permissions before allowing cross-contract interactions.
- Error Handling: Implement proper error handling for cases where called contracts might revert or throw exceptions.
- Upgradability: Consider using upgradable patterns if you need to change contract interactions in the future.
- 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.