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

Make epoch's increase auto-commit #92

Merged
merged 12 commits into from
Feb 24, 2025
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
# Compiler files
cache/
out/**/
!out/VaultImplementation.sol/
!out/VaultTokenizedImplementation.sol/
!out/VaultVotesImplementation.sol/
!out/v1.1/
!out/v1.1/Vault.sol/
!out/v1.1/VaultTokenized.sol/
!out/VaultVotes.sol/
!out/Vault.sol/
!out/VaultTokenized.sol/
!out/NetworkRestakeDelegator.sol/
Expand Down
2 changes: 1 addition & 1 deletion out/DelegatorHints.sol/BaseDelegatorHints.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion out/DelegatorHints.sol/FullRestakeDelegatorHints.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion out/DelegatorHints.sol/NetworkRestakeDelegatorHints.json

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion out/DelegatorHints.sol/OperatorSpecificDelegatorHints.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion out/SlasherHints.sol/BaseSlasherHints.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion out/SlasherHints.sol/SlasherHints.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion out/SlasherHints.sol/VetoSlasherHints.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion out/Vault.sol/Vault.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion out/VaultConfigurator.sol/VaultConfigurator.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion out/VaultHints.sol/VaultHints.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions out/VaultImplementation.sol/VaultImplementation.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion out/VaultTokenized.sol/VaultTokenized.json

Large diffs are not rendered by default.

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions out/VaultVotes.sol/VaultVotes.json

Large diffs are not rendered by default.

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions out/v1.1/Vault.sol/Vault.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions out/v1.1/VaultTokenized.sol/VaultTokenized.json

Large diffs are not rendered by default.

22 changes: 13 additions & 9 deletions src/contracts/vault/v1.1/Vault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ contract Vault is VaultStorage, MigratableEntity, AccessControlUpgradeable, Prox
using SafeERC20 for IERC20;
using Address for address;

/**
* @notice The minimum period of time that must be available to exit in case of epoch increase after migration.
*/
uint256 public constant MIN_EXIT_WINDOW = 7 days;

address private immutable IMPLEMENTATION;

constructor(
address delegatorFactory,
address slasherFactory,
address vaultFactory,
address implementation
) VaultStorage(delegatorFactory, slasherFactory) MigratableEntity(vaultFactory) {
constructor(address vaultFactory, address implementation) MigratableEntity(vaultFactory) {
IMPLEMENTATION = implementation;
}

Expand All @@ -52,7 +52,7 @@ contract Vault is VaultStorage, MigratableEntity, AccessControlUpgradeable, Prox
revert IVault.InvalidFlashParams();
}

epochDurationSetEpochsDelay = params.epochDurationSetEpochsDelay;
_epochDurationSetEpochsDelay = params.epochDurationSetEpochsDelay;

flashFeeRate = params.flashFeeRate;
flashFeeReceiver = params.flashFeeReceiver;
Expand Down Expand Up @@ -146,8 +146,8 @@ contract Vault is VaultStorage, MigratableEntity, AccessControlUpgradeable, Prox

burner = params.burner;

epochDurationInit = Time.timestamp();
epochDuration = params.epochDuration;
_epochDurationInit = Time.timestamp();
_epochDuration = params.epochDuration;

depositWhitelist = params.depositWhitelist;

Expand Down Expand Up @@ -175,5 +175,9 @@ contract Vault is VaultStorage, MigratableEntity, AccessControlUpgradeable, Prox
(IVault.MigrateParams memory params) = abi.decode(data, (IVault.MigrateParams));

_processMigrateParams(params);

if ((params.epochDurationSetEpochsDelay - 2) * _epochDuration < MIN_EXIT_WINDOW) {
revert IVault.InsufficientExitWindow();
}
}
}
159 changes: 98 additions & 61 deletions src/contracts/vault/v1.1/VaultImplementation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,35 +27,100 @@ contract VaultImplementation is VaultStorage, AccessControlUpgradeable, Reentran
using SafeCast for uint256;
using SafeERC20 for IERC20;

constructor(address delegatorFactory, address slasherFactory) VaultStorage(delegatorFactory, slasherFactory) {}
/**
* @inheritdoc IVault
*/
address public immutable DELEGATOR_FACTORY;

/**
* @inheritdoc IVault
*/
address public immutable SLASHER_FACTORY;

constructor(address delegatorFactory, address slasherFactory) {
DELEGATOR_FACTORY = delegatorFactory;
SLASHER_FACTORY = slasherFactory;
}

