-
Notifications
You must be signed in to change notification settings - Fork 14
Deployment Scripts via Forge & Contract docs #482
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 12 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
22e1481
wip started contracts readmes and added more documentation to timeboo…
alysiahuggins e354ee3
deployment of contracts in timeboost-contracts for testing and contra…
alysiahuggins e34d636
remove feature in cargo toml not needed at this time
alysiahuggins 9aa9952
merge from main
alysiahuggins 6e13297
refactor due to redundancies after merging in changes from main
alysiahuggins 1285767
update timeboost proto submodule and added a just command to update s…
alysiahuggins 8588c23
clean up docs
alysiahuggins 26753f4
Update contracts/README.md
alysiahuggins c461755
Update contracts/README.md
alysiahuggins e2ac79b
responding to review feedback - improving script defaults and readme …
alysiahuggins 7331bb4
remove stray char
alysiahuggins f239243
remove from the timeboost-contract readme, anything that is hard main…
alysiahuggins e80f762
remove dependency no longer needed
alysiahuggins 78d5b90
merge from main
alysiahuggins a9357e7
Remove contracts directory before adding as submodule
alysiahuggins bfdaf1e
add timeboost-contracts as a submodule
alysiahuggins 04736ac
Merge branch 'main' into contract-docs
alysiahuggins 778c1ab
remove new line at the end ofthe file
alysiahuggins 1038778
update links in readme
alysiahuggins File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
# Timeboost Smart Contracts | ||
|
||
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 | ||
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 | ||
of the protocol. This readme is directed at developers who are | ||
contributing to or making use of this decentralized timeboost | ||
implementation. | ||
|
||
## What Are These Contracts For? | ||
|
||
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. | ||
|
||
## Handling Upgradeability | ||
|
||
### The Upgrade Problem | ||
Once deployed, smart contracts can't be changed. To solve this, we use a proxy solution that performs functionally as upgradeable contracts. | ||
|
||
### The Proxy Solution | ||
We use a "proxy pattern" that works like this: | ||
|
||
1. **Users always interact with the proxy** - This address never changes | ||
2. **The proxy points to an implementation** - This can be updated | ||
3. **When you upgrade** - Just point the proxy to a new implementation | ||
4. **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. | ||
|
||
### Our Architecture | ||
``` | ||
User → Proxy Contract → Implementation Contract | ||
↓ | ||
Storage (persistent) | ||
``` | ||
|
||
## The Contracts | ||
|
||
### KeyManager - The Main Contract | ||
|
||
**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 members | ||
- `currentCommitteeId()` - Find which committee is active right now | ||
- `getCommitteeById()` - Get details about a specific committee | ||
- `setThresholdEncryptionKey()` - Set the encryption key for the protocol | ||
|
||
### ERC1967Proxy - The Upgrade Mechanism | ||
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 | ||
|
||
## Getting Started | ||
|
||
### Prerequisites | ||
- **Foundry** - For building and testing contracts | ||
|
||
### Building the Contracts | ||
```bash | ||
# Build all contracts | ||
just build-contracts | ||
|
||
# Or use forge directly | ||
forge build | ||
``` | ||
|
||
### Testing | ||
```bash | ||
# Run all tests | ||
just test-contracts | ||
|
||
# Run with detailed output | ||
forge test -vvv | ||
|
||
# Run specific test | ||
forge test --match-test test_setThresholdEncryptionKey | ||
``` | ||
|
||
### Integration Testing | ||
For testing contract interactions from Rust code, see the [timeboost-contract README](../timeboost-contract/README.md). | ||
|
||
## Deployment | ||
You can deploy 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). | ||
|
||
### Quick Start (Local Testing) | ||
```bash | ||
# 1. Start a local blockchain | ||
anvil | ||
|
||
# 2. Deploy the contracts | ||
cp env.example .env | ||
# Edit .env with your values | ||
./script/deploy.sh | ||
``` | ||
|
||
**📋 For detailed deployment instructions, see the [deployment script README](script/README.md)** | ||
|
||
## Security | ||
|
||
### Current Status | ||
- **ERC1967Proxy** - Audited by OpenZeppelin, widely used | ||
- **KeyManager** - Not yet audited (audit planned) | ||
|
||
### Security Considerations | ||
- **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 | ||
|
||
### Best Practices | ||
- **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 | ||
|
||
## Getting Help | ||
- Check the [deployment script README](script/README.md) for deployment issues | ||
- Review the [timeboost-contract README](../timeboost-contract/README.md) for integration questions |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Timeboost Contract Deployment Configuration | ||
# Copy this file to .env and fill in your actual values | ||
# DO NOT commit .env files to version control | ||
|
||
# Manager address for the KeyManager contract | ||
# This should be the address that will manage the KeyManager contract | ||
# Typically a multisig wallet or governance contract address | ||
# Example: MANAGER_ADDRESS=0x1234567890123456789012345678901234567890 | ||
MANAGER_ADDRESS= | ||
|
||
# RPC endpoint for the target network | ||
# For local development: http://localhost:8545 (Anvil) | ||
# For testnets: https://eth-sepolia.g.alchemy.com/v2/YOUR_KEY | ||
# For mainnet: https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY | ||
RPC_URL= | ||
|
||
# Deployment Account Mnemonic and account index | ||
# Your 12 or 24 word BIP39 mnemonic phrase for the deployment account | ||
# This account must have enough ETH to pay for gas fees | ||
# Example: MNEMONIC="abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" | ||
MNEMONIC= | ||
|
||
# Which account to use from the mnemonic (0 = first account, 1 = second, etc.) | ||
# Example: ACCOUNT_INDEX=0 | ||
ACCOUNT_INDEX= | ||
|
||
# Etherscan API key for contract verification (optional) | ||
# Get one at: https://etherscan.io/apis | ||
# This is used to verify your contracts on Etherscan after deployment | ||
# Example: ETHERSCAN_API_KEY=YourApiKeyToken | ||
ETHERSCAN_API_KEY= |
Submodule openzeppelin-contracts-upgradeable
updated
223 files
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.13; | ||
|
||
import {Script, console} from "forge-std/Script.sol"; | ||
import {KeyManager} from "../src/KeyManager.sol"; | ||
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; | ||
|
||
/// @title DeployKeyManager | ||
/// @notice Simple script to deploy KeyManager implementation and proxy, then initialize | ||
contract DeployKeyManager is Script { | ||
function run() external returns (address, address) { | ||
// Get the manager address from environment variable or use sender as fallback | ||
address manager = vm.envOr("MANAGER_ADDRESS", msg.sender); | ||
|
||
vm.startBroadcast(); | ||
|
||
// Deploy the KeyManager implementation | ||
KeyManager implementation = new KeyManager(); | ||
console.log("KeyManager implementation deployed at:", address(implementation)); | ||
|
||
// Prepare initialization data | ||
bytes memory initData = abi.encodeWithSelector(KeyManager.initialize.selector, manager); | ||
|
||
// Deploy the proxy and initialize it | ||
ERC1967Proxy proxy = new ERC1967Proxy(address(implementation), initData); | ||
console.log("ERC1967Proxy deployed at:", address(proxy)); | ||
|
||
// Verify initialization | ||
KeyManager proxyContract = KeyManager(address(proxy)); | ||
require(proxyContract.manager() == manager, "Manager not set correctly"); | ||
|
||
console.log("Deployment successful!"); | ||
console.log("Implementation:", address(implementation)); | ||
console.log("Proxy:", address(proxy)); | ||
console.log("Manager:", manager); | ||
|
||
vm.stopBroadcast(); | ||
|
||
return (address(proxy), address(implementation)); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
# Deploy KeyManager Contract | ||
|
||
This script deploys the KeyManager contract to any Ethereum network. | ||
|
||
## Quick Start | ||
|
||
1. **Set up your environment:** | ||
```bash | ||
cp env.example .env | ||
# Edit .env with your values | ||
``` | ||
|
||
2. **Start a local blockchain (if testing locally):** | ||
```bash | ||
anvil | ||
``` | ||
|
||
3. **Deploy:** | ||
```bash | ||
./script/deploy.sh | ||
``` | ||
|
||
That's it! The script will deploy your contract and show you the addresses. | ||
|
||
## What You Need | ||
|
||
- **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) | ||
|
||
## How It Works | ||
|
||
The script deploys two contracts: | ||
1. **KeyManager** - The actual contract with your business logic | ||
2. **Proxy** - Points to the KeyManager, so you can upgrade it later | ||
|
||
The proxy gets initialized with your manager address, and that's it! | ||
|
||
## Configuration | ||
|
||
All settings go in your `.env` file: | ||
|
||
```bash | ||
# Required: Who manages the contract | ||
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 | ||
``` | ||
|
||
## How it works | ||
The deployment script: | ||
1. **Deploys** the KeyManager implementation contract | ||
2. **Creates** an ERC1967 proxy pointing to the implementation | ||
3. **Initializes** the proxy with your manager address | ||
4. **Verifies** the deployment was successful | ||
5. **Returns** both proxy and implementation addresses | ||
|
||
|
||
## Troubleshooting | ||
|
||
**"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 |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.