Skip to content
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

feat(Gear.exe): impl initial election logic #4362

Merged
merged 50 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
b9e86ff
append symbiotic-core submodule
grishasobol Oct 24, 2024
c9d30e1
append initial middleware and simple test
grishasobol Oct 25, 2024
d0ad837
registrations and get stake implementations
grishasobol Oct 29, 2024
de72ac5
append getEnabledValidatorSet and tests
grishasobol Oct 29, 2024
522cb14
refactor subnetwork
grishasobol Oct 30, 2024
520bf0b
enabled oeprators -> active operators
grishasobol Oct 30, 2024
5092b6b
pinnedAddress -> pinnedData
grishasobol Oct 30, 2024
1c1e2e2
unregisterOperator(operator)
grishasobol Oct 30, 2024
f348ef8
-
grishasobol Oct 30, 2024
1116f9d
chore
grishasobol Oct 30, 2024
b058d01
chore
grishasobol Oct 30, 2024
629906a
st
grishasobol Oct 30, 2024
4fb9e0e
block.timestamp -> vm.getBlockTimestamp()
grishasobol Oct 31, 2024
8b651e8
fix potential problem with old timstamps
grishasobol Oct 31, 2024
5bf4106
Merge branch 'master' into gsobol-symbiotic-step1
grishasobol Nov 8, 2024
ec014cb
review fixes
grishasobol Nov 8, 2024
1a1c389
add slashing with tests
grishasobol Nov 6, 2024
0abb80d
veto
grishasobol Nov 7, 2024
9242d56
test many slash requests, fix bug
grishasobol Nov 7, 2024
e7899ca
split tests, fix bug for resolver
grishasobol Nov 7, 2024
3318c18
split stake tests
grishasobol Nov 7, 2024
ed29600
append roles for slashing
grishasobol Nov 7, 2024
552eb8b
remove veto from middleware - use separate resolver
grishasobol Nov 8, 2024
861c22c
chore
grishasobol Nov 8, 2024
a4686d0
fix after rebase
grishasobol Nov 8, 2024
04a53b4
cammel case
grishasobol Nov 11, 2024
ce697ad
change arg to array in executeSlash
grishasobol Nov 11, 2024
e321116
Merge branch 'master' into gsobol-symbiotic-slasher
grishasobol Nov 12, 2024
ba70f81
Merge branch 'master' into gsobol-symbiotic-slasher
grishasobol Nov 15, 2024
966be64
refactor: router and stuff
breathx Nov 18, 2024
5f2b0d9
patch 'ethexe-common'
breathx Nov 19, 2024
fde7b1c
patch everything else
breathx Nov 19, 2024
df8646b
fix tests
breathx Nov 20, 2024
d31cec4
rename meta storage fn item
breathx Nov 20, 2024
772dde8
Merge branch 'dn-rename-router-committed-block-fields' into gsobol-sy…
grishasobol Nov 21, 2024
bd64d0f
Merge branch 'master' into gsobol-symbiotic-slasher
grishasobol Nov 26, 2024
f88abf9
fix after merge
grishasobol Nov 26, 2024
6beac59
Merge branch 'master' into gsobol-symbiotic-slasher
grishasobol Nov 26, 2024
709bd7e
review fixes
grishasobol Nov 26, 2024
9dbee2f
use event selector
grishasobol Nov 27, 2024
d3ace88
review fixes
grishasobol Dec 2, 2024
eea2c8a
impl election/ test election / update libraries
grishasobol Nov 27, 2024
9cb9b71
fix versions
grishasobol Nov 27, 2024
962d8ad
topup version solc in toml
grishasobol Nov 27, 2024
03a8e63
fix tabs
grishasobol Nov 27, 2024
55938e3
add tag for forge-std
grishasobol Nov 27, 2024
adc230f
tag -> branch in submodules
grishasobol Nov 27, 2024
a5a456a
fix grammatic
grishasobol Nov 27, 2024
a40dddd
assert -> assertTrue
grishasobol Dec 2, 2024
59bf69b
Merge branch 'master' into gsobol-symbiotic-election
grishasobol Dec 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
[submodule "ethexe/contracts/lib/forge-std"]
path = ethexe/contracts/lib/forge-std
url = https://github.com/foundry-rs/forge-std
branch = "v1"
[submodule "ethexe/contracts/lib/openzeppelin-contracts"]
StackOverflowExcept1on marked this conversation as resolved.
Show resolved Hide resolved
path = ethexe/contracts/lib/openzeppelin-contracts
url = https://github.com/OpenZeppelin/openzeppelin-contracts
branch = "release-v5.1"
[submodule "ethexe/contracts/lib/openzeppelin-foundry-upgrades"]
path = ethexe/contracts/lib/openzeppelin-foundry-upgrades
url = https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades
branch = "main"
[submodule "ethexe/contracts/lib/openzeppelin-contracts-upgradeable"]
path = ethexe/contracts/lib/openzeppelin-contracts-upgradeable
url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable
branch = "release-v5.1"
[submodule "ethexe/contracts/lib/symbiotic-core"]
path = ethexe/contracts/lib/symbiotic-core
url = https://github.com/grishasobol/symbiotic-core
4 changes: 2 additions & 2 deletions ethexe/contracts/.vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"editor.defaultFormatter": "JuanBlanco.solidity"
},
"solidity.formatter": "forge",
"solidity.compileUsingRemoteVersion": "v0.8.25"
}
"solidity.compileUsingRemoteVersion": "v0.8.28"
}
2 changes: 2 additions & 0 deletions ethexe/contracts/foundry.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[profile.default]
solc_version = "0.8.28"
src = "src"
out = "out"
libs = ["lib"]
Expand All @@ -16,6 +17,7 @@ ignored_warnings_from = [
]
# Enable new EVM codegen
via_ir = true
fs_permissions = [{access = "read-write", path = "out"}, { access = "read", path = "lib"}]

