Skip to content

Commit

Permalink
exclude opt ins from vault
Browse files Browse the repository at this point in the history
  • Loading branch information
1kresh committed May 22, 2024
1 parent 68b1672 commit 573ff41
Show file tree
Hide file tree
Showing 16 changed files with 951 additions and 773 deletions.
29 changes: 19 additions & 10 deletions script/deploy/Core.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import {MigratablesRegistry} from "src/contracts/base/MigratablesRegistry.sol";
import {NonMigratablesRegistry} from "src/contracts/base/NonMigratablesRegistry.sol";
import {MetadataPlugin} from "src/contracts/plugins/MetadataPlugin.sol";
import {MiddlewarePlugin} from "src/contracts/plugins/MiddlewarePlugin.sol";
import {OptInPlugin} from "src/contracts/plugins/OptInPlugin.sol";
import {NetworkOptInPlugin} from "src/contracts/plugins/NetworkOptInPlugin.sol";
import {OperatorOptInPlugin} from "src/contracts/plugins/OperatorOptInPlugin.sol";

import {Vault} from "src/contracts/Vault.sol";

Expand All @@ -24,17 +25,25 @@ contract CoreScript is Script {
MetadataPlugin operatorMetadataPlugin = new MetadataPlugin(address(operatorRegistry));
MetadataPlugin networkMetadataPlugin = new MetadataPlugin(address(networkRegistry));
MiddlewarePlugin networkMiddlewarePlugin = new MiddlewarePlugin(address(networkRegistry));
OptInPlugin networkOptInPlugin = new OptInPlugin(address(operatorRegistry), address(networkRegistry));

address vault = address(
new Vault(
address(networkRegistry),
address(operatorRegistry),
address(networkMiddlewarePlugin),
address(networkOptInPlugin)
NetworkOptInPlugin networkVaultOptInPlugin =
new NetworkOptInPlugin(address(networkRegistry), address(vaultRegistry));
OperatorOptInPlugin operatorVaultOptInPlugin =
new OperatorOptInPlugin(address(operatorRegistry), address(vaultRegistry));
OperatorOptInPlugin operatorNetworkOptInPlugin =
new OperatorOptInPlugin(address(operatorRegistry), address(networkRegistry));

vaultRegistry.whitelist(
address(
new Vault(
address(networkRegistry),
address(operatorRegistry),
address(networkMiddlewarePlugin),
address(networkVaultOptInPlugin),
address(operatorVaultOptInPlugin),
address(operatorNetworkOptInPlugin)
)
)
);
vaultRegistry.whitelist(vault);
vaultRegistry.transferOwnership(owner);

vm.stopBroadcast();
Expand Down
49 changes: 36 additions & 13 deletions src/contracts/Vault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import {IVault} from "src/interfaces/IVault.sol";
import {ICollateral} from "src/interfaces/base/ICollateral.sol";
import {IRegistry} from "src/interfaces/base/IRegistry.sol";
import {IMiddlewarePlugin} from "src/interfaces/plugins/IMiddlewarePlugin.sol";
import {IOptInPlugin} from "src/interfaces/plugins/IOptInPlugin.sol";
import {INetworkOptInPlugin} from "src/interfaces/plugins/INetworkOptInPlugin.sol";
import {IOperatorOptInPlugin} from "src/interfaces/plugins/IOperatorOptInPlugin.sol";

import {VaultDelegation} from "./VaultDelegation.sol";
import {ERC4626Math} from "./libraries/ERC4626Math.sol";
Expand All @@ -25,8 +26,19 @@ contract Vault is VaultDelegation, MulticallUpgradeable, IVault {
address networkRegistry,
address operatorRegistry,
address networkMiddlewarePlugin,
address networkOptInPlugin
) VaultDelegation(networkRegistry, operatorRegistry, networkMiddlewarePlugin, networkOptInPlugin) {}
address networkVaultOptInPlugin,
address operatorVaultOptInPlugin,
address operatorNetworkOptInPlugin
)
VaultDelegation(
networkRegistry,
operatorRegistry,
networkMiddlewarePlugin,
networkVaultOptInPlugin,
operatorVaultOptInPlugin,
operatorNetworkOptInPlugin
)
{}

/**
* @inheritdoc IVault
Expand Down Expand Up @@ -171,19 +183,24 @@ contract Vault is VaultDelegation, MulticallUpgradeable, IVault {
revert InsufficientSlash();
}

if (!isNetworkOptedIn(network, resolver)) {
revert NetworkNotOptedIn();
}
uint256 edgeTimestamp = previousEpochStart();

if (!isOperatorOptedIn(operator)) {
revert OperatorNotOptedIn();
if (
!IOperatorOptInPlugin(OPERATOR_NETWORK_OPT_IN_PLUGIN).isOptedIn(operator, network)
&& IOperatorOptInPlugin(OPERATOR_NETWORK_OPT_IN_PLUGIN).lastOptOut(operator, network) < edgeTimestamp
) {
revert OperatorNotOptedInNetwork();
}

if (
!IOptInPlugin(NETWORK_OPT_IN_PLUGIN).isOptedIn(operator, network)
&& IOptInPlugin(NETWORK_OPT_IN_PLUGIN).lastOptOut(operator, network) < block.timestamp - epochDuration
!IOperatorOptInPlugin(OPERATOR_VAULT_OPT_IN_PLUGIN).isOptedIn(operator, address(this))
&& IOperatorOptInPlugin(OPERATOR_VAULT_OPT_IN_PLUGIN).lastOptOut(operator, address(this)) < edgeTimestamp
) {
revert OperatorNotOptedInNetwork();
revert OperatorNotOptedInVault();
}

if (!INetworkOptInPlugin(NETWORK_VAULT_OPT_IN_PLUGIN).isOptedIn(network, resolver, address(this))) {
revert NetworkNotOptedInVault();
}

uint256 slashAmount = Math.min(amount, maxSlash_);
Expand Down Expand Up @@ -228,8 +245,14 @@ contract Vault is VaultDelegation, MulticallUpgradeable, IVault {
revert SlashCompleted();
}

if (!isOperatorOptedIn(request.operator)) {
revert OperatorNotOptedIn();
uint256 edgeTimestamp = previousEpochStart();

if (
!IOperatorOptInPlugin(OPERATOR_VAULT_OPT_IN_PLUGIN).isOptedIn(request.operator, address(this))
&& IOperatorOptInPlugin(OPERATOR_VAULT_OPT_IN_PLUGIN).lastOptOut(request.operator, address(this))
< edgeTimestamp
) {
revert OperatorNotOptedInVault();
}

request.completed = true;
Expand Down
161 changes: 61 additions & 100 deletions src/contracts/VaultDelegation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ pragma solidity 0.8.25;

import {IVaultDelegation} from "src/interfaces/IVaultDelegation.sol";
import {IRegistry} from "src/interfaces/base/IRegistry.sol";
import {INetworkOptInPlugin} from "src/interfaces/plugins/INetworkOptInPlugin.sol";
import {IOperatorOptInPlugin} from "src/interfaces/plugins/IOperatorOptInPlugin.sol";

import {VaultStorage} from "./VaultStorage.sol";

Expand All @@ -15,28 +17,19 @@ contract VaultDelegation is VaultStorage, IVaultDelegation {
address networkRegistry,
address operatorRegistry,
address networkMiddlewarePlugin,
address networkOptInPlugin
) VaultStorage(networkRegistry, operatorRegistry, networkMiddlewarePlugin, networkOptInPlugin) {}

/**
* @inheritdoc IVaultDelegation
*/
function isNetworkOptedIn(address network, address resolver) public view returns (bool) {
return _isNetworkOptedIn[network][resolver];
}

/**
* @inheritdoc IVaultDelegation
*/
function isOperatorOptedIn(address operator) public view returns (bool) {
if (operatorOptOutAt[operator] == 0) {
return _isOperatorOptedIn[operator];
}
if (clock() < operatorOptOutAt[operator]) {
return true;
}
return false;
}
address networkVaultOptInPlugin,
address operatorVaultOptInPlugin,
address operatorNetworkOptInPlugin
)
VaultStorage(
networkRegistry,
operatorRegistry,
networkMiddlewarePlugin,
networkVaultOptInPlugin,
operatorVaultOptInPlugin,
operatorNetworkOptInPlugin
)
{}

/**
* @inheritdoc IVaultDelegation
Expand All @@ -55,81 +48,32 @@ contract VaultDelegation is VaultStorage, IVaultDelegation {
/**
* @inheritdoc IVaultDelegation
*/
function optInNetwork(address resolver, uint256 maxNetworkLimit_) external {
if (!IRegistry(NETWORK_REGISTRY).isEntity(msg.sender)) {
revert NotNetwork();
}

if (isNetworkOptedIn(msg.sender, resolver)) {
revert NetworkAlreadyOptedIn();
}

if (maxNetworkLimit_ == 0) {
revert InvalidMaxNetworkLimit();
function setMaxNetworkLimit(address resolver, uint256 amount) external {
if (maxNetworkLimit[msg.sender][resolver] == amount) {
revert AlreadySet();
}

_isNetworkOptedIn[msg.sender][resolver] = true;

_networkLimit[msg.sender][resolver].amount = 0;
nextNetworkLimit[msg.sender][resolver].timestamp = 0;

maxNetworkLimit[msg.sender][resolver] = maxNetworkLimit_;

emit OptInNetwork(msg.sender, resolver);
}

/**
* @inheritdoc IVaultDelegation
*/
function optOutNetwork(address resolver) external {
if (!isNetworkOptedIn(msg.sender, resolver)) {
revert NetworkNotOptedIn();
if (!IRegistry(NETWORK_REGISTRY).isEntity(msg.sender)) {
revert NotNetwork();
}

_updateLimit(_networkLimit[msg.sender][resolver], nextNetworkLimit[msg.sender][resolver]);

_isNetworkOptedIn[msg.sender][resolver] = false;

nextNetworkLimit[msg.sender][resolver].amount = 0;
nextNetworkLimit[msg.sender][resolver].timestamp = currentEpochStart() + 2 * epochDuration;
maxNetworkLimit[msg.sender][resolver] = amount;

maxNetworkLimit[msg.sender][resolver] = 0;

emit OptOutNetwork(msg.sender, resolver);
}

/**
* @inheritdoc IVaultDelegation
*/
function optInOperator() external {
if (!IRegistry(OPERATOR_REGISTRY).isEntity(msg.sender)) {
revert NotOperator();
}
Limit storage limit = _networkLimit[msg.sender][resolver];
DelayedLimit storage nextLimit = nextNetworkLimit[msg.sender][resolver];

if (isOperatorOptedIn(msg.sender)) {
revert OperatorAlreadyOptedIn();
}
_updateLimit(limit, nextLimit);

if (!_isOperatorOptedIn[msg.sender]) {
_isOperatorOptedIn[msg.sender] = true;
} else {
operatorOptOutAt[msg.sender] = 0;
if (limit.amount > amount) {
limit.amount = amount;
}

emit OptInOperator(msg.sender);
}

/**
* @inheritdoc IVaultDelegation
*/
function optOutOperator() external {
if (!isOperatorOptedIn(msg.sender)) {
revert OperatorNotOptedIn();
if (nextLimit.timestamp != 0) {
if (nextLimit.amount > amount) {
nextLimit.amount = amount;
}
}

operatorOptOutAt[msg.sender] = currentEpochStart() + 2 * epochDuration;

emit OptOutOperator(msg.sender);
emit SetMaxNetworkLimit(msg.sender, resolver, amount);
}

/**
Expand Down Expand Up @@ -179,14 +123,14 @@ contract VaultDelegation is VaultStorage, IVaultDelegation {
* @inheritdoc IVaultDelegation
*/
function setDepositorWhitelistStatus(address account, bool status) external onlyRole(DEPOSITOR_WHITELIST_ROLE) {
if (status && !depositWhitelist) {
revert NoDepositWhitelist();
}

if (isDepositorWhitelisted[account] == status) {
revert AlreadySet();
}

if (status && !depositWhitelist) {
revert NoDepositWhitelist();
}

isDepositorWhitelisted[account] = status;

emit SetDepositorWhitelistStatus(account, status);
Expand All @@ -200,15 +144,28 @@ contract VaultDelegation is VaultStorage, IVaultDelegation {
address resolver,
uint256 amount
) external onlyRole(NETWORK_LIMIT_SET_ROLE) {
if (!isNetworkOptedIn(network, resolver)) {
revert NetworkNotOptedIn();
}

if (amount > maxNetworkLimit[network][resolver]) {
revert ExceedsMaxNetworkLimit();
}

_setLimit(_networkLimit[network][resolver], nextNetworkLimit[network][resolver], amount);
Limit storage limit = _networkLimit[network][resolver];
DelayedLimit storage nextLimit = nextNetworkLimit[network][resolver];

if (
INetworkOptInPlugin(NETWORK_VAULT_OPT_IN_PLUGIN).isOptedIn(network, resolver, address(this))
|| INetworkOptInPlugin(NETWORK_VAULT_OPT_IN_PLUGIN).lastOptOut(network, resolver, address(this))
>= previousEpochStart()
) {
_setLimit(limit, nextLimit, amount);
} else {
if (amount != 0) {
revert NetworkNotOptedInVault();
} else {
limit.amount = 0;
nextLimit.amount = 0;
nextLimit.timestamp = 0;
}
}

emit SetNetworkLimit(network, resolver, amount);
}
Expand All @@ -224,16 +181,20 @@ contract VaultDelegation is VaultStorage, IVaultDelegation {
Limit storage limit = _operatorLimit[operator][network];
DelayedLimit storage nextLimit = nextOperatorLimit[operator][network];

if (!isOperatorOptedIn(operator)) {
if (
IOperatorOptInPlugin(OPERATOR_VAULT_OPT_IN_PLUGIN).isOptedIn(operator, address(this))
|| IOperatorOptInPlugin(OPERATOR_VAULT_OPT_IN_PLUGIN).lastOptOut(operator, address(this))
>= previousEpochStart()
) {
_setLimit(limit, nextLimit, amount);
} else {
if (amount != 0) {
revert OperatorNotOptedIn();
revert OperatorNotOptedInVault();
} else {
limit.amount = 0;
nextLimit.amount = 0;
nextLimit.timestamp = 0;
}
} else {
_setLimit(limit, nextLimit, amount);
}

emit SetOperatorLimit(operator, network, amount);
Expand Down
Loading

0 comments on commit 573ff41

Please sign in to comment.