CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-eth-brownie

A Python framework for Ethereum smart contract deployment, testing and interaction.

Pending
Overview
Eval results
Files

contracts.mddocs/

Contract Interaction

Smart contract deployment, method calls, event handling, and transaction management with comprehensive debugging and error reporting capabilities.

Capabilities

Contract Base Class

The core Contract class provides the interface for interacting with deployed smart contracts, handling method calls, transactions, and event parsing.

class Contract:
    """
    Interface for interacting with deployed smart contracts.
    
    Attributes:
        address (str): Contract's deployed address
        abi (list): Contract's ABI (Application Binary Interface)
        bytecode (str): Contract's bytecode
        tx (TransactionReceipt): Deployment transaction receipt
    """
    
    def __init__(self, address: str, abi: list, owner: Account = None):
        """
        Initialize contract interface.
        
        Args:
            address: Contract's deployed address
            abi: Contract's ABI definition
            owner: Account that deployed the contract
        """
        
    def __getattr__(self, name: str):
        """
        Access contract methods and attributes dynamically.
        
        Args:
            name: Method or attribute name
            
        Returns:
            ContractCall or ContractTx: Callable for contract interaction
        """
        
    def balance(self) -> Wei:
        """Get contract's ether balance."""
        
    def selectors(self) -> dict:
        """Get mapping of function names to their selectors."""
        
    def topics(self) -> dict:
        """Get mapping of event names to their topic hashes."""
        
    def decode_logs(self, logs: list) -> list:
        """
        Decode raw event logs using contract ABI.
        
        Args:
            logs: Raw event logs from transaction receipt
            
        Returns:
            list: Decoded event data
        """
        
    def get_method(self, calldata: str):
        """
        Get method information from transaction calldata.
        
        Args:
            calldata: Transaction input data
            
        Returns:
            Method information and decoded parameters
        """

Project Contract

Enhanced contract class with build information and deployment artifacts, providing additional metadata and debugging capabilities.

class ProjectContract(Contract):
    """
    Contract with associated build information and deployment artifacts.
    
    Additional attributes:
        _name (str): Contract name from source
        _sources (Sources): Associated source files
        _build (dict): Build artifacts and metadata
    """
    
    @classmethod
    def deploy(cls, *args, **kwargs) -> 'ProjectContract':
        """
        Deploy new instance of this contract.
        
        Args:
            *args: Constructor arguments
            **kwargs: Transaction parameters (from, gas_limit, etc.)
            
        Returns:
            ProjectContract: Deployed contract instance
        """
        
    @classmethod
    def at(cls, address: str, owner: Account = None) -> 'ProjectContract':
        """
        Connect to existing deployed contract.
        
        Args:
            address: Contract address
            owner: Account that owns the contract
            
        Returns:
            ProjectContract: Contract instance at address
        """
        
    def get_verification_info(self) -> dict:
        """Get contract verification information for block explorers."""
        
    def publish_source(self, silent: bool = False) -> str:
        """
        Publish contract source to block explorer.
        
        Args:
            silent: Suppress console output
            
        Returns:
            str: Verification URL or status
        """

Contract Container

Container class that manages multiple contract instances and provides deployment and access methods for contract types.

class ContractContainer:
    """
    Container for managing contracts of the same type.
    
    Attributes:
        _name (str): Contract name
        abi (list): Contract ABI
        bytecode (str): Contract bytecode
    """
    
    def __init__(self, project, build: dict):
        """Initialize container with project and build data."""
        
    def __call__(self, *args, **kwargs) -> ProjectContract:
        """Deploy new contract instance (alias for deploy)."""
        
    def __iter__(self):
        """Iterate over deployed contract instances."""
        
    def __getitem__(self, index: int) -> ProjectContract:
        """Get deployed contract by index."""
        
    def __len__(self) -> int:
        """Get number of deployed contracts."""
        
    def deploy(self, *args, **kwargs) -> ProjectContract:
        """
        Deploy new contract instance.
        
        Args:
            *args: Constructor arguments
            **kwargs: Transaction parameters
            
        Returns:
            ProjectContract: Newly deployed contract
        """
        
    def at(self, address: str, owner: Account = None) -> ProjectContract:
        """
        Connect to existing contract at address.
        
        Args:
            address: Contract address
            owner: Contract owner account
            
        Returns:
            ProjectContract: Contract instance
        """
        
    def remove(self, contract: ProjectContract) -> None:
        """Remove contract from container."""
        
    def estimate_gas(self, *args) -> int:
        """
        Estimate gas for contract deployment.
        
        Args:
            *args: Constructor arguments
            
        Returns:
            int: Estimated gas amount
        """

