Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
59 changes: 3 additions & 56 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,58 +1,5 @@
# Universal Registry Contract
All Interstate changes are in the README.md and the `/slasher` folder which has been renamed from `/example` all other files are the same as source: https://github.com/eth-fabric/urc/blob/main/src/Registry.sol

**These standards are currently under review / feedback and are not audited.**
Notes for auditors: We would additionally prefer to have MIN_COLLATERAL Field here https://github.com/interstate-labs/urc/blob/main/src/Registry.sol#L21 set to 0 to allow operators to default to restaking only if they wish.

The URC is a universal contract for…
- anyone to **register** for proposer commitments
- anyone to **slash** proposers that break commitments

it should…
- be governance-free and immutable
- be simple and maximally expressive
- use ETH as collateral
- not rely on any external contracts
- minimize switching costs
- be gas-efficient
- be open-source


### Usage
The URC is written using Foundry. To install:
```
curl -L https://foundry.paradigm.xyz | bash
```

To run the tests:
```
forge build
forge test
```

### Design
See the [docs](./docs/overview.md) for more information.

### Examples
See the [examples](./example/README.md) for reference implementations of Slasher contracts.

### References
- Justin Drake’s proposed requirements
> 1. The contract is super simple and short (ideally ~100 lines).
> 2. Only ETH for deposits.
> 3. All the constants are parametrised (so as to minimise bike shedding for now).
> 4. Slashing (and delegation) logic is encapsulated by pieces of signed EVM bytecode shared offchain between relevant parties (eg users and gateways). This is for maximum credible neutrality, forward compatibility, simplicity, and gas efficiency.
> 5. No dependence on any external code (especially restaking platforms).
> 6. Zero governance, fully immutable.
> 7. Open source from day 1, Apache 2.0 + MIT dual licensing.
> 8. Nice to have: support for underwriters
> 9. Nice to have: bootstrapping phase with freeze instead of burn
> 10. Code is maintained in a neutral Github org.
- [mteam’s writeup on the registry](https://hackmd.io/@mteam/unfiedpreconfregistry)
- [UniFi’s registry implementation](https://github.com/PufferFinance/UniFi/blob/main/l1-contracts/src/UniFiAVSManager.sol)
- [Nethermind/Taiko’s registry implementation](https://github.com/NethermindEth/taiko-Preconf-AVS/)
- [Jason's URC implementation from Sequencing Week](https://github.com/PufferFinance/preconfs)
- [Paradigm's solidity implementation of BLS12-381 using Pectra BLS precompiles](https://github.com/paradigmxyz/forge-alphanet/blob/main/src/sign/BLS.sol)
- [Jason's Sequencing week presentation](https://docs.google.com/presentation/d/1-iuKIMwV9lxw4BBdhHL3_hWDysTWOWS-lWPpCmDvl6g/edit#slide=id.g3131bf307dc_0_67)
- [Jason's Sequencing Day presentation](https://docs.google.com/presentation/d/1aR1iY4bcRc3RApAt2xx1gV7DEqcEQZZd0rgMo3ozXC0/edit#slide=id.p)

### License
MIT + Apache-2.0
These contracts allow a validator to register collateral and enable proposer commitments, a subset of Interstate's functionality. Native Ether or a restaking protocol can be used as collateral. We support Karak, Eigenlayer, and Symbiotic
29 changes: 29 additions & 0 deletions find_missing_imports.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/bin/bash

# Find Time.sol actual location
TIME_LOC=$(find lib -name Time.sol)
echo "Time.sol is located at: $TIME_LOC"

# Find Checkpoints.sol actual location
CHECKPOINTS_LOC=$(find lib -name Checkpoints.sol)
echo "Checkpoints.sol is located at: $CHECKPOINTS_LOC"

# Find EnumerableMap.sol actual location
ENUMERABLE_MAP_LOC=$(find lib -name EnumerableMap.sol)
echo "EnumerableMap.sol is located at: $ENUMERABLE_MAP_LOC"

# Find EnumerableSet.sol actual location
ENUMERABLE_SET_LOC=$(find lib -name EnumerableSet.sol)
echo "EnumerableSet.sol is located at: $ENUMERABLE_SET_LOC"

# Find IERC20.sol actual location
IERC20_LOC=$(find lib -name IERC20.sol)
echo "IERC20.sol is located at: $IERC20_LOC"

# Find UUPSUpgradeable.sol actual location
UUPS_LOC=$(find lib -name UUPSUpgradeable.sol)
echo "UUPSUpgradeable.sol is located at: $UUPS_LOC"

# Find OwnableUpgradeable.sol actual location
OWNABLE_LOC=$(find lib -name OwnableUpgradeable.sol)
echo "OwnableUpgradeable.sol is located at: $OWNABLE_LOC"
13 changes: 13 additions & 0 deletions fix_all_imports.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

# Find all Solidity files and update OpenZeppelin imports
find slashing -name "*.sol" -type f -exec sed -i '' 's|@openzeppelin/contracts/|openzeppelin-contracts/contracts/|g' {} \;
find slashing -name "*.sol" -type f -exec sed -i '' 's|@openzeppelin/contracts-upgradeable/|openzeppelin-contracts-upgradeable/contracts/|g' {} \;

find src -name "*.sol" -type f -exec sed -i '' 's|@openzeppelin/contracts/|openzeppelin-contracts/contracts/|g' {} \;
find src -name "*.sol" -type f -exec sed -i '' 's|@openzeppelin/contracts-upgradeable/|openzeppelin-contracts-upgradeable/contracts/|g' {} \;

find test -name "*.sol" -type f -exec sed -i '' 's|@openzeppelin/contracts/|openzeppelin-contracts/contracts/|g' {} \;
find test -name "*.sol" -type f -exec sed -i '' 's|@openzeppelin/contracts-upgradeable/|openzeppelin-contracts-upgradeable/contracts/|g' {} \;

echo "Updated import paths in all Solidity files in the project"
13 changes: 13 additions & 0 deletions fix_eigenlayer_helper.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

# Fix imports in EigenlayerRestakingHelper.sol
HELPER_FILE=slashing/Restaking/EigenlayerRestaking/EigenlayerRestakingHelper.sol

# Create a backup
cp $HELPER_FILE ${HELPER_FILE}.bak

# Update OpenZeppelin imports to use direct paths
sed -i '' 's|import {Time} from "openzeppelin-contracts/contracts/utils/types/Time.sol"|import {Time} from "@karak/node_modules/@openzeppelin/contracts/utils/types/Time.sol"|g' $HELPER_FILE
sed -i '' 's|import {OwnableUpgradeable} from "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol"|import {OwnableUpgradeable} from "@karak/node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"|g' $HELPER_FILE

echo "Fixed imports in EigenlayerRestakingHelper.sol"
11 changes: 11 additions & 0 deletions fix_eigenlayer_imports.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash

# Fix imports in EigenLayer contracts
find lib/eigenlayer-contracts -name "*.sol" -type f -exec sed -i '' 's|import "@openzeppelin/contracts/|import "lib/openzeppelin-contracts/contracts/|g' {} \;
find lib/eigenlayer-middleware -name "*.sol" -type f -exec sed -i '' 's|import "@openzeppelin/contracts/|import "lib/openzeppelin-contracts/contracts/|g' {} \;

# Fix imports for upgradeable contracts
find lib/eigenlayer-contracts -name "*.sol" -type f -exec sed -i '' 's|import "@openzeppelin/contracts-upgradeable/|import "lib/openzeppelin-contracts-upgradeable/contracts/|g' {} \;
find lib/eigenlayer-middleware -name "*.sol" -type f -exec sed -i '' 's|import "@openzeppelin/contracts-upgradeable/|import "lib/openzeppelin-contracts-upgradeable/contracts/|g' {} \;

echo "Fixed imports in EigenLayer contracts"
197 changes: 197 additions & 0 deletions fix_imports_with_actual_paths.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
#!/bin/bash

# Fix MapWithTimeData.sol
echo "Fixing MapWithTimeData.sol..."
cat > slashing/Restaking/library/MapWithTimeData.sol << 'EOF'
// SPDX-License-Identifier: MIT
pragma solidity 0.8.29;

// Credits: Symbiotic contributors.
// Ref: https://github.com/symbioticfi/cosmos-sdk/blob/c25b6d5f320eb8ea4189584fa04d28c47362c2a7/middleware/src/libraries/MapWithTimeData.sol

import {Checkpoints} from "lib/openzeppelin-contracts/contracts/utils/Checkpoints.sol";
import {Time} from "lib/karak/node_modules/@openzeppelin/contracts/utils/types/Time.sol";
import {EnumerableMap} from "lib/openzeppelin-contracts/contracts/utils/structs/EnumerableMap.sol";

library MapWithTimeData {
using EnumerableMap for EnumerableMap.AddressToUintMap;

error AlreadyAdded();
error NotEnabled();
error AlreadyEnabled();

uint256 private constant ENABLED_TIME_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFF;
uint256 private constant DISABLED_TIME_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFF << 48;

function add(EnumerableMap.AddressToUintMap storage self, address addr) internal {
if (!self.set(addr, uint256(0))) {
revert AlreadyAdded();
}
}

function disable(EnumerableMap.AddressToUintMap storage self, address addr) internal {
uint256 value = self.get(addr);

if (uint48(value) == 0 || uint48(value >> 48) != 0) {
revert NotEnabled();
}

value |= uint256(Time.timestamp()) << 48;
self.set(addr, value);
}

function enable(EnumerableMap.AddressToUintMap storage self, address addr) internal {
uint256 value = self.get(addr);

if (uint48(value) != 0 && uint48(value >> 48) == 0) {
revert AlreadyEnabled();
}

value = uint256(Time.timestamp());
self.set(addr, value);
}

function atWithTimes(
EnumerableMap.AddressToUintMap storage self,
uint256 idx
) internal view returns (address key, uint48 enabledTime, uint48 disabledTime) {
uint256 value;
(key, value) = self.at(idx);
enabledTime = uint48(value);
disabledTime = uint48(value >> 48);
}

function getTimes(
EnumerableMap.AddressToUintMap storage self,
address addr
) internal view returns (uint48 enabledTime, uint48 disabledTime) {
uint256 value = self.get(addr);
enabledTime = uint48(value);
disabledTime = uint48(value >> 48);
}
}
EOF

# Fix EigenlayerRestakingHelper.sol
echo "Fixing EigenlayerRestakingHelper.sol..."
cat > slashing/Restaking/EigenlayerRestaking/EigenlayerRestakingHelper.sol << 'EOF'
// SPDX-License-Identifier: MIT
pragma solidity 0.8.29;

// import {IValidatorRegistrySystem} from "../interfaces/IRegistry.sol";
import {IParameters} from "../IParameters.sol";
import {Time} from "lib/karak/node_modules/@openzeppelin/contracts/utils/types/Time.sol";
import {OwnableUpgradeable} from "lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol";

// Import our simplified interfaces
// Using EigenLayer interface directly
// Using EigenLayer interface directly

// Import interfaces using direct paths
import {IAVSDirectory} from "../../../lib/eigenlayer-contracts/src/contracts/interfaces/IAVSDirectory.sol";
import {IDelegationManager} from "../../../lib/eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol";
import {DelegationManagerStorage} from "../../../lib/eigenlayer-contracts/src/contracts/core/DelegationManagerStorage.sol";
import {StrategyManagerStorage} from "../../../lib/eigenlayer-contracts/src/contracts/core/StrategyManagerStorage.sol";
import {IStrategy} from "../../../lib/eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol";
import {ISignatureUtils} from "../../../lib/eigenlayer-contracts/src/contracts/interfaces/ISignatureUtils.sol";

contract RestakingHelper is OwnableUpgradeable {
uint48 public START_TIMESTAMP;

IParameters public parameters;
// IValidatorRegistrySystem public registry;
DelegationManagerStorage public DELEGATION_MANAGER;
IAVSDirectory public AVS_DIRECTORY;

StrategyManagerStorage public STRATEGY_MANAGER;
bytes32 public PROTOCOL_IDENTIFIER;

error NotRegistered();
error OperationForbidden();

function initialize(
address _owner,
address _parameters,
address _eigenlayerAVSDirectory,
address _eigenlayerDelegationManager,
address _eigenlayerStrategyManager
) public initializer {
__Ownable_init(_owner);
parameters = IParameters(_parameters);
// registry = IValidatorRegistrySystem(_registry);
START_TIMESTAMP = Time.timestamp();

AVS_DIRECTORY = IAVSDirectory(_eigenlayerAVSDirectory);
DELEGATION_MANAGER = DelegationManagerStorage(
_eigenlayerDelegationManager
);
STRATEGY_MANAGER = StrategyManagerStorage(_eigenlayerStrategyManager);
PROTOCOL_IDENTIFIER = keccak256("CONSENSUS_PROTOCOL");
}

function _getStartTime() public view returns (uint48) {
return START_TIMESTAMP;
}

function strategy_manager(address strategy) public view returns (bool) {
// Call strategyIsWhitelistedForDeposit from STRATEGY_MANAGER and return the result
return
STRATEGY_MANAGER.strategyIsWhitelistedForDeposit(
IStrategy(strategy)
);
}


function _checkDelegationIsOperator(
address Node
) public view returns (bool) {
return DELEGATION_MANAGER.isOperator(Node);
}


function _operatorShares(
address operator,
IStrategy strategyImpl
) public view returns (uint256) {
return DELEGATION_MANAGER.operatorShares(operator, strategyImpl);
}

function getPeriodAtTime(uint48 periodIndex) public view returns (uint48) {
return
(periodIndex - START_TIMESTAMP) / parameters.VALIDATOR_EPOCH_TIME();
}

function getPeriodStartTime(
uint48 epoch
) public view returns (uint48 periodIndex) {
return START_TIMESTAMP + epoch * parameters.VALIDATOR_EPOCH_TIME();
}



function _avsURI(string calldata metadataURI) public {
AVS_DIRECTORY.updateAVSMetadataURI(metadataURI);
}

function _avsDirector() public view returns (IAVSDirectory)
{
return AVS_DIRECTORY;
}

function _registerOperatorToAvs(
address operator,
ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature
) public {
AVS_DIRECTORY.registerOperatorToAVS(operator, operatorSignature);
}

function deregisterOperatorFromAVS(address operator) public {
if (msg.sender != operator) {
revert OperationForbidden();
}
AVS_DIRECTORY.deregisterOperatorFromAVS(operator);
}
}
EOF

echo "Done fixing imports in all files"
7 changes: 7 additions & 0 deletions fix_interface_conflicts.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

# Update EigenlayerRestakingHelper.sol to use EigenLayer's interfaces directly instead of custom ones
sed -i '' 's|import {ISignatureUtils} from "../../../src/interfaces/ISignatureUtils.sol";|// Using EigenLayer interface directly|g' slashing/Restaking/EigenlayerRestaking/EigenlayerRestakingHelper.sol
sed -i '' 's|import {IStrategy} from "../../../src/interfaces/IStrategy.sol";|// Using EigenLayer interface directly|g' slashing/Restaking/EigenlayerRestaking/EigenlayerRestakingHelper.sol

echo "Fixed interface conflicts in EigenlayerRestakingHelper.sol"
17 changes: 17 additions & 0 deletions fix_karak_imports.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash

# Fix imports in Karak contracts
find lib/karak -name "*.sol" -type f -exec sed -i '' 's|import {Create2} from "@openzeppelin/contracts/|import {Create2} from "lib/openzeppelin-contracts/contracts/|g' {} \;
find lib/karak -name "*.sol" -type f -exec sed -i '' 's|import "@openzeppelin/contracts/interfaces/|import "lib/openzeppelin-contracts/contracts/interfaces/|g' {} \;
find lib/karak -name "*.sol" -type f -exec sed -i '' 's|import {EnumerableSet} from "@openzeppelin/contracts/|import {EnumerableSet} from "lib/openzeppelin-contracts/contracts/|g' {} \;
find lib/karak -name "*.sol" -type f -exec sed -i '' 's|import {Math} from "@openzeppelin/contracts/|import {Math} from "lib/openzeppelin-contracts/contracts/|g' {} \;
find lib/karak -name "*.sol" -type f -exec sed -i '' 's|import "@openzeppelin/contracts/utils/structs/|import "lib/openzeppelin-contracts/contracts/utils/structs/|g' {} \;
find lib/karak -name "*.sol" -type f -exec sed -i '' 's|import {IERC20} from "@openzeppelin/contracts/|import {IERC20} from "lib/openzeppelin-contracts/contracts/|g' {} \;

# Fix imports in KarakRestaking.sol
echo "Fixing KarakRestaking.sol..."
find slashing/Restaking/KarakRestaking -name "*.sol" -type f -exec sed -i '' 's|import "@openzeppelin/contracts/|import "lib/openzeppelin-contracts/contracts/|g' {} \;
find slashing/Restaking/KarakRestaking -name "*.sol" -type f -exec sed -i '' 's|import {Create2} from "@openzeppelin/contracts/|import {Create2} from "lib/openzeppelin-contracts/contracts/|g' {} \;
find slashing/Restaking/KarakRestaking -name "*.sol" -type f -exec sed -i '' 's|import "@openzeppelin/contracts-upgradeable/|import "lib/openzeppelin-contracts-upgradeable/contracts/|g' {} \;

echo "Fixed imports in Karak contracts"
14 changes: 14 additions & 0 deletions fix_library_imports.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash

# Fix imports in MapWithTimeData.sol
MAP_FILE=slashing/Restaking/library/MapWithTimeData.sol

# Create a backup
cp $MAP_FILE ${MAP_FILE}.bak

# Update imports
sed -i '' 's|import {Checkpoints} from "openzeppelin-contracts/contracts/utils/structs/Checkpoints.sol"|import {Checkpoints} from "@karak/node_modules/@openzeppelin/contracts/utils/structs/Checkpoints.sol"|g' $MAP_FILE
sed -i '' 's|import {Time} from "openzeppelin-contracts/contracts/utils/types/Time.sol"|import {Time} from "@karak/node_modules/@openzeppelin/contracts/utils/types/Time.sol"|g' $MAP_FILE
sed -i '' 's|import {EnumerableMap} from "openzeppelin-contracts/contracts/utils/structs/EnumerableMap.sol"|import {EnumerableMap} from "@karak/node_modules/@openzeppelin/contracts/utils/structs/EnumerableMap.sol"|g' $MAP_FILE

echo "Fixed imports in MapWithTimeData.sol"
12 changes: 12 additions & 0 deletions fix_ownable_imports.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/bash

# Fix EigenlayerRestakingHelper.sol
echo "Fixing EigenlayerRestakingHelper.sol..."
sed -i '' 's|import {OwnableUpgradeable} from "lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol"|import {OwnableUpgradeable} from "lib/karak/node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"|g' slashing/Restaking/EigenlayerRestaking/EigenlayerRestakingHelper.sol

# Fix EigenlayerRestaking.sol
echo "Fixing EigenlayerRestaking.sol..."
sed -i '' 's|import {UUPSUpgradeable} from "openzeppelin-contracts/contracts/proxy/utils/UUPSUpgradeable.sol"|import {UUPSUpgradeable} from "lib/openzeppelin-contracts/contracts/proxy/utils/UUPSUpgradeable.sol"|g' slashing/Restaking/EigenlayerRestaking/EigenlayerRestaking.sol
sed -i '' 's|import {OwnableUpgradeable} from|import {OwnableUpgradeable} from "lib/karak/node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol" // Modified for initialOwner support\n// import {OwnableUpgradeable} from|g' slashing/Restaking/EigenlayerRestaking/EigenlayerRestaking.sol

echo "Done fixing imports"
Loading
Loading