[rpc_endpoints]
sepolia = "${SEPOLIA_RPC_URL}"
Expand Down
2 changes: 1 addition & 1 deletion ethexe/contracts/lib/openzeppelin-contracts
2 changes: 1 addition & 1 deletion ethexe/contracts/lib/openzeppelin-foundry-upgrades
Submodule openzeppelin-foundry-upgrades updated 34 files
+7 −4 .gitignore
+3 −0 .soldeerignore
+21 −0 CHANGELOG.md
+37 −20 README.md
+4 −0 docs/modules/api/pages/Options.adoc
+34 −0 docs/modules/api/pages/api-foundry-upgrades.adoc
+1 −1 docs/modules/pages/foundry-defender.adoc
+33 −21 docs/modules/pages/foundry-upgrades.adoc
+17 −1 foundry.toml
+5 −3 package.json
+19 −0 scripts/test-reference-builds.sh
+36 −1 src/Options.sol
+12 −0 src/Upgrades.sol
+56 −13 src/internal/Core.sol
+5 −1 src/internal/DefenderDeploy.sol
+2 −2 src/internal/Versions.sol
+0 −0 test-profiles/build-info-v1/src/.gitkeep
+6 −0 test-profiles/build-info-v1/test/contracts/MyContract.sol
+0 −0 test-profiles/build-info-v2-bad/src/.gitkeep
+32 −0 test-profiles/build-info-v2-bad/test/Upgrades.t.sol
+7 −0 test-profiles/build-info-v2-bad/test/contracts/MyContract.sol
+0 −0 test-profiles/build-info-v2-reference-contract/src/.gitkeep
+21 −0 test-profiles/build-info-v2-reference-contract/test/Upgrades.t.sol
+7 −0 test-profiles/build-info-v2-reference-contract/test/contracts/MyContract.sol
+0 −0 test-profiles/build-info-v2/src/.gitkeep
+20 −0 test-profiles/build-info-v2/test/Upgrades.t.sol
+8 −0 test-profiles/build-info-v2/test/contracts/MyContract.sol
+103 −13 test/Upgrades.t.sol
+40 −0 test/contracts/HasOwner.sol
+22 −0 test/contracts/UpgradeInterfaceVersions.sol
+104 −0 test/internal/Core.t.sol
+17 −23 test/internal/DefenderDeploy.t.sol
+18 −0 test/internal/StringHelper.sol
+108 −36 yarn.lock
2 changes: 1 addition & 1 deletion ethexe/contracts/lib/symbiotic-core
Submodule symbiotic-core updated 197 files
101 changes: 74 additions & 27 deletions ethexe/contracts/src/Middleware.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ import {IMigratableEntity} from "symbiotic-core/src/interfaces/common/IMigratabl

import {MapWithTimeData} from "./libraries/MapWithTimeData.sol";