Interface Container

Container for managing contract interfaces (ABI without bytecode) for interacting with contracts not deployed through the current project.

class InterfaceContainer:
    """
    Container for contract interfaces (ABI-only contracts).
    
    Used for interacting with contracts deployed elsewhere.
    """
    
    def __init__(self, name: str, abi: list):
        """
        Initialize interface container.
        
        Args:
            name: Interface name
            abi: Contract ABI
        """
        
    def __call__(self, address: str, owner: Account = None) -> Contract:
        """Create contract instance at address."""
        
    def at(self, address: str, owner: Account = None) -> Contract:
        """
        Connect to contract at address using this interface.
        
        Args:
            address: Contract address
            owner: Account for transactions
            
        Returns:
            Contract: Contract instance with interface ABI
        """

Contract Methods

Contract methods are accessed dynamically and return callable objects that handle both read operations and transactions.

class ContractCall:
    """
    Callable for contract view/pure methods (read-only operations).
    
    These methods don't modify blockchain state and don't require gas.
    """
    
    def __call__(self, *args, block_identifier: Union[int, str] = 'latest') -> Any:
        """
        Call contract method.
        
        Args:
            *args: Method arguments
            block_identifier: Block number or 'latest'/'pending'
            
        Returns:
            Any: Method return value
        """
        
    def call(self, tx_params: dict = None, block_identifier: Union[int, str] = 'latest') -> Any:
        """Call method with custom transaction parameters."""
        
    def estimate_gas(self, *args) -> int:
        """Estimate gas if method were called as transaction."""

class ContractTx:
    """
    Callable for contract state-changing methods (transactions).
    
    These methods modify blockchain state and require gas.
    """
    
    def __call__(self, *args, **kwargs) -> TransactionReceipt:
        """
        Execute contract method as transaction.
        
        Args:
            *args: Method arguments
            **kwargs: Transaction parameters (from, gas_limit, etc.)
            
        Returns:
            TransactionReceipt: Transaction receipt
        """
        
    def call(self, *args, tx_params: dict = None, block_identifier: Union[int, str] = 'latest') -> Any:
        """Call method without sending transaction (simulation)."""
        
    def estimate_gas(self, *args, tx_params: dict = None) -> int:
        """
        Estimate gas for method execution.
        
        Args:
            *args: Method arguments
            tx_params: Transaction parameters
            
        Returns:
            int: Estimated gas amount
        """
        
    def transact(self, *args, **kwargs) -> TransactionReceipt:
        """Execute method as transaction (alias for __call__)."""

Event Handling

class EventDict(dict):
    """
    Dictionary-like container for contract events with additional filtering methods.
    """
    
    def get_sequence(self) -> list:
        """Get events in chronological order."""
        
    def count(self) -> int:
        """Get total number of events."""

class Log:
    """
    Individual event log with decoded data.
    
    Attributes:
        address (str): Contract address that emitted the event
        topics (list): Event topics (including signature)
        data (str): Raw event data
        block_number (int): Block number
        transaction_hash (str): Transaction hash
        log_index (int): Log index within transaction
        event (str): Event name
        args (dict): Decoded event arguments
    """
    
    def __init__(self, log_dict: dict, abi: dict):
        """Initialize log with raw data and ABI."""

Usage Examples

Contract Deployment

from brownie import accounts, project

# Load project and account
p = project.load()
account = accounts[0]

# Deploy contract with constructor arguments
contract = p.MyContract.deploy(
    "constructor_string",
    42,
    ["array", "values"],
    {'from': account, 'gas_limit': 3000000}
)

