Deployment Guide¶
Complete guide to deploying Tesseract to testnets and production.
Deployment Overview¶
graph LR
A[Local Testing] --> B[Testnet Deployment]
B --> C[Security Audit]
C --> D[Production Deployment]
Prerequisites¶
- Python 3.11+ and Poetry installed
- Testnet ETH/tokens for gas
- RPC endpoints (Infura, Alchemy, etc.)
- Secure private key management
Local Deployment¶
Start Local Node¶
Deploy Contract¶
from web3 import Web3
import vyper
# Connect
w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545'))
deployer = w3.eth.accounts[0]
# Compile
with open('contracts/TesseractSimple.vy', 'r') as f:
source = f.read()
compiled = vyper.compile_code(source, output_formats=['abi', 'bytecode'])
# Deploy
Contract = w3.eth.contract(abi=compiled['abi'], bytecode=compiled['bytecode'])
tx_hash = Contract.constructor().transact({'from': deployer})
receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
print(f"Deployed at: {receipt.contractAddress}")
Testnet Deployment¶
Step 1: Get Testnet Funds¶
| Network | Faucet | Amount Needed |
|---|---|---|
| Sepolia | sepoliafaucet.com | ~0.1 ETH |
| Mumbai | faucet.polygon.technology | ~1 MATIC |
| Arbitrum Goerli | bridge.arbitrum.io | ~0.1 ETH |
| Optimism Goerli | app.optimism.io | ~0.1 ETH |
Step 2: Configure Environment¶
Create .env file:
# RPC URLs
SEPOLIA_RPC_URL=https://sepolia.infura.io/v3/YOUR_KEY
MUMBAI_RPC_URL=https://polygon-mumbai.infura.io/v3/YOUR_KEY
ARBITRUM_RPC_URL=https://arb-goerli.g.alchemy.com/v2/YOUR_KEY
OPTIMISM_RPC_URL=https://opt-goerli.g.alchemy.com/v2/YOUR_KEY
# Private keys (NEVER commit these!)
DEPLOYER_PRIVATE_KEY=0x...
OPERATOR_PRIVATE_KEY=0x...
Security
Never commit private keys. Use hardware wallets for production.
Step 3: Deploy Script¶
#!/usr/bin/env python3
"""Deploy Tesseract to testnet."""
import os
from web3 import Web3
from dotenv import load_dotenv
import vyper
import json
load_dotenv()
def deploy_to_network(rpc_url: str, private_key: str) -> str:
"""Deploy contract to specified network."""
# Connect
w3 = Web3(Web3.HTTPProvider(rpc_url))
account = w3.eth.account.from_key(private_key)
print(f"Deploying from: {account.address}")
print(f"Balance: {w3.eth.get_balance(account.address) / 1e18:.4f} ETH")
# Compile
with open('contracts/TesseractSimple.vy', 'r') as f:
source = f.read()
compiled = vyper.compile_code(source, output_formats=['abi', 'bytecode'])
# Build transaction
Contract = w3.eth.contract(abi=compiled['abi'], bytecode=compiled['bytecode'])
tx = Contract.constructor().build_transaction({
'from': account.address,
'nonce': w3.eth.get_transaction_count(account.address),
'gas': 2000000,
'gasPrice': w3.eth.gas_price
})
# Sign and send
signed = w3.eth.account.sign_transaction(tx, private_key)
tx_hash = w3.eth.send_raw_transaction(signed.rawTransaction)
print(f"Transaction: {tx_hash.hex()}")
# Wait for receipt
receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
print(f"Contract deployed at: {receipt.contractAddress}")
# Save artifacts
artifacts = {
'address': receipt.contractAddress,
'abi': compiled['abi'],
'deployer': account.address,
'tx_hash': tx_hash.hex()
}
with open('artifacts/deployment.json', 'w') as f:
json.dump(artifacts, f, indent=2)
return receipt.contractAddress
if __name__ == "__main__":
deploy_to_network(
os.environ['SEPOLIA_RPC_URL'],
os.environ['DEPLOYER_PRIVATE_KEY']
)
Step 4: Verify Deployment¶
# Run deployment
poetry run python scripts/deploy_testnet.py
# Verify on explorer
# Sepolia: https://sepolia.etherscan.io/address/YOUR_ADDRESS
Step 5: Initialize Contract¶
def initialize_contract(rpc_url: str, contract_address: str, private_key: str):
"""Initialize contract with operators."""
w3 = Web3(Web3.HTTPProvider(rpc_url))
account = w3.eth.account.from_key(private_key)
# Load contract
with open('artifacts/deployment.json', 'r') as f:
artifacts = json.load(f)
contract = w3.eth.contract(
address=contract_address,
abi=artifacts['abi']
)
# Add operator
operator_address = os.environ['OPERATOR_ADDRESS']
tx = contract.functions.add_operator(operator_address).build_transaction({
'from': account.address,
'nonce': w3.eth.get_transaction_count(account.address),
'gas': 100000,
'gasPrice': w3.eth.gas_price
})
signed = w3.eth.account.sign_transaction(tx, private_key)
tx_hash = w3.eth.send_raw_transaction(signed.rawTransaction)
w3.eth.wait_for_transaction_receipt(tx_hash)
print(f"Operator added: {operator_address}")
# Verify
is_operator = contract.functions.authorized_operators(operator_address).call()
print(f"Verified: {is_operator}")
Multi-Chain Deployment¶
Deploy to All Networks¶
NETWORKS = {
'sepolia': {
'rpc': os.environ['SEPOLIA_RPC_URL'],
'chain_id': 11155111
},
'mumbai': {
'rpc': os.environ['MUMBAI_RPC_URL'],
'chain_id': 80001
},
'arbitrum_goerli': {
'rpc': os.environ['ARBITRUM_RPC_URL'],
'chain_id': 421613
},
'optimism_goerli': {
'rpc': os.environ['OPTIMISM_RPC_URL'],
'chain_id': 420
}
}
def deploy_all():
"""Deploy to all networks."""
deployments = {}
for network, config in NETWORKS.items():
print(f"\nDeploying to {network}...")
try:
address = deploy_to_network(
config['rpc'],
os.environ['DEPLOYER_PRIVATE_KEY']
)
deployments[network] = {
'address': address,
'chain_id': config['chain_id']
}
except Exception as e:
print(f"Failed to deploy to {network}: {e}")
# Save all deployments
with open('artifacts/deployments.json', 'w') as f:
json.dump(deployments, f, indent=2)
return deployments
Production Deployment¶
Pre-Deployment Checklist¶
- [ ] Security audit completed
- [ ] All tests passing
- [ ] Gas costs estimated
- [ ] Monitoring infrastructure ready
- [ ] Incident response plan documented
- [ ] Key management solution in place
Hardware Wallet Deployment¶
from eth_account import Account
from eth_account.signers.ledger import LedgerSigner
def deploy_with_ledger(rpc_url: str):
"""Deploy using Ledger hardware wallet."""
w3 = Web3(Web3.HTTPProvider(rpc_url))
# Connect to Ledger
signer = LedgerSigner()
account = signer.address
print(f"Deploying from Ledger: {account}")
# ... rest of deployment logic
Gas Estimation¶
def estimate_deployment_cost(rpc_url: str):
"""Estimate deployment gas costs."""
w3 = Web3(Web3.HTTPProvider(rpc_url))
# Compile
with open('contracts/TesseractSimple.vy', 'r') as f:
source = f.read()
compiled = vyper.compile_code(source, output_formats=['bytecode'])
bytecode_size = len(compiled['bytecode']) // 2
# Estimate
gas_price = w3.eth.gas_price
estimated_gas = 1500000 # Conservative estimate
cost_wei = gas_price * estimated_gas
cost_eth = cost_wei / 1e18
print(f"Bytecode size: {bytecode_size} bytes")
print(f"Gas price: {gas_price / 1e9:.2f} gwei")
print(f"Estimated gas: {estimated_gas:,}")
print(f"Estimated cost: {cost_eth:.4f} ETH")
return cost_eth
Post-Deployment¶
Verify Contract Source¶
# Using Etherscan API
curl -X POST "https://api-sepolia.etherscan.io/api" \
-d "module=contract" \
-d "action=verifysourcecode" \
-d "contractaddress=YOUR_ADDRESS" \
-d "sourceCode=$(cat contracts/TesseractSimple.vy)" \
-d "contractname=TesseractSimple" \
-d "compilerversion=vyper:0.3.10" \
-d "apikey=YOUR_API_KEY"
Health Check¶
def health_check(rpc_url: str, contract_address: str):
"""Verify deployment health."""
w3 = Web3(Web3.HTTPProvider(rpc_url))
# Check contract exists
code = w3.eth.get_code(contract_address)
assert len(code) > 0, "No contract code found"
# Load contract
contract = w3.eth.contract(address=contract_address, abi=ABI)
# Check owner
owner = contract.functions.owner().call()
print(f"Owner: {owner}")
# Check coordination window
window = contract.functions.coordination_window().call()
print(f"Coordination window: {window}s")
# Check transaction count
count = contract.functions.transaction_count().call()
print(f"Transaction count: {count}")
print("Health check passed!")
Troubleshooting¶
Common Issues¶
Next Steps¶
- Multi-Chain Setup - Configure cross-chain operations
- Monitoring - Set up production monitoring
- Security Model - Security best practices