Skip to content

Commit 88d521c

Browse files
Port EspressoSystems/timeboost#482 into timeboost-contracts (#2)
* Port EspressoSystems/timeboost#482 into timeboost-contracts * remove redudunct readme and linked to the correct readme location for the timeboost repo * remove lock files in gitignore * improves readme
1 parent d367ab3 commit 88d521c

File tree

6 files changed

+421
-1
lines changed

6 files changed

+421
-1
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,6 @@ docs/
1212

1313
# Dotenv file
1414
.env
15+
16+
# Lock files
17+
foundry.lock

README.md

Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
# Timeboost Smart Contracts
2+
3+
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.
4+
5+
## Table of Contents
6+
7+
- [Background](#background)
8+
- [What Are These Contracts For?](#what-are-these-contracts-for)
9+
- [Handling Upgradeability](#handling-upgradeability)
10+
- [The Contracts](#the-contracts)
11+
- [Getting Started](#getting-started)
12+
- [Deployment](#deployment)
13+
- [Security](#security)
14+
- [Getting Help](#getting-help)
15+
16+
## Background
17+
Smart contracts are executable code, deployed on blockchains that
18+
can be read from / written to anyone with an internet connection.
19+
Transaction data and smart contract storage is public and can be
20+
accessed in blockchain explorers. In decentralized Timeboost,
21+
smart contracts are used to allow anyone to interact with various
22+
parts of the protocol. This readme is directed at developers who are
23+
contributing to or making use of this decentralized timeboost
24+
implementation.
25+
26+
## What Are These Contracts For?
27+
28+
Timeboost needs a way to coordinate cryptographic keys and committee members across a decentralized network. These smart contracts provide:
29+
30+
- **Key Management**: Store and manage public keys for the protocol
31+
- **Committee Coordination**: Track which nodes are part of the consensus committee
32+
- **Access Control**: Ensure only authorized parties can update critical protocol parameters
33+
- **Transparency**: All changes are recorded on-chain for public verification
34+
35+
These contracts act as the "coordination layer" that allows the Timeboost network to operate without a central authority.
36+
37+
## Handling Upgradeability
38+
39+
### The Upgrade Problem
40+
Once deployed, smart contracts can't be changed. To solve this, we use a proxy solution that functions as upgradeable contracts.
41+
42+
### The Proxy Solution
43+
We use a "proxy pattern" that works like this:
44+
45+
1. **Users always interact with the proxy** - This address never changes
46+
2. **The proxy points to an implementation** - This can be updated
47+
3. **When you upgrade** - Just point the proxy to a new implementation
48+
4. **All data stays safe** - Storage is preserved across upgrades
49+
50+
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.
51+
52+
### Our Architecture
53+
```
54+
User → Proxy Contract → Implementation Contract
55+
56+
Storage (persistent)
57+
```
58+
59+
## The Contracts
60+
61+
### KeyManager - The Main Contract
62+
63+
**What it stores:**
64+
- **Encryption keys** - The cryptographic keys used by the protocol
65+
- **Committee members** - Who's currently in the consensus committee
66+
- **Manager address** - Who can update the contract
67+
68+
**What it does:**
69+
- **Sets committees** - Updates which nodes are part of the network
70+
- **Manages keys** - Stores the threshold encryption key
71+
- **Controls access** - Only the manager can make changes
72+
- **Logs everything** - All changes are recorded as events
73+
74+
**Key functions:**
75+
- `setNextCommittee()` - Add a new committee with future members
76+
- `currentCommitteeId()` - Find which committee is active right now
77+
- `getCommitteeById()` - Get details about a specific committee
78+
- `setThresholdEncryptionKey()` - Set the encryption key for the protocol
79+
80+
### ERC1967Proxy - The Upgrade Mechanism
81+
This is the "shell" that makes upgrades possible:
82+
83+
- **Never changes** - Users always interact with this address
84+
- **Delegates calls** - Forwards requests to the current implementation
85+
- **Preserves data** - All storage survives upgrades
86+
- **SecOps Precautions** - it's important to call the initialize methods during deploys and upgrades so that those transactions aren't front-run
87+
88+
## Getting Started
89+
90+
### Prerequisites
91+
92+
Before you begin, make sure you have:
93+
94+
- **Foundry** - For building, testing, and deploying contracts
95+
```bash
96+
# Install Foundry
97+
curl -L https://foundry.paradigm.xyz | bash
98+
foundryup
99+
```
100+
101+
### Building the Contracts
102+
```bash
103+
# Build all contracts
104+
just build-contracts
105+
106+
# Or use forge directly
107+
forge build
108+
```
109+
110+
### Testing
111+
```bash
112+
# Run all tests
113+
just test-contracts
114+
115+
# Run with detailed output
116+
forge test -vvv
117+
118+
# Run specific test
119+
forge test --match-test test_setThresholdEncryptionKey
120+
```
121+
122+
### Integration Testing
123+
For testing contract interactions from Rust code, see the [timeboost-contract README](https://github.com/EspressoSystems/timeboost/tree/main/timeboost-contract/README.md) in the Rust repository.
124+
125+
## Deployment
126+
127+
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).
128+
129+
### Quick Start (Local Testing)
130+
131+
1. **Set up your environment:**
132+
```bash
133+
cp env.example .env
134+
# Edit .env with your values
135+
```
136+
137+
2. **Start a local blockchain (not needed if using remote rpc):**
138+
```bash
139+
anvil
140+
```
141+
142+
3. **Deploy the contracts:**
143+
```bash
144+
./script/deploy.sh
145+
```
146+
147+
That's it! The script will deploy your contracts and show you the addresses.
148+
149+
### Production Deployment
150+
151+
For production deployments, ensure you have:
152+
153+
1. **A secure wallet** with sufficient ETH for gas fees
154+
2. **A valid manager address** (preferably a multisig wallet)
155+
3. **The correct RPC URL** for your target network
156+
4. **Tested thoroughly** on testnets first
157+
158+
### What You Need
159+
160+
- **Manager Address**: Who will manage the contract (usually a multisig wallet)
161+
- **RPC URL**: Where to deploy (localhost for testing, or a real network)
162+
- **Mnemonic**: Your wallet phrase (optional for local testing)
163+
164+
### How It Works
165+
166+
The script deploys two contracts:
167+
1. **KeyManager** - The actual contract with your business logic
168+
2. **Proxy** - Points to the KeyManager, so you can upgrade it later
169+
170+
The proxy gets initialized with your manager address, and that's it!
171+
172+
### Configuration
173+
174+
All settings go in your `.env` file. Copy `env.example` to `.env` and customize:
175+
176+
```bash
177+
# Required: Who manages the contract (use a multisig for production)
178+
MANAGER_ADDRESS=0x1234567890123456789012345678901234567890
179+
180+
# Optional: Where to deploy (defaults to localhost)
181+
RPC_URL=http://localhost:8545
182+
183+
# Optional: Your wallet phrase (defaults to Anvil's test account)
184+
MNEMONIC="your twelve word mnemonic phrase here"
185+
ACCOUNT_INDEX=0
186+
```
187+
188+
**Example configurations:**
189+
190+
- **Local testing**: Use Anvil's default account (no mnemonic needed)
191+
- **Testnet**: Use a test wallet with testnet ETH
192+
- **Mainnet**: Use a secure multisig wallet
193+
194+
### Deployment Process
195+
196+
The deployment script:
197+
1. **Deploys** the KeyManager implementation contract
198+
2. **Creates** an ERC1967 proxy pointing to the implementation
199+
3. **Initializes** the proxy with your manager address
200+
4. **Verifies** the deployment was successful
201+
5. **Returns** both proxy and implementation addresses
202+
203+
### Troubleshooting
204+
205+
**"Manager address not set"**
206+
- Make sure you have `MANAGER_ADDRESS=0x...` in your `.env` file
207+
208+
**"Deployment failed"**
209+
- Check your RPC URL works
210+
- Make sure your wallet has enough ETH for gas
211+
- Verify your mnemonic is correct
212+
213+
**Need help?**
214+
- Make sure Foundry is installed: `forge --version`
215+
- Check your `.env` file has all required values
216+
217+
## Security
218+
219+
### Current Status
220+
- **ERC1967Proxy** - Audited by OpenZeppelin, widely used
221+
- **KeyManager** - Not yet audited (audit planned)
222+
223+
### Security Considerations
224+
- **Manager privileges** - The manager can update committees and keys
225+
- **Upgrade authority** - Only the contract owner can upgrade
226+
- **Committee validation** - Contracts validate committee transitions
227+
- **Event logging** - All changes are logged onchain for transparency
228+
229+
### Best Practices
230+
- **Use multisig wallets** - Don't use single-key wallets for manager/owner
231+
- **Test thoroughly** - Always test on testnets first
232+
- **Monitor events** - Watch for unexpected contract changes
233+
- **Keep keys secure** - Store private keys and mnemonics safely
234+
235+
## Quick Reference
236+
237+
### Common Commands
238+
```bash
239+
# Build contracts
240+
forge build
241+
242+
# Run tests
243+
forge test
244+
245+
# Deploy locally
246+
anvil
247+
./script/deploy.sh
248+
249+
# Run specific test
250+
forge test --match-test test_setThresholdEncryptionKey
251+
```
252+
253+
### Important Addresses
254+
- **Proxy Contract**: The address users interact with (never changes)
255+
- **Implementation Contract**: The actual contract logic (can be upgraded)
256+
- **Manager**: The address that can update committees and keys
257+
258+
## Getting Help
259+
- Review the [timeboost-contract README](https://github.com/EspressoSystems/timeboost/tree/main/timeboost-contract/README.md) in the Rust repo for integration questions
260+
- Check the troubleshooting section above for deployment issues

env.example

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Timeboost Contract Deployment Configuration
2+
# Copy this file to .env and fill in your actual values
3+
# DO NOT commit .env files to version control
4+
5+
# Manager address for the KeyManager contract
6+
# This should be the address that will manage the KeyManager contract
7+
# Typically a multisig wallet or governance contract address
8+
# Example: MANAGER_ADDRESS=0x1234567890123456789012345678901234567890
9+
MANAGER_ADDRESS=
10+
11+
# RPC endpoint for the target network
12+
# For local development: http://localhost:8545 (Anvil)
13+
# For testnets: https://eth-sepolia.g.alchemy.com/v2/YOUR_KEY
14+
# For mainnet: https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY
15+
RPC_URL=
16+
17+
# Deployment Account Mnemonic and account index
18+
# Your 12 or 24 word BIP39 mnemonic phrase for the deployment account
19+
# This account must have enough ETH to pay for gas fees
20+
# Example: MNEMONIC="abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
21+
MNEMONIC=
22+
23+
# Which account to use from the mnemonic (0 = first account, 1 = second, etc.)
24+
# Example: ACCOUNT_INDEX=0
25+
ACCOUNT_INDEX=
26+
27+
# Etherscan API key for contract verification (optional)
28+
# Get one at: https://etherscan.io/apis
29+
# This is used to verify your contracts on Etherscan after deployment
30+
# Example: ETHERSCAN_API_KEY=YourApiKeyToken
31+
ETHERSCAN_API_KEY=

script/DeployKeyManager.s.sol

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity ^0.8.13;
3+
4+
import {Script, console} from "forge-std/Script.sol";
5+
import {KeyManager} from "../src/KeyManager.sol";
6+
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
7+
8+
/// @title DeployKeyManager
9+
/// @notice Simple script to deploy KeyManager implementation and proxy, then initialize
10+
contract DeployKeyManager is Script {
11+
function run() external returns (address, address) {
12+
// Get the manager address from environment variable or use sender as fallback
13+
address manager = vm.envOr("MANAGER_ADDRESS", msg.sender);
14+
15+
vm.startBroadcast();
16+
17+
// Deploy the KeyManager implementation
18+
KeyManager implementation = new KeyManager();
19+
console.log("KeyManager implementation deployed at:", address(implementation));
20+
21+
// Prepare initialization data
22+
bytes memory initData = abi.encodeWithSelector(KeyManager.initialize.selector, manager);
23+
24+
// Deploy the proxy and initialize it
25+
ERC1967Proxy proxy = new ERC1967Proxy(address(implementation), initData);
26+
console.log("ERC1967Proxy deployed at:", address(proxy));
27+
28+
// Verify initialization
29+
KeyManager proxyContract = KeyManager(address(proxy));
30+
require(proxyContract.manager() == manager, "Manager not set correctly");
31+
32+
console.log("Deployment successful!");
33+
console.log("Implementation:", address(implementation));
34+
console.log("Proxy:", address(proxy));
35+
console.log("Manager:", manager);
36+
37+
vm.stopBroadcast();
38+
39+
return (address(proxy), address(implementation));
40+
}
41+
}

0 commit comments

Comments
 (0)