/**
* @inheritdoc IVault
*/
function epochDurationSetEpochsDelay() external view returns (uint256) {
if (_nextEpochDurationInit == 0 || Time.timestamp() < _nextEpochDurationInit) {
return _epochDurationSetEpochsDelay;
}
return _nextEpochDurationSetEpochsDelay;
}

/**
* @inheritdoc IVault
*/
function epochDuration() public view returns (uint48) {
if (_nextEpochDurationInit == 0 || Time.timestamp() < _nextEpochDurationInit) {
return _epochDuration;
}
return _nextEpochDuration;
}

/**
* @inheritdoc IVault
*/
function epochDurationInit() public view returns (uint48) {
if (_nextEpochDurationInit == 0 || Time.timestamp() < _nextEpochDurationInit) {
return _epochDurationInit;
}
return _nextEpochDurationInit;
}

/**
* @inheritdoc IVault
*/
function epochAt(
uint48 timestamp
) public view returns (uint256) {
if (timestamp < epochDurationInit) {
if (previousEpochDurationInit == 0 || timestamp < previousEpochDurationInit) {
if (timestamp < _epochDurationInit) {
if (_prevEpochDurationInit == 0 || timestamp < _prevEpochDurationInit) {
revert InvalidTimestamp();
}
return epochInit - (epochDurationInit - timestamp).ceilDiv(previousEpochDuration);
return _prevEpochDurationInitIndex + (timestamp - _prevEpochDurationInit) / _prevEpochDuration;
} else if (_nextEpochDurationInit == 0 || timestamp < _nextEpochDurationInit) {
return _epochDurationInitIndex + (timestamp - _epochDurationInit) / _epochDuration;
} else {
return _nextEpochInitIndex + (timestamp - _nextEpochDurationInit) / _nextEpochDuration;
}
}

/**
* @inheritdoc IVault
*/
function epochStart(
uint256 epoch
) public view returns (uint48) {
if (epoch < _prevEpochDurationInitIndex) {
revert InvalidEpoch();
}

if (epoch < _epochDurationInitIndex) {
return (_prevEpochDurationInit + (epoch - _prevEpochDurationInitIndex) * _prevEpochDuration).toUint48();
} else if (_nextEpochInitIndex == 0 || epoch < _nextEpochInitIndex) {
return (_epochDurationInit + (epoch - _epochDurationInitIndex) * _epochDuration).toUint48();
} else {
return (_nextEpochDurationInit + (epoch - _nextEpochInitIndex) * _nextEpochDuration).toUint48();
}
return epochInit + (timestamp - epochDurationInit) / epochDuration;
}

/**
* @inheritdoc IVault
*/
function currentEpoch() public view returns (uint256) {
return epochInit + (Time.timestamp() - epochDurationInit) / epochDuration;
return epochAt(Time.timestamp());
}

/**
* @inheritdoc IVault
*/
function currentEpochStart() public view returns (uint48) {
return (epochDurationInit + (currentEpoch() - epochInit) * epochDuration).toUint48();
return epochStart(currentEpoch());
}

/**
Expand All @@ -66,17 +131,14 @@ contract VaultImplementation is VaultStorage, AccessControlUpgradeable, Reentran
if (epoch == 0) {
revert NoPreviousEpoch();
}
if (epoch == epochInit) {
return epochDurationInit - previousEpochDuration;
}
return (epochDurationInit + (epoch - epochInit - 1) * epochDuration).toUint48();
return epochStart(epoch - 1);
}

/**
* @inheritdoc IVault
*/
function nextEpochStart() public view returns (uint48) {
return currentEpochStart() + epochDuration;
return epochStart(currentEpoch() + 1);
}

/**
Expand Down Expand Up @@ -197,7 +259,7 @@ contract VaultImplementation is VaultStorage, AccessControlUpgradeable, Reentran
if (token != collateral) {
revert UnsupportedToken();
}
return value.mulDiv(flashFeeRate, FLASH_FEE_BASE);
return flashFeeReceiver == address(0) ? 0 : value.mulDiv(flashFeeRate, FLASH_FEE_BASE);
}

/**
Expand All @@ -215,8 +277,6 @@ contract VaultImplementation is VaultStorage, AccessControlUpgradeable, Reentran
revert NotWhitelistedDepositor();
}

_tryAcceptEpochDuration();

uint256 balanceBefore = IERC20(collateral).balanceOf(address(this));
IERC20(collateral).safeTransferFrom(msg.sender, address(this), amount);
depositedAmount = IERC20(collateral).balanceOf(address(this)) - balanceBefore;
Expand Down Expand Up @@ -352,7 +412,7 @@ contract VaultImplementation is VaultStorage, AccessControlUpgradeable, Reentran
revert InvalidReturnAmount();
}

if (flashFeeReceiver != address(0)) {
if (fee > 0) {
IERC20(collateral_).safeTransfer(flashFeeReceiver, fee);
}

Expand Down Expand Up @@ -481,37 +541,37 @@ contract VaultImplementation is VaultStorage, AccessControlUpgradeable, Reentran
* @inheritdoc IVault
*/
function setEpochDuration(
uint48 epochDuration_
uint48 epochDuration_,
uint256 epochDurationSetEpochsDelay_
) external nonReentrant onlyRole(EPOCH_DURATION_SET_ROLE) {
_tryAcceptEpochDuration();
if (epochDurationSetEpochsDelay_ < 3) {
revert InvalidEpochDurationSetEpochsDelay();
}

if (epochDuration > epochDuration_) {
revert InvalidNewEpochDuration();
if (_nextEpochDurationInit != 0 && _nextEpochDurationInit <= Time.timestamp()) {
_prevEpochDurationInitIndex = _epochDurationInitIndex;
_prevEpochDuration = _epochDuration;
_prevEpochDurationInit = _epochDurationInit;
_epochDurationInitIndex = _nextEpochInitIndex;
_epochDuration = _nextEpochDuration;
_epochDurationInit = _nextEpochDurationInit;
_epochDurationSetEpochsDelay = _nextEpochDurationSetEpochsDelay;
}

if (nextEpochDurationInit != 0) {
nextEpochDuration = 0;
nextEpochDurationInit = 0;
} else if (epochDuration == epochDuration_) {
revert AlreadySet();
if (_epochDuration > epochDuration_) {
revert InvalidNewEpochDuration();
}

if (epochDuration != epochDuration_) {
nextEpochDuration = epochDuration_;
nextEpochDurationInit = (currentEpochStart() + epochDurationSetEpochsDelay * epochDuration).toUint48();
if (_epochDuration == epochDuration_ && _epochDurationSetEpochsDelay == epochDurationSetEpochsDelay_) {
revert AlreadySet();
}

emit SetEpochDuration(epochDuration_);
}
_nextEpochInitIndex = currentEpoch() + _epochDurationSetEpochsDelay;
_nextEpochDuration = epochDuration_;
_nextEpochDurationInit = (currentEpochStart() + _epochDurationSetEpochsDelay * _epochDuration).toUint48();
_nextEpochDurationSetEpochsDelay = epochDurationSetEpochsDelay_;

/**
* @inheritdoc IVault
*/
function acceptEpochDuration() external nonReentrant {
if (nextEpochDurationInit == 0 || nextEpochDurationInit > Time.timestamp()) {
revert NewEpochDurationNotReady();
}
_acceptEpochDuration();
emit SetEpochDuration(epochDuration_, epochDurationSetEpochsDelay_);
}

/**
Expand Down Expand Up @@ -599,8 +659,6 @@ contract VaultImplementation is VaultStorage, AccessControlUpgradeable, Reentran
uint256 withdrawnAssets,
uint256 burnedShares
) internal returns (uint256 mintedShares) {
_tryAcceptEpochDuration();

_activeSharesOf[msg.sender].push(Time.timestamp(), activeSharesOf(msg.sender) - burnedShares);
_activeShares.push(Time.timestamp(), activeShares() - burnedShares);
_activeStake.push(Time.timestamp(), activeStake() - withdrawnAssets);
Expand Down Expand Up @@ -638,26 +696,5 @@ contract VaultImplementation is VaultStorage, AccessControlUpgradeable, Reentran
isWithdrawalsClaimed[epoch][msg.sender] = true;
}

function _tryAcceptEpochDuration() internal {
if (nextEpochDurationInit != 0 && nextEpochDurationInit <= Time.timestamp()) {
_acceptEpochDuration();
}
}

function _acceptEpochDuration() internal {
uint256 currentEpoch_ = currentEpoch();
uint48 currentEpochStart_ = currentEpochStart();

previousEpochDuration = epochDuration;
previousEpochDurationInit = epochDurationInit;
epochInit = currentEpoch_;
epochDuration = nextEpochDuration;
epochDurationInit = currentEpochStart_;
nextEpochDuration = 0;
nextEpochDurationInit = 0;

emit AcceptEpochDuration();
}

function _Vault_init() external {}
}
Loading
Loading