This directory contains the smart contracts that power the decentralized Timeboost protocol. These contracts run on Ethereum-compatible blockchains and provide the foundation for secure, decentralized time synchronization.
- Background
- What Are These Contracts For?
- Handling Upgradeability
- The Contracts
- Getting Started
- Deployment
- Security
- Getting Help
Smart contracts are executable code, deployed on blockchains that can be read from / written to anyone with an internet connection. Transaction data and smart contract storage is public and can be accessed in blockchain explorers. In decentralized Timeboost, smart contracts are used to allow anyone to interact with various parts of the protocol. This readme is directed at developers who are contributing to or making use of this decentralized timeboost implementation.
Timeboost needs a way to coordinate cryptographic keys and committee members across a decentralized network. These smart contracts provide:
- Key Management: Store and manage public keys for the protocol
- Committee Coordination: Track which nodes are part of the consensus committee
- Access Control: Ensure only authorized parties can update critical protocol parameters
- Transparency: All changes are recorded on-chain for public verification
These contracts act as the "coordination layer" that allows the Timeboost network to operate without a central authority.
Once deployed, smart contracts can't be changed. To solve this, we use a proxy solution that functions as upgradeable contracts.
We use a "proxy pattern" that works like this:
- Users always interact with the proxy - This address never changes
- The proxy points to an implementation - This can be updated
- When you upgrade - Just point the proxy to a new implementation
- All data stays safe - Storage is preserved across upgrades
Think of it like changing the engine in a car - the car (proxy) stays the same, but you can swap out the engine (implementation) for a better one.
User → Proxy Contract → Implementation Contract
↓
Storage (persistent)
What it stores:
- Encryption keys - The cryptographic keys used by the protocol
- Committee members - Who's currently in the consensus committee
- Manager address - Who can update the contract
What it does:
- Sets committees - Updates which nodes are part of the network
- Manages keys - Stores the threshold encryption key
- Controls access - Only the manager can make changes
- Logs everything - All changes are recorded as events
Key functions:
setNextCommittee()
- Add a new committee with future memberscurrentCommitteeId()
- Find which committee is active right nowgetCommitteeById()
- Get details about a specific committeesetThresholdEncryptionKey()
- Set the encryption key for the protocol
This is the "shell" that makes upgrades possible:
- Never changes - Users always interact with this address
- Delegates calls - Forwards requests to the current implementation
- Preserves data - All storage survives upgrades
- SecOps Precautions - it's important to call the initialize methods during deploys and upgrades so that those transactions aren't front-run
Before you begin, make sure you have:
- Foundry - For building, testing, and deploying contracts
# Install Foundry curl -L https://foundry.paradigm.xyz | bash foundryup
# Build all contracts
just build-contracts
# Or use forge directly
forge build
# Run all tests
just test-contracts
# Run with detailed output
forge test -vvv
# Run specific test
forge test --match-test test_setThresholdEncryptionKey
For testing contract interactions from Rust code, see the timeboost-contract README in the Rust repository.
You can deploy to a local anvil network (as done in the test), a fork of a real network, a testnet network (e.g. Ethereum Sepolia) or a mainnet (e.g. Ethereum Mainnet).
-
Set up your environment:
cp env.example .env # Edit .env with your values
-
Start a local blockchain (not needed if using remote rpc):
anvil
-
Deploy the contracts:
./script/deploy.sh
That's it! The script will deploy your contracts and show you the addresses.
For production deployments, ensure you have:
- A secure wallet with sufficient ETH for gas fees
- A valid manager address (preferably a multisig wallet)
- The correct RPC URL for your target network
- Tested thoroughly on testnets first
- Manager Address: Who will manage the contract (usually a multisig wallet)
- RPC URL: Where to deploy (localhost for testing, or a real network)
- Mnemonic: Your wallet phrase (optional for local testing)
The script deploys two contracts:
- KeyManager - The actual contract with your business logic
- Proxy - Points to the KeyManager, so you can upgrade it later
The proxy gets initialized with your manager address, and that's it!
All settings go in your .env
file. Copy env.example
to .env
and customize:
# Required: Who manages the contract (use a multisig for production)
MANAGER_ADDRESS=0x1234567890123456789012345678901234567890
# Optional: Where to deploy (defaults to localhost)
RPC_URL=http://localhost:8545
# Optional: Your wallet phrase (defaults to Anvil's test account)
MNEMONIC="your twelve word mnemonic phrase here"
ACCOUNT_INDEX=0
Example configurations:
- Local testing: Use Anvil's default account (no mnemonic needed)
- Testnet: Use a test wallet with testnet ETH
- Mainnet: Use a secure multisig wallet
The deployment script:
- Deploys the KeyManager implementation contract
- Creates an ERC1967 proxy pointing to the implementation
- Initializes the proxy with your manager address
- Verifies the deployment was successful
- Returns both proxy and implementation addresses
"Manager address not set"
- Make sure you have
MANAGER_ADDRESS=0x...
in your.env
file
"Deployment failed"
- Check your RPC URL works
- Make sure your wallet has enough ETH for gas
- Verify your mnemonic is correct
Need help?
- Make sure Foundry is installed:
forge --version
- Check your
.env
file has all required values
- ERC1967Proxy - Audited by OpenZeppelin, widely used
- KeyManager - Not yet audited (audit planned)
- Manager privileges - The manager can update committees and keys
- Upgrade authority - Only the contract owner can upgrade
- Committee validation - Contracts validate committee transitions
- Event logging - All changes are logged onchain for transparency
- Use multisig wallets - Don't use single-key wallets for manager/owner
- Test thoroughly - Always test on testnets first
- Monitor events - Watch for unexpected contract changes
- Keep keys secure - Store private keys and mnemonics safely
# Build contracts
forge build
# Run tests
forge test
# Deploy locally
anvil
./script/deploy.sh
# Run specific test
forge test --match-test test_setThresholdEncryptionKey
- Proxy Contract: The address users interact with (never changes)
- Implementation Contract: The actual contract logic (can be upgraded)
- Manager: The address that can update committees and keys
- Review the timeboost-contract README in the Rust repo for integration questions
- Check the troubleshooting section above for deployment issues