Skip to content

Commit

Permalink
Introduce configurable lock period for worker contract
Browse files Browse the repository at this point in the history
  • Loading branch information
vanruch committed Jun 23, 2024
1 parent 8d4c0a9 commit 2dbc366
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 10 deletions.
4 changes: 2 additions & 2 deletions packages/contracts/src/GatewayRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ contract GatewayRegistry is AccessControlledPausableUpgradeable, IGatewayRegistr
*/
function stake(uint256 amount, uint128 durationBlocks, bool withAutoExtension) public whenNotPaused {
require(amount >= minStake, "Cannot stake below minStake");
require(durationBlocks >= router.networkController().epochLength(), "Cannot stake for less than an epoch");
require(durationBlocks >= router.networkController().workerEpochLength(), "Cannot stake for less than an epoch");
require(durationBlocks * averageBlockTime <= MAX_LOCK_DURATION, "Lock duration too long");
require(operators[msg.sender].stake.amount == 0, "Stake already exists, call addStake instead");
uint256 _computationUnits = computationUnitsAmount(amount, durationBlocks);
Expand Down Expand Up @@ -245,7 +245,7 @@ contract GatewayRegistry is AccessControlledPausableUpgradeable, IGatewayRegistr
}
uint256 computationUnits =
_stake.lockStart > blockNumber ? _stake.oldCUs : computationUnitsAmount(_stake.amount, _stake.duration);
uint256 epochLength = uint256(router.networkController().epochLength());
uint256 epochLength = uint256(router.networkController().workerEpochLength());
if (_stake.duration <= epochLength) {
return computationUnits;
}
Expand Down
25 changes: 21 additions & 4 deletions packages/contracts/src/NetworkController.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import "./interfaces/INetworkController.sol";
contract NetworkController is AccessControl, INetworkController {
uint256 internal constant ONE_BASIS_POINT = 10_000;

/// @notice deprecated
uint128 public epochLength;

uint128 public workerEpochLength;
uint128 public firstEpochBlock;
uint256 public bondAmount;
uint256 public stakingDeadlock = 2;
Expand All @@ -31,7 +34,7 @@ contract NetworkController is AccessControl, INetworkController {
for (uint256 i = 0; i < _allowedVestedTargets.length; i++) {
setAllowedVestedTarget(_allowedVestedTargets[i], true);
}
epochLength = _epochLength;
workerEpochLength = _epochLength;
firstEpochBlock = nextEpoch();
emit EpochLengthUpdated(_epochLength);

Expand All @@ -46,11 +49,25 @@ contract NetworkController is AccessControl, INetworkController {
uint128 nextEpochStart = nextEpoch();
epochCheckpoint = epochNumber();
firstEpochBlock = nextEpochStart;
epochLength = _epochLength;
workerEpochLength = _epochLength;

emit EpochLengthUpdated(_epochLength);
}

/// @dev Set how long the
function setLockPeriod(uint128 _lockPeriod) external onlyRole(DEFAULT_ADMIN_ROLE) {
require(_lockPeriod > 1, "Lock period too short");
require(_lockPeriod < 100000, "Lock period too long");

epochLength = _lockPeriod;

emit LockPeriodUpdated(_lockPeriod);
}

function lockPeriod() external view returns (uint128) {
return epochLength;
}

/// @dev Set amount of tokens required to register a worker
function setBondAmount(uint256 _bondAmount) public onlyRole(DEFAULT_ADMIN_ROLE) {
require(_bondAmount > 0, "Bond cannot be 0");
Expand Down Expand Up @@ -103,13 +120,13 @@ contract NetworkController is AccessControl, INetworkController {
function nextEpoch() public view returns (uint128) {
uint128 blockNumber = uint128(block.number);
if (blockNumber < firstEpochBlock) return firstEpochBlock;
return ((blockNumber - firstEpochBlock) / epochLength + 1) * epochLength + firstEpochBlock;
return ((blockNumber - firstEpochBlock) / workerEpochLength + 1) * workerEpochLength + firstEpochBlock;
}

/// @inheritdoc INetworkController
function epochNumber() public view returns (uint128) {
uint128 blockNumber = uint128(block.number);
if (blockNumber < firstEpochBlock) return epochCheckpoint;
return (blockNumber - firstEpochBlock) / epochLength + epochCheckpoint + 1;
return (blockNumber - firstEpochBlock) / workerEpochLength + epochCheckpoint + 1;
}
}
6 changes: 6 additions & 0 deletions packages/contracts/src/interfaces/INetworkController.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,16 @@ interface INetworkController {
event AllowedVestedTargetUpdated(address target, bool isAllowed);
event TargetCapacityUpdated(uint256 target);
event RewardCoefficientUpdated(uint256 coefficient);
event LockPeriodUpdated(uint256 lockPeriod);

/// @notice Deprecated
/// @dev Amount of blocks in one epoch
/// @notice It's now lock period for workers for compatibility reason
function epochLength() external view returns (uint128);

/// @dev Amount of blocks in one epoch
function workerEpochLength() external view returns (uint128);

/// @dev Amount of tokens required to register a worker
function bondAmount() external view returns (uint256);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ contract StakersRewardDistributionWithdrawTest is StakersRewardDistributionTest
}

function test_CannotWithdrawBeforeFullEpochEnds() public {
network.setEpochLength(50);
network.setLockPeriod(50);
assertEq(network.nextEpoch(), 5);
staking.deposit(workers[0], 100);
(, uint256 whenCanWithdraw) = staking.getDeposit(address(this), workers[0]);
Expand All @@ -96,9 +96,9 @@ contract StakersRewardDistributionWithdrawTest is StakersRewardDistributionTest
jumpToMomentWhenCanWithdraw(address(this));
staking.withdraw(workers[0], 50);
staking.deposit(workers[0], 100);
assertEq(network.nextEpoch(), 105);
(, whenCanWithdraw) = staking.getDeposit(address(this), workers[0]);
assertEq(whenCanWithdraw, 155);
assertEq(network.nextEpoch(), 57);
assertEq(whenCanWithdraw, 107);
}

// 2.5M gas for 100 distinct deposits
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import "./WorkerRegistration.sol";
contract WorkerRegistrationConstructorTest is WorkerRegistrationTest {
function testConstructor() public {
assertEq(address(workerRegistration.SQD()), address(token));
assertEq(workerRegistration.epochLength(), EPOCH_LENGTH);
assertEq(workerRegistration.lockPeriod(), EPOCH_LENGTH);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ contract WorkerRegistrationTest is BaseTest {
workerRegistration = WorkerRegistration(address(router.workerRegistration()));
networkController = NetworkController(address(router.networkController()));
networkController.setEpochLength(EPOCH_LENGTH);
networkController.setLockPeriod(EPOCH_LENGTH);
vm.roll(workerRegistration.nextEpoch());
staking = Staking(address(router.staking()));
token.approve(address(workerRegistration), workerRegistration.bondAmount());
Expand Down

2 comments on commit 2dbc366

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.