Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

README.md

EV-Reth Contracts

Smart contracts for EV-Reth, including the FeeVault for collecting and distributing fees.

AdminProxy

The AdminProxy contract solves the bootstrap problem for admin addresses at genesis. It acts as an intermediary owner/admin for other contracts and precompiles (like the Mint Precompile) when the final admin (e.g., a multisig) is not known at genesis time.

See AdminProxy documentation for detailed setup and usage instructions.

FeeVault (optional)

The FeeVault is an optional contract for chains that need on-chain fee splitting logic. The base fee redirect (baseFeeSink) works with any address — an EOA or multisig is sufficient if you just need fees sent to a single destination.

FeeVault is useful when you need:

  • Automatic splitting of accumulated fees between two recipients (e.g., 80% to a bridge contract, 20% to a treasury)
  • Minimum threshold to avoid distributing uneconomically small amounts
  • Keeper incentive (callFee) so anyone can trigger distribution and get compensated

If your chain only needs fees routed to a single address, skip FeeVault and point baseFeeSink directly at that address.

Prerequisites

Build

forge build

Test

forge test

Deploying FeeVault

The FeeVault uses CREATE2 for deterministic addresses across chains.

Environment Variables

All configuration is set via constructor arguments at deploy time:

Variable Required Description
OWNER Yes Owner address (can configure the vault post-deployment)
SALT No CREATE2 salt (default: 0x0). Use any bytes32 value
MINIMUM_AMOUNT No Minimum wei to distribute (default: 0)
CALL_FEE No Fee in wei for calling distribute() (default: 0)
BRIDGE_SHARE_BPS No Basis points to bridge (default: 10000 = 100%)
OTHER_RECIPIENT No* Address to receive non-bridged portion

*Required if BRIDGE_SHARE_BPS < 10000

Note: BRIDGE_RECIPIENT must be set via setBridgeRecipient() after deployment for the vault to be operational.

Choosing a Salt

Any bytes32 value works as a salt. Common approaches:

# Simple approach - just use a version number
export SALT=0x0000000000000000000000000000000000000000000000000000000000000001

# Or hash a meaningful string
export SALT=$(cast keccak "FeeVault-v1")

Compute Address Before Deploying

To see what address will be deployed to without actually deploying:

export OWNER=0xYourOwnerAddress
export SALT=0x0000000000000000000000000000000000000000000000000000000000000001
export DEPLOYER=0xYourDeployerAddress  # The address that will run the script

forge script script/DeployFeeVault.s.sol:ComputeFeeVaultAddress

Deploy

# Required
export OWNER=0xYourOwnerAddress
export SALT=0x0000000000000000000000000000000000000000000000000000000000000001

# Optional - configure at deploy time (can also be set later)
export MINIMUM_AMOUNT=1000000000000000000  # 1 ETH in wei
export CALL_FEE=100000000000000  # 0.0001 ETH
export BRIDGE_SHARE_BPS=8000  # 80% to bridge
export OTHER_RECIPIENT=0xOtherAddress

# Dry run (no broadcast)
forge script script/DeployFeeVault.s.sol:DeployFeeVault \
    --rpc-url <RPC_URL>

# Deploy for real
forge script script/DeployFeeVault.s.sol:DeployFeeVault \
    --rpc-url <RPC_URL> \
    --private-key <PRIVATE_KEY> \
    --broadcast

Post-Deployment: Set Bridge Recipient

After deployment, set the bridge recipient address:

cast send <FEEVAULT_ADDRESS> "setBridgeRecipient(address)" <BRIDGE_RECIPIENT_ADDRESS> \
    --rpc-url <RPC_URL> \
    --private-key <PRIVATE_KEY>

Admin Functions

All functions are owner-only:

Function Description
setBridgeRecipient(address) Set the bridge recipient address
setMinimumAmount(uint256) Set minimum amount to distribute
setCallFee(uint256) Set fee for calling distribute
setBridgeShare(uint256) Set bridge percentage (basis points)
setOtherRecipient(address) Set recipient for non-bridged funds
transferOwnership(address) Transfer contract ownership