// TODO: document all functions and variables
// TODO: implement election logic
// TODO (asap): document all functions and variables
// TODO (asap): implement rewards distribution
// TODO (asap): add validators commission
// TODO: implement forced operators removal
// TODO: implement forced vaults removal
// TODO: implement rewards distribution
// TODO: use hints for simbiotic calls
// TODO: use hints for symbiotic calls
contract Middleware {
using EnumerableMap for EnumerableMap.AddressToUintMap;
using MapWithTimeData for EnumerableMap.AddressToUintMap;
Expand All @@ -47,8 +47,8 @@ contract Middleware {
error VetoDurationTooShort();
error VetoDurationTooLong();
error IncompatibleVaultVersion();
error NotRegistredVault();
error NotRegistredOperator();
error NotRegisteredVault();
error NotRegisteredOperator();
error RoleMismatch();
error ResolverMismatch();
error ResolverSetDelayTooLong();
Expand All @@ -72,7 +72,7 @@ contract Middleware {
struct Config {
uint48 eraDuration;
uint48 minVaultEpochDuration;
uint48 operatoraGracePeriod;
uint48 operatorGracePeriod;
uint48 vaultGracePeriod;
uint48 minVetoDuration;
uint48 minSlashExecutionDelay;
Expand All @@ -94,7 +94,7 @@ contract Middleware {

uint48 public immutable eraDuration;
uint48 public immutable minVaultEpochDuration;
uint48 public immutable operatoraGracePeriod;
uint48 public immutable operatorGracePeriod;
uint48 public immutable vaultGracePeriod;
uint48 public immutable minVetoDuration;
uint48 public immutable minSlashExecutionDelay;
Expand All @@ -107,11 +107,12 @@ contract Middleware {
address public immutable networkOptIn;
address public immutable middlewareService;
address public immutable collateral;
address public immutable roleSlashRequester;
address public immutable roleSlashExecutor;
address public immutable vetoResolver;
bytes32 public immutable subnetwork;

address public roleSlashRequester;
address public roleSlashExecutor;

EnumerableMap.AddressToUintMap private operators;
EnumerableMap.AddressToUintMap private vaults;

Expand All @@ -120,7 +121,7 @@ contract Middleware {

eraDuration = cfg.eraDuration;
minVaultEpochDuration = cfg.minVaultEpochDuration;
operatoraGracePeriod = cfg.operatoraGracePeriod;
operatorGracePeriod = cfg.operatorGracePeriod;
vaultGracePeriod = cfg.vaultGracePeriod;
minVetoDuration = cfg.minVetoDuration;
minSlashExecutionDelay = cfg.minSlashExecutionDelay;
Expand All @@ -144,6 +145,14 @@ contract Middleware {
INetworkMiddlewareService(middlewareService).setMiddleware(address(this));
}

function changeSlashRequester(address newRole) external _onlyRole(roleSlashRequester) {
roleSlashRequester = newRole;
}

function changeSlashExecutor(address newRole) external _onlyRole(roleSlashExecutor) {
roleSlashExecutor = newRole;
}

// TODO: Check that total stake is big enough
function registerOperator() external {
if (!IRegistry(operatorRegistry).isEntity(msg.sender)) {
Expand All @@ -166,7 +175,7 @@ contract Middleware {
function unregisterOperator(address operator) external {
(, uint48 disabledTime) = operators.getTimes(operator);

if (disabledTime == 0 || Time.timestamp() < disabledTime + operatoraGracePeriod) {
if (disabledTime == 0 || Time.timestamp() < disabledTime + operatorGracePeriod) {
revert OperatorGracePeriodNotPassed();
}

Expand Down Expand Up @@ -267,12 +276,50 @@ contract Middleware {
vaults.remove(vault);
}

function getOperatorStakeAt(address operator, uint48 ts)
external
view
_validTimestamp(ts)
returns (uint256 stake)
{
function makeElectionAt(uint48 ts, uint256 maxValidators) public view returns (address[] memory) {
require(maxValidators > 0, "Max validators must be greater than zero");

(address[] memory activeOperators, uint256[] memory stakes) = getActiveOperatorsStakeAt(ts);

if (activeOperators.length <= maxValidators) {
return activeOperators;
}

// Bubble sort descending
StackOverflowExcept1on marked this conversation as resolved.
Show resolved Hide resolved
uint256 n = activeOperators.length;
for (uint256 i = 0; i < n; i++) {
for (uint256 j = 0; j < n - 1 - i; j++) {
if (stakes[j] < stakes[j + 1]) {
(stakes[j], stakes[j + 1]) = (stakes[j + 1], stakes[j]);
(activeOperators[j], activeOperators[j + 1]) = (activeOperators[j + 1], activeOperators[j]);
}
}
}

// Choose between validators with the same stake
uint256 sameStakeCount = 1;
uint256 lastStake = stakes[maxValidators - 1];
for (uint256 i = maxValidators; i < activeOperators.length; i++) {
if (stakes[i] != lastStake) {
break;
}
sameStakeCount += 1;
}

if (sameStakeCount > 1) {
// If there are multiple validators with the same stake, choose one randomly
uint256 randomIndex = uint256(keccak256(abi.encodePacked(ts))) % sameStakeCount;
activeOperators[maxValidators - 1] = activeOperators[maxValidators + randomIndex - 1];
}

assembly {
mstore(activeOperators, maxValidators)
}

return activeOperators;
}

function getOperatorStakeAt(address operator, uint48 ts) public view _validTimestamp(ts) returns (uint256 stake) {
(uint48 enabledTime, uint48 disabledTime) = operators.getTimes(operator);
if (!_wasActiveAt(enabledTime, disabledTime, ts)) {
return 0;
Expand All @@ -281,7 +328,7 @@ contract Middleware {
stake = _collectOperatorStakeFromVaultsAt(operator, ts);
}

// TODO: change return siggnature
// TODO: change return signature
function getActiveOperatorsStakeAt(uint48 ts)
public
view
Expand Down Expand Up @@ -315,14 +362,14 @@ contract Middleware {
for (uint256 i; i < data.length; ++i) {
SlashData calldata slashData = data[i];
if (!operators.contains(slashData.operator)) {
revert NotRegistredOperator();
revert NotRegisteredOperator();
}

for (uint256 j; j < slashData.vaults.length; ++j) {
VaultSlashData calldata vaultData = slashData.vaults[j];

if (!vaults.contains(vaultData.vault)) {
revert NotRegistredVault();
revert NotRegisteredVault();
}

address slasher = IVault(vaultData.vault).slasher();
Expand All @@ -338,7 +385,7 @@ contract Middleware {
SlashIdentifier calldata slash = slashes[i];

if (!vaults.contains(slash.vault)) {
revert NotRegistredVault();
revert NotRegisteredVault();
}

IVetoSlasher(IVault(slash.vault).slasher()).executeSlash(slash.index, new bytes(0));
Expand Down Expand Up @@ -388,7 +435,7 @@ contract Middleware {
// Operator grace period cannot be smaller than minimum vaults epoch duration.
// Otherwise, it would be impossible to do slash in the next era sometimes.
require(
cfg.operatoraGracePeriod >= cfg.minVaultEpochDuration,
cfg.operatorGracePeriod >= cfg.minVaultEpochDuration,
"Operator grace period must be bigger than min vaults epoch duration"
);

Expand All @@ -402,16 +449,16 @@ contract Middleware {
// Give some time for the resolvers to veto slashes.
require(cfg.minVetoDuration > 0, "Veto duration cannot be zero");

// Simbiotic guarantees that any veto slasher has veto duration less than vault epoch duration.
// But we also want to guaratie that there is some time to execute the slash.
// Symbiotic guarantees that any veto slasher has veto duration less than vault epoch duration.
// But we also want to guarantee that there is some time to execute the slash.
require(cfg.minSlashExecutionDelay > 0, "Min slash execution delay cannot be zero");
require(
cfg.minVetoDuration + cfg.minSlashExecutionDelay <= cfg.minVaultEpochDuration,
"Veto duration and slash execution delay must be less than ot equal to min vaults epoch duration"
);

// In order to be able to change resolver, we need to limit max delay in epochs.
// `3` - is minimal number of epochs, which is simbiotic veto slasher impl restrictions.
// `3` - is minimal number of epochs, which is symbiotic veto slasher impl restrictions.
require(cfg.maxResolverSetEpochsDelay >= 3, "Resolver set epochs delay must be at least 3");
}

Expand All @@ -422,7 +469,7 @@ contract Middleware {
revert IncorrectTimestamp();
}

uint48 gracePeriod = operatoraGracePeriod < vaultGracePeriod ? operatoraGracePeriod : vaultGracePeriod;
uint48 gracePeriod = operatorGracePeriod < vaultGracePeriod ? operatorGracePeriod : vaultGracePeriod;
if (ts + gracePeriod <= Time.timestamp()) {
revert IncorrectTimestamp();
}
Expand Down
Loading
Loading