This guide demonstrates how to use the SmartContractManager for deterministic smart contract deployment using CREATE2 opcodes. The examples are based on our comprehensive test suite that covers various deployment and interaction scenarios.
The SmartContractManager provides:
- Deterministic Deployment: Deploy contracts at predictable addresses using CREATE2
- Viem Integration: Modern, type-safe Ethereum interactions
- Test Framework Integration: Seamless integration with Playwright and our custom test framework
- State Management: Snapshot and revert capabilities for testing
Make sure you have Foundry installed. If not, install it:
curl -L https://foundry.paradigm.xyz | bash
foundryupSet the following environment variable to tell the SmartContractManager where to find your compiled contracts:
export E2E_CONTRACT_PROJECT_ROOT=../smart-contractsNavigate to the smart contracts directory, install dependencies, and build:
cd example/smart-contracts
forge install foundry-rs/forge-std
forge install OpenZeppelin/openzeppelin-contracts
forge buildThis will:
- Install forge-std and OpenZeppelin contracts libraries
- Compile all smart contracts
- Generate artifacts in the
out/directory
The SmartContractManager automatically deploys the deterministic deployment proxy at address 0x4e59b44847b379578588920ca78fbf26c0b4956c when needed. This proxy enables CREATE2 deployments.
Our test suite (example/frontend/e2e/smartContractDeployment.spec.ts) demonstrates various deployment scenarios:
test("should deploy SimpleToken contract using CREATE2")What it does:
- Deploys a SimpleToken contract using CREATE2 with a specific salt
- Verifies the contract was deployed at the expected address
- Checks that contract bytecode exists on-chain
Key concepts:
- CREATE2 produces deterministic addresses based on salt, bytecode, and constructor args
- The deployment address can be predicted before deployment
test("should deploy at deterministic address with same salt")What it does:
- Deploys a contract with a specific salt
- Takes a blockchain snapshot
- Reverts to the snapshot (simulating a fresh chain)
- Deploys again with the same salt
- Verifies both deployments produce the same address
Key concepts:
- CREATE2 addresses are deterministic across different chains/states
- Useful for multi-chain deployments or factory patterns
test("should interact with deployed contract")What it does:
- Deploys a SimpleToken contract
- Reads various contract states:
- Owner address
- Owner's token balance (100k tokens from constructor)
- Total supply
- Token name and symbol
Key concepts:
- The contract owner is the proxy contract (
0x4e59b44847b379578588920ca78fbf26c0b4956c) - Read-only operations don't require special permissions
- Constructor logic executes during deployment (minting initial tokens)
test("should perform batch operations")What it does:
- Demonstrates batch deployment of multiple contracts
- Uses
setContractStatefor complex deployment scenarios - Verifies deployments through event logs
Key concepts:
- Batch operations improve efficiency
- Useful for deploying interconnected contract systems
test("should handle contract with constructor arguments")What it does:
- Shows how to deploy contracts with constructor parameters
- Verifies successful deployment
Key concepts:
- Constructor args are encoded with the bytecode for CREATE2
- Arguments affect the deterministic address
test("should connect wallet and interact with deployed contract")What it does:
- Deploys a contract
- Connects MetaMask wallet to the dApp
- Demonstrates end-to-end user interaction flow
Key concepts:
- Test framework provides wallet fixtures (MetaMask, Coinbase)
- Wallet connection enables user-initiated transactions
test("should test contract state persistence across snapshots")What it does:
- Deploys a first contract
- Takes a snapshot of the blockchain state
- Deploys a second contract
- Reverts to the snapshot
- Verifies the second contract no longer exists
- Confirms the first contract persists with original state
Key concepts:
- Snapshots capture complete blockchain state
- Useful for testing different scenarios from same starting point
- State includes balances, storage, and deployed code
const address = await smartContractManager.deployContract({
name: "ContractName", // Must match .sol filename
args: [], // Constructor arguments
salt: "0x...", // 32-byte hex string
deployer: "0x...", // Deployer address
})const txHash = await smartContractManager.executeCall({
target: "0x...", // Contract address
functionName: "transfer", // Function to call
args: [recipient, amount], // Function arguments
account: "0x...", // Caller address
value: 0n, // ETH to send (optional)
})await smartContractManager.setContractState({
deployments: [
{ name: "Token", args: [], salt: "0x1...", deployer: "0x..." },
{ name: "NFT", args: ["MyNFT", "NFT"], salt: "0x2...", deployer: "0x..." },
],
calls: [
{ target: "0x...", functionName: "initialize", args: [], account: "0x..." },
],
}, node)The test framework automatically provides:
node: Local blockchain node instancesmartContractManager: Contract deployment managermetamask/coinbase: Wallet fixtures for testing user interactionspage: Playwright page object for UI interactions
When contracts are deployed via CREATE2 proxy:
- The proxy contract (
0x4e59b44847b379578588920ca78fbf26c0b4956c) becomes the initial owner - This affects functions with
onlyOwnermodifiers - Plan your contract initialization accordingly
The test fixtures may show TypeScript warnings about being possibly undefined. These are safe to ignore as the test framework ensures they're initialized before test execution.
-
"Artifact not found" error
- Run
forge buildin the smart-contracts directory - Ensure
E2E_CONTRACT_PROJECT_ROOTis set correctly
- Run
-
"HTTP request failed" error
- Make sure you're using the
nodefixture from the test framework - Don't create new
LocalNodeManagerinstances
- Make sure you're using the
-
"Chain ID mismatch" error
- The framework automatically detects the correct chain ID
- Don't hardcode chain configurations
-
Permission errors when calling contract functions
- Remember the proxy is the owner, not your test accounts
- Use read-only functions or design contracts with appropriate access control
# Run all smart contract deployment tests
yarn test:e2e smartContractDeployment
# Run with UI mode for debugging
yarn test:e2e --ui smartContractDeployment
# Run a specific test
yarn test:e2e -g "should deploy SimpleToken contract"- Study the test examples to understand different deployment patterns
- Modify the SimpleToken contract to add your own functionality
- Create new test cases for your specific use cases
- Explore multi-contract deployments and interactions