diff --git a/contracts/contracts/TACoApplication.sol b/contracts/contracts/TACoApplication.sol index 351e2a15..2c600ca9 100644 --- a/contracts/contracts/TACoApplication.sol +++ b/contracts/contracts/TACoApplication.sol @@ -151,8 +151,11 @@ contract TACoApplication is IApplication, ITACoChildToRoot, OwnableUpgradeable { uint256 public immutable minOperatorSeconds; uint256 public immutable rewardDuration; uint256 public immutable deauthorizationDuration; + uint64 public immutable commitmentDurationOption1; uint64 public immutable commitmentDurationOption2; + uint64 public immutable commitmentDurationOption3; + uint64 public immutable commitmentDurationOption4; IStaking public immutable tStaking; IERC20 public immutable token; @@ -179,8 +182,7 @@ contract TACoApplication is IApplication, ITACoChildToRoot, OwnableUpgradeable { * @param _minOperatorSeconds Min amount of seconds while an operator can't be changed * @param _rewardDuration Duration of one reward cycle in seconds * @param _deauthorizationDuration Duration of decreasing authorization in seconds - * @param _commitmentDurationOption1 Option 1 for commitment duration - * @param _commitmentDurationOption2 Option 2 for commitment duration + * @param _commitmentDurationOptions Options for commitment duration */ constructor( IERC20 _token, @@ -189,16 +191,14 @@ contract TACoApplication is IApplication, ITACoChildToRoot, OwnableUpgradeable { uint256 _minOperatorSeconds, uint256 _rewardDuration, uint256 _deauthorizationDuration, - uint64 _commitmentDurationOption1, - uint64 _commitmentDurationOption2 + uint64[] memory _commitmentDurationOptions ) { require( _rewardDuration != 0 && _tStaking.authorizedStake(address(this), address(this)) == 0 && _token.totalSupply() > 0 && - _commitmentDurationOption1 > 0 && - _commitmentDurationOption2 > 0 && - _commitmentDurationOption1 != _commitmentDurationOption2, + _commitmentDurationOptions.length >= 1 && + _commitmentDurationOptions.length <= 4, "Wrong input parameters" ); rewardDuration = _rewardDuration; @@ -207,8 +207,16 @@ contract TACoApplication is IApplication, ITACoChildToRoot, OwnableUpgradeable { token = _token; tStaking = _tStaking; minOperatorSeconds = _minOperatorSeconds; - commitmentDurationOption1 = _commitmentDurationOption1; - commitmentDurationOption2 = _commitmentDurationOption2; + commitmentDurationOption1 = _commitmentDurationOptions[0]; + commitmentDurationOption2 = _commitmentDurationOptions.length >= 2 + ? _commitmentDurationOptions[1] + : 0; + commitmentDurationOption3 = _commitmentDurationOptions.length >= 3 + ? _commitmentDurationOptions[2] + : 0; + commitmentDurationOption4 = _commitmentDurationOptions.length >= 4 + ? _commitmentDurationOptions[3] + : 0; _disableInitializers(); } @@ -540,19 +548,24 @@ contract TACoApplication is IApplication, ITACoChildToRoot, OwnableUpgradeable { /** * @notice Make a commitment to not request authorization decrease for specified duration * @param _stakingProvider Staking provider address - * @param _commitmentDurationOption2 If set to true then will be used second option of commitment duration. Otherwise first + * @param _commitmentDuration Duration of commitment */ function makeCommitment( address _stakingProvider, - bool _commitmentDurationOption2 + uint64 _commitmentDuration ) external onlyOwnerOrStakingProvider(_stakingProvider) { - uint64 duration = !_commitmentDurationOption2 - ? commitmentDurationOption1 - : commitmentDurationOption2; + require( + _commitmentDuration > 0 && + (_commitmentDuration == commitmentDurationOption1 || + _commitmentDuration == commitmentDurationOption2 || + _commitmentDuration == commitmentDurationOption3 || + _commitmentDuration == commitmentDurationOption4), + "Commitment duration must be equal to one of options" + ); StakingProviderInfo storage info = stakingProviderInfo[_stakingProvider]; require(info.endDeauthorization == 0, "Commitment can't be made during deauthorization"); require(info.endCommitment == 0, "Commitment already made"); - info.endCommitment = uint64(block.timestamp) + duration; + info.endCommitment = uint64(block.timestamp) + _commitmentDuration; emit CommitmentMade(_stakingProvider, info.endCommitment); } diff --git a/tests/application/conftest.py b/tests/application/conftest.py index ebf441ab..4e8e6d6b 100644 --- a/tests/application/conftest.py +++ b/tests/application/conftest.py @@ -29,7 +29,8 @@ DEAUTHORIZATION_DURATION = 60 * 60 * 24 * 60 # 60 days in seconds TOTAL_SUPPLY = Web3.to_wei(1_000_000_000, "ether") # TODO NU(1_000_000_000, 'NU').to_units() COMMITMENT_DURATION_1 = 182 * 60 * 24 * 60 # 182 days in seconds -COMMITMENT_DURATION_2 = 365 * 60 * 24 * 60 # 365 days in seconds +COMMITMENT_DURATION_2 = 2 * COMMITMENT_DURATION_1 # 365 days in seconds +COMMITMENT_DURATION_3 = 3 * COMMITMENT_DURATION_1 # 365 days in seconds DEPENDENCY = project.dependencies["openzeppelin"]["4.9.1"] @@ -77,8 +78,7 @@ def taco_application(project, creator, token, threshold_staking): MIN_OPERATOR_SECONDS, REWARD_DURATION, DEAUTHORIZATION_DURATION, - COMMITMENT_DURATION_1, - COMMITMENT_DURATION_2, + [COMMITMENT_DURATION_1, COMMITMENT_DURATION_2, COMMITMENT_DURATION_3], ) proxy_admin = DEPENDENCY.ProxyAdmin.deploy(sender=creator) diff --git a/tests/application/test_authorization.py b/tests/application/test_authorization.py index faadae9d..359279f8 100644 --- a/tests/application/test_authorization.py +++ b/tests/application/test_authorization.py @@ -413,7 +413,7 @@ def test_authorization_decrease_request( taco_application.finishAuthorizationDecrease(staking_provider, sender=creator) threshold_staking.authorizationIncreased(staking_provider, 0, value, sender=creator) commitment_duration = taco_application.commitmentDurationOption1() - taco_application.makeCommitment(staking_provider, False, sender=staking_provider) + taco_application.makeCommitment(staking_provider, commitment_duration, sender=staking_provider) # Commitment is still active with ape.reverts("Can't request deauthorization before end of commitment"): @@ -696,12 +696,13 @@ def test_commitment(accounts, threshold_staking, taco_application, chain): value = 2 * minimum_authorization commitment_duration_1 = taco_application.commitmentDurationOption1() commitment_duration_2 = taco_application.commitmentDurationOption2() + commitment_duration_3 = taco_application.commitmentDurationOption3() # Commitment can be made only for authorized staking provider with ape.reverts("Not owner or provider"): - taco_application.makeCommitment(staking_provider, False, sender=staking_provider) - with ape.reverts("Not owner or provider"): - taco_application.makeCommitment(staking_provider, True, sender=staking_provider) + taco_application.makeCommitment( + staking_provider, commitment_duration_1, sender=staking_provider + ) # Prepare staking provider threshold_staking.authorizationIncreased(staking_provider, 0, value, sender=creator) @@ -713,9 +714,9 @@ def test_commitment(accounts, threshold_staking, taco_application, chain): # Commitment can't be made during deauthorization with ape.reverts("Commitment can't be made during deauthorization"): - taco_application.makeCommitment(staking_provider, False, sender=staking_provider) - with ape.reverts("Commitment can't be made during deauthorization"): - taco_application.makeCommitment(staking_provider, True, sender=staking_provider) + taco_application.makeCommitment( + staking_provider, commitment_duration_3, sender=staking_provider + ) # Finish deauthorization chain.pending_timestamp += deauthorization_duration @@ -723,12 +724,22 @@ def test_commitment(accounts, threshold_staking, taco_application, chain): # Commitment can be made only by staking provider with ape.reverts("Not owner or provider"): - taco_application.makeCommitment(staking_provider, False, sender=another_staking_provider) - with ape.reverts("Not owner or provider"): - taco_application.makeCommitment(staking_provider, True, sender=another_staking_provider) + taco_application.makeCommitment( + staking_provider, commitment_duration_3, sender=another_staking_provider + ) + + # Commitment duration must be equal to one of options + with ape.reverts("Commitment duration must be equal to one of options"): + taco_application.makeCommitment(staking_provider, 0, sender=staking_provider) + with ape.reverts("Commitment duration must be equal to one of options"): + taco_application.makeCommitment( + staking_provider, commitment_duration_1 + 1, sender=staking_provider + ) # And make a commitment for shorter duration - tx = taco_application.makeCommitment(staking_provider, False, sender=staking_provider) + tx = taco_application.makeCommitment( + staking_provider, commitment_duration_1, sender=staking_provider + ) timestamp = chain.pending_timestamp - 1 end_commitment = timestamp + commitment_duration_1 assert ( @@ -743,17 +754,17 @@ def test_commitment(accounts, threshold_staking, taco_application, chain): # Commitment can't be made twice with ape.reverts("Commitment already made"): - taco_application.makeCommitment(staking_provider, False, sender=staking_provider) - with ape.reverts("Commitment already made"): - taco_application.makeCommitment(staking_provider, True, sender=staking_provider) + taco_application.makeCommitment( + staking_provider, commitment_duration_2, sender=staking_provider + ) # Another staking provider makes a commitment for longer period of time threshold_staking.authorizationIncreased(another_staking_provider, 0, value, sender=creator) tx = taco_application.makeCommitment( - another_staking_provider, True, sender=another_staking_provider + another_staking_provider, commitment_duration_3, sender=another_staking_provider ) timestamp = chain.pending_timestamp - 1 - end_commitment = timestamp + commitment_duration_2 + end_commitment = timestamp + commitment_duration_3 assert ( taco_application.stakingProviderInfo(another_staking_provider)[END_COMMITMENT_SLOT] == end_commitment