A Python framework for Ethereum smart contract deployment, testing and interaction.
—
Brownie project creation, contract compilation, script execution, and build artifact management with support for both Solidity and Vyper smart contracts.
Functions for creating new brownie projects and loading existing ones with proper configuration and dependency management.
def new(path: str = ".", name: str = None, ignore_existing: bool = False) -> Project:
"""
Create a new brownie project.
Args:
path: Directory path for the new project
name: Project name (derived from path if None)
ignore_existing: Don't raise error if directory exists
Returns:
Project: Newly created project instance
Raises:
FileExistsError: If directory exists and ignore_existing is False
"""
def load(project_path: str = ".", name: str = None) -> Project:
"""
Load an existing brownie project.
Args:
project_path: Path to project directory
name: Project name override
Returns:
Project: Loaded project instance
Raises:
ProjectNotFound: If project directory doesn't contain brownie project
"""
def from_brownie_mix(path: str, project_name: str = None, ignore_existing: bool = False) -> Project:
"""
Create project from brownie-mix template.
Args:
path: Brownie-mix repository path or name
project_name: Name for the new project
ignore_existing: Don't raise error if directory exists
Returns:
Project: Project created from template
"""
def check_for_project(path: str = ".") -> bool:
"""
Check if directory contains a brownie project.
Args:
path: Directory path to check
Returns:
bool: True if directory contains brownie project
"""
def get_loaded_projects() -> list:
"""
Get list of currently loaded projects.
Returns:
list: List of loaded Project instances
"""Functions for compiling smart contract source code with support for multiple Solidity and Vyper versions.
def compile_source(
source: str,
solc_version: str = None,
vyper_version: str = None,
**kwargs
) -> TempProject:
"""
Compile contract source code without a project.
Args:
source: Contract source code
solc_version: Solidity compiler version
vyper_version: Vyper compiler version
**kwargs: Additional compiler options
Returns:
TempProject: Temporary project with compiled contracts
Raises:
CompilerError: If compilation fails
IncompatibleSolcVersion: If Solidity version unsupported
IncompatibleVyperVersion: If Vyper version unsupported
"""
def run(script_path: str, method_name: str = None, *args, **kwargs):
"""
Run a project script.
Args:
script_path: Path to script file
method_name: Specific method to run (main if None)
*args: Arguments to pass to script
**kwargs: Keyword arguments to pass to script
Returns:
Any: Return value from script execution
"""The main Project class manages project lifecycle, compilation, and artifact handling.
class Project:
"""
Main project class for managing brownie projects.
Attributes:
_name (str): Project name
_path (Path): Project directory path
_active (bool): Whether project is currently active
_compiler_config (dict): Compiler configuration
_network_config (dict): Network configuration
"""
def __init__(self, name: str, project_path: Path):
"""
Initialize project instance.
Args:
name: Project name
project_path: Path to project directory
"""
def load_config(self) -> None:
"""Load project configuration from brownie-config.yaml."""
def compile(self, **kwargs) -> None:
"""
Compile all project contracts.
Args:
**kwargs: Compiler options
- contracts: List of specific contracts to compile
- optimizer: Optimizer settings
- solc_version: Solidity version override
- vyper_version: Vyper version override
"""
def close(self, raises: bool = True) -> None:
"""
Close project and clean up resources.
Args:
raises: Raise exception if project not active
"""
def __getattr__(self, name: str):
"""Access contract containers by name."""
def __getitem__(self, name: str):
"""Access contract containers by name (dict-style)."""
def __iter__(self):
"""Iterate over contract containers."""
def __contains__(self, name: str) -> bool:
"""Check if contract exists in project."""
def __len__(self) -> int:
"""Get number of contract containers."""
def dict(self) -> dict:
"""Get dictionary of contract containers."""
def keys(self) -> list:
"""Get list of contract names."""
def interface(self):
"""Access to interface containers."""Temporary projects handle ad-hoc source compilation without full project structure.
class TempProject:
"""
Temporary project for compiling source code without full project structure.
Used by compile_source() function for one-off compilation tasks.
"""
def __init__(self, name: str, contracts: dict):
"""
Initialize temporary project.
Args:
name: Temporary project name
contracts: Compiled contract data
"""
def __getattr__(self, name: str):
"""Access contract containers by name."""
def __getitem__(self, name: str):
"""Access contract containers by name (dict-style)."""
def close(self) -> None:
"""Clean up temporary project resources."""The Build class manages compilation artifacts, metadata, and dependency tracking.
class Build:
"""
Build artifacts manager for handling compilation results and metadata.
Attributes:
_path (Path): Build directory path
_contracts (dict): Contract build artifacts
_interfaces (dict): Interface definitions
"""
def __init__(self, project_path: Path):
"""
Initialize build manager.
Args:
project_path: Project directory path
"""
def get(self, name: str) -> dict:
"""
Get build artifact for contract.
Args:
name: Contract name
Returns:
dict: Build artifact data
"""
def contains(self, name: str) -> bool:
"""
Check if build contains contract.
Args:
name: Contract name
Returns:
bool: True if contract exists in build
"""
def _compile(self, contracts: dict, compiler_data: dict, silent: bool = False) -> None:
"""
Compile contracts and store artifacts.
Args:
contracts: Contract source data
compiler_data: Compiler configuration
silent: Suppress compilation output
"""
def _generate_dependency_map(self) -> dict:
"""Generate dependency mapping for contracts."""
def _get_contract_dependencies(self, name: str) -> list:
"""
Get dependencies for specific contract.
Args:
name: Contract name
Returns:
list: List of dependency contract names
"""The Sources class manages project source files and change tracking for incremental compilation.
class Sources:
"""
Source file manager with change tracking for incremental compilation.
Attributes:
_contracts (dict): Contract source files
_interfaces (dict): Interface source files
_libraries (dict): Library source files
"""
def __init__(self, project_path: Path):
"""
Initialize source manager.
Args:
project_path: Project directory path
"""
def get_contract_list(self) -> list:
"""
Get list of contract source files.
Returns:
list: Contract file paths
"""
def get_interface_list(self) -> list:
"""
Get list of interface source files.
Returns:
list: Interface file paths
"""
def get_interface_sources(self) -> dict:
"""
Get interface source code.
Returns:
dict: Interface name to source mapping
"""
def get_source_path(self, contract_name: str) -> Path:
"""
Get source file path for contract.
Args:
contract_name: Contract name
Returns:
Path: Source file path
"""
def get_contract_names(self) -> list:
"""
Get list of contract names.
Returns:
list: Contract names
"""
def check_for_changed_files(self, build_artifacts: dict) -> bool:
"""
Check if source files have changed since last compilation.
Args:
build_artifacts: Previous build artifacts
Returns:
bool: True if files have changed
"""The Flattener class provides contract source flattening for verification and deployment.
class Flattener:
"""
Contract source flattening utility for verification and deployment.
"""
def __init__(self, contract_name: str, project_path: Path):
"""
Initialize flattener for specific contract.
Args:
contract_name: Contract to flatten
project_path: Project directory path
"""
def flatten(self, output_path: str = None) -> str:
"""
Flatten contract source and all dependencies.
Args:
output_path: Output file path (return string if None)
Returns:
str: Flattened source code
"""from brownie import project
# Create new project
new_project = project.new('./my-defi-project', name='MyDefiProject')
print(f"Created project: {new_project._name}")
# Create from brownie-mix template
token_project = project.from_brownie_mix('token')
# Load existing project
existing_project = project.load('./existing-project')
print(f"Loaded project with {len(existing_project)} contracts")from brownie import project
# Load and compile project
p = project.load()
p.compile()
# Compile specific contracts
p.compile(contracts=['Token', 'Exchange'])
# Compile with optimizer
p.compile(optimizer={'enabled': True, 'runs': 200})
# Compile ad-hoc source
source_code = '''
pragma solidity ^0.8.0;
contract SimpleStorage {
uint256 public data;
function setData(uint256 _data) public { data = _data; }
}
'''
temp_project = project.compile_source(source_code)
contract = temp_project.SimpleStorage.deploy({'from': accounts[0]})from brownie import project, accounts
# Load project
p = project.load()
# Check available contracts
print(f"Available contracts: {list(p.keys())}")
print(f"Total contracts: {len(p)}")
# Check if contract exists
if 'Token' in p:
print("Token contract available")
# Access contract containers
token_container = p.Token
exchange_container = p['Exchange']
# Deploy contracts
account = accounts[0]
token = p.Token.deploy("MyToken", "MTK", 18, 1000000, {'from': account})
exchange = p.Exchange.deploy(token.address, {'from': account})
# Access deployed contracts
deployed_tokens = list(p.Token)
print(f"Deployed {len(deployed_tokens)} token contracts")from brownie import project
# Run main script
project.run('scripts/deploy.py')
# Run specific function
project.run('scripts/deploy.py', 'deploy_token', 'MyToken', 'MTK')
# Run with arguments
project.run('scripts/manage.py', 'transfer_tokens',
recipient='0x742d35Cc6634C0532925a3b8D8D944d0Cdbc1234',
amount=1000)from brownie import project
p = project.load()
# Access build information
build = p._build
token_artifact = build.get('Token')
print(f"Token ABI: {token_artifact['abi']}")
print(f"Token bytecode: {token_artifact['bytecode'][:100]}...")
# Check dependencies
if build.contains('Exchange'):
deps = build._get_contract_dependencies('Exchange')
print(f"Exchange dependencies: {deps}")from brownie import project
p = project.load()
# Access interface containers
erc20_interface = p.interface.IERC20
# Connect to existing contract using interface
usdc_contract = erc20_interface.at('0xA0b86a33E6442496c5D58f95EF3CE-1234')
# Check balance using interface
balance = usdc_contract.balanceOf(accounts[0])
print(f"USDC balance: {balance}")from brownie import project
p = project.load()
sources = p._sources
# Get contract information
contract_list = sources.get_contract_list()
print(f"Contract files: {contract_list}")
contract_names = sources.get_contract_names()
print(f"Contract names: {contract_names}")
# Get source path
token_path = sources.get_source_path('Token')
print(f"Token source: {token_path}")
# Check for changes
build_artifacts = p._build._contracts
has_changes = sources.check_for_changed_files(build_artifacts)
if has_changes:
print("Source files have changed, recompilation needed")from brownie import project
p = project.load()
# Flatten contract for verification
flattener = project.Flattener('Token', p._path)
flattened_source = flattener.flatten()
# Save to file
flattener.flatten('./flattened/Token_flattened.sol')
print("Contract flattened and saved")from brownie import project
p = project.load()
# Load custom configuration
p.load_config()
# Access compiler configuration
compiler_config = p._compiler_config
print(f"Solc version: {compiler_config.get('solc', {}).get('version')}")
print(f"Optimizer enabled: {compiler_config.get('solc', {}).get('optimizer', {}).get('enabled')}")
# Access network configuration
network_config = p._network_config
print(f"Networks: {list(network_config.keys())}")from brownie import project
# Load multiple projects
token_project = project.load('./token-project')
exchange_project = project.load('./exchange-project')
# Check loaded projects
loaded_projects = project.get_loaded_projects()
print(f"Loaded {len(loaded_projects)} projects")
# Work with specific project
token = token_project.Token.deploy({'from': accounts[0]})
exchange = exchange_project.Exchange.deploy(token.address, {'from': accounts[0]})
# Close projects when done
token_project.close()
exchange_project.close()from brownie import project, network, accounts
# Setup development environment
network.connect('development')
p = project.load()
try:
# Compile contracts
p.compile()
# Deploy core contracts
account = accounts[0]
project.run('scripts/deploy_core.py')
# Run tests
project.run('scripts/run_tests.py')
# Deploy additional contracts
project.run('scripts/deploy_features.py')
print("Development workflow completed successfully")
except Exception as e:
print(f"Error in development workflow: {e}")
finally:
# Clean up
p.close()
network.disconnect()# Type aliases for project operations
ProjectType = Union[Project, TempProject]
ContractArtifact = Dict[str, Any]
CompilerConfig = Dict[str, Any]
BuildData = Dict[str, ContractArtifact]
SourceData = Dict[str, str]
DependencyMap = Dict[str, List[str]]Install with Tessl CLI
npx tessl i tessl/pypi-eth-brownie@1.21.1