print(f"Contract deployed at: {contract.address}")
print(f"Transaction hash: {contract.tx.txid}")

Contract Method Calls

# Call view/pure methods (no gas required)
result = contract.myViewMethod(arg1, arg2)
print(f"Method returned: {result}")

# Call at specific block
historical_result = contract.myViewMethod(arg1, block_identifier=1000000)

# Execute state-changing methods (requires gas)
tx = contract.myStateMethod(
    arg1, 
    arg2,
    {'from': account, 'gas_limit': 200000}
)

print(f"Transaction hash: {tx.txid}")
print(f"Gas used: {tx.gas_used}")
print(f"Events emitted: {tx.events}")

Interacting with Existing Contracts

# Connect to deployed contract by address
existing_contract = p.MyContract.at("0x742d35Cc6634C0532925a3b8D8D944d0Cdbc-1234")

# Use interface for contracts deployed elsewhere
interface_contract = p.interface.IERC20.at("0xA0b86a33E6442496c5D58f95EF3cE-5678")

# Call methods on existing contract
balance = interface_contract.balanceOf(account.address)

Event Filtering and Analysis

# Get all events from transaction
tx = contract.myMethod({'from': account})
all_events = tx.events

# Access specific event type
my_events = tx.events['MyEvent']
print(f"Number of MyEvent events: {len(my_events)}")

# Iterate through events
for event in my_events:
    print(f"Event args: {event.args}")
    print(f"Block number: {event.block_number}")

# Filter events from multiple transactions
transfer_filter = contract.events.Transfer.createFilter(
    fromBlock=1000000,
    argument_filters={'from': account.address}
)
transfers = transfer_filter.get_all_entries()

Error Handling and Debugging

from brownie import reverts

# Handle expected reverts
with reverts("Insufficient balance"):
    contract.withdraw(1000000, {'from': account})

# Allow reverted transactions for analysis
tx = contract.riskyMethod({'from': account, 'allow_revert': True})

if tx.status == 0:
    print(f"Transaction reverted: {tx.revert_msg}")
    tx.traceback()  # Detailed error trace
    tx.call_trace()  # Step-by-step execution trace

# Simulate transaction before sending
try:
    result = contract.myMethod.call(arg1, {'from': account})
    print(f"Method would return: {result}")
except ValueError as e:
    print(f"Method would revert: {e}")

Gas Estimation and Optimization

# Estimate gas for deployment
estimated_gas = p.MyContract.estimate_gas("constructor_arg", 42)
print(f"Deployment will use ~{estimated_gas} gas")

# Estimate gas for method call
method_gas = contract.myMethod.estimate_gas(arg1, {'from': account})
print(f"Method call will use ~{method_gas} gas")

# Use gas strategies for automatic optimization
from brownie.network.gas import LinearScalingStrategy

gas_strategy = LinearScalingStrategy("20 gwei", "50 gwei", 1.1)
tx = contract.myMethod(arg1, {'from': account, 'gas_strategy': gas_strategy})

Advanced Features

Multicall Operations

from brownie import multicall

# Batch multiple contract calls
with multicall:
    balance1 = token.balanceOf(account1)
    balance2 = token.balanceOf(account2)
    total_supply = token.totalSupply()

# All calls executed in single transaction
print(f"Balance 1: {balance1}")
print(f"Balance 2: {balance2}")
print(f"Total supply: {total_supply}")

Contract Verification

# Publish contract source to block explorer
verification_url = contract.publish_source()
print(f"Contract verified at: {verification_url}")

# Get verification info
verification_info = contract.get_verification_info()
print(f"Compiler version: {verification_info['compiler_version']}")

Type Definitions

# Type aliases for contract operations
ContractType = Union[Contract, ProjectContract]
AbiType = List[Dict[str, Any]]
EventFilter = Dict[str, Any]
CallResult = Any
TxReceipt = TransactionReceipt

Install with Tessl CLI

npx tessl i tessl/pypi-eth-brownie@1.21.1

docs

accounts.md

cli.md

contracts.md

conversion-testing.md

index.md

network.md

project.md

tile.json